Explorar el Código

feature: 合同功能修改

liuyaqi hace 2 años
padre
commit
975a016702

+ 229 - 144
opms_parent/app/dao/contract/internal/ctr_contract.go

@@ -7,13 +7,15 @@ package internal
 import (
 	"context"
 	"database/sql"
+	"fmt"
+	"strings"
+	"time"
+
 	"github.com/gogf/gf/container/garray"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/frame/gmvc"
 	"github.com/gogf/gf/util/gconv"
-	"strings"
-	"time"
 
 	model "dashoo.cn/micro/app/model/contract"
 )
@@ -29,43 +31,47 @@ type CtrContractDao struct {
 
 // CtrContractColumns defines and stores column names for table ctr_contract.
 type ctrContractColumns struct {
-	Id                string // 主键
-	ContractCode      string // 合同编号
-	ContractName      string // 合同名称
-	CustId            string // 关联客户
-	CustName          string // 客户名称
-	ProductLine       string // 产品线
-	IsBig             string // 是否为大项目
-	CustProvinceId    string // 所在省ID
-	CustProvince      string // 所在省
-	CustCityId        string // 所在市ID
-	CustCity          string // 所在市
-	NboId             string // 关联项目
-	NboName           string // 项目名称
-	ApproStatus       string // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
-	ContractType      string // 合同类型
-	ContractAmount    string // 合同金额
-	InvoiceAmount     string // 已开票金额
-	CollectedAmount   string // 已回款金额
-	ContractStartTime string // 合同开始时间
-	ContractEndTime   string // 合同结束时间
-	InchargeId        string // 负责人ID
-	InchargeName      string // 负责人(销售工程师)
-	SignatoryId       string // 公司签约人ID
-	SignatoryName     string // 公司签约人
-	SignatoryType     string // 签订单位类型 10 终端用户 20 经销商 30 代理商
-	CustSignatoryId   string // 客户签约人ID
-	CustSignatoryName string // 客户签约人
-	DistributorId     string // 经销商ID
-	DistributorName   string // 经销商
-	Remark            string // 备注
-	CreatedBy         string // 创建者
-	CreatedName       string // 创建人
-	CreatedTime       string // 创建时间
-	UpdatedBy         string // 更新者
-	UpdatedName       string // 更新人
-	UpdatedTime       string // 更新时间
-	DeletedTime       string // 删除时间
+	Id                  string // 主键
+	ContractCode        string // 合同编号
+	ContractName        string // 合同名称
+	CustId              string // 关联客户
+	CustName            string // 客户名称
+	ProductLine         string // 产品线
+	IsBig               string // 是否为大项目
+	CustProvinceId      string // 所在省ID
+	CustProvince        string // 所在省
+	CustCityId          string // 所在市ID
+	CustCity            string // 所在市
+	NboId               string // 关联项目
+	NboName             string // 项目名称
+	ApproStatus         string // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
+	ContractType        string // 合同类型
+	ContractAmount      string // 合同金额
+	InvoiceAmount       string // 已开票金额
+	CollectedAmount     string // 已回款金额
+	ContractStartTime   string // 合同开始时间
+	ContractEndTime     string // 合同结束时间
+	ContractSignTime    string // 合同签订时间
+	InchargeId          string // 负责人ID
+	InchargeName        string // 负责人(销售工程师)
+	SignatoryId         string // 公司签约人ID
+	SignatoryName       string // 公司签约人
+	SignatoryType       string // 签订单位类型 10 终端用户 20 经销商 30 代理商
+	SignatoryUnit       string // 合同签订单位
+	EarnestMoney        string // 质量/履约保证金(元)
+	CustSignatoryId     string // 客户签约人ID
+	CustSignatoryName   string // 客户签约人
+	DistributorId       string // 经销商ID
+	DistributorName     string // 经销商
+	ServiceFeeAgreement string // 运维服务费约定
+	Remark              string // 备注
+	CreatedBy           string // 创建者
+	CreatedName         string // 创建人
+	CreatedTime         string // 创建时间
+	UpdatedBy           string // 更新者
+	UpdatedName         string // 更新人
+	UpdatedTime         string // 更新时间
+	DeletedTime         string // 删除时间
 }
 
 var (
@@ -75,43 +81,47 @@ var (
 		DB:    g.DB("default"),
 		Table: "ctr_contract",
 		C: ctrContractColumns{
-			Id:                "id",
-			ContractCode:      "contract_code",
-			ContractName:      "contract_name",
-			CustId:            "cust_id",
-			CustName:          "cust_name",
-			ProductLine:       "product_line",
-			IsBig:             "is_big",
-			CustProvinceId:    "cust_province_id",
-			CustProvince:      "cust_province",
-			CustCityId:        "cust_city_id",
-			CustCity:          "cust_city",
-			NboId:             "nbo_id",
-			NboName:           "nbo_name",
-			ApproStatus:       "appro_status",
-			ContractType:      "contract_type",
-			ContractAmount:    "contract_amount",
-			InvoiceAmount:     "invoice_amount",
-			CollectedAmount:   "collected_amount",
-			ContractStartTime: "contract_start_time",
-			ContractEndTime:   "contract_end_time",
-			InchargeId:        "incharge_id",
-			InchargeName:      "incharge_name",
-			SignatoryId:       "signatory_id",
-			SignatoryName:     "signatory_name",
-			SignatoryType:     "signatory_type",
-			CustSignatoryId:   "cust_signatory_id",
-			CustSignatoryName: "cust_signatory_name",
-			DistributorId:     "distributor_id",
-			DistributorName:   "distributor_name",
-			Remark:            "remark",
-			CreatedBy:         "created_by",
-			CreatedName:       "created_name",
-			CreatedTime:       "created_time",
-			UpdatedBy:         "updated_by",
-			UpdatedName:       "updated_name",
-			UpdatedTime:       "updated_time",
-			DeletedTime:       "deleted_time",
+			Id:                  "id",
+			ContractCode:        "contract_code",
+			ContractName:        "contract_name",
+			CustId:              "cust_id",
+			CustName:            "cust_name",
+			ProductLine:         "product_line",
+			IsBig:               "is_big",
+			CustProvinceId:      "cust_province_id",
+			CustProvince:        "cust_province",
+			CustCityId:          "cust_city_id",
+			CustCity:            "cust_city",
+			NboId:               "nbo_id",
+			NboName:             "nbo_name",
+			ApproStatus:         "appro_status",
+			ContractType:        "contract_type",
+			ContractAmount:      "contract_amount",
+			InvoiceAmount:       "invoice_amount",
+			CollectedAmount:     "collected_amount",
+			ContractStartTime:   "contract_start_time",
+			ContractEndTime:     "contract_end_time",
+			ContractSignTime:    "contract_sign_time",
+			InchargeId:          "incharge_id",
+			InchargeName:        "incharge_name",
+			SignatoryId:         "signatory_id",
+			SignatoryName:       "signatory_name",
+			SignatoryType:       "signatory_type",
+			SignatoryUnit:       "signatory_unit",
+			EarnestMoney:        "earnest_money",
+			CustSignatoryId:     "cust_signatory_id",
+			CustSignatoryName:   "cust_signatory_name",
+			DistributorId:       "distributor_id",
+			DistributorName:     "distributor_name",
+			ServiceFeeAgreement: "service_fee_agreement",
+			Remark:              "remark",
+			CreatedBy:           "created_by",
+			CreatedName:         "created_name",
+			CreatedTime:         "created_time",
+			UpdatedBy:           "updated_by",
+			UpdatedName:         "updated_name",
+			UpdatedTime:         "updated_time",
+			DeletedTime:         "deleted_time",
 		},
 	}
 )
@@ -123,43 +133,47 @@ func NewCtrContractDao(tenant string) CtrContractDao {
 		DB:    g.DB(tenant),
 		Table: "ctr_contract",
 		C: ctrContractColumns{
-			Id:                "id",
-			ContractCode:      "contract_code",
-			ContractName:      "contract_name",
-			CustId:            "cust_id",
-			CustName:          "cust_name",
-			ProductLine:       "product_line",
-			IsBig:             "is_big",
-			CustProvinceId:    "cust_province_id",
-			CustProvince:      "cust_province",
-			CustCityId:        "cust_city_id",
-			CustCity:          "cust_city",
-			NboId:             "nbo_id",
-			NboName:           "nbo_name",
-			ApproStatus:       "appro_status",
-			ContractType:      "contract_type",
-			ContractAmount:    "contract_amount",
-			InvoiceAmount:     "invoice_amount",
-			CollectedAmount:   "collected_amount",
-			ContractStartTime: "contract_start_time",
-			ContractEndTime:   "contract_end_time",
-			InchargeId:        "incharge_id",
-			InchargeName:      "incharge_name",
-			SignatoryId:       "signatory_id",
-			SignatoryName:     "signatory_name",
-			SignatoryType:     "signatory_type",
-			CustSignatoryId:   "cust_signatory_id",
-			CustSignatoryName: "cust_signatory_name",
-			DistributorId:     "distributor_id",
-			DistributorName:   "distributor_name",
-			Remark:            "remark",
-			CreatedBy:         "created_by",
-			CreatedName:       "created_name",
-			CreatedTime:       "created_time",
-			UpdatedBy:         "updated_by",
-			UpdatedName:       "updated_name",
-			UpdatedTime:       "updated_time",
-			DeletedTime:       "deleted_time",
+			Id:                  "id",
+			ContractCode:        "contract_code",
+			ContractName:        "contract_name",
+			CustId:              "cust_id",
+			CustName:            "cust_name",
+			ProductLine:         "product_line",
+			IsBig:               "is_big",
+			CustProvinceId:      "cust_province_id",
+			CustProvince:        "cust_province",
+			CustCityId:          "cust_city_id",
+			CustCity:            "cust_city",
+			NboId:               "nbo_id",
+			NboName:             "nbo_name",
+			ApproStatus:         "appro_status",
+			ContractType:        "contract_type",
+			ContractAmount:      "contract_amount",
+			InvoiceAmount:       "invoice_amount",
+			CollectedAmount:     "collected_amount",
+			ContractStartTime:   "contract_start_time",
+			ContractEndTime:     "contract_end_time",
+			ContractSignTime:    "contract_sign_time",
+			InchargeId:          "incharge_id",
+			InchargeName:        "incharge_name",
+			SignatoryId:         "signatory_id",
+			SignatoryName:       "signatory_name",
+			SignatoryType:       "signatory_type",
+			SignatoryUnit:       "signatory_unit",
+			EarnestMoney:        "earnest_money",
+			CustSignatoryId:     "cust_signatory_id",
+			CustSignatoryName:   "cust_signatory_name",
+			DistributorId:       "distributor_id",
+			DistributorName:     "distributor_name",
+			ServiceFeeAgreement: "service_fee_agreement",
+			Remark:              "remark",
+			CreatedBy:           "created_by",
+			CreatedName:         "created_name",
+			CreatedTime:         "created_time",
+			UpdatedBy:           "updated_by",
+			UpdatedName:         "updated_name",
+			UpdatedTime:         "updated_time",
+			DeletedTime:         "deleted_time",
 		},
 	}
 	return dao
@@ -760,28 +774,10 @@ func (d *CtrContractDao) Unscoped() *CtrContractDao {
 }
 
 // DataScope enables the DataScope feature.
-func (d *CtrContractDao) DataScope(ctx context.Context, userCol ...string) *CtrContractDao {
+func (d *CtrContractDao) DataScope(ctx context.Context, args ...interface{}) *CtrContractDao {
 	cs := ctx.Value("contextService")
 	dataScope := gconv.Map(gconv.String(gconv.Map(cs)["dataScope"]))
 	if dataScope != nil {
-		tableAs := d.TableAs
-		if d.TableAs != "" {
-			tableAs += "."
-		}
-		userIds, ok := dataScope["userIds"]
-		delete(dataScope, "userIds")
-		var orColumns []string
-		var orValues []interface{}
-		if ok && userIds != "-1" {
-			column := "created_by"
-			if len(userCol) == 1 {
-				column = userCol[0]
-			}
-			if ok, _ := d.M.HasField(column); ok {
-				orColumns = append(orColumns, tableAs+column+" IN (?) ")
-				orValues = append(orValues, userIds)
-			}
-		}
 		// 销售工程师判断
 		var salesEngineerFlag bool
 		if roles, ok := dataScope["roles"]; ok {
@@ -790,22 +786,34 @@ func (d *CtrContractDao) DataScope(ctx context.Context, userCol ...string) *CtrC
 				salesEngineerFlag = true
 			}
 		}
-		// 非销售工程师权限加成
-		if !salesEngineerFlag {
-			bigColumns := "is_big"
-			if ok, _ := d.M.HasField("is_big"); ok {
-				if val, ok := dataScope[bigColumns]; ok && val != "" {
-					orColumns = append(orColumns, tableAs+bigColumns+" = ? ")
-					orValues = append(orValues, val)
+		userIds, ok := dataScope["userIds"]
+		specialFlag, userCols, orColsMap := d.checkColumnsName(dataScope, args...)
+
+		var orColumns []string
+		var orValues []interface{}
+		if ok && userIds != "-1" {
+			for _, column := range userCols {
+				if ok, _ := d.M.HasField(column); ok || specialFlag {
+					orColumns = append(orColumns, column+" IN (?) ")
+					orValues = append(orValues, userIds)
 				}
-				delete(dataScope, bigColumns)
 			}
+		}
+		for col, params := range orColsMap {
+			if ok, _ := d.M.HasField(col); ok || specialFlag {
+				orColumns = append(orColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+				orValues = append(orValues, params)
+			}
+		}
+
+		// 销售工程师权限加成
+		if !salesEngineerFlag {
 			var andColumns []string
 			var andValues []interface{}
-			for k, v := range dataScope {
-				if ok, _ := d.M.HasField(k); ok {
-					andColumns = append(andColumns, tableAs+k+" IN (?) ")
-					andValues = append(andValues, v)
+			for col, params := range dataScope {
+				if ok, _ := d.M.HasField(col); ok || specialFlag {
+					andColumns = append(andColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+					andValues = append(andValues, params)
 				}
 			}
 			if len(andColumns) > 0 {
@@ -820,3 +828,80 @@ func (d *CtrContractDao) DataScope(ctx context.Context, userCol ...string) *CtrC
 	}
 	return d
 }
+
+// args 1、字段
+// args 2、字段、表名
+// args 3、字段对应关系
+func (d *CtrContractDao) checkColumnsName(dataScope map[string]interface{}, args ...interface{}) (bool, []string, map[string]interface{}) {
+	var userCols []string
+	tableAs, specialFlag := "", false
+	orColsMap, colsContrast := map[string]interface{}{}, map[string]interface{}{}
+
+	if d.TableAs != "" && len(args) <= 1 {
+		tableAs = d.TableAs + "."
+	}
+	if len(args) > 1 {
+		specialFlag = true
+		if val, ok := args[1].(string); ok {
+			tableAs = val + "."
+		}
+	}
+	if len(args) > 0 {
+		userCols = []string{"created_by"}
+		if column, ok := args[0].(string); ok {
+			userCols = []string{tableAs + column}
+		}
+		if cols, ok := args[0].([]string); ok {
+			for _, v := range cols {
+				userCols = append(userCols, tableAs+v)
+			}
+		}
+		if val, ok := args[0].(map[string]interface{}); ok {
+			specialFlag = true
+			colsContrast = val
+			if orcols, ok := val["orcols"]; ok {
+				if col, ok := orcols.(string); ok && gconv.String(val[col]) != "" {
+					orColsMap[col] = val[col]
+					delete(colsContrast, col)
+				}
+				if cols, ok := orcols.([]string); ok {
+					for _, col := range cols {
+						if gconv.String(val[col]) == "" {
+							continue
+						}
+						orColsMap[col] = val[col]
+						delete(colsContrast, col)
+					}
+				}
+			}
+			delete(colsContrast, "orcols")
+		}
+	}
+	bigColumns := "is_big"
+	if isBig, ok := dataScope[bigColumns]; ok {
+		if bigCol, ok := colsContrast[bigColumns]; ok {
+			orColsMap[bigCol.(string)] = isBig
+			delete(colsContrast, bigCol.(string))
+		} else {
+			if ok, _ := d.M.HasField(bigColumns); ok && specialFlag {
+				orColsMap[tableAs+bigColumns] = isBig
+			}
+		}
+	}
+
+	delete(dataScope, "userIds")
+	delete(dataScope, "roles")
+	delete(dataScope, "posts")
+	delete(dataScope, bigColumns)
+	for k, v := range dataScope {
+		if data, ok := colsContrast[k]; ok {
+			dataScope[data.(string)] = v
+		}
+		delete(dataScope, k)
+		delete(colsContrast, k)
+	}
+	for k, v := range colsContrast {
+		dataScope[k] = v
+	}
+	return specialFlag, userCols, orColsMap
+}

+ 110 - 41
opms_parent/app/dao/contract/internal/ctr_contract_collection_plan.go

@@ -7,13 +7,15 @@ package internal
 import (
 	"context"
 	"database/sql"
+	"fmt"
+	"strings"
+	"time"
+
 	"github.com/gogf/gf/container/garray"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/frame/gmvc"
 	"github.com/gogf/gf/util/gconv"
-	"strings"
-	"time"
 
 	model "dashoo.cn/micro/app/model/contract"
 )
@@ -37,6 +39,8 @@ type ctrContractCollectionPlanColumns struct {
 	ContractStatus string // 回款状态(10待回款20部分回款30全部回款)
 	PlanAmount     string // 计划回款金额
 	PlanDatetime   string // 计划回款日期
+	PlanScale      string // 计划回款比例
+	PlanCondition  string // 回款条件
 	CashedAmount   string // 实际回款金额
 	CashedDatetime string // 实际回款日期
 	Remark         string // 备注
@@ -64,6 +68,8 @@ var (
 			ContractStatus: "contract_status",
 			PlanAmount:     "plan_amount",
 			PlanDatetime:   "plan_datetime",
+			PlanScale:      "plan_scale",
+			PlanCondition:  "plan_condition",
 			CashedAmount:   "cashed_amount",
 			CashedDatetime: "cashed_datetime",
 			Remark:         "remark",
@@ -93,6 +99,8 @@ func NewCtrContractCollectionPlanDao(tenant string) CtrContractCollectionPlanDao
 			ContractStatus: "contract_status",
 			PlanAmount:     "plan_amount",
 			PlanDatetime:   "plan_datetime",
+			PlanScale:      "plan_scale",
+			PlanCondition:  "plan_condition",
 			CashedAmount:   "cashed_amount",
 			CashedDatetime: "cashed_datetime",
 			Remark:         "remark",
@@ -706,59 +714,43 @@ func (d *CtrContractCollectionPlanDao) Unscoped() *CtrContractCollectionPlanDao
 func (d *CtrContractCollectionPlanDao) DataScope(ctx context.Context, args ...interface{}) *CtrContractCollectionPlanDao {
 	cs := ctx.Value("contextService")
 	dataScope := gconv.Map(gconv.String(gconv.Map(cs)["dataScope"]))
-
 	if dataScope != nil {
-		var specialFlag bool
-		var tableAs string
-		if d.TableAs != "" && len(args) <= 1 {
-			tableAs = d.TableAs + "."
-		}
-		if len(args) > 1 {
-			specialFlag = true
-			if val, ok := args[1].(string); ok {
-				tableAs = val + "."
+		// 销售工程师判断
+		var salesEngineerFlag bool
+		if roles, ok := dataScope["roles"]; ok {
+			arr := garray.NewArrayFrom(roles.([]interface{}), true)
+			if arr.Len() == 1 && arr.Contains("SalesEngineer") {
+				salesEngineerFlag = true
 			}
 		}
 		userIds, ok := dataScope["userIds"]
-		delete(dataScope, "userIds")
+		specialFlag, userCols, orColsMap := d.checkColumnsName(dataScope, args...)
+
 		var orColumns []string
 		var orValues []interface{}
 		if ok && userIds != "-1" {
-			column := "created_by"
-			if len(args) > 0 {
-				column = args[0].(string)
-			}
-			if ok, _ := d.M.HasField(column); ok || specialFlag {
-				orColumns = append(orColumns, tableAs+column+" IN (?) ")
-				orValues = append(orValues, userIds)
+			for _, column := range userCols {
+				if ok, _ := d.M.HasField(column); ok || specialFlag {
+					orColumns = append(orColumns, column+" IN (?) ")
+					orValues = append(orValues, userIds)
+				}
 			}
 		}
-		// 销售工程师判断
-		var salesEngineerFlag bool
-		if roles, ok := dataScope["roles"]; ok {
-			delete(dataScope, "roles")
-			delete(dataScope, "posts")
-			arr := garray.NewArrayFrom(roles.([]interface{}), true)
-			if arr.Len() == 1 && arr.Contains("SalesEngineer") {
-				salesEngineerFlag = true
+		for col, params := range orColsMap {
+			if ok, _ := d.M.HasField(col); ok || specialFlag {
+				orColumns = append(orColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+				orValues = append(orValues, params)
 			}
 		}
-		// 非销售工程师权限加成
+
+		// 销售工程师权限加成
 		if !salesEngineerFlag {
-			bigColumns := "is_big"
-			if ok, _ := d.M.HasField("is_big"); ok || specialFlag {
-				if val, ok := dataScope[bigColumns]; ok && val != "" {
-					orColumns = append(orColumns, tableAs+bigColumns+" = ? ")
-					orValues = append(orValues, val)
-				}
-				delete(dataScope, bigColumns)
-			}
 			var andColumns []string
 			var andValues []interface{}
-			for k, v := range dataScope {
-				if ok, _ := d.M.HasField(k); ok || specialFlag {
-					andColumns = append(andColumns, tableAs+k+" IN (?) ")
-					andValues = append(andValues, v)
+			for col, params := range dataScope {
+				if ok, _ := d.M.HasField(col); ok || specialFlag {
+					andColumns = append(andColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+					andValues = append(andValues, params)
 				}
 			}
 			if len(andColumns) > 0 {
@@ -773,3 +765,80 @@ func (d *CtrContractCollectionPlanDao) DataScope(ctx context.Context, args ...in
 	}
 	return d
 }
+
+// args 1、字段
+// args 2、字段、表名
+// args 3、字段对应关系
+func (d *CtrContractCollectionPlanDao) checkColumnsName(dataScope map[string]interface{}, args ...interface{}) (bool, []string, map[string]interface{}) {
+	var userCols []string
+	tableAs, specialFlag := "", false
+	orColsMap, colsContrast := map[string]interface{}{}, map[string]interface{}{}
+
+	if d.TableAs != "" && len(args) <= 1 {
+		tableAs = d.TableAs + "."
+	}
+	if len(args) > 1 {
+		specialFlag = true
+		if val, ok := args[1].(string); ok {
+			tableAs = val + "."
+		}
+	}
+	if len(args) > 0 {
+		userCols = []string{"created_by"}
+		if column, ok := args[0].(string); ok {
+			userCols = []string{tableAs + column}
+		}
+		if cols, ok := args[0].([]string); ok {
+			for _, v := range cols {
+				userCols = append(userCols, tableAs+v)
+			}
+		}
+		if val, ok := args[0].(map[string]interface{}); ok {
+			specialFlag = true
+			colsContrast = val
+			if orcols, ok := val["orcols"]; ok {
+				if col, ok := orcols.(string); ok && gconv.String(val[col]) != "" {
+					orColsMap[col] = val[col]
+					delete(colsContrast, col)
+				}
+				if cols, ok := orcols.([]string); ok {
+					for _, col := range cols {
+						if gconv.String(val[col]) == "" {
+							continue
+						}
+						orColsMap[col] = val[col]
+						delete(colsContrast, col)
+					}
+				}
+			}
+			delete(colsContrast, "orcols")
+		}
+	}
+	bigColumns := "is_big"
+	if isBig, ok := dataScope[bigColumns]; ok {
+		if bigCol, ok := colsContrast[bigColumns]; ok {
+			orColsMap[bigCol.(string)] = isBig
+			delete(colsContrast, bigCol.(string))
+		} else {
+			if ok, _ := d.M.HasField(bigColumns); ok && specialFlag {
+				orColsMap[tableAs+bigColumns] = isBig
+			}
+		}
+	}
+
+	delete(dataScope, "userIds")
+	delete(dataScope, "roles")
+	delete(dataScope, "posts")
+	delete(dataScope, bigColumns)
+	for k, v := range dataScope {
+		if data, ok := colsContrast[k]; ok {
+			dataScope[data.(string)] = v
+		}
+		delete(dataScope, k)
+		delete(colsContrast, k)
+	}
+	for k, v := range colsContrast {
+		dataScope[k] = v
+	}
+	return specialFlag, userCols, orColsMap
+}

+ 193 - 90
opms_parent/app/dao/contract/internal/ctr_contract_product.go

@@ -7,13 +7,15 @@ package internal
 import (
 	"context"
 	"database/sql"
+	"fmt"
+	"strings"
+	"time"
+
 	"github.com/gogf/gf/container/garray"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
 	"github.com/gogf/gf/frame/gmvc"
 	"github.com/gogf/gf/util/gconv"
-	"strings"
-	"time"
 
 	model "dashoo.cn/micro/app/model/contract"
 )
@@ -29,25 +31,35 @@ type CtrContractProductDao struct {
 
 // CtrContractProductColumns defines and stores column names for table ctr_contract_product.
 type ctrContractProductColumns struct {
-	Id            string // 主键
-	ContractId    string // 关联合同
-	ProdId        string // 关联产品
-	ProdCode      string // 产品型号
-	ProdName      string // 产品名称
-	ProdClass     string // 产品类别
-	ProdNum       string // 产品数量
-	MaintTerm     string // 维保期
-	SugSalesPrice string // 建议成交价
-	TranPrice     string // 成交价格
-	ContractPrive string // 合同总价
-	Remark        string // 备注
-	CreatedBy     string // 创建者
-	CreatedName   string // 创建人
-	CreatedTime   string // 创建时间
-	UpdatedBy     string // 更新者
-	UpdatedName   string // 更新人
-	UpdatedTime   string // 更新时间
-	DeletedTime   string // 删除时间
+	Id                string // 主键
+	ContractId        string // 关联合同
+	ContractCode      string // 合同编号
+	ProdId            string // 关联产品
+	ProdCode          string // 产品型号
+	ProdName          string // 产品名称
+	ProdClass         string // 产品类别
+	ProdNum           string // 产品数量
+	MaintTerm         string // 维保期
+	SugSalesPrice     string // 建议成交价
+	TranPrice         string // 成交价格
+	ContractPrive     string // 合同总价
+	PurchaseCost      string // 采购成本
+	DevCost           string // 二次开发成本
+	MaintainCost      string // 产品维保成本
+	DirectCost        string // 直接成本
+	MaintainPeriod    string // 质保期(天)
+	WarrantPeriod     string // 运维期(天)
+	MaintainStartTime string // 运维开始时间
+	MaintainRemark    string // 运维约定条款
+	AcceptTime        string // 验收时间
+	Remark            string // 备注
+	CreatedBy         string // 创建者
+	CreatedName       string // 创建人
+	CreatedTime       string // 创建时间
+	UpdatedBy         string // 更新者
+	UpdatedName       string // 更新人
+	UpdatedTime       string // 更新时间
+	DeletedTime       string // 删除时间
 }
 
 var (
@@ -57,25 +69,35 @@ var (
 		DB:    g.DB("default"),
 		Table: "ctr_contract_product",
 		C: ctrContractProductColumns{
-			Id:            "id",
-			ContractId:    "contract_id",
-			ProdId:        "prod_id",
-			ProdCode:      "prod_code",
-			ProdName:      "prod_name",
-			ProdClass:     "prod_class",
-			ProdNum:       "prod_num",
-			MaintTerm:     "maint_term",
-			SugSalesPrice: "sug_sales_price",
-			TranPrice:     "tran_price",
-			ContractPrive: "contract_prive",
-			Remark:        "remark",
-			CreatedBy:     "created_by",
-			CreatedName:   "created_name",
-			CreatedTime:   "created_time",
-			UpdatedBy:     "updated_by",
-			UpdatedName:   "updated_name",
-			UpdatedTime:   "updated_time",
-			DeletedTime:   "deleted_time",
+			Id:                "id",
+			ContractId:        "contract_id",
+			ContractCode:      "contract_code",
+			ProdId:            "prod_id",
+			ProdCode:          "prod_code",
+			ProdName:          "prod_name",
+			ProdClass:         "prod_class",
+			ProdNum:           "prod_num",
+			MaintTerm:         "maint_term",
+			SugSalesPrice:     "sug_sales_price",
+			TranPrice:         "tran_price",
+			ContractPrive:     "contract_prive",
+			PurchaseCost:      "purchase_cost",
+			DevCost:           "dev_cost",
+			MaintainCost:      "maintain_cost",
+			DirectCost:        "direct_cost",
+			MaintainPeriod:    "maintain_period",
+			WarrantPeriod:     "warrant_period",
+			MaintainStartTime: "maintain_start_time",
+			MaintainRemark:    "maintain_remark",
+			AcceptTime:        "accept_time",
+			Remark:            "remark",
+			CreatedBy:         "created_by",
+			CreatedName:       "created_name",
+			CreatedTime:       "created_time",
+			UpdatedBy:         "updated_by",
+			UpdatedName:       "updated_name",
+			UpdatedTime:       "updated_time",
+			DeletedTime:       "deleted_time",
 		},
 	}
 )
@@ -87,25 +109,35 @@ func NewCtrContractProductDao(tenant string) CtrContractProductDao {
 		DB:    g.DB(tenant),
 		Table: "ctr_contract_product",
 		C: ctrContractProductColumns{
-			Id:            "id",
-			ContractId:    "contract_id",
-			ProdId:        "prod_id",
-			ProdCode:      "prod_code",
-			ProdName:      "prod_name",
-			ProdClass:     "prod_class",
-			ProdNum:       "prod_num",
-			MaintTerm:     "maint_term",
-			SugSalesPrice: "sug_sales_price",
-			TranPrice:     "tran_price",
-			ContractPrive: "contract_prive",
-			Remark:        "remark",
-			CreatedBy:     "created_by",
-			CreatedName:   "created_name",
-			CreatedTime:   "created_time",
-			UpdatedBy:     "updated_by",
-			UpdatedName:   "updated_name",
-			UpdatedTime:   "updated_time",
-			DeletedTime:   "deleted_time",
+			Id:                "id",
+			ContractId:        "contract_id",
+			ContractCode:      "contract_code",
+			ProdId:            "prod_id",
+			ProdCode:          "prod_code",
+			ProdName:          "prod_name",
+			ProdClass:         "prod_class",
+			ProdNum:           "prod_num",
+			MaintTerm:         "maint_term",
+			SugSalesPrice:     "sug_sales_price",
+			TranPrice:         "tran_price",
+			ContractPrive:     "contract_prive",
+			PurchaseCost:      "purchase_cost",
+			DevCost:           "dev_cost",
+			MaintainCost:      "maintain_cost",
+			DirectCost:        "direct_cost",
+			MaintainPeriod:    "maintain_period",
+			WarrantPeriod:     "warrant_period",
+			MaintainStartTime: "maintain_start_time",
+			MaintainRemark:    "maintain_remark",
+			AcceptTime:        "accept_time",
+			Remark:            "remark",
+			CreatedBy:         "created_by",
+			CreatedName:       "created_name",
+			CreatedTime:       "created_time",
+			UpdatedBy:         "updated_by",
+			UpdatedName:       "updated_name",
+			UpdatedTime:       "updated_time",
+			DeletedTime:       "deleted_time",
 		},
 	}
 	return dao
@@ -706,28 +738,10 @@ func (d *CtrContractProductDao) Unscoped() *CtrContractProductDao {
 }
 
 // DataScope enables the DataScope feature.
-func (d *CtrContractProductDao) DataScope(ctx context.Context, userCol ...string) *CtrContractProductDao {
+func (d *CtrContractProductDao) DataScope(ctx context.Context, args ...interface{}) *CtrContractProductDao {
 	cs := ctx.Value("contextService")
 	dataScope := gconv.Map(gconv.String(gconv.Map(cs)["dataScope"]))
 	if dataScope != nil {
-		tableAs := d.TableAs
-		if d.TableAs != "" {
-			tableAs += "."
-		}
-		userIds, ok := dataScope["userIds"]
-		delete(dataScope, "userIds")
-		var orColumns []string
-		var orValues []interface{}
-		if ok && userIds != "-1" {
-			column := "created_by"
-			if len(userCol) == 1 {
-				column = userCol[0]
-			}
-			if ok, _ := d.M.HasField(column); ok {
-				orColumns = append(orColumns, tableAs+column+" IN (?) ")
-				orValues = append(orValues, userIds)
-			}
-		}
 		// 销售工程师判断
 		var salesEngineerFlag bool
 		if roles, ok := dataScope["roles"]; ok {
@@ -736,22 +750,34 @@ func (d *CtrContractProductDao) DataScope(ctx context.Context, userCol ...string
 				salesEngineerFlag = true
 			}
 		}
-		// 非销售工程师权限加成
-		if !salesEngineerFlag {
-			bigColumns := "is_big"
-			if ok, _ := d.M.HasField("is_big"); ok {
-				if val, ok := dataScope[bigColumns]; ok && val != "" {
-					orColumns = append(orColumns, tableAs+bigColumns+" = ? ")
-					orValues = append(orValues, val)
+		userIds, ok := dataScope["userIds"]
+		specialFlag, userCols, orColsMap := d.checkColumnsName(dataScope, args...)
+
+		var orColumns []string
+		var orValues []interface{}
+		if ok && userIds != "-1" {
+			for _, column := range userCols {
+				if ok, _ := d.M.HasField(column); ok || specialFlag {
+					orColumns = append(orColumns, column+" IN (?) ")
+					orValues = append(orValues, userIds)
 				}
-				delete(dataScope, bigColumns)
 			}
+		}
+		for col, params := range orColsMap {
+			if ok, _ := d.M.HasField(col); ok || specialFlag {
+				orColumns = append(orColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+				orValues = append(orValues, params)
+			}
+		}
+
+		// 销售工程师权限加成
+		if !salesEngineerFlag {
 			var andColumns []string
 			var andValues []interface{}
-			for k, v := range dataScope {
-				if ok, _ := d.M.HasField(k); ok {
-					andColumns = append(andColumns, tableAs+k+" IN (?) ")
-					andValues = append(andValues, v)
+			for col, params := range dataScope {
+				if ok, _ := d.M.HasField(col); ok || specialFlag {
+					andColumns = append(andColumns, fmt.Sprintf(" ( %s IN (?) )", col))
+					andValues = append(andValues, params)
 				}
 			}
 			if len(andColumns) > 0 {
@@ -766,3 +792,80 @@ func (d *CtrContractProductDao) DataScope(ctx context.Context, userCol ...string
 	}
 	return d
 }
+
+// args 1、字段
+// args 2、字段、表名
+// args 3、字段对应关系
+func (d *CtrContractProductDao) checkColumnsName(dataScope map[string]interface{}, args ...interface{}) (bool, []string, map[string]interface{}) {
+	var userCols []string
+	tableAs, specialFlag := "", false
+	orColsMap, colsContrast := map[string]interface{}{}, map[string]interface{}{}
+
+	if d.TableAs != "" && len(args) <= 1 {
+		tableAs = d.TableAs + "."
+	}
+	if len(args) > 1 {
+		specialFlag = true
+		if val, ok := args[1].(string); ok {
+			tableAs = val + "."
+		}
+	}
+	if len(args) > 0 {
+		userCols = []string{"created_by"}
+		if column, ok := args[0].(string); ok {
+			userCols = []string{tableAs + column}
+		}
+		if cols, ok := args[0].([]string); ok {
+			for _, v := range cols {
+				userCols = append(userCols, tableAs+v)
+			}
+		}
+		if val, ok := args[0].(map[string]interface{}); ok {
+			specialFlag = true
+			colsContrast = val
+			if orcols, ok := val["orcols"]; ok {
+				if col, ok := orcols.(string); ok && gconv.String(val[col]) != "" {
+					orColsMap[col] = val[col]
+					delete(colsContrast, col)
+				}
+				if cols, ok := orcols.([]string); ok {
+					for _, col := range cols {
+						if gconv.String(val[col]) == "" {
+							continue
+						}
+						orColsMap[col] = val[col]
+						delete(colsContrast, col)
+					}
+				}
+			}
+			delete(colsContrast, "orcols")
+		}
+	}
+	bigColumns := "is_big"
+	if isBig, ok := dataScope[bigColumns]; ok {
+		if bigCol, ok := colsContrast[bigColumns]; ok {
+			orColsMap[bigCol.(string)] = isBig
+			delete(colsContrast, bigCol.(string))
+		} else {
+			if ok, _ := d.M.HasField(bigColumns); ok && specialFlag {
+				orColsMap[tableAs+bigColumns] = isBig
+			}
+		}
+	}
+
+	delete(dataScope, "userIds")
+	delete(dataScope, "roles")
+	delete(dataScope, "posts")
+	delete(dataScope, bigColumns)
+	for k, v := range dataScope {
+		if data, ok := colsContrast[k]; ok {
+			dataScope[data.(string)] = v
+		}
+		delete(dataScope, k)
+		delete(colsContrast, k)
+	}
+	for k, v := range colsContrast {
+		dataScope[k] = v
+	}
+	return specialFlag, userCols, orColsMap
+}

+ 14 - 0
opms_parent/app/handler/contract/ctr_contract.go

@@ -164,6 +164,20 @@ func (c *CtrContract) Update(ctx context.Context, req *model.CtrContractUpdateRe
 	return nil
 }
 
+// Swagger:CtrContract 合同,测试tag 更新合同产品
+func (c *CtrContract) UpdateProduct(ctx context.Context, req *model.CtrContractUpdateProductReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.UpdateProduct request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	err = s.UpdateProduct(ctx, req)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
 // Swagger:CtrContract 合同,测试tag 转移合同
 func (c *CtrContract) Transfer(ctx context.Context, req *model.CtrContractTransferReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContract.Transfer request %#v ", *req)

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

@@ -72,11 +72,14 @@ type CtrContractAddReq struct {
 	// CollectedAmount   float64         `json:"collectedAmount"`   // 已回款金额
 	ContractStartTime   *gtime.Time     `json:"contractStartTime"`   // 合同开始时间
 	ContractEndTime     *gtime.Time     `json:"contractEndTime"`     // 合同结束时间
+	ContractSignTime    *gtime.Time     `json:"contractSignTime"`    // 合同签订时间
 	InchargeId          int             `json:"inchargeId"`          // 负责人ID
 	InchargeName        string          `json:"inchargeName"`        // 负责人
 	SignatoryId         int             `json:"signatoryId"`         // 公司签约人ID
 	SignatoryName       string          `json:"signatoryName"`       // 公司签约人
 	SignatoryType       string          `json:"signatoryType"`       // 签订单位类型 10 终端用户 20 经销商 30 代理商
+	SignatoryUnit       string          `json:"signatoryUnit"`       // 合同签订单位
+	EarnestMoney        float64         `json:"earnestMoney"`        // 质量/履约保证金(元)
 	CustSignatoryId     int             `json:"custSignatoryId"`     // 客户签约人ID
 	CustSignatoryName   string          `json:"custSignatoryName"`   // 客户签约人
 	DistributorId       int             `json:"distributorId"`       // 经销商ID
@@ -101,11 +104,14 @@ type CtrContractUpdateReq struct {
 	// CollectedAmount   float64          `json:"collectedAmount"`   // 已回款金额
 	ContractStartTime *gtime.Time      `json:"contractStartTime"` // 合同开始时间
 	ContractEndTime   *gtime.Time      `json:"contractEndTime"`   // 合同结束时间
+	ContractSignTime  *gtime.Time      `json:"contractSignTime"`  // 合同签订时间
 	InchargeId        int              `json:"inchargeId"`        // 负责人ID
 	InchargeName      string           `json:"inchargeName"`      // 负责人
 	SignatoryId       int              `json:"signatoryId"`       // 公司签约人ID
 	SignatoryName     string           `json:"signatoryName"`     // 公司签约人
 	SignatoryType     string           `json:"signatoryType"`     // 签订单位类型 10 终端用户 20 经销商 30 代理商
+	SignatoryUnit     string           `json:"signatoryUnit"`     // 合同签订单位
+	EarnestMoney      *float64         `json:"earnestMoney"`      // 质量/履约保证金(元)
 	CustSignatoryId   int              `json:"custSignatoryId"`   // 客户签约人ID
 	CustSignatoryName string           `json:"custSignatoryName"` // 客户签约人
 	DistributorId     int              `json:"distributorId"`     // 经销商ID
@@ -114,6 +120,19 @@ type CtrContractUpdateReq struct {
 	Product           *[]CtrAddProduct `json:"product"` // 产品
 }
 
+type CtrContractUpdateProductReq struct {
+	Id                int         `json:"id" v:"required#请输入Id"`
+	MaintainPeriod    *int        `json:"maintainPeriod"`    // 质保期(天)
+	WarrantPeriod     *int        `json:"warrantPeriod"`     // 运维期(天)
+	MaintainStartTime *gtime.Time `json:"maintainStartTime"` // 运维开始时间
+	MaintainRemark    *string     `json:"maintainRemark"`    // 运维约定条款
+	AcceptTime        *gtime.Time `json:"acceptTime"`        // 验收时间
+	PurchaseCost      *float64    `json:"purchaseCost"`      // 采购成本
+	DevCost           *float64    `json:"devCost"`           // 二次开发成本
+	MaintainCost      *float64    `json:"maintainCost"`      // 产品维保成本
+	DirectCost        *float64    `json:"directCost"`        // 直接成本
+}
+
 type CtrContractTransferReq struct {
 	Id           []int  `json:"id" v:"required#请输入Id"`
 	InchargeId   int    `json:"inchargeId"`   // 负责人ID

+ 8 - 4
opms_parent/app/model/contract/ctr_contract_collection_plan.go

@@ -40,8 +40,10 @@ type CtrContractCollectionPlanAddReq struct {
 	ContractId int `json:"contractId"` // 关联合同
 	// ContractCode   string      `json:"contractCode"`   // 合同编号
 	// ContractStatus string      `json:"contractStatus"` // 回款状态(10待回款20部分回款30全部回款)
-	PlanAmount   float64     `json:"planAmount"`   // 计划回款金额
-	PlanDatetime *gtime.Time `json:"planDatetime"` // 计划回款日期
+	PlanAmount    float64     `json:"planAmount"`    // 计划回款金额
+	PlanDatetime  *gtime.Time `json:"planDatetime"`  // 计划回款日期
+	PlanScale     float64     `json:"planScale"`     // 计划回款比例
+	PlanCondition string      `json:"planCondition"` // 回款条件
 	// CashedAmount   float64     `json:"cashedAmount"`   // 实际回款金额
 	// CashedDatetime *gtime.Time `json:"cashedDatetime"` // 实际回款日期
 	Remark string `json:"remark"` // 备注
@@ -54,8 +56,10 @@ type CtrContractCollectionPlanUpdateReq struct {
 	// ContractId int `json:"contractId"` // 关联合同
 	// ContractCode   string      `json:"contractCode"`   // 合同编号
 	// ContractStatus string      `json:"contractStatus"` // 回款状态(10待回款20部分回款30全部回款)
-	PlanAmount   *float64    `json:"planAmount"`   // 计划回款金额
-	PlanDatetime *gtime.Time `json:"planDatetime"` // 计划回款日期
+	PlanAmount    *float64    `json:"planAmount"`    // 计划回款金额
+	PlanDatetime  *gtime.Time `json:"planDatetime"`  // 计划回款日期
+	PlanScale     *float64    `json:"planScale"`     // 计划回款比例
+	PlanCondition *string     `json:"planCondition"` // 回款条件
 	// CashedAmount   *float64    `json:"cashedAmount"`   // 实际回款金额
 	// CashedDatetime *gtime.Time `json:"cashedDatetime"` // 实际回款日期
 	Remark *string `json:"remark"`

+ 41 - 38
opms_parent/app/model/contract/internal/ctr_contract.go

@@ -10,42 +10,45 @@ import (
 
 // CtrContract is the golang structure for table ctr_contract.
 type CtrContract struct {
-	Id                  int         `orm:"id,primary"          json:"id"`                   // 主键
-	ContractCode        string      `orm:"contract_code"       json:"contractCode"`         // 合同编号
-	ContractName        string      `orm:"contract_name"       json:"contractName"`         // 合同名称
-	CustId              int         `orm:"cust_id"             json:"custId"`               // 关联客户
-	CustName            string      `orm:"cust_name"           json:"custName"`             // 客户名称
-	ProductLine         string      `orm:"product_line"        json:"productLine"`          // 产品线
-	IsBig               string      `orm:"is_big"              json:"isBig"`                // 是否为大项目
-	CustProvinceId      int         `orm:"cust_province_id"    json:"custProvinceId"`       // 所在省ID
-	CustProvince        string      `orm:"cust_province"       json:"custProvince"`         // 所在省
-	CustCityId          int         `orm:"cust_city_id"        json:"custCityId"`           // 所在市ID
-	CustCity            string      `orm:"cust_city"           json:"custCity"`             // 所在市
-	NboId               int         `orm:"nbo_id"              json:"nboId"`                // 关联项目
-	NboName             string      `orm:"nbo_name"            json:"nboName"`              // 项目名称
-	ApproStatus         string      `orm:"appro_status"        json:"approStatus"`          // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
-	ContractType        string      `orm:"contract_type"       json:"contractType"`         // 合同类型
-	ContractAmount      float64     `orm:"contract_amount"     json:"contractAmount"`       // 合同金额
-	InvoiceAmount       float64     `orm:"invoice_amount"      json:"invoiceAmount"`        // 已开票金额
-	CollectedAmount     float64     `orm:"collected_amount"    json:"collectedAmount"`      // 已回款金额
-	ContractStartTime   *gtime.Time `orm:"contract_start_time" json:"contractStartTime"`    // 合同开始时间
-	ContractEndTime     *gtime.Time `orm:"contract_end_time"   json:"contractEndTime"`      // 合同结束时间
-	InchargeId          int         `orm:"incharge_id"         json:"inchargeId"`           // 负责人ID
-	InchargeName        string      `orm:"incharge_name"       json:"inchargeName"`         // 负责人(销售工程师)
-	SignatoryId         int         `orm:"signatory_id"        json:"signatoryId"`          // 公司签约人ID
-	SignatoryName       string      `orm:"signatory_name"      json:"signatoryName"`        // 公司签约人
-	SignatoryType       string      `orm:"signatory_type"      json:"signatoryType"`        // 签订单位类型 10 终端用户 20 经销商 30 代理商
-	CustSignatoryId     int         `orm:"cust_signatory_id"   json:"custSignatoryId"`      // 客户签约人ID
-	CustSignatoryName   string      `orm:"cust_signatory_name" json:"custSignatoryName"`    // 客户签约人
-	DistributorId       int         `orm:"distributor_id"      json:"distributorId"`        // 经销商ID
-	DistributorName     string      `orm:"distributor_name"    json:"distributorName"`      // 经销商
-	Remark              string      `orm:"remark"              json:"remark"`               // 备注
-	ServiceFeeAgreement string      `orm:"service_fee_agreement"json:"serviceFeeAgreement"` // 运维服务费约定
-	CreatedBy           int         `orm:"created_by"          json:"createdBy"`            // 创建者
-	CreatedName         string      `orm:"created_name"        json:"createdName"`          // 创建人
-	CreatedTime         *gtime.Time `orm:"created_time"        json:"createdTime"`          // 创建时间
-	UpdatedBy           int         `orm:"updated_by"          json:"updatedBy"`            // 更新者
-	UpdatedName         string      `orm:"updated_name"        json:"updatedName"`          // 更新人
-	UpdatedTime         *gtime.Time `orm:"updated_time"        json:"updatedTime"`          // 更新时间
-	DeletedTime         *gtime.Time `orm:"deleted_time"        json:"deletedTime"`          // 删除时间
+	Id                  int         `orm:"id,primary"            json:"id"`                  // 主键
+	ContractCode        string      `orm:"contract_code"         json:"contractCode"`        // 合同编号
+	ContractName        string      `orm:"contract_name"         json:"contractName"`        // 合同名称
+	CustId              int         `orm:"cust_id"               json:"custId"`              // 关联客户
+	CustName            string      `orm:"cust_name"             json:"custName"`            // 客户名称
+	ProductLine         string      `orm:"product_line"          json:"productLine"`         // 产品线
+	IsBig               string      `orm:"is_big"                json:"isBig"`               // 是否为大项目
+	CustProvinceId      int         `orm:"cust_province_id"      json:"custProvinceId"`      // 所在省ID
+	CustProvince        string      `orm:"cust_province"         json:"custProvince"`        // 所在省
+	CustCityId          int         `orm:"cust_city_id"          json:"custCityId"`          // 所在市ID
+	CustCity            string      `orm:"cust_city"             json:"custCity"`            // 所在市
+	NboId               int         `orm:"nbo_id"                json:"nboId"`               // 关联项目
+	NboName             string      `orm:"nbo_name"              json:"nboName"`             // 项目名称
+	ApproStatus         string      `orm:"appro_status"          json:"approStatus"`         // 审核状态 10 待提交审核 20 待审核 30 审核已同意 40 审核已拒绝 50 审核已撤销
+	ContractType        string      `orm:"contract_type"         json:"contractType"`        // 合同类型
+	ContractAmount      float64     `orm:"contract_amount"       json:"contractAmount"`      // 合同金额
+	InvoiceAmount       float64     `orm:"invoice_amount"        json:"invoiceAmount"`       // 已开票金额
+	CollectedAmount     float64     `orm:"collected_amount"      json:"collectedAmount"`     // 已回款金额
+	ContractStartTime   *gtime.Time `orm:"contract_start_time"   json:"contractStartTime"`   // 合同开始时间
+	ContractEndTime     *gtime.Time `orm:"contract_end_time"     json:"contractEndTime"`     // 合同结束时间
+	ContractSignTime    *gtime.Time `orm:"contract_sign_time"    json:"contractSignTime"`    // 合同签订时间
+	InchargeId          int         `orm:"incharge_id"           json:"inchargeId"`          // 负责人ID
+	InchargeName        string      `orm:"incharge_name"         json:"inchargeName"`        // 负责人(销售工程师)
+	SignatoryId         int         `orm:"signatory_id"          json:"signatoryId"`         // 公司签约人ID
+	SignatoryName       string      `orm:"signatory_name"        json:"signatoryName"`       // 公司签约人
+	SignatoryType       string      `orm:"signatory_type"        json:"signatoryType"`       // 签订单位类型 10 终端用户 20 经销商 30 代理商
+	SignatoryUnit       string      `orm:"signatory_unit"        json:"signatoryUnit"`       // 合同签订单位
+	EarnestMoney        float64     `orm:"earnest_money"         json:"earnestMoney"`        // 质量/履约保证金(元)
+	CustSignatoryId     int         `orm:"cust_signatory_id"     json:"custSignatoryId"`     // 客户签约人ID
+	CustSignatoryName   string      `orm:"cust_signatory_name"   json:"custSignatoryName"`   // 客户签约人
+	DistributorId       int         `orm:"distributor_id"        json:"distributorId"`       // 经销商ID
+	DistributorName     string      `orm:"distributor_name"      json:"distributorName"`     // 经销商
+	ServiceFeeAgreement string      `orm:"service_fee_agreement" json:"serviceFeeAgreement"` // 运维服务费约定
+	Remark              string      `orm:"remark"                json:"remark"`              // 备注
+	CreatedBy           int         `orm:"created_by"            json:"createdBy"`           // 创建者
+	CreatedName         string      `orm:"created_name"          json:"createdName"`         // 创建人
+	CreatedTime         *gtime.Time `orm:"created_time"          json:"createdTime"`         // 创建时间
+	UpdatedBy           int         `orm:"updated_by"            json:"updatedBy"`           // 更新者
+	UpdatedName         string      `orm:"updated_name"          json:"updatedName"`         // 更新人
+	UpdatedTime         *gtime.Time `orm:"updated_time"          json:"updatedTime"`         // 更新时间
+	DeletedTime         *gtime.Time `orm:"deleted_time"          json:"deletedTime"`         // 删除时间
 }

+ 2 - 0
opms_parent/app/model/contract/internal/ctr_contract_collection_plan.go

@@ -18,6 +18,8 @@ type CtrContractCollectionPlan struct {
 	ContractStatus string      `orm:"contract_status" json:"contractStatus"` // 回款状态(10待回款20部分回款30全部回款)
 	PlanAmount     float64     `orm:"plan_amount"     json:"planAmount"`     // 计划回款金额
 	PlanDatetime   *gtime.Time `orm:"plan_datetime"   json:"planDatetime"`   // 计划回款日期
+	PlanScale      float64     `orm:"plan_scale"      json:"planScale"`      // 计划回款比例
+	PlanCondition  string      `orm:"plan_condition"  json:"planCondition"`  // 回款条件
 	CashedAmount   float64     `orm:"cashed_amount"   json:"cashedAmount"`   // 实际回款金额
 	CashedDatetime *gtime.Time `orm:"cashed_datetime" json:"cashedDatetime"` // 实际回款日期
 	Remark         string      `orm:"remark"          json:"remark"`         // 备注

+ 29 - 19
opms_parent/app/model/contract/internal/ctr_contract_product.go

@@ -10,23 +10,33 @@ import (
 
 // CtrContractProduct is the golang structure for table ctr_contract_product.
 type CtrContractProduct struct {
-	Id            int         `orm:"id,primary"      json:"id"`            // 主键
-	ContractId    int         `orm:"contract_id"     json:"contractId"`    // 关联合同
-	ProdId        int         `orm:"prod_id"         json:"prodId"`        // 关联产品
-	ProdCode      string      `orm:"prod_code"       json:"prodCode"`      // 产品型号
-	ProdName      string      `orm:"prod_name"       json:"prodName"`      // 产品名称
-	ProdClass     string      `orm:"prod_class"      json:"prodClass"`     // 产品类别
-	ProdNum       int         `orm:"prod_num"        json:"prodNum"`       // 产品数量
-	MaintTerm     int         `orm:"maint_term"      json:"maintTerm"`     // 维保期
-	SugSalesPrice float64     `orm:"sug_sales_price" json:"sugSalesPrice"` // 建议成交价
-	TranPrice     float64     `orm:"tran_price"      json:"tranPrice"`     // 成交价格
-	ContractPrive float64     `orm:"contract_prive"  json:"contractPrive"` // 合同总价
-	Remark        string      `orm:"remark"          json:"remark"`        // 备注
-	CreatedBy     int         `orm:"created_by"      json:"createdBy"`     // 创建者
-	CreatedName   string      `orm:"created_name"    json:"createdName"`   // 创建人
-	CreatedTime   *gtime.Time `orm:"created_time"    json:"createdTime"`   // 创建时间
-	UpdatedBy     int         `orm:"updated_by"      json:"updatedBy"`     // 更新者
-	UpdatedName   string      `orm:"updated_name"    json:"updatedName"`   // 更新人
-	UpdatedTime   *gtime.Time `orm:"updated_time"    json:"updatedTime"`   // 更新时间
-	DeletedTime   *gtime.Time `orm:"deleted_time"    json:"deletedTime"`   // 删除时间
+	Id                int         `orm:"id,primary"          json:"id"`                // 主键
+	ContractId        int         `orm:"contract_id"         json:"contractId"`        // 关联合同
+	ContractCode      string      `orm:"contract_code"       json:"contractCode"`      // 合同编号
+	ProdId            int         `orm:"prod_id"             json:"prodId"`            // 关联产品
+	ProdCode          string      `orm:"prod_code"           json:"prodCode"`          // 产品型号
+	ProdName          string      `orm:"prod_name"           json:"prodName"`          // 产品名称
+	ProdClass         string      `orm:"prod_class"          json:"prodClass"`         // 产品类别
+	ProdNum           int         `orm:"prod_num"            json:"prodNum"`           // 产品数量
+	MaintTerm         int         `orm:"maint_term"          json:"maintTerm"`         // 维保期
+	SugSalesPrice     float64     `orm:"sug_sales_price"     json:"sugSalesPrice"`     // 建议成交价
+	TranPrice         float64     `orm:"tran_price"          json:"tranPrice"`         // 成交价格
+	ContractPrive     float64     `orm:"contract_prive"      json:"contractPrive"`     // 合同总价
+	PurchaseCost      float64     `orm:"purchase_cost"       json:"purchaseCost"`      // 采购成本
+	DevCost           float64     `orm:"dev_cost"            json:"devCost"`           // 二次开发成本
+	MaintainCost      float64     `orm:"maintain_cost"       json:"maintainCost"`      // 产品维保成本
+	DirectCost        float64     `orm:"direct_cost"         json:"directCost"`        // 直接成本
+	MaintainPeriod    int         `orm:"maintain_period"     json:"maintainPeriod"`    // 质保期(天)
+	WarrantPeriod     int         `orm:"warrant_period"      json:"warrantPeriod"`     // 运维期(天)
+	MaintainStartTime *gtime.Time `orm:"maintain_start_time" json:"maintainStartTime"` // 运维开始时间
+	MaintainRemark    string      `orm:"maintain_remark"     json:"maintainRemark"`    // 运维约定条款
+	AcceptTime        *gtime.Time `orm:"accept_time"         json:"acceptTime"`        // 验收时间
+	Remark            string      `orm:"remark"              json:"remark"`            // 备注
+	CreatedBy         int         `orm:"created_by"          json:"createdBy"`         // 创建者
+	CreatedName       string      `orm:"created_name"        json:"createdName"`       // 创建人
+	CreatedTime       *gtime.Time `orm:"created_time"        json:"createdTime"`       // 创建时间
+	UpdatedBy         int         `orm:"updated_by"          json:"updatedBy"`         // 更新者
+	UpdatedName       string      `orm:"updated_name"        json:"updatedName"`       // 更新人
+	UpdatedTime       *gtime.Time `orm:"updated_time"        json:"updatedTime"`       // 更新时间
+	DeletedTime       *gtime.Time `orm:"deleted_time"        json:"deletedTime"`       // 删除时间
 }

+ 140 - 3
opms_parent/app/service/contract/ctr_contract.go

@@ -34,6 +34,8 @@ import (
 	"dashoo.cn/opms_libary/utils"
 	"github.com/gogf/gf/database/gdb"
 	"github.com/gogf/gf/frame/g"
+	"github.com/gogf/gf/os/gcron"
+	"github.com/gogf/gf/os/glog"
 	"github.com/gogf/gf/os/gtime"
 	"github.com/gogf/gf/util/gvalid"
 )
@@ -250,7 +252,7 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	return total, ents, err
 }
 
-func (s CtrContractService) BindProduct(tx *gdb.TX, id int, product []model.CtrAddProduct) error {
+func (s CtrContractService) BindProduct(tx *gdb.TX, id int, code string, product []model.CtrAddProduct) error {
 	var amount float64
 	for _, p := range product {
 		amount += (p.TranPrice * float64(p.ProdNum))
@@ -272,6 +274,7 @@ func (s CtrContractService) BindProduct(tx *gdb.TX, id int, product []model.CtrA
 		}
 		tocreate = append(tocreate, model.CtrContractProduct{
 			ContractId:    id,
+			ContractCode:  code,
 			ProdId:        p.ProdId,
 			ProdCode:      product.ProdCode,
 			ProdName:      product.ProdName,
@@ -398,11 +401,14 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		CollectedAmount:     0,
 		ContractStartTime:   req.ContractStartTime,
 		ContractEndTime:     req.ContractEndTime,
+		ContractSignTime:    req.ContractSignTime,
 		InchargeId:          req.InchargeId,
 		InchargeName:        req.InchargeName,
 		SignatoryId:         req.SignatoryId,
 		SignatoryName:       req.SignatoryName,
 		SignatoryType:       req.SignatoryType,
+		SignatoryUnit:       req.SignatoryUnit,
+		EarnestMoney:        req.EarnestMoney,
 		CustSignatoryId:     req.CustSignatoryId,
 		CustSignatoryName:   req.CustSignatoryName,
 		DistributorId:       req.DistributorId,
@@ -423,7 +429,7 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 		if err != nil {
 			return err
 		}
-		err = s.BindProduct(tx, int(ctrid), req.Product)
+		err = s.BindProduct(tx, int(ctrid), ctr.ContractCode, req.Product)
 		if err != nil {
 			return err
 		}
@@ -801,6 +807,9 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 	if req.ContractEndTime != nil {
 		toupdate["contract_end_time"] = req.ContractEndTime
 	}
+	if req.ContractSignTime != nil {
+		toupdate["contract_sign_time"] = req.ContractSignTime
+	}
 	//if req.InchargeId != 0 {
 	//	toupdate["incharge_id"] = req.InchargeId
 	//}
@@ -816,6 +825,12 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 	if req.SignatoryType != "" {
 		toupdate["signatory_type"] = req.SignatoryType
 	}
+	if req.SignatoryUnit != "" {
+		toupdate["signatory_unit"] = req.SignatoryUnit
+	}
+	if req.EarnestMoney != nil {
+		toupdate["earnest_money"] = req.EarnestMoney
+	}
 	if req.CustSignatoryId != 0 {
 		toupdate["cust_signatory_id"] = req.CustSignatoryId
 	}
@@ -849,7 +864,7 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 				return err
 			}
 			if req.Product != nil {
-				err = s.BindProduct(tx, req.Id, *req.Product)
+				err = s.BindProduct(tx, req.Id, ent.ContractCode, *req.Product)
 				if err != nil {
 					return err
 				}
@@ -863,6 +878,72 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 	return nil
 }
 
+func (s CtrContractService) UpdateProduct(ctx context.Context, req *model.CtrContractUpdateProductReq) error {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return myerrors.TipsError(validErr.Current().Error())
+	}
+
+	ent, err := s.CtrProductDao.Where("id = ?", req.Id).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.TipsError(fmt.Sprintf("合同产品记录不存在: %d", req.Id))
+	}
+
+	toupdate := map[string]interface{}{}
+	if req.MaintainPeriod != nil {
+		toupdate["maintain_period"] = req.MaintainPeriod
+	}
+	if req.WarrantPeriod != nil {
+		toupdate["warrant_period"] = req.WarrantPeriod
+	}
+	if req.MaintainStartTime != nil {
+		toupdate["maintain_start_time"] = req.MaintainStartTime
+	}
+	if req.MaintainRemark != nil {
+		toupdate["maintain_remark"] = req.MaintainRemark
+	}
+	if req.AcceptTime != nil {
+		toupdate["accept_time"] = req.AcceptTime
+	}
+	if req.PurchaseCost != nil {
+		toupdate["purchase_cost"] = req.PurchaseCost
+	}
+	if req.DevCost != nil {
+		toupdate["dev_cost"] = req.DevCost
+	}
+	if req.MaintainCost != nil {
+		toupdate["maintain_cost"] = req.MaintainCost
+	}
+	if req.DirectCost != nil {
+		toupdate["direct_cost"] = req.DirectCost
+	}
+
+	if len(toupdate) != 0 {
+		toupdate["updated_by"] = int(s.userInfo.Id)
+		toupdate["updated_name"] = s.userInfo.NickName
+		toupdate["updated_time"] = gtime.Now()
+
+		txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+			_, err = tx.Update("ctr_contract_product", toupdate, "id = ?", req.Id)
+			if err != nil {
+				return err
+			}
+			err = s.AddDynamicsByCurrentUser(tx, ent.ContractId, "更新合同产品信息", toupdate)
+			if err != nil {
+				return err
+			}
+			return nil
+		})
+		if txerr != nil {
+			return txerr
+		}
+	}
+	return nil
+}
+
 func (s CtrContractService) Transfer(ctx context.Context, req *model.CtrContractTransferReq) error {
 	if len(req.Id) == 0 {
 		return nil
@@ -970,3 +1051,59 @@ func (s CtrContractService) Delete(ctx context.Context, id []int) error {
 	_, err := s.Dao.Where("Id  IN (?)", id).Delete()
 	return err
 }
+
+func init() {
+	tenant := g.Config().GetString("micro_srv.tenant")
+	if tenant == "" {
+		panic("定时任务租户码未设置,请前往配置")
+	}
+	contractDao := dao.NewCtrContractDao(tenant)
+	produceDao := dao.NewCtrContractProductDao(tenant)
+
+	job := func() {
+		alert := map[int]*[]model.CtrContractProduct{
+			180: {},
+			90:  {},
+			30:  {},
+			10:  {},
+			// 7:   {},
+		}
+		where := `DATE_FORMAT(DATE_ADD(maintain_start_time, INTERVAL ? day), "%Y-%m-%d") = DATE_FORMAT(NOW(), "%Y-%m-%d")`
+
+		for day, p := range alert {
+			err := produceDao.Where(where, day).Structs(p)
+			if err != nil {
+				glog.Error(err)
+			}
+			glog.Infof("运维期到期 %d 天提醒,产品个数 %d", day, len(*p))
+		}
+		for day, p := range alert {
+			for _, i := range *p {
+				ctr, err := contractDao.Where("id = ?", i.ContractId).One()
+				if err != nil {
+					glog.Error(err)
+				}
+
+				text := fmt.Sprintf("合同:%s-%s 中的产品:%s 距离运维到期还有 %d 天",
+					ctr.ContractCode, ctr.ContractName, i.ProdName, day)
+				msg := g.MapStrStr{
+					"msgTitle":    "运维期到期提醒",
+					"msgContent":  text,
+					"msgType":     "20",
+					"recvUserIds": strconv.Itoa(ctr.InchargeId),
+					"msgStatus":   "10",
+					"sendType":    "10",
+				}
+				if err := service.CreateSystemMessage(msg); err != nil {
+					glog.Error("消息提醒异常:", err)
+				}
+				glog.Infof("%s", text)
+			}
+		}
+	}
+
+	// 每天凌晨2点执行
+	gcron.AddSingleton("0 0 2 * * *", job)
+	// job()
+
+}

+ 8 - 0
opms_parent/app/service/contract/ctr_contract_collection_plan.go

@@ -152,6 +152,8 @@ func (s CtrContractCollectionPlanService) Add(ctx context.Context, req *model.Ct
 		ContractStatus: "10",
 		PlanAmount:     req.PlanAmount,
 		PlanDatetime:   req.PlanDatetime,
+		PlanScale:      req.PlanScale,
+		PlanCondition:  req.PlanCondition,
 		CashedAmount:   0,
 		CashedDatetime: nil,
 		Remark:         req.Remark,
@@ -223,6 +225,12 @@ func (s CtrContractCollectionPlanService) Update(ctx context.Context, req *model
 	if req.PlanDatetime != nil {
 		toupdate["plan_datetime"] = req.PlanDatetime
 	}
+	if req.PlanScale != nil {
+		toupdate["plan_scale"] = req.PlanScale
+	}
+	if req.PlanCondition != nil {
+		toupdate["plan_condition"] = req.PlanCondition
+	}
 	// if req.CashedAmount != nil {
 	// 	toupdate["cashed_amount"] = *req.CashedAmount
 	// }

+ 11 - 0
opms_parent/schema/contract.sql

@@ -18,6 +18,7 @@ CREATE TABLE `ctr_contract` (
     `collected_amount` decimal(24, 6) NOT NULL COMMENT '已回款金额',
     `contract_start_time` datetime NOT NULL COMMENT '合同开始时间',
     `contract_end_time` datetime COMMENT '合同结束时间',
+    `contract_sign_time` datetime COMMENT '合同签订时间',
     `incharge_id` int(11) COMMENT '负责人ID',
     `incharge_name` varchar(90) COMMENT '负责人(销售工程师)',
     `signatory_id` int(11) DEFAULT NULL COMMENT '公司签约人ID',
@@ -123,6 +124,7 @@ CREATE TABLE `ctr_contract_invoice` (
 CREATE TABLE `ctr_contract_product` (
     `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
     `contract_id` int(11) NOT NULL COMMENT '关联合同',
+    `contract_code` varchar(32) NOT NULL COMMENT '合同编号',
     `prod_id` int(11) NOT NULL COMMENT '关联产品',
     `prod_code` varchar(32) NOT NULL COMMENT '产品型号',
     `prod_name` varchar(90) NOT NULL COMMENT '产品名称',
@@ -132,6 +134,15 @@ CREATE TABLE `ctr_contract_product` (
     `sug_sales_price` decimal(24, 6) DEFAULT NULL COMMENT '建议成交价',
     `tran_price` decimal(24, 6) DEFAULT NULL COMMENT '成交价格',
     `contract_prive` decimal(24, 6) DEFAULT NULL COMMENT '合同总价',
+    `purchase_cost` decimal(24, 6) DEFAULT NULL COMMENT '采购成本',
+    `dev_cost` decimal(24, 6) DEFAULT NULL COMMENT '二次开发成本',
+    `maintain_cost` decimal(24, 6) DEFAULT NULL COMMENT '产品维保成本',
+    `direct_cost` decimal(24, 6) DEFAULT NULL COMMENT '直接成本',
+    `maintain_period` int(11) DEFAULT NULL COMMENT '质保期(天)',
+    `warrant_period` int(11) DEFAULT NULL COMMENT '运维期(天)',
+    `maintain_start_time` datetime DEFAULT NULL COMMENT '运维开始时间',
+    `maintain_remark` text DEFAULT NULL COMMENT '运维约定条款',
+    `accept_time` datetime DEFAULT NULL COMMENT '验收时间',
     `remark` text DEFAULT NULL COMMENT '备注',
     `created_by` int(11) NOT NULL COMMENT '创建者',
     `created_name` varchar(90) NOT NULL COMMENT '创建人',

+ 21 - 0
opms_parent/schema/tmp.sql

@@ -26,3 +26,24 @@ alter table ctr_contract modify `contract_end_time` datetime COMMENT '合同结
 
 alter table base_distributor add `invoice_header` varchar(255) DEFAULT NULL COMMENT '开票抬头' after sale_num;
 alter table cust_customer add `invoice_header` varchar(255) DEFAULT NULL COMMENT '开票抬头' after follow_up_man;
+
+
+
+-- 2023-05-05
+alter table ctr_contract  add  `contract_sign_time` datetime COMMENT '合同签订时间' after contract_end_time;
+alter table ctr_contract  add  `signatory_unit` varchar(90) COMMENT '合同签订单位' after signatory_type;
+alter table ctr_contract  add  `earnest_money` decimal(24, 6) COMMENT '质量/履约保证金(元)' after signatory_unit;
+
+alter table ctr_contract_product  add `contract_code` varchar(32) NOT NULL COMMENT '合同编号' after contract_id;
+alter table ctr_contract_product add `purchase_cost` decimal(24, 6) DEFAULT NULL COMMENT '采购成本' after contract_prive;
+alter table ctr_contract_product add `dev_cost` decimal(24, 6) DEFAULT NULL COMMENT '二次开发成本' after purchase_cost;
+alter table ctr_contract_product add `maintain_cost` decimal(24, 6) DEFAULT NULL COMMENT '产品维保成本' after dev_cost;
+alter table ctr_contract_product add `direct_cost` decimal(24, 6) DEFAULT NULL COMMENT '直接成本' after maintain_cost;
+alter table ctr_contract_product add `maintain_period` int(11) DEFAULT NULL COMMENT '质保期(天)' after direct_cost;
+alter table ctr_contract_product add `warrant_period` int(11) DEFAULT NULL COMMENT '运维期(天)' after maintain_period;
+alter table ctr_contract_product add `maintain_start_time` datetime DEFAULT NULL COMMENT '运维开始时间' after warrant_period;
+alter table ctr_contract_product add `maintain_remark` text DEFAULT NULL COMMENT '运维约定条款' after maintain_start_time;
+alter table ctr_contract_product add `accept_time` datetime DEFAULT NULL COMMENT '验收时间' after maintain_remark;
+
+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;