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
}