Files
tyapi-server/internal/domains/certification/entities/value_objects/enterprise_info.go

363 lines
10 KiB
Go
Raw Normal View History

2025-07-21 15:13:26 +08:00
package value_objects
import (
"errors"
"fmt"
"regexp"
"strings"
)
// EnterpriseInfo 企业信息值对象
// 封装企业认证所需的核心信息,包含完整的业务规则验证
type EnterpriseInfo struct {
// 企业基本信息
2025-07-28 01:46:39 +08:00
CompanyName string `json:"company_name"` // 企业名称
UnifiedSocialCode string `json:"unified_social_code"` // 统一社会信用代码
2025-07-21 15:13:26 +08:00
// 法定代表人信息
2025-07-28 01:46:39 +08:00
LegalPersonName string `json:"legal_person_name"` // 法定代表人姓名
LegalPersonID string `json:"legal_person_id"` // 法定代表人身份证号
LegalPersonPhone string `json:"legal_person_phone"` // 法定代表人手机号
2025-07-21 15:13:26 +08:00
// 企业详细信息
2025-07-28 01:46:39 +08:00
RegisteredAddress string `json:"registered_address"` // 注册地址
EnterpriseAddress string `json:"enterprise_address"` // 企业地址(新增)
2025-07-21 15:13:26 +08:00
}
// NewEnterpriseInfo 创建企业信息值对象
2025-07-30 00:51:22 +08:00
func NewEnterpriseInfo(companyName, unifiedSocialCode, legalPersonName, legalPersonID, legalPersonPhone, enterpriseAddress string) (*EnterpriseInfo, error) {
2025-07-21 15:13:26 +08:00
info := &EnterpriseInfo{
CompanyName: strings.TrimSpace(companyName),
UnifiedSocialCode: strings.TrimSpace(unifiedSocialCode),
LegalPersonName: strings.TrimSpace(legalPersonName),
LegalPersonID: strings.TrimSpace(legalPersonID),
LegalPersonPhone: strings.TrimSpace(legalPersonPhone),
2025-07-28 01:46:39 +08:00
EnterpriseAddress: strings.TrimSpace(enterpriseAddress),
2025-07-21 15:13:26 +08:00
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if err := info.Validate(); err != nil {
return nil, fmt.Errorf("企业信息验证失败: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return info, nil
}
// Validate 验证企业信息的完整性和格式
func (e *EnterpriseInfo) Validate() error {
if err := e.validateCompanyName(); err != nil {
return err
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if err := e.validateUnifiedSocialCode(); err != nil {
return err
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if err := e.validateLegalPersonName(); err != nil {
return err
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if err := e.validateLegalPersonID(); err != nil {
return err
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if err := e.validateLegalPersonPhone(); err != nil {
return err
}
2025-07-28 01:46:39 +08:00
if err := e.validateEnterpriseAddress(); err != nil {
return err
}
2025-07-21 15:13:26 +08:00
return nil
}
// validateCompanyName 验证企业名称
func (e *EnterpriseInfo) validateCompanyName() error {
if e.CompanyName == "" {
return errors.New("企业名称不能为空")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if len(e.CompanyName) < 2 {
return errors.New("企业名称长度不能少于2个字符")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if len(e.CompanyName) > 100 {
return errors.New("企业名称长度不能超过100个字符")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 检查是否包含非法字符
invalidChars := []string{"`", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "+", "=", "{", "}", "[", "]", "\\", "|", ";", ":", "'", "\"", "<", ">", ",", ".", "?", "/"}
for _, char := range invalidChars {
if strings.Contains(e.CompanyName, char) {
return fmt.Errorf("企业名称不能包含特殊字符: %s", char)
}
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return nil
}
// validateUnifiedSocialCode 验证统一社会信用代码
func (e *EnterpriseInfo) validateUnifiedSocialCode() error {
if e.UnifiedSocialCode == "" {
return errors.New("统一社会信用代码不能为空")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 统一社会信用代码格式验证18位数字和字母
pattern := `^[0-9A-HJ-NPQRTUWXY]{2}[0-9]{6}[0-9A-HJ-NPQRTUWXY]{10}$`
matched, err := regexp.MatchString(pattern, e.UnifiedSocialCode)
if err != nil {
return fmt.Errorf("统一社会信用代码格式验证错误: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if !matched {
return errors.New("统一社会信用代码格式不正确应为18位数字和字母组合")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return nil
}
// validateLegalPersonName 验证法定代表人姓名
func (e *EnterpriseInfo) validateLegalPersonName() error {
if e.LegalPersonName == "" {
return errors.New("法定代表人姓名不能为空")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if len(e.LegalPersonName) < 2 {
return errors.New("法定代表人姓名长度不能少于2个字符")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if len(e.LegalPersonName) > 50 {
return errors.New("法定代表人姓名长度不能超过50个字符")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 中文姓名格式验证
2025-07-28 01:46:39 +08:00
pattern := "^[一-龥·]+$"
2025-07-21 15:13:26 +08:00
matched, err := regexp.MatchString(pattern, e.LegalPersonName)
if err != nil {
return fmt.Errorf("法定代表人姓名格式验证错误: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if !matched {
return errors.New("法定代表人姓名只能包含中文字符和间隔号")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return nil
}
// validateLegalPersonID 验证法定代表人身份证号
func (e *EnterpriseInfo) validateLegalPersonID() error {
if e.LegalPersonID == "" {
return errors.New("法定代表人身份证号不能为空")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 身份证号格式验证18位
if len(e.LegalPersonID) != 18 {
return errors.New("身份证号必须为18位")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
pattern := `^[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$`
matched, err := regexp.MatchString(pattern, e.LegalPersonID)
if err != nil {
return fmt.Errorf("身份证号格式验证错误: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if !matched {
return errors.New("身份证号格式不正确")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 身份证号校验码验证
if !e.validateIDChecksum() {
return errors.New("身份证号校验码错误")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return nil
}
// validateIDChecksum 验证身份证号校验码
func (e *EnterpriseInfo) validateIDChecksum() bool {
if len(e.LegalPersonID) != 18 {
return false
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 加权因子
weights := []int{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}
// 校验码对应表
checkCodes := []string{"1", "0", "X", "9", "8", "7", "6", "5", "4", "3", "2"}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
sum := 0
for i := 0; i < 17; i++ {
digit := int(e.LegalPersonID[i] - '0')
sum += digit * weights[i]
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
checkCodeIndex := sum % 11
expectedCheckCode := checkCodes[checkCodeIndex]
actualCheckCode := strings.ToUpper(string(e.LegalPersonID[17]))
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return expectedCheckCode == actualCheckCode
}
// validateLegalPersonPhone 验证法定代表人手机号
func (e *EnterpriseInfo) validateLegalPersonPhone() error {
if e.LegalPersonPhone == "" {
return errors.New("法定代表人手机号不能为空")
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 手机号格式验证11位数字1开头
pattern := `^1[3-9]\d{9}$`
matched, err := regexp.MatchString(pattern, e.LegalPersonPhone)
if err != nil {
return fmt.Errorf("手机号格式验证错误: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
if !matched {
return errors.New("手机号格式不正确应为11位数字且以1开头")
}
2025-07-28 01:46:39 +08:00
return nil
}
// validateEnterpriseAddress 验证企业地址
func (e *EnterpriseInfo) validateEnterpriseAddress() error {
if strings.TrimSpace(e.EnterpriseAddress) == "" {
return errors.New("企业地址不能为空")
}
if len(e.EnterpriseAddress) < 5 {
return errors.New("企业地址长度不能少于5个字符")
}
if len(e.EnterpriseAddress) > 200 {
return errors.New("企业地址长度不能超过200个字符")
}
return nil
}
2025-07-21 15:13:26 +08:00
// IsComplete 检查企业信息是否完整
func (e *EnterpriseInfo) IsComplete() bool {
return e.CompanyName != "" &&
e.UnifiedSocialCode != "" &&
e.LegalPersonName != "" &&
e.LegalPersonID != "" &&
2025-07-28 01:46:39 +08:00
e.LegalPersonPhone != "" &&
2025-07-30 00:51:22 +08:00
e.EnterpriseAddress != ""
2025-07-21 15:13:26 +08:00
}
// IsDetailComplete 检查企业详细信息是否完整
func (e *EnterpriseInfo) IsDetailComplete() bool {
return e.IsComplete() &&
e.RegisteredAddress != "" &&
2025-07-28 01:46:39 +08:00
e.EnterpriseAddress != ""
2025-07-21 15:13:26 +08:00
}
// GetDisplayName 获取显示用的企业名称
func (e *EnterpriseInfo) GetDisplayName() string {
if e.CompanyName == "" {
return "未知企业"
}
return e.CompanyName
}
// GetMaskedUnifiedSocialCode 获取脱敏的统一社会信用代码
func (e *EnterpriseInfo) GetMaskedUnifiedSocialCode() string {
if len(e.UnifiedSocialCode) != 18 {
return e.UnifiedSocialCode
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 保留前6位和后4位中间用*替代
return e.UnifiedSocialCode[:6] + "********" + e.UnifiedSocialCode[14:]
}
// GetMaskedLegalPersonID 获取脱敏的法定代表人身份证号
func (e *EnterpriseInfo) GetMaskedLegalPersonID() string {
if len(e.LegalPersonID) != 18 {
return e.LegalPersonID
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 保留前6位和后4位中间用*替代
return e.LegalPersonID[:6] + "********" + e.LegalPersonID[14:]
}
// GetMaskedLegalPersonPhone 获取脱敏的法定代表人手机号
func (e *EnterpriseInfo) GetMaskedLegalPersonPhone() string {
if len(e.LegalPersonPhone) != 11 {
return e.LegalPersonPhone
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
// 保留前3位和后4位中间用*替代
return e.LegalPersonPhone[:3] + "****" + e.LegalPersonPhone[7:]
}
// Equals 比较两个企业信息是否相等
func (e *EnterpriseInfo) Equals(other *EnterpriseInfo) bool {
if other == nil {
return false
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return e.CompanyName == other.CompanyName &&
e.UnifiedSocialCode == other.UnifiedSocialCode &&
e.LegalPersonName == other.LegalPersonName &&
e.LegalPersonID == other.LegalPersonID &&
2025-07-30 00:51:22 +08:00
e.LegalPersonPhone == other.LegalPersonPhone
2025-07-21 15:13:26 +08:00
}
// Clone 创建企业信息的副本
func (e *EnterpriseInfo) Clone() *EnterpriseInfo {
return &EnterpriseInfo{
2025-07-28 01:46:39 +08:00
CompanyName: e.CompanyName,
UnifiedSocialCode: e.UnifiedSocialCode,
LegalPersonName: e.LegalPersonName,
LegalPersonID: e.LegalPersonID,
LegalPersonPhone: e.LegalPersonPhone,
RegisteredAddress: e.RegisteredAddress,
EnterpriseAddress: e.EnterpriseAddress,
2025-07-21 15:13:26 +08:00
}
}
// String 返回企业信息的字符串表示
func (e *EnterpriseInfo) String() string {
2025-07-28 01:46:39 +08:00
return fmt.Sprintf("企业信息[名称:%s, 信用代码:%s, 法人:%s]",
e.CompanyName,
e.GetMaskedUnifiedSocialCode(),
2025-07-21 15:13:26 +08:00
e.LegalPersonName)
}
// ToMap 转换为map格式用于序列化
func (e *EnterpriseInfo) ToMap() map[string]interface{} {
return map[string]interface{}{
"company_name": e.CompanyName,
"unified_social_code": e.UnifiedSocialCode,
"legal_person_name": e.LegalPersonName,
"legal_person_id": e.LegalPersonID,
"legal_person_phone": e.LegalPersonPhone,
"registered_address": e.RegisteredAddress,
2025-07-28 01:46:39 +08:00
"enterprise_address": e.EnterpriseAddress,
2025-07-21 15:13:26 +08:00
}
}
// FromMap 从map格式创建企业信息用于反序列化
func FromMap(data map[string]interface{}) (*EnterpriseInfo, error) {
getString := func(key string) string {
if val, exists := data[key]; exists {
if str, ok := val.(string); ok {
return strings.TrimSpace(str)
}
}
return ""
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
info := &EnterpriseInfo{
2025-07-28 01:46:39 +08:00
CompanyName: getString("company_name"),
UnifiedSocialCode: getString("unified_social_code"),
LegalPersonName: getString("legal_person_name"),
LegalPersonID: getString("legal_person_id"),
LegalPersonPhone: getString("legal_person_phone"),
RegisteredAddress: getString("registered_address"),
EnterpriseAddress: getString("enterprise_address"),
}
2025-07-21 15:13:26 +08:00
if err := info.Validate(); err != nil {
return nil, fmt.Errorf("从Map创建企业信息失败: %w", err)
}
2025-07-28 01:46:39 +08:00
2025-07-21 15:13:26 +08:00
return info, nil
2025-07-28 01:46:39 +08:00
}