caipin 4 年之前
父節點
當前提交
8128f94c57

+ 14 - 16
bootstrap/bootstrap.go

@@ -7,7 +7,6 @@
 package bootstrap
 
 import (
-	"log"
 	"time"
 
 	"github.com/iris-contrib/middleware/csrf"
@@ -15,7 +14,6 @@ import (
 	"github.com/kataras/iris/v12/middleware/logger"
 	"github.com/kataras/iris/v12/middleware/recover"
 	"go.mod/conf"
-	"google.golang.org/grpc"
 )
 
 //配置器,定制化的配置--方法类型
@@ -32,16 +30,15 @@ type Bootstrapper struct {
 	AppSpawnDate time.Time
 }
 
-var RpcConnect *grpc.ClientConn
-
+//var RpcConnect *grpc.ClientConn
 func init() {
-	log.Println("RpcConnect 初始化中...")
-	conn, err := grpc.Dial(conf.NodeRpcHost, grpc.WithInsecure())
-	if err != nil {
-		log.Fatalf("did not connect: %v", err)
-	}
-	RpcConnect = conn
-	log.Println("RpcConnect 初始化成功")
+	// log.Println("RpcConnect 初始化中...")
+	// conn, err := grpc.Dial(conf.NodeRpcHost, grpc.WithInsecure())
+	// if err != nil {
+	// 	log.Fatalf("did not connect: %v", err)
+	// }
+	// RpcConnect = conn
+	// log.Println("RpcConnect 初始化成功")
 }
 
 //新建和返回一个Bootstrapper
@@ -120,10 +117,11 @@ func (b *Bootstrapper) SetupCsrfHandlers(csrfKey string) {
 
 // 装配rpcClient
 func (b *Bootstrapper) SetupRpcClient() {
-	b.Use(func(ctx iris.Context) {
-		ctx.Values().Set("RpcConnect", RpcConnect)
-		ctx.Next()
-	})
+	// b.Use(func(ctx iris.Context) {
+	// 	ctx.Values().Set("RpcConnect", RpcConnect)
+	// 	ctx.Next()
+	// })
+	// log.Println("RpcConnect 注入成功")
 }
 
 //处理异常--设置错误信息展示
@@ -184,7 +182,7 @@ func (b *Bootstrapper) Bootstrap() *Bootstrapper {
 	// 设置jwt
 	//b.SetupJwtHandlers(JwtKey)
 	// 设置rpc
-	b.SetupRpcClient()
+	//b.SetupRpcClient()
 	//设置异常信息
 	b.SetupErrorHandlers()
 

+ 8 - 8
conf/project.go

@@ -29,17 +29,17 @@ var RunningCrontabService = false
 
 // 审批常量
 type auditStatus struct {
-	uncheck int
+	uncheck  int
 	checking int
-	checked int
-	checkNo int
+	checked  int
+	checkNo  int
 }
 
-func NewAuditConsts() AuditStatus {
-	return &auditStatus {
-		uncheck: 0, // 待审批
+func NewAuditConsts() *auditStatus {
+	return &auditStatus{
+		uncheck:  0, // 待审批
 		checking: 1, // 审批中
-		checked: 2, // 审批完成
-		checkNo: 3,// 退回
+		checked:  2, // 审批完成
+		checkNo:  3, // 退回
 	}
 }

+ 164 - 10
dao/contract_dao.go

@@ -43,7 +43,7 @@ func (d *ContractDao) Get(id int) *models.CmContracts {
 // contractData *models.CmContracts
 // contractTotal 合同总数
 // priceTotal 收入总金额
-func (d *ContractDao) Add(contractData *models.CmContracts, contractTotal int, priceTotal float64) error {
+func (d *ContractDao) Add(contractData *models.CmContracts) error {
 	session := d.engine.NewSession()
 	defer session.Close()
 	err := session.Begin()
@@ -67,22 +67,176 @@ func (d *ContractDao) Add(contractData *models.CmContracts, contractTotal int, p
 		return errors.New("新增合同出错-项目节更新失败")
 	}
 
-	// 3.更新标段目录金额合计
-	// 3-1 获得项目-标段下合同总数
-	// 3-2 获得项目标段下合同收入中金额
-	_, err = session.Exec("UPDATE  cm_tree SET `contracts` = ?,`contracts_income` = ? "+
-		"where project_id = ? and bidsection_id = ? ",
-		contractTotal, priceTotal,
-		contractData.ProjectId, contractData.BidsectionId)
+	err = session.Commit()
 	if err != nil {
 		session.Rollback()
-		return errors.New("新增合同出错-标段目录更新失败")
+		return errors.New("新增合同出错-db")
+	}
+	return nil
+}
+
+// 更新合同
+func (d *ContractDao) Update(contractsCm *models.CmContracts, columns []string, projectId int, bidsectionId int, treeId int) error {
+	session := d.engine.NewSession()
+	defer session.Close()
+	err := session.Begin()
+	if err != nil {
+		return errors.New("session出错-db")
+	}
+
+	// 1.更新合同表
+	successNum, err := session.Id(contractsCm.Id).MustCols(columns...).Update(contractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("更新失败")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("合同数据异常,更新失败")
+	}
+
+	// 2.更新项目节表
+	_, err = session.Exec("UPDATE  cm_tree_contracts SET `contract_name` = ?,`contract_price` = ? "+
+		"where tree_id = ? and project_id = ? and bidsection_id = ? ",
+		contractsCm.Name, contractsCm.Price,
+		treeId, projectId, bidsectionId)
+	if err != nil {
+		session.Rollback()
+		return errors.New("编辑合同出错-项目节更新失败")
 	}
 
 	err = session.Commit()
 	if err != nil {
 		session.Rollback()
-		return errors.New("新增合同出错-db")
+		return errors.New("session出错-db")
+	}
+	return nil
+}
+
+// 删除合同
+func (d *ContractDao) Delete(projectId int, bidsectionId int, treeId int, id int) error {
+
+	contractsCm := models.CmContracts{}
+
+	session := d.engine.NewSession()
+	defer session.Close()
+	err := session.Begin()
+	if err != nil {
+		return errors.New("session出错-db")
+	}
+	// 1.删除合同
+	successNum, err := session.Where("id = ? and tree_id=? and bidsection_id= ? and project_id=? ", id, treeId, bidsectionId, projectId).Delete(contractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("删除失败")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("合同数据异常,删除失败")
+	}
+
+	// 2.删除项目节上合同信息
+	_, err = session.Exec("UPDATE  cm_tree_contracts SET `contract_name` = '',`contract_code` = '',`contract_price` = 0,`contract_id` = 0,`contract_returned` = 0,`contracts_paid` = 0,`contract_status` = 0 "+
+		"where tree_id = ? and project_id = ? and bidsection_id = ? ",
+		treeId, projectId, bidsectionId)
+	if err != nil {
+		session.Rollback()
+		return errors.New("编辑合同出错-项目节更新失败")
+	}
+
+	err = session.Commit()
+	if err != nil {
+		session.Rollback()
+		return errors.New("session出错-db")
+	}
+	return nil
+}
+
+// 删除合同
+func (d *ContractDao) Close(projectId int, bidsectionId int, treeId int, id int) error {
+
+	session := d.engine.NewSession()
+	defer session.Close()
+	err := session.Begin()
+	if err != nil {
+		return errors.New("session出错-db")
+	}
+
+	// 1.关闭合同-关闭合同,默认锁定合同
+	contractsCm := models.CmContracts{}
+	contractsCm.Status = 2
+	contractsCm.Locking = 1
+	successNum, err := session.Where("id = ? and project_id = ? and bidsection_id = ? ", id, projectId, bidsectionId).Update(contractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("关闭合同出错")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("关闭合同异常")
+	}
+
+	// 2.更新项目节合同状态,锁定合同
+	treeContractsCm := models.CmTreeContracts{}
+	treeContractsCm.ContractStatus = 2
+	treeContractsCm.ContractLocking = 1
+	successNum, err = session.Where("tree_id = ? and project_id = ? and bidsection_id = ? ", treeId, projectId, bidsectionId).Update(treeContractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("关闭合同出错-项目节")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("关闭合同异常-项目节")
+	}
+
+	err = session.Commit()
+	if err != nil {
+		session.Rollback()
+		return errors.New("session出错-db")
+	}
+	return nil
+}
+
+// 删除合同
+func (d *ContractDao) Unlock(projectId int, bidsectionId int, treeId int, id int) error {
+	session := d.engine.NewSession()
+	defer session.Close()
+	err := session.Begin()
+	if err != nil {
+		return errors.New("session出错-db")
+	}
+
+	// 1.解锁合同
+	contractsCm := models.CmContracts{}
+	contractsCm.Locking = 0
+	successNum, err := session.Where("id = ? and project_id = ? and bidsection_id = ? ", id, projectId, bidsectionId).Cols("locking").Update(contractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("解锁合同出错")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("解锁合同异常")
+	}
+
+	// 2.更新项目节上合同锁状态
+	treeContractsCm := models.CmTreeContracts{}
+	treeContractsCm.ContractLocking = 0
+	successNum, err = session.Where("tree_id = ? and project_id = ? and bidsection_id = ? ", treeId, projectId, bidsectionId).Cols("contract_locking").Update(treeContractsCm)
+	if err != nil {
+		session.Rollback()
+		return errors.New("解锁合同出错-项目节")
+	}
+	if successNum == 0 {
+		session.Rollback()
+		return errors.New("解锁合同异常-项目节")
+	}
+
+	err = session.Commit()
+	if err != nil {
+		session.Rollback()
+		return errors.New("session出错-db")
 	}
 	return nil
 }

+ 14 - 0
dao/tree_dao.go

@@ -348,6 +348,20 @@ func (d *TreeDao) Update(data *models.CmTree, columns []string) error {
 	return err
 }
 
+// 更新标段目录上合同金额和总数
+func (d *TreeDao) UpdateContractsAndIncomePrice(projectId int, bidsectionId int, contractTotal int, priceTotal float64) error {
+	_, err := d.engine.Exec("UPDATE  cm_tree SET `contracts` = ?,`contracts_income` = ? "+
+		"where project_id = ? and bidsection_id = ? ",
+		contractTotal, priceTotal,
+		projectId, bidsectionId)
+	if err != nil {
+		return errors.New("编辑标段目录-金额合计出错")
+	}
+	// _, err :=d.engine.Where("project_id = ? and bidsection_id = ?",projectId,bidsectionId).MustCols().Update(treeCm)
+	// _, err := d.engine.Id(data.Id).MustCols(columns...).Update(data)
+	return nil
+}
+
 //替换项目节归属
 func (d *TreeDao) replaceContractAttribution(session *xorm.Session, attributionChildren string, moveAttributionChildren string, projectId int) error {
 	// 1.获得需要替换的数据

+ 6 - 5
models/cm_contracts.go

@@ -7,9 +7,9 @@ import (
 type CmContracts struct {
 	Id            int       `xorm:"not null pk autoincr comment('自增ID') INT(11)"`
 	TreeId        int       `xorm:"not null default 0 comment('树ID') INT(11)"`
-	ContractsType int       `xorm:"not null comment('合同类型(1收入合同2支出合同)') TINYINT(1)"`
+	ContractsType int       `xorm:"not null default 1 comment('合同类型(1收入合同2支出合同)') TINYINT(1)"`
 	ProjectId     int       `xorm:"not null default 0 comment('项目ID') INT(11)"`
-	BidsectionId  int       `xorm:"comment('标段ID') INT(11)"`
+	BidsectionId  int       `xorm:"default 0 comment('标段ID') INT(11)"`
 	Name          string    `xorm:"not null comment('合同名称') VARCHAR(64)"`
 	Content       string    `xorm:"comment('合同内容') VARCHAR(1024)"`
 	Code          string    `xorm:"comment('合同编号') VARCHAR(32)"`
@@ -19,10 +19,11 @@ type CmContracts struct {
 	PartyBSigner  string    `xorm:"comment('乙方签约人') VARCHAR(32)"`
 	SignerTime    time.Time `xorm:"comment('签约日期') DATETIME"`
 	Remarks       string    `xorm:"comment('备注') VARCHAR(1024)"`
-	Price         string    `xorm:"not null comment('合同金额 0') DECIMAL(12,2)"`
-	Returned      string    `xorm:"not null comment('回款总金额 0') DECIMAL(12,2)"`
+	Price         string    `xorm:"not null default 0.00 comment('合同金额') DECIMAL(12,2)"`
+	Returned      string    `xorm:"not null default 0.00 comment('回款总金额') DECIMAL(12,2)"`
 	Paid          string    `xorm:"not null default 0.00 comment('合同已支付金额 0') DECIMAL(12,2)"`
-	Status        int       `xorm:"not null comment('合同状态(0履行中1待关闭2已关闭)') TINYINT(1)"`
+	Status        int       `xorm:"not null default 0 comment('合同状态(0履行中1待关闭2已关闭)') TINYINT(1)"`
+	Locking       int       `xorm:"not null default 0 comment('锁定(0未锁定1锁定)') TINYINT(1)"`
 	CreateTime    time.Time `xorm:"comment('创建时间') DATETIME"`
 	UpdateTime    time.Time `xorm:"not null default 'CURRENT_TIMESTAMP' comment('更新时间') TIMESTAMP"`
 }

+ 1 - 0
models/cm_tree_contracts.go

@@ -23,5 +23,6 @@ type CmTreeContracts struct {
 	ContractReturned string    `xorm:"not null default 0.00 comment('回款金额') DECIMAL(12,2)"`
 	ContractsPaid    string    `xorm:"not null default 0.00 comment('合同已支付金额') DECIMAL(12,2)"`
 	ContractStatus   int       `xorm:"not null default 0 comment('合同状态(0履行中1待关闭2正常关闭)') TINYINT(1)"`
+	ContractLocking  int       `xorm:"not null default 0 comment('合同锁定(0未锁定1锁定)') TINYINT(1)"`
 	CreateTime       time.Time `xorm:"comment('创建时间') DATETIME"`
 }

+ 236 - 23
services/contract_service.go

@@ -9,11 +9,14 @@ package services
 import (
 	"errors"
 	"fmt"
+	"html"
 	"log"
 	"strconv"
 	"time"
 
 	"github.com/kataras/iris/v12"
+	"go.mod/comm"
+	"go.mod/conf"
 	"go.mod/dao"
 	"go.mod/datasource"
 	"go.mod/models"
@@ -29,6 +32,8 @@ type ContractService interface {
 	ValidRuleGet(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
 	ValidRuleSerial(ctx iris.Context) (*viewmodels.TreeSectionContract, error)
 	ValidRuleContractAdd(ctx iris.Context) (*viewmodels.Contracts, error)
+	ValidRuleContractEdi(ctx iris.Context) (*viewmodels.Contracts, error)
+	ValidRuleContractDel(ctx iris.Context) (*viewmodels.Contracts, error)
 
 	Get(treeId int, bidsectionId int, projectId int) *viewmodels.TreeSectionContract
 	GetSectionTreeContract(attribution string, bidsectionId int, projectId int) []*viewmodels.Contracts
@@ -41,19 +46,19 @@ type ContractService interface {
 	MoveDepth(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int) error
 	MoveSerial(sectionData *viewmodels.TreeSectionContract, bidsectionId int, projectId int) error
 
-	GetContract(contractId int) *models.CmContracts
+	GetContract(contractId int) *viewmodels.Contracts
 	Add(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
+	Update(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error
+	Delete(projectId int, bidsectionId int, treeId int, id int) error
+	Close(projectId int, bidsectionId int, treeId int, id int) error
+	Unlock(projectId int, bidsectionId int, treeId int, id int) error
 }
 
 //返回service操作类
 type contractService struct {
 	treeContractDao *dao.TreeContractDao
 	contractDao     *dao.ContractDao
-	// dao *dao.ProjectAccountDao
-	// projectDao        *dao.ProjectDao
-	// bidsectionDao     *dao.BidsectionDao
-
-	// bidAccountDao     *dao.BidAccountDao
+	treeDao         *dao.TreeDao
 }
 
 //创建项目用户service
@@ -61,11 +66,7 @@ func NewContractService() ContractService {
 	return &contractService{
 		treeContractDao: dao.NewTreeContractDao(datasource.InstanceDbMaster()),
 		contractDao:     dao.NewContractDao(datasource.InstanceDbMaster()),
-		// projectAccountDao: dao.NewProjectAccountDao(datasource.InstanceDbMaster()),
-		// projectDao:        dao.NewProjectDao(datasource.InstanceDbMaster()),
-		// bidsectionDao:     dao.NewBidsectionDao(datasource.InstanceDbMaster()),
-
-		// bidAccountDao:     dao.NewBidAccountDao(datasource.InstanceDbMaster()),
+		treeDao:         dao.NewTreeDao(datasource.InstanceDbMaster()),
 	}
 }
 
@@ -190,6 +191,60 @@ func (s *contractService) ValidRuleContractAdd(ctx iris.Context) (*viewmodels.Co
 		log.Println("参数验证错误, error=", err)
 		return contractsVaild, err
 	}
+
+	// xss
+	contractsVaild.Code = html.EscapeString(contractsVaild.Code)
+	contractsVaild.Name = html.EscapeString(contractsVaild.Name)
+	contractsVaild.Price = html.EscapeString(contractsVaild.Price)
+
+	return contractsVaild, nil
+}
+
+// 校验编辑接口
+func (s *contractService) ValidRuleContractEdi(ctx iris.Context) (*viewmodels.Contracts, error) {
+	// 创建一个存放前端传过来参数
+	contractsVaild := &viewmodels.Contracts{}
+	// 存放raw的值,放入到contractsVaild
+	err := ctx.ReadJSON(contractsVaild)
+	if err != nil {
+		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
+		return contractsVaild, err
+	}
+	// 验证合同传参
+	err = contractsVaild.ValidateEdi()
+	if err != nil {
+		log.Println("参数验证错误, error=", err)
+		return contractsVaild, err
+	}
+
+	contractsVaild.Content = html.EscapeString(contractsVaild.Content)
+	contractsVaild.Name = html.EscapeString(contractsVaild.Name)
+	contractsVaild.Price = html.EscapeString(contractsVaild.Price)
+
+	contractsVaild.PartyA = html.EscapeString(contractsVaild.PartyA)
+	contractsVaild.PartyASigner = html.EscapeString(contractsVaild.PartyASigner)
+	contractsVaild.PartyB = html.EscapeString(contractsVaild.PartyB)
+	contractsVaild.PartyBSigner = html.EscapeString(contractsVaild.PartyBSigner)
+
+	return contractsVaild, nil
+}
+
+func (s *contractService) ValidRuleContractDel(ctx iris.Context) (*viewmodels.Contracts, error) {
+	// 创建一个存放前端传过来参数
+	contractsVaild := &viewmodels.Contracts{}
+	// 存放raw的值,放入到contractsVaild
+	err := ctx.ReadJSON(contractsVaild)
+	if err != nil {
+		log.Println("folder-ValidRule-ReadForm转换异常, error=", err)
+		return contractsVaild, err
+	}
+	// 验证合同传参
+	err = contractsVaild.ValidateDel()
+	if err != nil {
+		log.Println("参数验证错误, error=", err)
+		return contractsVaild, err
+	}
+
 	return contractsVaild, nil
 }
 
@@ -203,8 +258,37 @@ func (s *contractService) Get(treeId int, bidsectionId int, projectId int) *view
 }
 
 // 获得合同详情
-func (s *contractService) GetContract(contractId int) *models.CmContracts {
-	return s.contractDao.Get(contractId)
+func (s *contractService) GetContract(contractId int) *viewmodels.Contracts {
+	contract := s.contractDao.Get(contractId)
+	contractsVM := &viewmodels.Contracts{}
+
+	id, _ := comm.AesEncrypt(strconv.Itoa(contract.Id), conf.SignSecret)
+	treeId, _ := comm.AesEncrypt(strconv.Itoa(contract.TreeId), conf.SignSecret)
+	bidsectionId, _ := comm.AesEncrypt(strconv.Itoa(contract.BidsectionId), conf.SignSecret)
+
+	contractsVM.Id = id
+	contractsVM.TreeId = treeId
+	contractsVM.ContractsType = contract.ContractsType
+	contractsVM.BidsectionId = bidsectionId
+
+	contractsVM.Name = contract.Name
+	contractsVM.Content = contract.Content
+	contractsVM.Code = contract.Code
+	contractsVM.PartyA = contract.PartyA
+	contractsVM.PartyASigner = contract.PartyASigner
+	contractsVM.PartyB = contract.PartyB
+	contractsVM.PartyBSigner = contract.PartyBSigner
+	contractsVM.Remarks = contract.Remarks
+	contractsVM.Price = contract.Price
+	contractsVM.Returned = contract.Returned
+	contractsVM.Paid = contract.Paid
+	contractsVM.Status = contract.Status
+
+	contractsVM.CreateTime = contract.CreateTime.Format(conf.SysTimeform)
+	contractsVM.UpdateTime = contract.UpdateTime.Format(conf.SysTimeform)
+	contractsVM.SignerTime = contract.SignerTime.Format(conf.SysTimeform)
+
+	return contractsVM
 }
 
 // 新增合同
@@ -235,23 +319,152 @@ func (s *contractService) Add(contractData *viewmodels.Contracts, projectId int,
 	contractsCm.CreateTime = time.Now()
 	contractsCm.UpdateTime = time.Now()
 
-	// 获得该标段下合同总数 - 总收入金额
+	err := s.contractDao.Add(contractsCm)
+	if err != nil {
+		return err
+	}
+
+	// 3.获得该标段下合同总数 - 总收入金额
+	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId)
+	// 更新标段目录上合同金额和总数
+	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// 更新合同
+func (s *contractService) Update(contractData *viewmodels.Contracts, projectId int, bidsectionId int, treeId int) error {
+	// 1. 项目节存在
+	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId)
+	if contractsTree.Id == 0 {
+		return errors.New("未找到项目节")
+	}
+	// 2.项目节是没有合同
+	if contractsTree.ContractId == 0 {
+		return errors.New("该项目节上没有找到合同")
+	}
+
+	contractsCm := &models.CmContracts{}
+	contractsCm.Id = contractsTree.ContractId
+	contractsCm.Content = contractData.Content
+	contractsCm.Name = contractData.Name
+	contractsCm.Price = contractData.Price
+	contractsCm.PartyA = contractData.PartyA
+	contractsCm.PartyASigner = contractData.PartyASigner
+	contractsCm.PartyB = contractData.PartyB
+	contractsCm.PartyBSigner = contractData.PartyBSigner
+
+	loc, _ := time.LoadLocation("Local")
+	SignerTime, err := time.ParseInLocation(conf.SysTimeform, contractData.SignerTime, loc)
+	if err != nil {
+		return errors.New("签约时间填写异常")
+	}
+	contractsCm.SignerTime = SignerTime
+	contractsCm.Remarks = contractData.Remarks
+
+	columns := []string{"Content", "Name", "Price", "PartyA", "PartyASigner", "PartyB", "PartyBSigner"}
+	err = s.contractDao.Update(contractsCm, columns, projectId, bidsectionId, treeId)
+	if err != nil {
+		return err
+	}
+	// 3.获得该标段下合同总数 - 总收入金额
+	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId)
+	// 更新标段目录上合同金额和总数
+	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 删除合同
+func (s *contractService) Delete(projectId int, bidsectionId int, treeId int, id int) error {
+	// 1. 项目节存在
+	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId)
+	if contractsTree.Id == 0 {
+		return errors.New("未找到项目节")
+	}
+	// 2.项目节是没有合同
+	if contractsTree.ContractId == 0 {
+		return errors.New("该项目节上没有找到合同")
+	}
+
+	// 删除合同
+	err := s.contractDao.Delete(projectId, bidsectionId, treeId, id)
+	if err != nil {
+		return err
+	}
+	// 3.获得该标段下合同总数 - 总收入金额
+	contractTotal, priceTotal := s.getContractTotalAndPrice(bidsectionId, projectId)
+	// 更新标段目录上合同金额和总数
+	err = s.treeDao.UpdateContractsAndIncomePrice(projectId, bidsectionId, contractTotal, priceTotal)
+	if err != nil {
+		return err
+	}
+	return nil
+}
+
+// 关闭合同
+func (s *contractService) Close(projectId int, bidsectionId int, treeId int, id int) error {
+	// 1. 项目节存在
+	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId)
+	if contractsTree.Id == 0 {
+		return errors.New("未找到项目节")
+	}
+	// 2.项目节是没有合同
+	if contractsTree.ContractId == 0 {
+		return errors.New("该项目节上没有找到合同")
+	}
+
+	// 删除合同
+	err := s.contractDao.Close(projectId, bidsectionId, treeId, id)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// 解锁合同
+func (s *contractService) Unlock(projectId int, bidsectionId int, treeId int, id int) error {
+	// 1. 项目节存在
+	contractsTree := s.treeContractDao.Get(treeId, bidsectionId, projectId)
+	if contractsTree.Id == 0 {
+		return errors.New("未找到项目节")
+	}
+	// 2.项目节是没有合同
+	if contractsTree.ContractId == 0 {
+		return errors.New("该项目节上没有找到合同")
+	}
+
+	// 删除合同
+	err := s.contractDao.Unlock(projectId, bidsectionId, treeId, id)
+	if err != nil {
+		return err
+	}
+
+	return nil
+}
+
+// 获得合同总数量和总金额
+func (s *contractService) getContractTotalAndPrice(bidsectionId int, projectId int) (contractTotal int, priceTotal float64) {
 	contractList := s.treeContractDao.GetContract(bidsectionId, projectId)
-	priceTotal := 0.00
+	priceTotal = 0.00
 	for _, item := range contractList {
 		contractPrice, _ := strconv.ParseFloat(item.ContractPrice, 64)
 		priceTotal = priceTotal + contractPrice
 	}
 	// 合同总数
-	contractTotal := len(contractList) + 1
+	// contractTotal = len(contractList) + 1
+	contractTotal = len(contractList)
 	// 合同收入总金额
-	price, _ := strconv.ParseFloat(contractsCm.Price, 64)
-	priceTotal = priceTotal + price
+	// price, _ := strconv.ParseFloat(priceString, 64)
+	// priceTotal = priceTotal + price
 	// 保留2位小数
 	priceTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", priceTotal), 64)
-	err := s.contractDao.Add(contractsCm, contractTotal, priceTotal)
-	if err != nil {
-		return err
-	}
-	return nil
+
+	return contractTotal, priceTotal
 }

+ 169 - 7
web/api/contract_api.go

@@ -11,7 +11,6 @@ import (
 
 	"github.com/kataras/iris/v12"
 	"go.mod/lib"
-	"go.mod/models"
 	"go.mod/services"
 	"go.mod/web/utils"
 	"go.mod/web/viewmodels"
@@ -166,7 +165,7 @@ func (c *ContractApi) GetIncome() {
 	}
 	// 获得合同详情
 	contractId, _ := utils.GetDecryptId(section.ContractId)
-	contract := &models.CmContracts{}
+	contract := &viewmodels.Contracts{}
 	if contractId != 0 {
 		contract = c.ServiceContract.GetContract(contractId)
 	}
@@ -228,11 +227,74 @@ func (c *ContractApi) PostIncomeCreate() {
 	c.Ctx.JSON(iris.Map{"code": 0, "msg": "新增成功"})
 }
 
-// 编辑合同
+// @Summary 编辑合同
+// @Tags 合同管理
+// @Description 编辑合同
+// @Accept  json
+// @Produce  json
+// @Security ApiKeyAuth
+// @Param   treeId     path    string     true        "项目节ID"
+// @Param   bidsectionId     path    string     true        "标段ID"
+// @Param   content     path    string     true        "合同内容"
+// @Param   name     path    string     true        "合同名称"
+// @Param   price     path    string     true        "合同金额"
+// @Param   partyA     path    string     true        "甲方"
+// @Param   partyASigner     path    string     true        "甲方签约人"
+// @Param   partyB     path    string     true        "已方"
+// @Param   partyBSigner     path    string     true        "已方签约人"
+// @Param   signerTime     path    string     true        "签约时间"
+// @Param   remarks     path    string     true        "备注"
+// @Success 200 {object} viewmodels.TreeSectionContract "{code:0成功,-1参数类错误,msg:错误信息}"
+// @Router /api/contract/income/create [post]
 func (c *ContractApi) PostIncomeUpdate() {
+	// 验证参数
+	contractData, err := c.ServiceContract.ValidRuleContractEdi(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
 
-	// 获得模板号
-	contractData, err := c.ServiceContract.ValidRuleContractAdd(c.Ctx)
+	// 项目ID
+	projectIdInt, err := utils.GetProjectId(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 标段ID
+	bidsectionId, err := utils.GetDecryptId(contractData.BidsectionId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 项目节ID
+	treeId, err := utils.GetDecryptId(contractData.TreeId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	err = c.ServiceContract.Update(contractData, projectIdInt, bidsectionId, treeId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	c.Ctx.JSON(iris.Map{"code": 0, "msg": "编辑成功"})
+}
+
+// @Summary 删除合同
+// @Tags 合同管理
+// @Description 删除合同
+// @Accept  json
+// @Produce  json
+// @Security ApiKeyAuth
+// @Param   id     path    string     true        "合同ID"
+// @Param   treeId     path    string     true        "项目节ID"
+// @Param   bidsectionId     path    string     true        "标段ID"
+// @Success 200 {object} viewmodels.TreeSectionContract "{code:0成功,-1参数类错误,msg:错误信息}"
+// @Router /api/contract [delete]
+func (c *ContractApi) Delete() {
+	// 验证参数
+	contractData, err := c.ServiceContract.ValidRuleContractDel(c.Ctx)
 	if err != nil {
 		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
 		return
@@ -256,11 +318,111 @@ func (c *ContractApi) PostIncomeUpdate() {
 		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
 		return
 	}
+	// 合同ID
+	id, err := utils.GetDecryptId(contractData.Id)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
 
-	err = c.ServiceContract.Add(contractData, projectIdInt, bidsectionId, treeId)
+	err = c.ServiceContract.Delete(projectIdInt, bidsectionId, treeId, id)
 	if err != nil {
 		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
 		return
 	}
-	c.Ctx.JSON(iris.Map{"code": 0, "msg": "新增成功"})
+	c.Ctx.JSON(iris.Map{"code": 0, "msg": "删除成功"})
+}
+
+// @Summary 关闭合同
+// @Tags 合同管理
+// @Description 关闭合同
+// @Accept  json
+// @Produce  json
+// @Security ApiKeyAuth
+// @Param   id     path    string     true        "合同ID"
+// @Param   treeId     path    string     true        "项目节ID"
+// @Param   bidsectionId     path    string     true        "标段ID"
+// @Success 200 {object} viewmodels.TreeSectionContract "{code:0成功,-1参数类错误,msg:错误信息}"
+// @Router /api/contract/close [post]
+func (c *ContractApi) PostClose() {
+	// 验证参数
+	contractData, err := c.ServiceContract.ValidRuleContractDel(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	// 项目ID
+	projectIdInt, err := utils.GetProjectId(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 标段ID
+	bidsectionId, err := utils.GetDecryptId(contractData.BidsectionId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 项目节ID
+	treeId, err := utils.GetDecryptId(contractData.TreeId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 合同ID
+	id, err := utils.GetDecryptId(contractData.Id)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	err = c.ServiceContract.Close(projectIdInt, bidsectionId, treeId, id)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	c.Ctx.JSON(iris.Map{"code": 0, "msg": "关闭成功"})
+}
+
+// 解锁合同
+func (c *ContractApi) PostUnlock() {
+	// 验证参数
+	contractData, err := c.ServiceContract.ValidRuleContractDel(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	// 项目ID
+	projectIdInt, err := utils.GetProjectId(c.Ctx)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 标段ID
+	bidsectionId, err := utils.GetDecryptId(contractData.BidsectionId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 项目节ID
+	treeId, err := utils.GetDecryptId(contractData.TreeId)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	// 合同ID
+	id, err := utils.GetDecryptId(contractData.Id)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+
+	err = c.ServiceContract.Unlock(projectIdInt, bidsectionId, treeId, id)
+	if err != nil {
+		c.Ctx.JSON(iris.Map{"code": -1, "msg": fmt.Sprintf("%s", err)})
+		return
+	}
+	c.Ctx.JSON(iris.Map{"code": 0, "msg": "解锁成功"})
 }

+ 2 - 2
web/middleware/sessions.go

@@ -21,13 +21,13 @@ func SessionsAuth(ctx iris.Context) {
 	// 获得cookie
 	cookie, err := ctx.Request().Cookie("cm")
 	if err != nil {
-		ctx.JSON(iris.Map{"code": 1, "msg": ""})
+		ctx.JSON(iris.Map{"code": 1, "msg": "请重新登陆"})
 		return
 	}
 	// 格式化
 	params, err := url.ParseQuery(cookie.Value)
 	if err != nil {
-		ctx.JSON(iris.Map{"code": 1, "msg": ""})
+		ctx.JSON(iris.Map{"code": 1, "msg": "请重新登陆"})
 		return
 	}
 

+ 44 - 22
web/viewmodels/contract.go

@@ -7,33 +7,31 @@
 package viewmodels
 
 import (
-	"time"
-
 	validation "github.com/go-ozzo/ozzo-validation/v3"
 )
 
 type Contracts struct {
-	Id            string    `form:"id" json:"id" `
-	TreeId        string    `form:"treeId" json:"treeId" `
-	ContractsType int       `form:"contractsType" json:"contractsType" `
-	ProjectId     string    `form:"projectId" json:"projectId" `
-	BidsectionId  string    `form:"bidsectionId" json:"bidsectionId" `
-	Name          string    `form:"name" json:"name" `
-	Code          string    `form:"code" json:"code" `
-	Price         string    `form:"price" json:"price" `
-	Returned      string    `form:"returned" json:"returned" `
-	Paid          string    `form:"paid" json:"paid" `
-	Status        int       `form:"status" json:"status" `
-	CreateTime    time.Time `form:"createTime" json:"createTime" `
-	UpdateTime    time.Time `form:"updateTime" json:"updateTime" `
+	Id            string `form:"id" json:"id" `
+	TreeId        string `form:"treeId" json:"treeId" `
+	ContractsType int    `form:"contractsType" json:"contractsType" `
+	ProjectId     string `form:"projectId" json:"projectId" `
+	BidsectionId  string `form:"bidsectionId" json:"bidsectionId" `
+	Name          string `form:"name" json:"name" `
+	Code          string `form:"code" json:"code" `
+	Price         string `form:"price" json:"price" `
+	Returned      string `form:"returned" json:"returned" `
+	Paid          string `form:"paid" json:"paid" `
+	Status        int    `form:"status" json:"status" `
+	CreateTime    string `form:"createTime" json:"createTime" `
+	UpdateTime    string `form:"updateTime" json:"updateTime" `
 
-	Content      string    `xorm:"comment('合同内容') VARCHAR(1024)"`
-	PartyA       string    `xorm:"comment('甲方') VARCHAR(32)"`
-	PartyASigner string    `xorm:"comment('甲方签约人') VARCHAR(32)"`
-	PartyB       string    `xorm:"comment('乙方') VARCHAR(32)"`
-	PartyBSigner string    `xorm:"comment('乙方签约人') VARCHAR(32)"`
-	SignerTime   time.Time `xorm:"comment('签约日期') DATETIME"`
-	Remarks      string    `xorm:"comment('备注') VARCHAR(1024)"`
+	Content      string `form:"content" json:"content" `
+	PartyA       string `form:"partyA" json:"partyA" `
+	PartyASigner string `form:"partyASigner" json:"partyASigner" `
+	PartyB       string `form:"partyB" json:"partyB" `
+	PartyBSigner string `form:"partyBSigner" json:"partyBSigner" `
+	SignerTime   string `form:"signerTime" json:"signerTime" `
+	Remarks      string `form:"remarks" json:"remarks" `
 }
 
 // 验证方法
@@ -47,3 +45,27 @@ func (l Contracts) ValidateAdd() error {
 		validation.Field(&l.Price, validation.Required.Error("合同金额不能为空")),
 	)
 }
+
+func (l Contracts) ValidateEdi() error {
+	return validation.ValidateStruct(&l,
+		validation.Field(&l.TreeId, validation.Required.Error("项目节ID不能为空")),
+		validation.Field(&l.BidsectionId, validation.Required.Error("标段ID不能为空")),
+		validation.Field(&l.Name, validation.Required.Error("名称不能为空")),
+		validation.Field(&l.Content, validation.Required.Error("合同内容不能为空")),
+		validation.Field(&l.Price, validation.Required.Error("合同金额不能为空")),
+
+		validation.Field(&l.PartyA, validation.Required.Error("甲方名称不能为空")),
+		validation.Field(&l.PartyASigner, validation.Required.Error("甲方签约人不能为空")),
+		validation.Field(&l.PartyB, validation.Required.Error("乙方不能为空")),
+		validation.Field(&l.PartyBSigner, validation.Required.Error("乙方签约人不能为空")),
+		validation.Field(&l.SignerTime, validation.Required.Error("合同签约日期不能为空")),
+	)
+}
+
+func (l Contracts) ValidateDel() error {
+	return validation.ValidateStruct(&l,
+		validation.Field(&l.Id, validation.Required.Error("合同ID不能为空")),
+		validation.Field(&l.TreeId, validation.Required.Error("项目节ID不能为空")),
+		validation.Field(&l.BidsectionId, validation.Required.Error("标段ID不能为空")),
+	)
+}