Explorar o código

feature:添加续签合同相关功能

sunxinyuan hai 1 ano
pai
achega
2d8128245f

+ 6 - 4
opms_parent/app/dao/contract/internal/ctr_contract.go

@@ -8,15 +8,14 @@ import (
 	"context"
 	"database/sql"
 	"fmt"
-	"github.com/gogf/gf/text/gstr"
-	"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/text/gstr"
 	"github.com/gogf/gf/util/gconv"
+	"strings"
+	"time"
 
 	model "dashoo.cn/micro/app/model/contract"
 )
@@ -35,6 +34,7 @@ type ctrContractColumns struct {
 	Id                           string // 主键
 	ContractCode                 string // 合同编号
 	ContractName                 string // 合同名称
+	ContractId                   string // 关联合同
 	CustId                       string // 关联客户
 	CustName                     string // 客户名称
 	ProductLine                  string // 产品线
@@ -92,6 +92,7 @@ var (
 			Id:                           "id",
 			ContractCode:                 "contract_code",
 			ContractName:                 "contract_name",
+			ContractId:                   "contract_id",
 			CustId:                       "cust_id",
 			CustName:                     "cust_name",
 			ProductLine:                  "product_line",
@@ -151,6 +152,7 @@ func NewCtrContractDao(tenant string) CtrContractDao {
 			Id:                           "id",
 			ContractCode:                 "contract_code",
 			ContractName:                 "contract_name",
+			ContractId:                   "contract_id",
 			CustId:                       "cust_id",
 			CustName:                     "cust_name",
 			ProductLine:                  "product_line",

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

@@ -57,6 +57,31 @@ func (c *CtrContract) List(ctx context.Context, req *model.CtrContractListReq, r
 	return nil
 }
 
+// Swagger:CtrContract 合同,测试tag 查询合同
+func (c *CtrContract) RenewList(ctx context.Context, req *model.CtrRenewContractListReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.List request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	ent, err := s.RenewList(ctx, req)
+	//_, err, code, msg := myerrors.CheckError(err)
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		ent = []*model.CtrContractListRsp{}
+	}
+	//rsp.Code = code
+	//rsp.Msg = msg
+	//rsp.Data = map[string]interface{}{
+	//	"total": total,
+	//	"list":  ent,
+	//}
+	rsp.Data = ent
+	return nil
+}
+
 // Swagger:CtrContract 合同,测试tag 查询合同动态列表
 func (c *CtrContract) DynamicsList(ctx context.Context, req *model.CtrContractDynamicsListReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContract.GetDynamicsList request %#v ", *req)
@@ -101,6 +126,25 @@ func (c *CtrContract) Add(ctx context.Context, req *model.CtrContractAddReq, rsp
 	return nil
 }
 
+// Swagger:CtrContract 合同  续签合同
+func (c *CtrContract) ReNew(ctx context.Context, req *model.CtrContractReNewReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.Add request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	id, err := s.ReNew(ctx, req)
+	//_, err, code, msg := myerrors.CheckError(err)
+	if err != nil {
+		return err
+	}
+	//rsp.Code = code
+	//rsp.Msg = msg
+	//rsp.Data = id
+	rsp.Data = g.Map{"list": id}
+	return nil
+}
+
 // Swagger:CtrContract 合同,测试tag 提交审核
 func (c *CtrContract) Commit(ctx context.Context, req *model.CtrContractCommitReq, rsp *comm_def.CommonMsg) error {
 	g.Log().Infof("CtrContract.Commit request %#v ", *req)
@@ -177,6 +221,23 @@ func (c *CtrContract) Update(ctx context.Context, req *model.CtrContractUpdateRe
 	return nil
 }
 
+// Swagger:CtrContract 合同,测试tag 更新续签合同
+func (c *CtrContract) UpdateReNew(ctx context.Context, req *model.CtrContractUpdateReNewReq, rsp *comm_def.CommonMsg) error {
+	g.Log().Infof("CtrContract.Update request %#v ", *req)
+	s, err := service.NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
+	err = s.UpdateReNew(ctx, req)
+	//	_, err, code, msg := myerrors.CheckError(err)
+	if err != nil {
+		return err
+	}
+	//rsp.Code = code
+	//rsp.Msg = msg
+	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)

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

@@ -50,6 +50,7 @@ type CtrContractListReq struct {
 	ContractSignTimeStart string `json:"contractSignTimeStart"` //合同签订时间开始
 	ContractSignTimeEnd   string `json:"contractSignTimeEnd"`   //合同签订时间结束
 
+	IsNotMaintenanceContract          string      `json:"isNotMaintenanceContract"`          // 是否为非续签合同
 	SoftwareMaintenanceBeginTimeStart *gtime.Time `json:"softwareMaintenanceBeginTimeStart"` // 软件运维开始时间
 	SoftwareMaintenanceBeginTimeEnd   *gtime.Time `json:"softwareMaintenanceBeginTimeEnd"`   // 软件运维开始时间
 	SoftwareMaintenanceEndTimeStart   *gtime.Time `json:"softwareMaintenanceEndTimeStart"`   // 软件运维结束时间
@@ -60,6 +61,12 @@ type CtrContractListReq struct {
 	HardwareMaintenanceEndTimeEnd     *gtime.Time `json:"hardwareMaintenanceEndTimeEnd"`     // 硬件运维结束时间
 }
 
+type CtrRenewContractListReq struct {
+	ContractId int    `json:"contractId"` // 关联合同
+	SearchText string `json:"searchText"` // 合同编号,合同名称,客户名称,项目名称
+
+}
+
 type CtrAddProduct struct {
 	// ContractId    int     `json:"contractId"`    // 关联合同
 	ProdId int `json:"prodId"` // 关联产品
@@ -108,6 +115,19 @@ type CtrContractAddReq struct {
 	MaintenanceClause        string          `json:"maintenanceClause"`        // 运维条款
 }
 
+type CtrContractReNewReq struct {
+	ContractId                   int         `json:"contractId" v:"required#请关联合同"` // 关联合同
+	SoftwareMaintenanceBeginTime *gtime.Time `json:"softwareMaintenanceBeginTime"`  // 软件运维开始时间
+	SoftwareMaintenanceEndTime   *gtime.Time `json:"softwareMaintenanceEndTime"`    // 软件运维结束时间
+	HardwareMaintenanceBeginTime *gtime.Time `json:"hardwareMaintenanceBeginTime"`  // 硬件运维开始时间
+	HardwareMaintenanceEndTime   *gtime.Time `json:"hardwareMaintenanceEndTime"`    // 硬件运维结束时间
+	CtrContractAddReq
+}
+type CtrContractUpdateReNewReq struct {
+	Id int `json:"id" v:"required#请输入Id"`
+	CtrContractReNewReq
+}
+
 type CtrContractUpdateReq struct {
 	Id int `json:"id" v:"required#请输入Id"`
 	// ContractCode string `json:"contractCode"` // 合同编号

+ 1 - 0
opms_parent/app/model/contract/internal/ctr_contract.go

@@ -13,6 +13,7 @@ type CtrContract struct {
 	Id                           int         `orm:"id,primary"                      json:"id"`                           // 主键
 	ContractCode                 string      `orm:"contract_code"                   json:"contractCode"`                 // 合同编号
 	ContractName                 string      `orm:"contract_name"                   json:"contractName"`                 // 合同名称
+	ContractId                   int         `orm:"contract_id"                     json:"contractId"`                   // 关联合同
 	CustId                       int         `orm:"cust_id"                         json:"custId"`                       // 关联客户
 	CustName                     string      `orm:"cust_name"                       json:"custName"`                     // 客户名称
 	ProductLine                  string      `orm:"product_line"                    json:"productLine"`                  // 产品线

+ 50 - 7
opms_parent/app/service/base.go

@@ -3,9 +3,9 @@ package service
 import (
 	"context"
 	"dashoo.cn/opms_libary/multipart"
+	"encoding/base64"
 	"fmt"
 	"github.com/gogf/gf/encoding/gurl"
-	"github.com/gogf/gf/os/gfile"
 	"github.com/gogf/gf/text/gstr"
 	"github.com/gogf/gf/util/guid"
 	"github.com/xuri/excelize/v2"
@@ -523,8 +523,45 @@ func CommonExportExcel(ctx context.Context, fileName string, exportStruct interf
 	if fileName == "" {
 		fileName = "Sheet1"
 	}
+	colStyle, err := xlsxFile.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{
+			Horizontal: "center",
+			Vertical:   "center",
+			WrapText:   true,
+		},
+		Font: &excelize.Font{
+			Size:   11,
+			Family: "宋体",
+		},
+	})
+	headerStyle, err := xlsxFile.NewStyle(&excelize.Style{
+		Alignment: &excelize.Alignment{
+			Horizontal: "center",
+		},
+		Fill: excelize.Fill{
+			Type:    "pattern",
+			Color:   []string{"#a6a6a6"},
+			Pattern: 1,
+		},
+		Border: []excelize.Border{
+			{Type: "left", Color: "#000000", Style: 1},
+			{Type: "top", Color: "#000000", Style: 1},
+			{Type: "bottom", Color: "#000000", Style: 1},
+			{Type: "right", Color: "#000000", Style: 1},
+		},
+	})
+	lastColName, err := excelize.ColumnNumberToName(len(headerList))
+
+	xlsxFile.SetColStyle("Sheet1", "A:"+lastColName, colStyle)
+	xlsxFile.SetCellStyle("Sheet1", "A1", lastColName+"1", headerStyle)
+	xlsxFile.SetColWidth("Sheet1", "A", lastColName, 20)
+
 	xlsxFile.SetSheetName("Sheet1", fileName)
 	xlsxFile.SetSheetRow(fileName, "A1", &headerList)
+	if err != nil {
+		return "", err
+	}
+
 	for k, item := range dataList {
 		var row []interface{}
 		for _, h := range headerList {
@@ -536,12 +573,18 @@ func CommonExportExcel(ctx context.Context, fileName string, exportStruct interf
 		}
 		xlsxFile.SetSheetRow(fileName, fmt.Sprintf("A%d", k+2), &row)
 	}
-	dir := g.Config().GetString("setting.export-path")
-	gfile.Mkdir(dir)
-	path = dir + "/" + fileName + gtime.Now().Format("Y-m-d_H-i-s") + ".xlsx"
-	// 根据指定路径保存文件
-	if err := xlsxFile.SaveAs(path); err != nil {
-		g.Log().Error(ctx, err)
+
+	//dir := g.Config().GetString("setting.export-path")
+	//gfile.Mkdir(dir)
+	//path = dir + "/" + fileName + gtime.Now().Format("Y-m-d_H-i-s") + ".xlsx"
+	//// 根据指定路径保存文件
+	//if err := xlsxFile.SaveAs(path); err != nil {
+	//	g.Log().Error(ctx, err)
+	//}
+	buf, err := xlsxFile.WriteToBuffer()
+	if err != nil {
+		return "", err
 	}
+	path = base64.StdEncoding.EncodeToString(buf.Bytes())
 	return path, err
 }

+ 384 - 17
opms_parent/app/service/contract/ctr_contract.go

@@ -261,30 +261,34 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	if req.ProductLine != "" {
 		dao = dao.Where("a.product_line = ?", req.ProductLine)
 	}
+
 	if req.SoftwareMaintenanceBeginTimeStart != nil {
-		dao = dao.Where("a.software_maintenance_begin_time >= ?", req.SoftwareMaintenanceBeginTimeStart)
+		dao = dao.Where("DATE(a.software_maintenance_begin_time) >= DATE(?)", req.SoftwareMaintenanceBeginTimeStart)
 	}
 	if req.SoftwareMaintenanceBeginTimeEnd != nil {
-		dao = dao.Where("a.software_maintenance_begin_time <= ?", req.SoftwareMaintenanceBeginTimeEnd)
+		dao = dao.Where("DATE(a.software_maintenance_begin_time) <= DATE(?)", req.SoftwareMaintenanceBeginTimeEnd)
 	}
 	if req.SoftwareMaintenanceEndTimeStart != nil {
-		dao = dao.Where("a.software_maintenance_end_time >= ?", req.SoftwareMaintenanceEndTimeStart)
+		dao = dao.Where("DATE(a.software_maintenance_end_time) >= DATE(?)", req.SoftwareMaintenanceEndTimeStart)
 	}
 	if req.SoftwareMaintenanceEndTimeEnd != nil {
-		dao = dao.Where("a.software_maintenance_end_time <= ?", req.SoftwareMaintenanceEndTimeEnd)
+		dao = dao.Where("DATE(a.software_maintenance_end_time) <= DATE(?)", req.SoftwareMaintenanceEndTimeEnd)
 	}
 
 	if req.HardwareMaintenanceBeginTimeStart != nil {
-		dao = dao.Where("a.hardware_maintenance_begin_time >= ?", req.HardwareMaintenanceBeginTimeStart)
+		dao = dao.Where("DATE(a.hardware_maintenance_begin_time) >= DATE(?)", req.HardwareMaintenanceBeginTimeStart)
 	}
 	if req.HardwareMaintenanceBeginTimeEnd != nil {
-		dao = dao.Where("a.hardware_maintenance_begin_time <= ?", req.HardwareMaintenanceBeginTimeEnd)
+		dao = dao.Where("DATE(a.hardware_maintenance_begin_time) <= DATE(?)", req.HardwareMaintenanceBeginTimeEnd)
 	}
 	if req.HardwareMaintenanceEndTimeStart != nil {
-		dao = dao.Where("a.hardware_maintenance_end_time >= ?", req.HardwareMaintenanceEndTimeStart)
+		dao = dao.Where("DATE(a.hardware_maintenance_end_time) >= DATE(?)", req.HardwareMaintenanceEndTimeStart)
 	}
 	if req.HardwareMaintenanceEndTimeEnd != nil {
-		dao = dao.Where("a.hardware_maintenance_end_time <= ?", req.HardwareMaintenanceEndTimeEnd)
+		dao = dao.Where("DATE(a.hardware_maintenance_end_time) <= DATE(?)", req.HardwareMaintenanceEndTimeEnd)
+	}
+	if req.IsNotMaintenanceContract == "10" {
+		dao = dao.Where("a.contract_id = 0 or a.contract_id is NULL")
 	}
 	total, err := dao.Count()
 	if err != nil {
@@ -307,6 +311,26 @@ func (s CtrContractService) List(ctx context.Context, req *model.CtrContractList
 	return total, ents, err
 }
 
+func (s CtrContractService) RenewList(ctx context.Context, req *model.CtrRenewContractListReq) ([]*model.CtrContractListRsp, error) {
+	ctx = context.WithValue(ctx, "contextService", s)
+	dao := s.Dao.DataScope(ctx, "incharge_id").As("a").Where("contract_id=?", req.ContractId)
+
+	if req.SearchText != "" {
+		likestr := fmt.Sprintf("%%%s%%", req.SearchText)
+		dao = dao.Where("(a.contract_code LIKE ? || a.contract_name LIKE ? || a.cust_name LIKE ? || a.nbo_name LIKE ?)", likestr, likestr, likestr, likestr)
+	}
+
+	orderby := "a.contract_sign_time desc"
+	dao = dao.Order(orderby)
+
+	ents := []*model.CtrContractListRsp{}
+	err := dao.Structs(&ents)
+	if err != nil && err != sql.ErrNoRows {
+		return nil, err
+	}
+	return ents, err
+}
+
 func (s CtrContractService) BindProduct(tx *gdb.TX, id int, code string, product []model.CtrAddProduct) error {
 	var amount float64
 	for _, p := range product {
@@ -517,6 +541,303 @@ func (s CtrContractService) Add(ctx context.Context, req *model.CtrContractAddRe
 	})
 	return id, txerr
 }
+func (s CtrContractService) ReNew(ctx context.Context, req *model.CtrContractReNewReq) (int, error) {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return 0, myerrors.TipsError(validErr.Current().Error())
+	}
+	if len(req.Product) == 0 {
+		return 0, myerrors.TipsError("产品不能为空")
+	}
+	for _, p := range req.Product {
+		if p.ProdNum < 1 {
+			return 0, myerrors.TipsError("产品数量必须大于 0")
+		}
+	}
+
+	nbo, err := s.ProjBusinessDao.Where("id = ?", req.NboId).One()
+	if err != nil {
+		return 0, err
+	}
+	if nbo == nil {
+		return 0, myerrors.TipsError("项目不存在")
+	}
+	oldContract, err := s.Dao.Where("id = ?", req.ContractId).One()
+	if err != nil {
+		return 0, err
+	}
+	if oldContract == nil {
+		return 0, myerrors.TipsError("合同不存在")
+	}
+
+	var sequence int
+	if req.ContractType == "XS" { // 销售合同
+		sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_xs")
+		if err != nil {
+			return 0, err
+		}
+	} else if req.ContractType == "JS" { // 技术合同
+		sequence, err = service.SequenceYearRest(s.Dao.DB, "contract_code_js")
+		if err != nil {
+			return 0, err
+		}
+	} else {
+		return 0, myerrors.TipsError("不支持的合同类型")
+	}
+
+	if req.ContractCode == "" {
+		req.ContractCode = fmt.Sprintf("DH%s%s-%03d", req.ContractType, time.Now().Format("0601"), sequence)
+	}
+	c, err := s.Dao.Where("contract_code = ?", req.ContractCode).One()
+	if err != nil {
+		return 0, err
+	}
+	if c != nil {
+		return 0, myerrors.TipsError(fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
+	}
+
+	var contractAmount float64
+	for _, p := range req.Product {
+		contractAmount += (p.TranPrice * float64(p.ProdNum))
+	}
+	softSub := req.SoftwareMaintenanceEndTime.Sub(req.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
+	req.SoftwareMaintenanceLimit = int(softSub)
+	hardSub := req.HardwareMaintenanceEndTime.Sub(req.HardwareMaintenanceBeginTime).Hours() / 24 / 365
+	req.HardwareMaintenanceLimit = int(hardSub)
+	ctr := model.CtrContract{
+		ContractCode:                 req.ContractCode,
+		ContractName:                 req.ContractName,
+		CustId:                       nbo.CustId,
+		CustName:                     nbo.CustName,
+		ContractId:                   req.ContractId,
+		NboId:                        nbo.Id,
+		NboName:                      nbo.NboName,
+		IsBig:                        nbo.IsBig,
+		ProductLine:                  nbo.ProductLine,
+		CustProvinceId:               nbo.CustProvinceId,
+		CustProvince:                 nbo.CustProvince,
+		CustCityId:                   nbo.CustCityId,
+		CustCity:                     nbo.CustCity,
+		ApproStatus:                  "10",
+		ContractType:                 req.ContractType,
+		ContractAmount:               contractAmount,
+		InvoiceAmount:                0,
+		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,
+		DistributorName:              req.DistributorName,
+		Remark:                       req.Remark,
+		ServiceFeeAgreement:          req.ServiceFeeAgreement,
+		SoftwareMaintenanceBeginTime: req.SoftwareMaintenanceBeginTime,
+		SoftwareMaintenanceEndTime:   req.SoftwareMaintenanceEndTime,
+		HardwareMaintenanceBeginTime: req.HardwareMaintenanceBeginTime,
+		HardwareMaintenanceEndTime:   req.HardwareMaintenanceEndTime,
+		SoftwareMaintenanceLimit:     req.SoftwareMaintenanceLimit,
+		HardwareMaintenanceLimit:     req.HardwareMaintenanceLimit,
+		MaintenanceClause:            req.MaintenanceClause,
+		CreatedBy:                    s.userInfo.Id,
+		CreatedName:                  s.userInfo.NickName,
+		CreatedTime:                  gtime.Now(),
+		UpdatedBy:                    s.userInfo.Id,
+		UpdatedName:                  s.userInfo.NickName,
+		UpdatedTime:                  gtime.Now(),
+	}
+
+	var id int
+	txerr := s.Dao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
+		ctrid, err := tx.InsertAndGetId("ctr_contract", ctr)
+		if err != nil {
+			return err
+		}
+		err = s.BindProduct(tx, int(ctrid), ctr.ContractCode, req.Product)
+		if err != nil {
+			return err
+		}
+		//ContractApplyApproval
+		err = s.AddDynamicsByCurrentUser(tx, int(ctrid), "创建合同", map[string]interface{}{})
+		if err != nil {
+			return err
+		}
+		_, err = tx.Update("proj_business", map[string]interface{}{
+			"nbo_type": projsrv.StatusDeal,
+		}, "id = ?", nbo.Id)
+		if err != nil {
+			return err
+		}
+
+		err = s.AddDynamicsByCurrentUser(tx, int(req.ContractId), "创建续签合同", map[string]interface{}{
+			"contractName": req.ContractName,
+		})
+		if err != nil {
+			return err
+		}
+
+		id = int(ctrid)
+		return nil
+	})
+	return id, txerr
+}
+func (s CtrContractService) UpdateReNew(ctx context.Context, req *model.CtrContractUpdateReNewReq) error {
+	validErr := gvalid.CheckStruct(ctx, req, nil)
+	if validErr != nil {
+		return myerrors.TipsError(validErr.Current().Error())
+	}
+
+	ent, err := s.Dao.Where("id = ?", req.Id).One()
+	if err != nil {
+		return err
+	}
+	if ent == nil {
+		return myerrors.TipsError(fmt.Sprintf("合同不存在: %d", req.Id))
+	}
+
+	//if req.ContractName != "" {
+	//	exist, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
+	//	if err != nil {
+	//		return err
+	//	}
+	//	if exist != nil && exist.Id != req.Id {
+	//		return myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
+	//	}
+	//}
+
+	var nbo *proj.ProjBusiness
+	if req.NboId != 0 {
+		nbo, err = s.ProjBusinessDao.Where("id = ?", req.NboId).One()
+		if err != nil {
+			return err
+		}
+		if nbo == nil {
+			return myerrors.TipsError("项目不存在")
+		}
+	}
+
+	toupdate := map[string]interface{}{}
+
+	if req.ContractName != "" {
+		toupdate["contract_name"] = req.ContractName
+	}
+	if req.NboId != 0 {
+		toupdate["cust_id"] = nbo.CustId
+		toupdate["cust_name"] = nbo.CustName
+		toupdate["nbo_id"] = nbo.Id
+		toupdate["nbo_name"] = nbo.NboName
+		toupdate["is_big"] = nbo.IsBig
+		toupdate["product_line"] = nbo.ProductLine
+		toupdate["cust_province_id"] = nbo.CustProvinceId
+		toupdate["cust_province"] = nbo.CustProvince
+		toupdate["cust_city_id"] = nbo.CustCityId
+		toupdate["cust_city"] = nbo.CustCity
+	}
+
+	if req.ContractType != "" {
+		toupdate["contract_type"] = req.ContractType
+	}
+
+	if req.ContractStartTime != nil {
+		toupdate["contract_start_time"] = req.ContractStartTime
+	}
+	if req.ContractEndTime != nil {
+		toupdate["contract_end_time"] = req.ContractEndTime
+	}
+	if req.ContractSignTime != nil {
+		toupdate["contract_sign_time"] = req.ContractSignTime
+	}
+
+	if req.SignatoryId != 0 {
+		toupdate["signatory_id"] = req.SignatoryId
+	}
+	if req.SignatoryName != "" {
+		toupdate["signatory_name"] = req.SignatoryName
+	}
+	if req.SignatoryType != "" {
+		toupdate["signatory_type"] = req.SignatoryType
+	}
+	if req.SignatoryUnit != "" {
+		toupdate["signatory_unit"] = req.SignatoryUnit
+	}
+	if req.EarnestMoney != 0 {
+		toupdate["earnest_money"] = req.EarnestMoney
+	}
+	if req.CustSignatoryId != 0 {
+		toupdate["cust_signatory_id"] = req.CustSignatoryId
+	}
+	if req.CustSignatoryName != "" {
+		toupdate["cust_signatory_name"] = req.CustSignatoryName
+	}
+	if req.DistributorId != 0 {
+		toupdate["distributor_id"] = req.DistributorId
+	}
+	if req.DistributorName != "" {
+		toupdate["distributor_name"] = req.DistributorName
+	}
+	if req.SoftwareMaintenanceBeginTime != nil {
+		toupdate["software_maintenance_begin_time"] = req.SoftwareMaintenanceBeginTime
+	}
+	if req.SoftwareMaintenanceEndTime != nil {
+		toupdate["software_maintenance_end_time"] = req.SoftwareMaintenanceEndTime
+	}
+	if req.HardwareMaintenanceBeginTime != nil {
+		toupdate["hardware_maintenance_begin_time"] = req.HardwareMaintenanceBeginTime
+	}
+	if req.HardwareMaintenanceEndTime != nil {
+		toupdate["hardware_maintenance_end_time"] = req.HardwareMaintenanceEndTime
+	}
+	softSub := req.SoftwareMaintenanceEndTime.Sub(req.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
+	req.SoftwareMaintenanceLimit = int(softSub)
+	hardSub := req.HardwareMaintenanceEndTime.Sub(req.HardwareMaintenanceBeginTime).Hours() / 24 / 365
+	req.HardwareMaintenanceLimit = int(hardSub)
+	if req.SoftwareMaintenanceLimit != 0 {
+		toupdate["software_maintenance_limit"] = req.SoftwareMaintenanceLimit
+	}
+	if req.HardwareMaintenanceLimit != 0 {
+		toupdate["hardware_maintenance_limit"] = req.HardwareMaintenanceLimit
+	}
+	if req.Remark != "" {
+		toupdate["remark"] = req.Remark
+	}
+	if req.Product != nil {
+		var contractAmount float64
+		for _, p := range req.Product {
+			contractAmount += (p.TranPrice * float64(p.ProdNum))
+		}
+		toupdate["contract_amount"] = contractAmount
+	}
+	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", toupdate, "id = ?", req.Id)
+			if err != nil {
+				return err
+			}
+			if req.Product != nil {
+				err = s.BindProduct(tx, req.Id, ent.ContractCode, req.Product)
+				if err != nil {
+					return err
+				}
+			}
+			return nil
+		})
+		if txerr != nil {
+			return txerr
+		}
+	}
+	return nil
+}
 
 var ContractApplyProcessCode = "PROC-7057E20A-2066-4644-9B35-9331E4DA912C" // 创建合同
 
@@ -950,6 +1271,9 @@ func ContractApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow
 		return fmt.Errorf("合同不存在:%s Id: %d", flow.BizCode, flow.Id)
 	}
 
+	if err != nil {
+		return err
+	}
 	if msg.ProcessType != "finish" && msg.ProcessType != "terminate" {
 		return fmt.Errorf("无法识别的 ProcessType :%s", msg.ProcessType)
 	}
@@ -978,9 +1302,52 @@ func ContractApplyApproval(ctx context.Context, flow *workflowModel.PlatWorkflow
 	if status != "30" {
 		return nil
 	}
+	s, err := NewCtrContractService(ctx)
+	if err != nil {
+		return err
+	}
 
 	return contractDao.DB.Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
 		// 交付状态(0发起 10项目立项 15进行中 20 完成 30审批拒绝40关闭)
+		if contract.ContractId != 0 {
+			oldContract, err := contractDao.TX(tx).Where("id = ?", contract.ContractId).One()
+			if err != nil {
+				return err
+			}
+
+			softSub := contract.SoftwareMaintenanceEndTime.Sub(oldContract.SoftwareMaintenanceBeginTime).Hours() / 24 / 365
+			SoftwareMaintenanceLimit := int(softSub)
+			hardSub := contract.HardwareMaintenanceEndTime.Sub(oldContract.HardwareMaintenanceBeginTime).Hours() / 24 / 365
+			HardwareMaintenanceLimit := int(hardSub)
+			err = s.AddDynamicsByCurrentUser(tx, int(contract.ContractId), "续签合同审批通过", map[string]interface{}{
+				"contractId":                      contract.ContractId,
+				"contractName":                    contract.ContractName,
+				"contractCode":                    contract.ContractCode,
+				"oldSoftwareMaintenanceBeginTime": oldContract.SoftwareMaintenanceBeginTime,
+				"oldSoftwareMaintenanceEndTime":   oldContract.SoftwareMaintenanceEndTime,
+				"oldHardwareMaintenanceBeginTime": oldContract.HardwareMaintenanceBeginTime,
+				"oldHardwareMaintenanceEndTime":   oldContract.HardwareMaintenanceEndTime,
+				"newSoftwareMaintenanceBeginTime": contract.SoftwareMaintenanceBeginTime,
+				"newSoftwareMaintenanceEndTime":   contract.SoftwareMaintenanceEndTime,
+				"newHardwareMaintenanceBeginTime": contract.HardwareMaintenanceBeginTime,
+				"newHardwareMaintenanceEndTime":   contract.HardwareMaintenanceEndTime,
+			})
+			if err != nil {
+				return err
+			}
+
+			_, err = s.Dao.TX(tx).Where("id = ?", contract.ContractId).Data(map[string]interface{}{
+				"software_maintenance_end_time": contract.SoftwareMaintenanceEndTime,
+				"hardware_maintenance_end_time": contract.HardwareMaintenanceEndTime,
+				"software_maintenance_limit":    SoftwareMaintenanceLimit,
+				"hardware_maintenance_limit":    HardwareMaintenanceLimit,
+			}).Update()
+
+			if err != nil {
+				return err
+			}
+		}
+
 		_, err = worksrv.DeliverOrderAdd(tx, contractId, request.UserInfo{}, nil, "10")
 		return err
 	})
@@ -1009,15 +1376,15 @@ func (s CtrContractService) Update(ctx context.Context, req *model.CtrContractUp
 	// 		return myerrors.NewMsgError(nil, fmt.Sprintf("合同编号:%s 已存在", req.ContractCode))
 	// 	}
 	// }
-	if req.ContractName != "" {
-		exist, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
-		if err != nil {
-			return err
-		}
-		if exist != nil && exist.Id != req.Id {
-			return myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
-		}
-	}
+	//if req.ContractName != "" {
+	//	exist, err := s.Dao.Where("contract_name = ?", req.ContractName).One()
+	//	if err != nil {
+	//		return err
+	//	}
+	//	if exist != nil && exist.Id != req.Id {
+	//		return myerrors.TipsError(fmt.Sprintf("合同名称:%s 已存在", req.ContractName))
+	//	}
+	//}
 
 	var nbo *proj.ProjBusiness
 	if req.NboId != 0 {