package logic import ( "encoding/base64" "errors" "fmt" "github.com/golangkit/formatime" "github.com/jinzhu/gorm" "github.com/shopspring/decimal" "github.com/thecodingmachine/gotenberg-go-client/v7" "gopkg.in/gomail.v2" "log" "math/rand" "path/filepath" "recook/configs" "recook/internal/dbc" "recook/internal/libs/bean" "recook/internal/libs/docx" "recook/internal/libs/images" "recook/internal/model/gys" "recook/internal/model/vend" "recook/internal/static_path" "recook/tools" "regexp" "strconv" "sync" "time" ) type EnterpriseInfo struct { EnterpriseName string `json:"enterpriseName" form:"enterpriseName"` // 企业名称 RegistrationAddress int `json:"registrationAddress" form:"registrationAddress"` // 注册地区 Trade int `json:"trade" form:"trade"` // 贸易类型 CompanyType int `json:"companyType" form:"companyType"` // 公司类型 CompanyTypeInfo string `json:"companyTypeInfo" form:"companyTypeInfo"` // 类型说明 Capital string `json:"capital" form:"capital"` // 注册资本 CapitalDecimal decimal.Decimal Currency string `json:"currency" form:"currency"` // 货币类型 BusinessStart string `json:"businessStart" form:"businessStart"` // 营业期限开始时间 BusinessStartTime time.Time BusinessEnd string `json:"businessEnd" form:"businessEnd"` // 营业期限截止时间 BusinessEndTime time.Time RegistrationProvince string `json:"registrationProvince" form:"registrationProvince"` // 注册地省份 RegistrationCity string `json:"registrationCity" form:"registrationCity"` // 注册地市 RegistrationDistrict string `json:"registrationDistrict" form:"registrationDistrict"` // 注册地区 RegistrationDetailAddress string `json:"registrationDetailAddress" form:"registrationDetailAddress"` // 注册地址 OperationProvince string `json:"operationProvince" form:"operationProvince"` // 经营地省份 OperationCity string `json:"operationCity" form:"operationCity"` // 经营地市 OperationDistrict string `json:"operationDistrict" form:"operationDistrict"` // 经营地区 OperationAddress string `json:"operationAddress" form:"operationAddress"` // 经营地址 EnterpriseCode string `json:"enterpriseCode" form:"enterpriseCode"` // 工商注册号 LicenseUrl string `json:"licenseUrl" form:"licenseUrl"` // 营业执照地址 PayTaxes int `json:"payTaxes" form:"payTaxes"` // 纳税人类型 PaytaxesUrl string `json:"payTaxesUrl" form:"payTaxesUrl"` // 一般纳税人资质 AccountUrl string `json:"accountUrl" form:"accountUrl"` // 银行开户证明 LegalPerson string `json:"legalPerson" form:"legalPerson"` // 法人姓名 LegalPersonCode string `json:"legalPersonCode" form:"legalPersonCode"` // 法人证件号 LegalPersonUrl string `json:"legalPersonUrl" form:"legalPersonUrl"` // 法人证件照 OverseasRegistration string `json:"overseasRegistration" form:"overseasRegistration"` // 注册国家地区 OverseasOperation string `json:"overseasOperation" form:"overseasOperation"` // 经营国家地区 OverseasOperationInfo string `json:"overseasOperationInfo" form:"overseasOperationInfo"` // 详细经营地址 OverseasCode string `json:"overseasCode" form:"overseasCode"` // 商业登记号 OverseasCodeUrl string `json:"overseasCodeUrl" form:"overseasCodeUrl"` // 商业登记注册文件 OverseasAccountUrl string `json:"overseasAccountUrl" form:"overseasAccountUrl"` // 海外银行开户证明 OverseasLegalPerson string `json:"overseasLegalPerson" form:"overseasLegalPerson"` // 法人姓名 OverseasLegalPersonUrl string `json:"overseasLegalPersonUrl" form:"overseasLegalPersonUrl"` // 法人身份证明文件 Sales Sector `json:"sales" form:"sales"` // 业务人员 AfterSales Sector `json:"afterSales" form:"afterSales"` // 售后人员 Account Sector `json:"account" form:"account"` // 对账人员 Brand []BrandItem `json:"brand" form:"brand"` // 品牌信息 } var ( EnterpriseLogic = &enterprise{} mu sync.Mutex date = time.Now().Format("20060102") noMap = map[int]bool{} ) type enterprise struct { } // @Style 企业信息验证 func (e *enterprise) Verfiy(info *EnterpriseInfo) (err error) { if info.EnterpriseName == "" { return errors.New("请填写企业名称") } if info.RegistrationAddress < 1 || info.RegistrationAddress > 3 { return errors.New("注册地非法") } if info.RegistrationAddress == 1 { if info.Trade != 1 && info.Trade != 2 { return errors.New("贸易类型非法") } } else { if info.Trade != 3 { return errors.New("贸易类型非法") } } if info.CompanyType < 1 || info.CompanyType > 4 { return errors.New("公司类型非法") } if info.CompanyType == 4 && info.CompanyTypeInfo == "" { return errors.New("请填写公司类型描述") } if info.Capital == "" { return errors.New("请填写注册资金") } info.CapitalDecimal, err = decimal.NewFromString(info.Capital) if err != nil { return errors.New("注册资金错误") } if info.Currency == "" { return errors.New("请选择资金币种") } if info.BusinessStart == "" || info.BusinessEnd == "" { return errors.New("请选择营业期限") } info.BusinessStartTime, err = time.ParseInLocation("2006-01-02", info.BusinessStart, time.Local) if err != nil { return errors.New("请正确填写营业期限") } info.BusinessEndTime, err = time.ParseInLocation("2006-01-02", info.BusinessEnd, time.Local) if err != nil { return errors.New("请正确填写营业期限") } if info.RegistrationAddress == 1 { if info.RegistrationProvince == "" { return errors.New("请选择注册省份") } if info.RegistrationCity == "" { return errors.New("请选择注册城市") } if info.RegistrationDistrict == "" { return errors.New("请选择注册区县") } if info.OperationProvince == "" { return errors.New("请选择经营省份") } if info.OperationCity == "" { return errors.New("请选择经营城市") } if info.OperationDistrict == "" { return errors.New("请选择经营区县") } if info.OperationAddress == "" { return errors.New("请填写详细地址") } if info.EnterpriseCode == "" { return errors.New("请填写统一社会信用代码") } if info.LicenseUrl == "" { return errors.New("请上传营业执照副本") } if info.PayTaxes < 1 || info.PayTaxes > 2 { return errors.New("纳税人类型非法") } if info.PaytaxesUrl == "" { return errors.New("请上传纳税人资质") } if info.AccountUrl == "" { return errors.New("请上传银行开户证明") } if info.LegalPerson == "" { return errors.New("请填写法人证明") } if !tools.VerifyIdCard(info.LegalPersonCode) { return errors.New("请正确填写法人身份证号") } if info.LegalPersonUrl == "" { return errors.New("请上传法人身份证") } } else { if info.OverseasRegistration == "" { return errors.New("请选择注册国家/地区") } if info.OverseasOperation == "" { return errors.New("请选择经营国家/地区") } if info.OverseasOperationInfo == "" { return errors.New("请填写经营地区详细地址") } if info.OverseasCode == "" { return errors.New("请填写商业登记号码") } if info.OverseasCodeUrl == "" { return errors.New("请上传公司登记注册文件") } if info.OverseasAccountUrl == "" { return errors.New("请上传海外银行开户证明") } if info.OverseasLegalPerson == "" { return errors.New("请填写法人姓名") } if info.OverseasLegalPersonUrl == "" { return errors.New("请上传身份证明文件") } } // 联系人验证 if err := SectorLogic.VerfiySector(info.Sales); err != nil { return err } if err := SectorLogic.VerfiySector(info.AfterSales); err != nil { return err } if err := SectorLogic.VerfiySector(info.Account); err != nil { return err } // 品牌信息验证 if err := BrandLogic.VerfiyBrand(&info.Brand); err != nil { return err } return } // 企业提交资料 func (e *enterprise) Create(data *vend.GysEnterpriseState, db *gorm.DB) { db.Create(data) } // @Style 更新企业资料 func (e *enterprise) Updates(enterpriseId uint, data *vend.GysEnterpriseState, db *gorm.DB) int64 { return db.Table(data.TableName()).Where("id = ?", enterpriseId).Updates(&data).RowsAffected } // @Style 发送邮件 func (e *enterprise) SendEmail(email string, userId uint) error { m := gomail.NewMessage() m.SetHeader("From", configs.Config_Gys_Email_Setting_Mail) m.SetHeader("To", email) m.SetHeader("Subject", "瑞库客平台消息通知--【审核通知】!") state := vend.GysEnterpriseState{} dbc.DB.First(&state, "user_id = ?", userId) gysUser := vend.GysUsers{} dbc.DB.First(&gysUser, "id = ?", userId) if state.ID <= 0 { log.Println("sendMailError: 未查询到供应商信息 user_id:", userId, ";email:", email) return nil } m.SetBody("text/html", fmt.Sprintf(`尊敬的供应商 %s:

您好!

恭喜您通过瑞库客供应商资质审核,请下载附件签署纸质协议,盖章后请寄送至浙江省宁波市高新区菁华路108号德邦大厦4楼,收件人:瑞库客招商部 400-889-4489

瑞库客供应商后台地址:%s
账号:%s
密码:%s
系统邮件,请勿回复!`, state.EnterpriseName, configs.GYS_Login_Url, configs.GYS_Login_Url, gysUser.Username, gysUser.Password)) doc, err := e.GetContractDoc(state) if err != nil { log.Println("sendMailError: err:", err, " ;user_id:", userId, ";email:", email) return err } c := &gotenberg.Client{Hostname: configs.Config_Gotenberg} docx, err := gotenberg.NewDocumentFromPath("contract.docx", doc) if err != nil { return err } req := gotenberg.NewOfficeRequest(docx) req.WaitTimeout(30) filename := static_path.Dir.Root + "/contract/pdf/瑞库客平台合作协议_" + state.ContractNo + ".pdf" if err := c.Store(req, filename); err != nil { return err } m.Attach(filename, gomail.Rename("=?utf-8?B?"+base64.StdEncoding.EncodeToString([]byte("瑞库客平台合作协议_"+state.ContractNo+".pdf"))+"?=")) d := gomail.NewDialer(configs.Config_Gys_Email_Setting_Smtp, configs.Config_Gys_Email_Setting_Port, configs.Config_Gys_Email_Setting_User, configs.Config_Gys_Email_Setting_Pass) if err := d.DialAndSend(m); err != nil { return err } return nil } type ArgsYes struct { PayTaxes int `json:"payTaxes" form:"payTaxes"` EnterpriseId uint `json:"enterpriseId" form:"enterpriseId"` ContractStart string `json:"contractStart" form:"contractStart"` ContractStartTime formatime.Second ContraceEnd string `json:"contraceEnd" form:"contraceEnd"` ContraceEndTime formatime.Second Deposit float64 `json:"deposit" form:"deposit"` Period int `json:"period" form:"period"` PaytaxesUrl string `json:"paytaxesUrl" form:"paytaxesUrl"` } // @Style 审核成功验证 func (e *enterprise) Verified(data *ArgsYes) error { if data.PayTaxes > 2 { return errors.New("一般纳税人错误") } if data.PayTaxes < 1 { return errors.New("一般纳税人错误") } if data.EnterpriseId <= 0 { return errors.New("参数错误") } if data.ContractStart == "" { return errors.New("合同开始时间不能为空") } contractStart, err := time.ParseInLocation("2006-01-02", data.ContractStart, time.Local) if err != nil { return err } data.ContractStartTime = formatime.NewSecondFrom(contractStart) contractEnd, err := time.ParseInLocation("2006-01-02", data.ContraceEnd, time.Local) if err != nil { return err } data.ContraceEndTime = formatime.NewSecondFrom(contractEnd) if data.Deposit < 0 { return errors.New("保证金错误") } if data.Period <= 0 { return errors.New("账期错误") } if data.PayTaxes == 1 { if data.PaytaxesUrl == "" { return errors.New("请上传纳税人资格证") } } return nil } // @Style 合同初始化 func (*enterprise) ContractInit(contractNo string, companyName, taxNumber, address, bankName, bankCode string, source gys.GysSource) error { contractPath := filepath.Join(static_path.Dir.Root, static_path.Dir.Photo, "/contract") font := "./credentials/font/simsun.ttc" filename := tools.MD5(contractNo+"-contract-01.jpg") + ".jpg" err := images.WaterMark(contractPath+"/contract-01.jpg", font, contractPath+"/"+filename, []images.ContentItem{ { Content: contractNo, X: 622, Y: 125, }, { Content: source.Name, X: 330, Y: 710, FontSizt: 16, }, { Content: source.OperationAddress, X: 235, Y: 734, FontSizt: 16, }, { Content: companyName, X: 330, Y: 780, FontSizt: 16, }, { Content: address, X: 235, Y: 802, FontSizt: 16, }, }, []images.FileItem{}) if err != nil { return err } filename = tools.MD5(contractNo+"-contract-03.jpg") + ".jpg" err = images.WaterMark(contractPath+"/contract-03.jpg", font, contractPath+"/"+filename, []images.ContentItem{ { Content: companyName, X: 215, Y: 225, }, { Content: taxNumber, X: 242, Y: 256, }, { Content: address, X: 184, Y: 288, }, { Content: bankName, X: 200, Y: 318, }, { Content: bankCode, X: 184, Y: 350, }, }, []images.FileItem{}) if err != nil { return err } filename = tools.MD5(contractNo+"-contract-04.jpg") + ".jpg" err = images.WaterMark(contractPath+"/contract-04.jpg", font, contractPath+"/"+filename, []images.ContentItem{ { Content: companyName, X: 215, Y: 225, }, { Content: taxNumber, X: 242, Y: 256, }, { Content: address, X: 184, Y: 288, }, { Content: bankName, X: 200, Y: 318, }, { Content: bankCode, X: 184, Y: 350, }, { Content: source.Name, X: 215, Y: 907, }, { Content: source.TaxNumber, X: 242, Y: 938, }, { Content: source.Address, X: 184, Y: 970, }, { Content: source.BankName, X: 200, Y: 1000, }, { Content: source.BankCode, X: 184, Y: 1032, }, }, []images.FileItem{}) if err != nil { return err } filename = tools.MD5(contractNo+"-contract-05.jpg") + ".jpg" err = images.WaterMark(contractPath+"/contract-05.jpg", font, contractPath+"/"+filename, []images.ContentItem{ { Content: companyName, X: 215, Y: 225, }, { Content: taxNumber, X: 242, Y: 256, }, { Content: address, X: 184, Y: 288, }, { Content: bankName, X: 200, Y: 318, }, { Content: bankCode, X: 184, Y: 350, }, }, []images.FileItem{}) if err != nil { return err } return nil } // @Style 获取合同编号 func (e *enterprise) GetContractNo() (no string, err error) { nowDate := time.Now().Format("20060102") mu.Lock() defer mu.Unlock() if date != nowDate { date = nowDate noMap = map[int]bool{} } else { if len(noMap) >= 10000 { return "", errors.New("合同编号生成失败") } } for { contractNo := rand.Intn(9998) + 1 if !noMap[contractNo] { noMap[contractNo] = true return fmt.Sprintf("%s%.4d", date, contractNo), err } } } // @Style 合同 func (e *enterprise) GetContractDoc(state vend.GysEnterpriseState) (string, error) { gysSource := &gys.GysSource{} dbc.DB.First(&gysSource, "id = ?", state.Source) r, err := docx.ReadDocxFile("./credentials/contract/contract.docx") if err != nil { return "", err } defer r.Close() docx1 := r.Editable() now := time.Now() docx1.Replace("Year", now.Format("2006"), -1) docx1.Replace("Month", now.Format("01"), -1) docx1.Replace("Day", now.Format("02"), -1) docx1.Replace("SourceName", gysSource.Name, -1) docx1.Replace("SourceOperationAddress", gysSource.OperationAddress, -1) docx1.Replace("SourceTaxNumber", gysSource.TaxNumber, -1) docx1.Replace("SourceAddress", gysSource.Address, -1) docx1.Replace("SourceBankName", gysSource.BankName, -1) docx1.Replace("SourceBankCode", gysSource.BankCode, -1) docx1.Replace("ContractNo", state.ContractNo, -1) docx1.Replace("EnterpriseName", state.EnterpriseName, -1) docx1.Replace("OperationAddress", state.OperationAddress, -1) docx1.Replace("Address", state.RegistrationDetailAddress, -1) docx1.Replace("UpDeposit", e.ConvertNumToCny(float64(state.Deposit.IntPart())), -1) docx1.Replace("Deposit", state.Deposit.String(), -1) docx1.Replace("TaxNumber", state.TaxNumber, -1) docx1.Replace("BankName", state.BankName, -1) docx1.Replace("BankCode", state.BankCode, -1) if state.Period == 1 { docx1.Replace("PeriodText", "乙方以甲方后台出具的对账单为结算依据,一个月四次对账期,每月 1 日-7 日,8 日核对;8 日-14 日,15 日核对; 15 日-21 日,22 日核对;22 日-30 日(或 31 日),次月1日核对,遇节假日顺延", -1) } else { docx1.Replace("PeriodText", "乙方以甲方后台出具的对账单为结算依据,一个月两次对账期, 每月 1 日-15 日,16 日核对;16 日-30 日(或 31 日),次月 1 日核对,遇节假日顺延", -1) } docx1.Replace("ContractStart", state.ContractStart.Time.Format(" 2006 年 01 月 02 日"), -1) docx1.Replace("ContractEnd", state.ContractEnd.Time.Format(" 2006 年 01 月 02 日"), -1) filename := static_path.Dir.Root + "/contract/瑞库客平台合作协议_" + state.ContractNo + ".docx" err = docx1.WriteToFile(filename) if err != nil { return "", err } return filename, nil } // @Style 人民币转大写 func (e *enterprise) ConvertNumToCny(num float64) string { if num == 0 { return "零" } strnum := strconv.FormatFloat(num*100, 'f', 0, 64) sliceUnit := []string{"仟", "佰", "拾", "亿", "仟", "佰", "拾", "万", "仟", "佰", "拾", "元", "角", "分"} s := sliceUnit[len(sliceUnit)-len(strnum) : len(sliceUnit)] upperDigitUnit := map[string]string{"0": "零", "1": "壹", "2": "贰", "3": "叁", "4": "肆", "5": "伍", "6": "陆", "7": "柒", "8": "捌", "9": "玖"} str := "" for k, v := range strnum[:] { str = str + upperDigitUnit[string(v)] + s[k] } reg, err := regexp.Compile(`零角零分$`) str = reg.ReplaceAllString(str, "") reg, err = regexp.Compile(`零角`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零分$`) str = reg.ReplaceAllString(str, "") reg, err = regexp.Compile(`零[仟佰拾]`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零{2,}`) str = reg.ReplaceAllString(str, "零") reg, err = regexp.Compile(`零亿`) str = reg.ReplaceAllString(str, "亿") reg, err = regexp.Compile(`零万`) str = reg.ReplaceAllString(str, "万") reg, err = regexp.Compile(`零*元`) str = reg.ReplaceAllString(str, "") reg, err = regexp.Compile(`亿万`) str = reg.ReplaceAllString(str, "亿") reg, err = regexp.Compile(`零元`) str = reg.ReplaceAllString(str, "零") if err != nil { } return str } func (e *enterprise) Lists(status int, enterpriseName, contractNo string, source uint, comitTimeStart, comitTimeEnd, adminDateStart, adminDateEnd string, page bean.Page) (total int, lists []vend.GysEnterpriseState) { lists = []vend.GysEnterpriseState{} // 状态 whereStr := "company_id > 0 and state = ? " whereValue := []interface{}{status} // 企业名称 if enterpriseName != "" { whereStr += "and enterprise_name like ? " whereValue = append(whereValue, "%"+enterpriseName+"%") } // 合同编号 if contractNo != "" { whereStr += "and contract_no = ? " whereValue = append(whereValue, contractNo) } // 运营方 if source > 0 { whereStr += "and source = ? " whereValue = append(whereValue, source) } // 申请时间 if comitTimeStart != "" && comitTimeEnd != "" { whereStr += "and comit_time between ? and ? " whereValue = append(whereValue, comitTimeStart+" 00:00:00", comitTimeEnd+" 23:59:59") } // 审核时间 if adminDateStart != "" && adminDateEnd != "" { whereStr += "and admin_date between ? and ? " whereValue = append(whereValue, adminDateStart+" 00:00:00", adminDateEnd+" 23:59:59") } start := page.GetStart() dbc.DB.Model(&vend.GysEnterpriseState{}).Where(whereStr, whereValue...).Count(&total) if total > start { dbc.DB.Model(&vend.GysEnterpriseState{}).Where(whereStr, whereValue...).Offset(start).Limit(page.GetLimit()).Find(&lists) } return }