Selaa lähdekoodia

feature: 合同、回款功能优化

liuyaqi 2 vuotta sitten
vanhempi
commit
7eb31231fd

+ 1 - 1
opms_parent/app/handler/contract/ctr_contract_collection.go

@@ -25,7 +25,7 @@ func (c *CtrContractCollection) List(ctx context.Context, req *model.CtrContract
 		return err
 	}
 	if ent == nil {
-		ent = []*model.CtrContractCollection{}
+		ent = []*model.CtrContractCollectionListRsp{}
 	}
 	//rsp.Code = code
 	//rsp.Msg = msg

+ 1 - 1
opms_parent/app/handler/contract/ctr_contract_collection_plan.go

@@ -43,7 +43,7 @@ func (c *CtrContractCollectionPlan) List(ctx context.Context, req *model.CtrCont
 		return err
 	}
 	if ent == nil {
-		ent = []*model.CtrContractCollectionPlan{}
+		ent = []*model.CtrContractCollectionPlanListRsp{}
 	}
 	//rsp.Code = code
 	//rsp.Msg = msg

+ 5 - 0
opms_parent/app/model/contract/ctr_contract.go

@@ -42,6 +42,11 @@ type CtrContractListReq struct {
 	SignatoryName   string `json:"signatoryName"`   // 公司签约人
 	DistributorId   int    `json:"distributorId"`   // 经销商ID
 	DistributorName string `json:"distributorName"` // 经销商
+
+	ContractSignTimeStart string `p:"contractSignTimeStart"` //开始时间
+	ContractSignTimeEnd   string `p:"contractSignTimeEnd"`   //结束时间
+	CustProvinceId        int    `json:"custProvinceId"`     // 所在省ID
+	CustCityId            int    `json:"custCityId"`         // 所在市ID
 }
 
 type CtrAddProduct struct {

+ 19 - 0
opms_parent/app/model/contract/ctr_contract_collection.go

@@ -27,8 +27,27 @@ type CtrContractCollectionListReq struct {
 	CollectionType string `json:"collectionType"` // 回款方式
 	ApproStatus    string `json:"approStatus"`    // 审核状态 10 未回款 20 已回款
 	// ContractAmount     float64     `json:"contractAmount"`     // 合同金额
+	CollectionDatetimeStart *gtime.Time `json:"collectionDatetimeStart"` // 回款日期
+	CollectionDatetimeEnd   *gtime.Time `json:"collectionDatetimeEnd"`   // 回款日期
+	InchargeId              int         `json:"inchargeId"`              // 负责人(销售工程师)
+	InchargeName            string      `json:"inchargeName"`            // 负责人(销售工程师)
+	CustProvinceId          int         `json:"custProvinceId"`          // 所在省ID
+	CustCityId              int         `json:"custCityId"`              // 所在市ID
 }
 
+type CollectionContractInfo struct {
+	InchargeName   string `json:"inchargeName"`   // 负责人(销售工程师)
+	InchargeId     int    `json:"inchargeId"`     // 负责人(销售工程师)
+	CustProvinceId int    `json:"custProvinceId"` // 所在省ID
+	CustProvince   string `json:"custProvince"`   // 所在省
+	CustCityId     int    `json:"custCityId"`     // 所在市ID
+	CustCity       string `json:"custCity"`       // 所在市
+}
+
+type CtrContractCollectionListRsp struct {
+	CtrContractCollection
+	CollectionContractInfo
+}
 type CtrContractCollectionAddReq struct {
 	PlanId int `json:"planId"` // 合同回款计划
 	// CustId             int         `json:"custId"`             // 关联客户

+ 11 - 0
opms_parent/app/model/contract/ctr_contract_collection_plan.go

@@ -28,11 +28,22 @@ type CtrContractCollectionPlanListReq struct {
 	ContractId     int    `json:"contractId"`     // 关联合同
 	ContractCode   string `json:"contractCode"`   // 合同编号
 	ContractStatus string `json:"contractStatus"` // 回款状态(10待回款20部分回款30全部回款)
+	PlanBeginTime  string `p:"planBeginTime"`     //开始时间
+	PlanEndTime    string `p:"planEndTime"`       //结束时间
+	InchargeId     int    `json:"inchargeId"`     // 负责人(销售工程师)
+	InchargeName   string `json:"inchargeName"`   // 负责人(销售工程师)
+	CustProvinceId int    `json:"custProvinceId"` // 所在省ID
+	CustCityId     int    `json:"custCityId"`     // 所在市ID
+
 	// PlanAmount     float64     `json:"planAmount"`     // 计划回款金额
 	// PlanDatetime   *gtime.Time `json:"planDatetime"`   // 计划回款日期
 	// CashedAmount   float64     `json:"cashedAmount"`   // 实际回款金额
 	// CashedDatetime *gtime.Time `json:"cashedDatetime"` // 实际回款日期
 }
+type CtrContractCollectionPlanListRsp struct {
+	CtrContractCollectionPlan
+	CollectionContractInfo
+}
 
 type CtrContractCollectionPlanAddReq struct {
 	// CustId         int         `json:"custId"`         // 关联客户

+ 14 - 2
opms_parent/app/service/contract/ctr_contract.go

@@ -230,6 +230,18 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	if req.EndTime != "" {
 		dao = dao.Where("a.created_time < ?", req.EndTime)
 	}
+	if req.ContractSignTimeStart != "" {
+		dao = dao.Where("a.contract_sign_time >= ?", req.ContractSignTimeStart)
+	}
+	if req.ContractSignTimeEnd != "" {
+		dao = dao.Where("a.contract_sign_time <= ?", req.ContractSignTimeEnd)
+	}
+	if req.CustProvinceId != 0 {
+		dao = dao.Where("a.cust_province_id = ?", req.CustProvinceId)
+	}
+	if req.CustCityId != 0 {
+		dao = dao.Where("a.cust_city_id = ?", req.CustCityId)
+	}
 
 	total, err := dao.Count()
 	if err != nil {
@@ -238,7 +250,7 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	if req.PageNum != 0 {
 		dao = dao.Page(req.GetPage())
 	}
-	orderby := "a.created_time desc"
+	orderby := "a.contract_sign_time desc"
 	if req.OrderBy != "" {
 		orderby = req.OrderBy
 	}
@@ -367,7 +379,7 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		return 0, err
 	}
 	if req.ContractCode == "" {
-		req.ContractCode = fmt.Sprintf("DS%s%s%s", req.ContractType, time.Now().Format("0601"), sequence)
+		req.ContractCode = fmt.Sprintf("DS%s%s-%s", req.ContractType, time.Now().Format("0601"), sequence)
 	}
 	c, err = s.Dao.Where("contract_code = ?", req.ContractCode).One()
 	if err != nil {

+ 23 - 4
opms_parent/app/service/contract/ctr_contract_collection.go

@@ -59,7 +59,7 @@ func NewCtrContractCollectionService(ctx context.Context) (*CtrContractCollectio
 	}, nil
 }
 
-func (s CtrContractCollectionService) List(ctx context.Context, req *model.CtrContractCollectionListReq) (int, []*model.CtrContractCollection, error) {
+func (s CtrContractCollectionService) List(ctx context.Context, req *model.CtrContractCollectionListReq) (int, []*model.CtrContractCollectionListRsp, error) {
 	ctx = context.WithValue(ctx, "contextService", s)
 	dao := s.Dao.As("collection").LeftJoin(dao.CtrContract.Table, "contract", "contract.id=collection.contract_id").
 		DataScope(ctx, "incharge_id", "contract")
@@ -97,6 +97,25 @@ func (s CtrContractCollectionService) List(ctx context.Context, req *model.CtrCo
 	if req.EndTime != "" {
 		dao = dao.Where("collection.created_time < ?", req.EndTime)
 	}
+	if req.CollectionDatetimeStart != nil {
+		dao = dao.Where("collection.collection_datetime > ?", req.CollectionDatetimeStart)
+	}
+	if req.CollectionDatetimeEnd != nil {
+		dao = dao.Where("collection.collection_datetime < ?", req.CollectionDatetimeEnd)
+	}
+	if req.InchargeId != 0 {
+		dao = dao.Where("contract.incharge_id = ?", req.InchargeId)
+	}
+	if req.InchargeName != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.InchargeName)
+		dao = dao.Where("contract.incharge_name like ?", likestr)
+	}
+	if req.CustProvinceId != 0 {
+		dao = dao.Where("contract.cust_province_id = ?", req.CustProvinceId)
+	}
+	if req.CustCityId != 0 {
+		dao = dao.Where("contract.cust_city_id = ?", req.CustCityId)
+	}
 
 	total, err := dao.Count()
 	if err != nil {
@@ -105,14 +124,14 @@ func (s CtrContractCollectionService) List(ctx context.Context, req *model.CtrCo
 	if req.PageNum != 0 {
 		dao = dao.Page(req.GetPage())
 	}
-	orderby := "collection.created_time desc"
+	orderby := "collection.collection_datetime desc"
 	if req.OrderBy != "" {
 		orderby = req.OrderBy
 	}
 	dao = dao.Order(orderby)
 
-	ents := []*model.CtrContractCollection{}
-	err = dao.Fields("collection.*").Structs(&ents)
+	ents := []*model.CtrContractCollectionListRsp{}
+	err = dao.Fields("collection.*, contract.incharge_id, contract.incharge_name, contract.cust_province_id, contract.cust_city_id, contract.cust_province, contract.cust_city").Structs(&ents)
 	if err != nil && err != sql.ErrNoRows {
 		return 0, nil, err
 	}

+ 23 - 4
opms_parent/app/service/contract/ctr_contract_collection_plan.go

@@ -77,7 +77,7 @@ func (s CtrContractCollectionPlanService) Get(ctx context.Context, id int) (*mod
 	}, nil
 }
 
-func (s CtrContractCollectionPlanService) List(ctx context.Context, req *model.CtrContractCollectionPlanListReq) (int, []*model.CtrContractCollectionPlan, error) {
+func (s CtrContractCollectionPlanService) List(ctx context.Context, req *model.CtrContractCollectionPlanListReq) (int, []*model.CtrContractCollectionPlanListRsp, error) {
 	ctx = context.WithValue(ctx, "contextService", s)
 	dao := s.Dao.As("plan").LeftJoin(dao.CtrContract.Table, "contract", "contract.id=plan.contract_id").
 		DataScope(ctx, "incharge_id", "contract")
@@ -108,6 +108,25 @@ func (s CtrContractCollectionPlanService) List(ctx context.Context, req *model.C
 	if req.EndTime != "" {
 		dao = dao.Where("plan.created_time < ?", req.EndTime)
 	}
+	if req.PlanBeginTime != "" {
+		dao = dao.Where("plan.plan_datetime > ?", req.PlanBeginTime)
+	}
+	if req.PlanEndTime != "" {
+		dao = dao.Where("plan.plan_datetime < ?", req.PlanEndTime)
+	}
+	if req.InchargeId != 0 {
+		dao = dao.Where("contract.incharge_id = ?", req.InchargeId)
+	}
+	if req.InchargeName != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.InchargeName)
+		dao = dao.Where("contract.incharge_name like ?", likestr)
+	}
+	if req.CustProvinceId != 0 {
+		dao = dao.Where("contract.cust_province_id = ?", req.CustProvinceId)
+	}
+	if req.CustCityId != 0 {
+		dao = dao.Where("contract.cust_city_id = ?", req.CustCityId)
+	}
 
 	total, err := dao.Count()
 	if err != nil {
@@ -116,14 +135,14 @@ func (s CtrContractCollectionPlanService) List(ctx context.Context, req *model.C
 	if req.PageNum != 0 {
 		dao = dao.Page(req.GetPage())
 	}
-	orderby := "plan.created_time desc"
+	orderby := "plan.plan_datetime desc"
 	if req.OrderBy != "" {
 		orderby = req.OrderBy
 	}
 	dao = dao.Order(orderby)
 
-	ents := []*model.CtrContractCollectionPlan{}
-	err = dao.Fields("plan.*").Structs(&ents)
+	ents := []*model.CtrContractCollectionPlanListRsp{}
+	err = dao.Fields("plan.*, contract.incharge_id, contract.incharge_name, contract.cust_province_id, contract.cust_city_id, contract.cust_province, contract.cust_city").Structs(&ents)
 	if err != nil && err != sql.ErrNoRows {
 		return 0, nil, err
 	}

+ 2 - 4
opms_parent/go.mod

@@ -11,10 +11,8 @@ require (
 	github.com/robfig/cron v1.2.0
 	github.com/shopspring/decimal v1.3.1
 	github.com/smallnest/rpcx v1.8.0
-	github.com/stretchr/testify v1.8.0 // indirect
-	golang.org/x/crypto v0.5.0 // indirect
-	golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 // indirect
-	golang.org/x/tools v0.1.12
+	github.com/xuri/excelize/v2 v2.7.1
+	golang.org/x/tools v0.6.0
 	gopkg.in/yaml.v3 v3.0.1
 )
 

+ 32 - 14
opms_parent/go.sum

@@ -374,6 +374,11 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
 github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
 github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
+github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
+github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
+github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
+github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
+github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
 github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
 github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
@@ -467,6 +472,12 @@ github.com/xtaci/kcp-go v5.4.20+incompatible h1:TN1uey3Raw0sTz0Fg8GkfM0uH3YwzhnZ
 github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
 github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37 h1:EWU6Pktpas0n8lLQwDsRyZfmkPeRbdgPtW609es+/9E=
 github.com/xtaci/lossyconn v0.0.0-20200209145036-adba10fffc37/go.mod h1:HpMP7DB2CyokmAh4lp0EQnnWhmycP/TvwBGzvuie+H0=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
+github.com/xuri/efp v0.0.0-20220603152613-6918739fd470/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
+github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdVI=
+github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
+github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
@@ -497,12 +508,12 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
-golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
+golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
+golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
-golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
+golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
+golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
@@ -511,8 +522,9 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
 golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -549,8 +561,9 @@ golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.0.0-20220630215102-69896b714898/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -565,8 +578,9 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -613,11 +627,13 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220702020025-31831981b65f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220708085239-5a0f0661e09d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@@ -625,8 +641,9 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -647,8 +664,9 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
 golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
 golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

+ 138 - 0
opms_parent/schema/distributor.sql

@@ -0,0 +1,138 @@
+CREATE TABLE `base_distributor` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_code` varchar(32) NOT NULL COMMENT '经销商编码',
+  `dist_name` varchar(90) NOT NULL COMMENT '经销商名称',
+  `abbr_name` varchar(90) DEFAULT NULL COMMENT '助记名',
+  `dist_desc` text DEFAULT NULL COMMENT '经销商说明',
+  `dist_boss` varchar(90) NOT NULL COMMENT '负责人',
+  `dist_boss_phone` varchar(255) NOT NULL COMMENT '负责人电话',
+  `province_id` int(11) NOT NULL COMMENT '所属省份ID',
+  `province_desc` varchar(90) NOT NULL COMMENT '所属省份',
+  `business_scope` varchar(255) NOT NULL COMMENT '业务范围',
+  `belong_sale_id` int(11) NOT NULL COMMENT '归属销售ID',
+  `belong_sale` varchar(90) DEFAULT NULL COMMENT '归属销售',
+  `capital` decimal(24, 6) DEFAULT NULL COMMENT '注册资金',
+  `sale_num` int(11) DEFAULT NULL COMMENT '销售人数',
+  `invoice_header` varchar(255) DEFAULT NULL COMMENT '开票抬头',
+  `dist_type` varchar(4) DEFAULT '10' COMMENT '经销商类型 10 经销商 20 代理商',
+  `customer_type` varchar(255) NOT NULL COMMENT '授权客户类型',
+  `existed_product` text DEFAULT NULL COMMENT '已有代理品牌和产品',
+  `assistant_sale_id` text DEFAULT NULL COMMENT '助理人员Id',
+  `assistant_sale` text DEFAULT NULL COMMENT '助理人员',
+  `register_district` varchar(255) DEFAULT NULL COMMENT '注册地',
+  `history_customer` text DEFAULT NULL COMMENT '历史合作的终端客户名称',
+  `proxy_start_time` datetime DEFAULT NULL COMMENT '代理签约有效期开始(代理商)',
+  `proxy_end_time` datetime DEFAULT NULL COMMENT '代理签约有效期结束(代理商)',
+  `proxy_district` varchar(255) DEFAULT NULL COMMENT '授权代理区域(代理商)',
+  `contract_url` text DEFAULT NULL COMMENT '代理合同(代理商)',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 27 DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '经销商信息';
+CREATE TABLE `base_distributor_dynamics` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '经销商/代理商ID',
+  `opn_people_id` int(11) NOT NULL COMMENT '操作人ID',
+  `opn_people` varchar(90) NOT NULL COMMENT '操作人',
+  `opn_date` datetime NOT NULL COMMENT '操作日期',
+  `opn_type` varchar(10) NOT NULL COMMENT '操作类型',
+  `opn_content` text DEFAULT NULL COMMENT '操作内容',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`)
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '经销商/代理商动态';
+CREATE TABLE `base_distributor_contact` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '所属经销商',
+  `name` varchar(90) NOT NULL COMMENT '姓名',
+  `post` varchar(255) NOT NULL COMMENT '岗位',
+  `phone` varchar(255) NOT NULL COMMENT '电话',
+  `wechat` varchar(255) DEFAULT NULL COMMENT '微信',
+  `mail` varchar(255) DEFAULT NULL COMMENT '邮箱',
+  `honorific` varchar(255) DEFAULT NULL COMMENT '尊称',
+  `territory` text DEFAULT NULL COMMENT '负责区域/业务线',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '经销商联系人';
+CREATE TABLE `base_distributor_record` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '所属经销商',
+  `dist_type` varchar(4) DEFAULT '10' COMMENT '经销商类型 10 经销商 20 代理商',
+  `business_scope` varchar(255) NOT NULL COMMENT '业务范围',
+  `customer_type` varchar(255) NOT NULL COMMENT '授权客户类型',
+  `proxy_district` varchar(255) DEFAULT NULL COMMENT '授权代理区域(代理商)',
+  `proxy_start_time` datetime DEFAULT NULL COMMENT '代理签约有效期开始(代理商)',
+  `proxy_end_time` datetime DEFAULT NULL COMMENT '代理签约有效期结束(代理商)',
+  `contract_url` text DEFAULT NULL COMMENT '代理合同(代理商)',
+  `existed_product` text DEFAULT NULL COMMENT '已有代理品牌和产品',
+  `history_customer` text DEFAULT NULL COMMENT '历史合作的终端客户名称',
+  `to_dist_reason` text DEFAULT NULL COMMENT '转移经销商原因',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '历史代理记录';
+CREATE TABLE `base_distributor_target` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '所属经销商',
+  `year` int(11) NOT NULL COMMENT '年度',
+  `q1` decimal(24, 6) NOT NULL COMMENT 'q1指标(万元)',
+  `q2` decimal(24, 6) NOT NULL COMMENT 'q2指标(万元)',
+  `q3` decimal(24, 6) NOT NULL COMMENT 'q3指标(万元)',
+  `q4` decimal(24, 6) NOT NULL COMMENT 'q4指标(万元)',
+  `total` decimal(24, 6) NOT NULL COMMENT '年度指标(万元)',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '代理商业务指标';
+-- * 经销商名称:
+-- * 所在省份:
+-- * 注册资金:
+-- * 业务范围:
+-- * 授权客户类型:
+-- *已有代理品牌和产品:
+-- 助记名称:
+-- 归属人员:
+-- 助理人员:
+-- * 注册地:
+-- * 现有销售人数:
+-- * 历史合作的终端客户名称:
+-- * 代理签约有效期:
+-- * 代理指标:
+--   Q1代理指标
+--   Q2代理指标
+--   Q3代理指标
+--   Q4代理指标
+--   年度代理指标
+-- * 授权代理区域:
+-- 代理合同:

+ 78 - 0
opms_parent/schema/tmp.sql

@@ -47,3 +47,81 @@ alter table ctr_contract_product add `accept_time` datetime DEFAULT NULL COMMENT
 
 alter table ctr_contract_collection_plan add `plan_scale` decimal(24, 6) COMMENT '计划回款比例' after plan_datetime;
 alter table ctr_contract_collection_plan add `plan_condition` text COMMENT '回款条件' after plan_scale;
+
+
+
+-- 2023-05-11
+alter table base_distributor add `dist_type` varchar(4) DEFAULT '10' COMMENT '经销商类型 10 经销商 20 代理商' after invoice_header;
+alter table base_distributor add `customer_type` varchar(255) NOT NULL COMMENT  '授权客户类型' after dist_type;
+alter table base_distributor add `existed_product` text DEFAULT NULL COMMENT '已有代理品牌和产品' after customer_type;
+alter table base_distributor add `assistant_sale_id` text DEFAULT NULL COMMENT '助理人员Id' after existed_product;
+alter table base_distributor add `assistant_sale` text DEFAULT NULL COMMENT '助理人员' after assistant_sale_id;
+alter table base_distributor add `register_district`  varchar(255) DEFAULT NULL COMMENT '注册地' after assistant_sale;
+alter table base_distributor add `history_customer` text DEFAULT NULL COMMENT '历史合作的终端客户名称' after register_district;
+alter table base_distributor add `proxy_start_time` datetime DEFAULT NULL COMMENT '代理签约有效期开始(代理商)' after history_customer;
+alter table base_distributor add `proxy_end_time` datetime DEFAULT NULL COMMENT '代理签约有效期结束(代理商)' after proxy_start_time;
+alter table base_distributor add `proxy_district` varchar(255) DEFAULT NULL COMMENT '授权代理区域(代理商)' after proxy_end_time;
+alter table base_distributor add `contract_url` text DEFAULT NULL COMMENT '代理合同(代理商)' after proxy_district;
+CREATE TABLE `base_distributor_dynamics` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '经销商/代理商ID',
+  `opn_people_id` int(11) NOT NULL COMMENT '操作人ID',
+  `opn_people` varchar(90) NOT NULL COMMENT '操作人',
+  `opn_date` datetime NOT NULL COMMENT '操作日期',
+  `opn_type` varchar(10) NOT NULL COMMENT '操作类型',
+  `opn_content` text DEFAULT NULL COMMENT '操作内容',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '经销商/代理商动态';
+alter table base_distributor_contact add `honorific` varchar(255) DEFAULT NULL COMMENT '尊称' after mail;
+alter table base_distributor_contact add `territory` text DEFAULT NULL COMMENT '负责区域/业务线' after honorific;
+CREATE TABLE `base_distributor_record` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '所属经销商',
+  `dist_type` varchar(4) DEFAULT '10' COMMENT '经销商类型 10 经销商 20 代理商',
+  `business_scope` varchar(255) NOT NULL COMMENT '业务范围',
+  `customer_type` varchar(255) NOT NULL COMMENT '授权客户类型',
+  `proxy_district` varchar(255) DEFAULT NULL COMMENT '授权代理区域(代理商)',
+  `proxy_start_time` datetime DEFAULT NULL COMMENT '代理签约有效期开始(代理商)',
+  `proxy_end_time` datetime DEFAULT NULL COMMENT '代理签约有效期结束(代理商)',
+  `contract_url` text DEFAULT NULL COMMENT '代理合同(代理商)',
+  `existed_product` text DEFAULT NULL COMMENT '已有代理品牌和产品',
+  `history_customer` text DEFAULT NULL COMMENT '历史合作的终端客户名称',
+  `to_dist_reason` text DEFAULT NULL COMMENT '转移经销商原因',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '历史代理记录';
+CREATE TABLE `base_distributor_target` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `dist_id` int(11) NOT NULL COMMENT '所属经销商',
+  `year` int(11) NOT NULL COMMENT '年度',
+  `q1` decimal(24, 6) NOT NULL COMMENT 'q1指标(万元)',
+  `q2` decimal(24, 6) NOT NULL COMMENT 'q2指标(万元)',
+  `q3` decimal(24, 6) NOT NULL COMMENT 'q3指标(万元)',
+  `q4` decimal(24, 6) NOT NULL COMMENT 'q4指标(万元)',
+  `total` decimal(24, 6) NOT NULL COMMENT '年度指标(万元)',
+  `remark` text DEFAULT NULL COMMENT '备注',
+  `created_by` int(11) NOT NULL COMMENT '创建者',
+  `created_name` varchar(90) NOT NULL COMMENT '创建人',
+  `created_time` datetime NOT NULL COMMENT '创建时间',
+  `updated_by` int(11) DEFAULT NULL COMMENT '更新者',
+  `updated_name` varchar(90) DEFAULT NULL COMMENT '更新人',
+  `updated_time` datetime DEFAULT NULL COMMENT '更新时间',
+  `deleted_time` datetime DEFAULT NULL COMMENT '删除时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMMENT = '代理商业务指标';
+-- alter table base_distributor_contact modify `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键';

+ 941 - 0
opms_parent/script/main.go

@@ -0,0 +1,941 @@
+package main
+
+import (
+	"bytes"
+	"context"
+	"database/sql"
+	"fmt"
+	"io/ioutil"
+	"strings"
+	"time"
+
+	basedao "dashoo.cn/micro/app/dao/base"
+	contractdao "dashoo.cn/micro/app/dao/contract"
+	projao "dashoo.cn/micro/app/dao/proj"
+	basemodel "dashoo.cn/micro/app/model/base"
+	model "dashoo.cn/micro/app/model/contract"
+	"github.com/gogf/gf/database/gdb"
+	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/util/gconv"
+
+	"github.com/gogf/gf/os/gtime"
+	"github.com/xuri/excelize/v2"
+)
+
+func main() {
+	// contract()
+	// product()
+	// collectionplan()
+	// collection()
+	// dist()
+	// prepareuser()
+	// prepare()
+	// fmt.Println(Usermap)
+	// fmt.Println(MapProvince)
+	// distContact()
+	projectRelate()
+}
+
+func projectRelate() {
+	projao := projao.NewProjBusinessDao("prod")
+	contractdao := contractdao.NewCtrContractDao("prod")
+
+	fileb, err := ioutil.ReadFile("/home/lai/项目关联.xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	coderow, err := e.GetRows("Sheet1")
+	if err != nil {
+		panic(err)
+	}
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		for rown, row := range coderow[1:] {
+			projcode := strings.TrimSpace(row[0])
+			contrcode := strings.TrimSpace(row[1])
+
+			fmt.Println(rown, projcode, contrcode)
+
+			nbo, err := projao.Where("nbo_code = ?", projcode).One()
+			if err != nil {
+				return err
+			}
+			if nbo == nil {
+				return fmt.Errorf("项目不存在")
+			}
+			contract, err := contractdao.Where("contract_code = ?", contrcode).One()
+			if err != nil {
+				return err
+			}
+			if contract == nil {
+				return fmt.Errorf("合同不存在")
+			}
+
+			_, err = tx.Update("ctr_contract", map[string]interface{}{
+				"cust_id":          nbo.CustId,
+				"cust_name":        nbo.CustName,
+				"nbo_id":           nbo.Id,
+				"nbo_name":         nbo.NboName,
+				"is_big":           nbo.IsBig,
+				"product_line":     nbo.ProductLine,
+				"cust_province_id": nbo.CustProvinceId,
+				"cust_province":    nbo.CustProvince,
+				"cust_city_id":     nbo.CustCityId,
+				"cust_city":        nbo.CustCity,
+			}, "contract_code = ?", contrcode)
+			if err != nil {
+				return err
+			}
+		}
+		// return fmt.Errorf("测试")
+		return nil
+	})
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+func distContact() {
+	dao := basedao.NewBaseDistributorDao("prod")
+	distMap := map[string]*basemodel.BaseDistributor{}
+	ent, err := dao.All()
+	if err != nil {
+		panic(err)
+	}
+	for _, i := range ent {
+		distMap[i.DistName] = i
+	}
+	fmt.Println(distMap)
+
+	fileb, err := ioutil.ReadFile("/home/lai/渠道信息联系方式.xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	contact, err := e.GetRows("Sheet1")
+	if err != nil {
+		panic(err)
+	}
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		for rown, row := range contact[1:] {
+			distname := strings.TrimSpace(row[2])
+			name := strings.TrimSpace(row[3])
+			position := strings.TrimSpace(row[5])
+			phone := strings.TrimSpace(row[6])
+			email := strings.TrimSpace(row[7])
+			wechat := strings.TrimSpace(row[8])
+			business := strings.TrimSpace(row[9])
+
+			fmt.Println(rown, distname, name, position, phone, email, wechat, business, distMap[distname].Id)
+
+			p := basemodel.BaseDistributorContact{
+				DistId:      distMap[distname].Id,
+				Name:        name,
+				Post:        position,
+				Phone:       phone,
+				Wechat:      wechat,
+				Mail:        email,
+				Honorific:   "未知",
+				Territory:   business,
+				Remark:      "",
+				CreatedBy:   1000,
+				CreatedName: "dashoo",
+				CreatedTime: gtime.Now(),
+				UpdatedBy:   1000,
+				UpdatedName: "dashoo",
+				UpdatedTime: gtime.Now(),
+			}
+
+			_, err = tx.Insert("base_distributor_contact", p)
+			if err != nil {
+				return err
+			}
+		}
+		// return fmt.Errorf("测试")
+		return nil
+	})
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+type User struct {
+	Id       int
+	NickName string
+	UserName string
+}
+
+var Usermap = map[string]User{}
+
+func prepareuser() {
+	users := []User{}
+	err := g.DB("prod").Table("sys_user").Structs(&users)
+	if err != nil {
+		panic(err)
+	}
+	for _, u := range users {
+		Usermap[u.NickName] = u
+	}
+}
+
+func dist() {
+	prepare()
+	prepareuser()
+	var custtypMap = map[string]string{
+		"医院":   "10",
+		"科研单位": "20",
+		"高校":   "30",
+		"疾控":   "40",
+		"细胞公司": "50",
+		"生物药企": "60",
+		"其他":   "90",
+	}
+
+	fileb, err := ioutil.ReadFile("/home/lai/渠道信息台账0523(1)(1).xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	proxy, err := e.GetRows("代理商列表详情")
+	if err != nil {
+		panic(err)
+	}
+	dist, err := e.GetRows("经销商列表详情")
+	if err != nil {
+		panic(err)
+	}
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+
+		for rowtype, distlist := range [][][]string{dist, proxy} {
+
+			distType := "10"
+			if rowtype == 1 {
+				distType = "20"
+			}
+
+			for rown, row := range distlist[2:] {
+				createdStr := strings.TrimSpace(row[1])
+				seller := strings.TrimSpace(row[2])
+				name := strings.TrimSpace(row[3])
+				province := strings.TrimSpace(row[4])
+
+				var sellerNumStr string
+				var product string
+				var hisCust string
+				var custTypStr string
+				var proxydistrict string
+				var startStr string
+				var endStr string
+				var business string
+				var capitalStr string
+				var register string
+				if len(row) > 5 {
+					business = strings.TrimSpace(row[5])
+					capitalStr = strings.TrimSpace(row[6])
+					register = strings.TrimSpace(row[7])
+					if len(row) > 8 {
+						sellerNumStr = strings.TrimSpace(row[8])
+						if len(row) > 9 {
+							product = strings.TrimSpace(row[9])
+							if len(row) > 10 {
+								hisCust = strings.TrimSpace(row[10])
+								if len(row) > 11 {
+									if distType == "10" {
+										custTypStr = strings.TrimSpace(row[11])
+									} else {
+										// fmt.Println(row)
+										proxydistrict = strings.TrimSpace(row[12])
+										startStr = strings.TrimSpace(row[13])
+										endStr = strings.TrimSpace(row[14])
+										custTypStr = strings.TrimSpace(row[15])
+									}
+								}
+							}
+						}
+					}
+				}
+
+				created, err := time.Parse("2006/01/02 15:04:05", createdStr)
+				if err != nil {
+					panic(fmt.Errorf("%s, %s", createdStr, err.Error()))
+				}
+				start, err := time.Parse("2006/01/02", startStr)
+				if err != nil {
+					if distType == "10" {
+						start = time.Time{}
+					} else {
+						panic(fmt.Errorf("%s, %s", startStr, err.Error()))
+					}
+				}
+				end, err := time.Parse("2006/01/02", endStr)
+				if err != nil {
+					if distType == "10" {
+						start = time.Time{}
+					} else {
+						panic(fmt.Errorf("%s, %s", endStr, err.Error()))
+					}
+				}
+				sellerNum := gconv.Int(sellerNumStr)
+				capital := gconv.Float64(capitalStr)
+
+				var custypes string
+				if custTypStr == "" {
+					custypes = ""
+				} else {
+					custTypeslice := strings.Split(custTypStr, ",")
+					custypeslice := []string{}
+					for _, t := range custTypeslice {
+						if t == "企业" {
+							continue
+						}
+						if t == "医疗" {
+							continue
+						}
+						if t == "科研" {
+							continue
+						}
+						if t == "细胞企业" {
+							continue
+						}
+						if t == "生物药企、医院" {
+							custypeslice = append(custypeslice, custtypMap["生物药企"])
+							custypeslice = append(custypeslice, custtypMap["医院"])
+							continue
+						}
+						if custtypMap[t] == "" {
+							panic(t + ":custypeslice")
+						}
+						custypeslice = append(custypeslice, custtypMap[t])
+					}
+					custypes = strings.Join(custypeslice, ",")
+					if Usermap[seller].Id == 0 {
+						panic(seller + ":seller")
+					}
+				}
+
+				fmt.Println(rown, distType, created, seller, name, province, MapProvince[province], business, capital, register, sellerNum, product, hisCust, custypes, proxydistrict, start, end)
+
+				p := basemodel.BaseDistributor{
+					DistCode:         "",
+					DistName:         name,
+					AbbrName:         "",
+					DistDesc:         "",
+					DistBoss:         "",
+					DistBossPhone:    "",
+					ProvinceId:       MapProvince[province],
+					ProvinceDesc:     province,
+					BusinessScope:    business,
+					BelongSaleId:     Usermap[seller].Id,
+					BelongSale:       seller,
+					Capital:          capital,
+					SaleNum:          sellerNum,
+					InvoiceHeader:    "",
+					DistType:         distType,
+					CustomerType:     custypes,
+					ExistedProduct:   product,
+					AssistantSaleId:  "",
+					AssistantSale:    "",
+					RegisterDistrict: register,
+					HistoryCustomer:  hisCust,
+					ProxyStartTime:   gtime.NewFromTime(start),
+					ProxyEndTime:     gtime.NewFromTime(end),
+					ProxyDistrict:    proxydistrict,
+					ContractUrl:      "",
+					Remark:           "",
+					CreatedBy:        1000,
+					CreatedName:      "dashoo",
+					CreatedTime:      gtime.Now(),
+					UpdatedBy:        1000,
+					UpdatedName:      "dashoo",
+					UpdatedTime:      gtime.Now(),
+				}
+
+				_, err = tx.Insert("base_distributor", p)
+				if err != nil {
+					return err
+				}
+			}
+		}
+		// return fmt.Errorf("测试")
+		return nil
+	})
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+func collection() {
+	var typMap = map[string]string{
+		"电汇": "10",
+		"承兑": "20",
+		"现金": "30",
+	}
+
+	var contractMap = map[string]*model.CtrContract{}
+
+	fileb, err := ioutil.ReadFile("/home/lai/OMS合同管理17-23合同信息0519(1).xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	rows2021_2023, err := e.GetRows("2021-2023年回款管理")
+	if err != nil {
+		panic(err)
+	}
+	rows2017_2020, err := e.GetRows("2017-2020年回款管理")
+	if err != nil {
+		panic(err)
+	}
+	rows := append(rows2021_2023[1:], rows2017_2020[1:]...)
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+
+		for rown, row := range rows {
+			custname := strings.TrimSpace(row[0])
+			contractcode := strings.TrimSpace(row[1])
+			amountStr := strings.TrimSpace(row[2])
+			typ := strings.TrimSpace(row[3])
+			var ctimeStr string
+			if len(row) > 5 {
+				ctimeStr = strings.TrimSpace(row[5])
+			}
+
+			if ctimeStr == "" {
+				ctimeStr = "0001/1/2"
+			}
+
+			ctime, err := time.Parse("2006/1/2", ctimeStr)
+			if err != nil {
+				ctime, err = time.Parse("01-02-06", ctimeStr)
+			}
+			if err != nil {
+				ctime, err = time.Parse("2006.1.2", ctimeStr)
+			}
+			if err != nil {
+				if ctimeStr == "" {
+					ctime = time.Time{}
+				} else {
+					panic(fmt.Errorf("%s, %s", ctimeStr, err.Error()))
+				}
+			}
+			amount := gconv.Float64(amountStr)
+
+			fmt.Println(rown, custname, contractcode, amount, typ, ctime)
+
+			if _, ok := contractMap[contractcode]; !ok {
+				c := &model.CtrContract{}
+				err := tx.GetStruct(c, "select * from ctr_contract where contract_code = ?", contractcode)
+				if err != nil {
+					fmt.Println(c.ContractCode)
+					return err
+				}
+				contractMap[contractcode] = c
+			}
+
+			p := model.CtrContractCollection{
+				PlanId:             0,
+				CustId:             0,
+				CustName:           custname,
+				ContractId:         contractMap[contractcode].Id,
+				ContractCode:       contractMap[contractcode].ContractCode,
+				CollectionDatetime: gtime.NewFromTime(ctime),
+				CollectionAmount:   amount,
+				CollectionType:     typMap[typ],
+				ApproStatus:        "20",
+				ContractAmount:     contractMap[contractcode].ContractAmount,
+				Remark:             "",
+				CreatedBy:          1000,
+				CreatedName:        "dashoo",
+				CreatedTime:        gtime.Now(),
+				UpdatedBy:          1000,
+				UpdatedName:        "dashoo",
+				UpdatedTime:        gtime.Now(),
+			}
+
+			_, err = tx.Insert("ctr_contract_collection", p)
+			if err != nil {
+				return err
+			}
+		}
+		return nil
+		// return fmt.Errorf("测试")
+	})
+	fmt.Println(contractMap)
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+func collectionplan() {
+	var statusMap = map[string]string{
+		"已回款": "30",
+		"未回款": "10",
+	}
+
+	var contractMap = map[string]*model.CtrContract{}
+
+	fileb, err := ioutil.ReadFile("/home/lai/OMS合同管理17-23合同信息0519(1).xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	rows2021_2023, err := e.GetRows("2021-2023年回款计划")
+	if err != nil {
+		panic(err)
+	}
+	rows := rows2021_2023[1:]
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+
+		for rown, row := range rows {
+			custname := strings.TrimSpace(row[0])
+			contractcode := strings.TrimSpace(row[1])
+			amountStr := strings.TrimSpace(row[2])
+			status := strings.TrimSpace(row[3])
+			planTimeStr := strings.TrimSpace(row[4])
+			scaleStr := strings.TrimSpace(row[5])
+			var criteria string
+			if len(row) > 6 {
+				criteria = strings.TrimSpace(row[6])
+			}
+
+			if planTimeStr == "" {
+				planTimeStr = "0001/1/2"
+			}
+
+			planTime, err := time.Parse("2006/1/2", planTimeStr)
+			if err != nil {
+				planTime, err = time.Parse("01-02-06", planTimeStr)
+			}
+			if err != nil {
+				if planTimeStr == "" {
+					planTime = time.Time{}
+				} else {
+					panic(fmt.Errorf("%s, %s", planTimeStr, err.Error()))
+				}
+			}
+			amount := gconv.Float64(amountStr)
+			scale := gconv.Float64(strings.Replace(scaleStr, "%", "", -1))
+
+			var CashedAmount float64
+			if status == "已回款" {
+				CashedAmount = amount
+			}
+
+			fmt.Println(rown, custname, contractcode, amount, status, scale, criteria)
+
+			if _, ok := contractMap[contractcode]; !ok {
+				c := &model.CtrContract{}
+				err := tx.GetStruct(c, "select * from ctr_contract where contract_code = ?", contractcode)
+				if err != nil {
+					fmt.Println(c.ContractCode)
+					return err
+				}
+				contractMap[contractcode] = c
+			}
+
+			p := model.CtrContractCollectionPlan{
+				CustId:         0,
+				CustName:       custname,
+				ContractId:     contractMap[contractcode].Id,
+				ContractCode:   contractMap[contractcode].ContractCode,
+				ContractStatus: statusMap[status],
+				PlanAmount:     amount,
+				PlanDatetime:   gtime.NewFromTime(planTime),
+				PlanScale:      scale,
+				PlanCondition:  criteria,
+				CashedAmount:   CashedAmount,
+				CashedDatetime: nil,
+				Remark:         "",
+				CreatedBy:      1000,
+				CreatedName:    "dashoo",
+				CreatedTime:    gtime.Now(),
+				UpdatedBy:      1000,
+				UpdatedName:    "dashoo",
+				UpdatedTime:    gtime.Now(),
+			}
+
+			_, err = tx.Insert("ctr_contract_collection_plan", p)
+			if err != nil {
+				return err
+			}
+		}
+		// return fmt.Errorf("测试")
+		return nil
+	})
+	fmt.Println(contractMap)
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+func product() {
+	var ProdClassMap = map[string]string{
+		"BIOBANK":  "10",
+		"Biobank":  "10",
+		"CELLSOP":  "20",
+		"CellSOP":  "20",
+		"CellsSOP": "20",
+		"LIMS":     "30",
+		"LIMS+基因":  "30",
+		"MCS":      "60",
+		"咨询服务":     "70",
+		"外购":       "90",
+		"智能硬件":     "40",
+		"液氮罐":      "50",
+		"设备":       "",
+	}
+	var productMap = map[string]*basemodel.BaseProduct{}
+	var contractMap = map[string]*model.CtrContract{}
+
+	fileb, err := ioutil.ReadFile("/home/lai/OMS合同管理17-23合同信息0519(1).xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	rows2021_2023, err := e.GetRows("2021-2023年产品信息")
+	if err != nil {
+		panic(err)
+	}
+	rows2017_2020, err := e.GetRows("2017-2020年产品信息")
+	if err != nil {
+		panic(err)
+	}
+	rows := append(rows2021_2023[1:], rows2017_2020[1:]...)
+
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+
+		for rown, row := range rows {
+			contractcode := strings.TrimSpace(row[0])
+			ProdClass := strings.TrimSpace(row[1])
+			ProdName := strings.TrimSpace(row[2])
+			ProdCode := strings.TrimSpace(row[3])
+			priceStr := strings.TrimSpace(row[4])
+			numStr := strings.TrimSpace(row[5])
+			sumStr := strings.TrimSpace(row[6])
+			var zhibaoStr string
+			var maintainStr string
+			var maintainTerm string
+			var acceptTimeStr string
+			if len(row) > 7 {
+				zhibaoStr = strings.TrimSpace(row[7])
+				if len(row) > 8 {
+					maintainStr = strings.TrimSpace(row[8])
+					if len(row) > 9 {
+						maintainTerm = strings.TrimSpace(row[9])
+						if len(row) > 10 {
+							acceptTimeStr = strings.TrimSpace(row[10])
+						}
+					}
+				}
+			}
+
+			acceptTime, err := time.Parse("2006/1/2", acceptTimeStr)
+			if err != nil {
+				acceptTime, err = time.Parse("01-02-06", acceptTimeStr)
+			}
+			if err != nil {
+				acceptTime, err = time.Parse("2006年1月2日", acceptTimeStr)
+			}
+			if err != nil {
+				if acceptTimeStr == "" {
+					acceptTime = time.Time{}
+				} else {
+					panic(fmt.Errorf("%s, %s", acceptTimeStr, err.Error()))
+				}
+			}
+			price := gconv.Float64(priceStr)
+			num := gconv.Int(numStr)
+			sum := gconv.Float64(sumStr)
+			zhibao := gconv.Int(zhibaoStr)
+			maintain := gconv.Int(maintainStr)
+
+			fmt.Println(rown, contractcode, ProdClass, ProdName, ProdCode, price,
+				num, sum, zhibao, maintain, maintainTerm, acceptTime)
+
+			p := basemodel.BaseProduct{
+				ProdCode:    ProdCode,
+				ProdName:    ProdName,
+				ProdClass:   ProdClassMap[ProdClass],
+				GuidPrice:   0,
+				DistPrice:   0,
+				AgentPrice:  0,
+				MarketPrice: 0,
+				Remark:      "",
+				CreatedBy:   1000,
+				CreatedName: "dashoo",
+				CreatedTime: gtime.Now(),
+				UpdatedBy:   1000,
+				UpdatedName: "dashoo",
+				UpdatedTime: gtime.Now(),
+				DeletedTime: gtime.Now(),
+			}
+			if _, ok := productMap[p.ProdName]; !ok {
+				dbexistp := &basemodel.BaseProduct{}
+				err := tx.GetStruct(dbexistp, "select * from base_product where prod_name = ?", p.ProdName)
+				if err == sql.ErrNoRows {
+					id, err := tx.InsertAndGetId("base_product", p)
+					if err != nil {
+						return err
+					}
+					p.Id = int(id)
+					productMap[p.ProdName] = &p
+				} else {
+					if err != nil {
+						return err
+					}
+					productMap[p.ProdName] = dbexistp
+				}
+			}
+			if _, ok := contractMap[contractcode]; !ok {
+				c := &model.CtrContract{}
+				err := tx.GetStruct(c, "select * from ctr_contract where contract_code = ?", contractcode)
+				if err != nil {
+					fmt.Println(c.ContractCode)
+					return err
+				}
+				contractMap[contractcode] = c
+			}
+
+			cp := model.CtrContractProduct{
+				ContractId:        contractMap[contractcode].Id,
+				ContractCode:      contractMap[contractcode].ContractCode,
+				ProdId:            productMap[p.ProdName].Id,
+				ProdCode:          productMap[p.ProdName].ProdCode,
+				ProdName:          productMap[p.ProdName].ProdName,
+				ProdClass:         productMap[p.ProdName].ProdClass,
+				ProdNum:           num,
+				MaintTerm:         0,
+				SugSalesPrice:     0,
+				TranPrice:         price,
+				ContractPrive:     contractMap[contractcode].ContractAmount,
+				PurchaseCost:      0,
+				DevCost:           0,
+				MaintainCost:      0,
+				DirectCost:        0,
+				MaintainPeriod:    zhibao * 365,
+				WarrantPeriod:     maintain * 365,
+				MaintainStartTime: nil,
+				MaintainRemark:    maintainTerm,
+				AcceptTime:        gtime.NewFromTime(acceptTime),
+				Remark:            "",
+				CreatedBy:         1000,
+				CreatedName:       "dashoo",
+				CreatedTime:       gtime.Now(),
+				UpdatedBy:         1000,
+				UpdatedName:       "dashoo",
+				UpdatedTime:       gtime.Now(),
+			}
+			_, err = tx.Insert("ctr_contract_product", cp)
+			if err != nil {
+				return err
+			}
+		}
+		// return fmt.Errorf("测试")
+		return nil
+	})
+	fmt.Println(contractMap)
+	fmt.Println(productMap)
+	fmt.Println(ProdClassMap)
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+func contract() {
+	prepare()
+	contract := parse()
+	fmt.Println(MapProductLine)
+	txerr := g.DB("prod").Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
+		_, err := tx.Insert("ctr_contract", contract)
+		return err
+	})
+	if txerr != nil {
+		panic(txerr)
+	}
+}
+
+var MapProvince = map[string]int{}
+var MapCity = map[string]int{}
+var MapProductLine = map[string]string{
+	"BIOBANK": "10",
+	"CELLSOP": "20",
+	"LIMS+基因": "30",
+	"MCS":     "60",
+	"咨询服务":    "70",
+	"外购":      "90",
+	"智能硬件":    "40",
+	"石油":      "80",
+}
+var Mapcontracttype = map[string]string{
+	"销售合同": "XS",
+	"技术合同": "JS",
+}
+var MapSignatoryType = map[string]string{
+	"终端用户": "10",
+	"经销商":  "20",
+	"代理商":  "30",
+}
+
+func prepare() {
+	dao := basedao.NewBaseDistrictDao("prod")
+	province, err := dao.Where("dist_level = 1").All()
+	if err != nil {
+		panic(err)
+	}
+	for _, p := range province {
+		MapProvince[p.DistName] = p.Id
+	}
+	city, err := dao.Where("dist_level = 2").All()
+	if err != nil {
+		panic(err)
+	}
+	for _, c := range city {
+		MapCity[c.DistName] = c.Id
+	}
+
+}
+
+func parse() []model.CtrContract {
+	fileb, err := ioutil.ReadFile("/home/lai/OMS合同管理17-23合同信息0519(1).xlsx")
+	if err != nil {
+		panic(err)
+	}
+
+	e, err := excelize.OpenReader(bytes.NewBuffer(fileb))
+	if err != nil {
+		panic(err)
+	}
+	rows2021_2023, err := e.GetRows("2021-2023年合同基本信息")
+	if err != nil {
+		panic(err)
+	}
+	rows2017_2020, err := e.GetRows("2017-2020年合同基本信息")
+	if err != nil {
+		panic(err)
+	}
+	rows := append(rows2021_2023[1:], rows2017_2020[1:]...)
+
+	contract := []model.CtrContract{}
+	for rown, row := range rows {
+
+		code := strings.TrimSpace(row[0])
+		name := strings.TrimSpace(row[1])
+		custname := strings.TrimSpace(row[2])
+		nobname := strings.TrimSpace(row[3])
+		province := strings.TrimSpace(row[4])
+		city := strings.TrimSpace(row[5])
+		amountstr := strings.TrimSpace(row[6])
+		InchargeName := strings.TrimSpace(row[7])
+		ContractType := strings.TrimSpace(row[8])
+		ContractSignTimestr := strings.TrimSpace(row[9])
+		ContractEndTimestr := strings.TrimSpace(row[10])
+		SignatoryName := strings.TrimSpace(row[11])
+		ProductLine := strings.TrimSpace(row[12])
+		SignatoryUnit := strings.TrimSpace(row[13])
+		SignatoryType := strings.TrimSpace(row[14])
+
+		if ContractEndTimestr == "" {
+			ContractEndTimestr = "0001/1/2"
+		}
+		if ContractSignTimestr == "" {
+			ContractSignTimestr = "0001/1/2"
+		}
+
+		amount := gconv.Float64(amountstr)
+		ContractSignTime, err := time.Parse("2006/1/2", ContractSignTimestr)
+		if err != nil {
+			ContractSignTime, err = time.Parse("01-02-06", ContractSignTimestr)
+		}
+		if err != nil {
+			panic(fmt.Errorf("%s, %s", ContractSignTimestr, err.Error()))
+		}
+		ContractEndTime, err := time.Parse("2006/1/2", ContractEndTimestr)
+		if err != nil {
+			ContractEndTime, err = time.Parse("01-02-06", ContractEndTimestr)
+		}
+		if err != nil {
+			panic(fmt.Errorf("%s, %s", ContractEndTimestr, err.Error()))
+		}
+		provinceId := MapProvince[province]
+		cityId := MapCity[city]
+		var DistributorName string
+		if SignatoryType == "经销商" || SignatoryType == "代理商" {
+			DistributorName = SignatoryUnit
+		}
+
+		fmt.Println(rown, code, name, custname, nobname, province, city,
+			amount, InchargeName, ContractType, ContractSignTime,
+			ContractEndTime, SignatoryName, ProductLine, SignatoryType)
+
+		contract = append(contract, model.CtrContract{
+			ContractCode:        code,
+			ContractName:        name,
+			CustId:              0,
+			CustName:            custname,
+			ProductLine:         MapProductLine[ProductLine],
+			IsBig:               "20",
+			CustProvinceId:      provinceId,
+			CustProvince:        province,
+			CustCityId:          cityId,
+			CustCity:            city,
+			NboId:               0,
+			NboName:             nobname,
+			ApproStatus:         "30",
+			ContractType:        Mapcontracttype[ContractType],
+			ContractAmount:      amount,
+			InvoiceAmount:       0,
+			CollectedAmount:     0,
+			ContractStartTime:   gtime.NewFromTime(ContractSignTime),
+			ContractEndTime:     gtime.NewFromTime(ContractEndTime),
+			ContractSignTime:    gtime.NewFromTime(ContractSignTime),
+			InchargeId:          0,
+			InchargeName:        InchargeName,
+			SignatoryId:         0,
+			SignatoryName:       SignatoryName,
+			SignatoryType:       MapSignatoryType[SignatoryType],
+			SignatoryUnit:       SignatoryUnit,
+			EarnestMoney:        0,
+			CustSignatoryId:     0,
+			CustSignatoryName:   "",
+			DistributorId:       0,
+			DistributorName:     DistributorName,
+			ServiceFeeAgreement: "",
+			Remark:              "",
+			CreatedBy:           1000,
+			CreatedName:         "dashoo",
+			CreatedTime:         gtime.Now(),
+			UpdatedBy:           1000,
+			UpdatedName:         "dashoo",
+			UpdatedTime:         gtime.Now(),
+		})
+	}
+	return contract
+}