ziwen 2 years ago
parent
commit
534982e79f
3 changed files with 375 additions and 105 deletions
  1. 353 0
      controller/contract/pre_payment.go
  2. 19 105
      models/fms/contract_pre_payment.go
  3. 3 0
      routers/contract.go

+ 353 - 0
controller/contract/pre_payment.go

@@ -1,6 +1,7 @@
 package contract
 
 import (
+	"encoding/json"
 	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/go-playground/validator/v10"
@@ -8,6 +9,12 @@ import (
 	"hongze/fms_api/global"
 	"hongze/fms_api/models/base"
 	"hongze/fms_api/models/fms"
+	"hongze/fms_api/models/system"
+	"hongze/fms_api/services/alarm_msg"
+	fmsService "hongze/fms_api/services/fms"
+	"hongze/fms_api/utils"
+	"strconv"
+	"time"
 )
 
 // // RegisterController 合同登记
@@ -72,3 +79,349 @@ func (rg *PrePaymentController) List(c *gin.Context) {
 	baseData.SetList(list)
 	resp.OkData("获取成功", baseData, c)
 }
+
+// Add
+// @Title 新增到款预登记
+// @Description 新增到款预登记
+// @Param	request  body  fms.PrepayAddReq  true  "type json string"
+// @Success 200 string "操作成功"
+// @router /contract/pre_pay/add [post]
+func (rg *PrePaymentController) Add(c *gin.Context) {
+	req := new(fms.PrepayAddReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	claims, _ := c.Get("adminInfo")
+	adminInfo := claims.(*system.SysAdmin)
+
+	// 日期校验
+	startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
+	if e != nil {
+		resp.FailMsg("合同开始日期格式有误", "合同开始日期格式有误, Err: "+e.Error(), c)
+		return
+	}
+	endDate, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
+	if e != nil {
+		resp.FailMsg("合同结束日期格式有误", "合同结束日期格式有误, Err: "+e.Error(), c)
+		return
+	}
+
+	// 货币及汇率
+	rateList, e := fmsService.GetTodayCurrencyRateList()
+	if e != nil {
+		resp.FailMsg("操作失败", "获取今日货币汇率失败, Err: "+e.Error(), c)
+		return
+	}
+	var rate float64
+	for i := range rateList {
+		if req.CurrencyUnit == rateList[i].Code {
+			rate = rateList[i].RMBRate
+			break
+		}
+	}
+	if rate <= 0 {
+		resp.FailMsg("操作失败", "货币汇率信息有误", c)
+		return
+	}
+
+	ob := new(fms.ContractPrePayment)
+	ob.CompanyName = req.CompanyName
+	ob.SellerId = req.SellerId
+	ob.SellerName = req.SellerName
+	ob.CurrencyUnit = req.CurrencyUnit
+	ob.StartDate = startDate
+	ob.EndDate = endDate
+	ob.AdminId = int(adminInfo.AdminId)
+	ob.AdminName = adminInfo.AdminName
+	ob.Amount = req.Amount * rate
+	ob.OriginAmount = req.Amount
+	ob.CurrencyUnit = req.CurrencyUnit
+	ob.Remark = req.Remark
+	ob.Set()
+
+
+	// 新增合同及套餐
+	if e = ob.Create(); e != nil {
+		resp.FailMsg("操作失败", "新增合同及套餐失败, Err: "+e.Error(), c)
+		return
+	}
+
+	resp.Ok("操作成功", c)
+}
+
+// Edit
+// @Title 编辑到款预登记
+// @Description 编辑到款预登记
+// @Param	request  body  fms.ContractRegisterEditReq  true  "type json string"
+// @Success 200 string "操作成功"
+// @router /contract/pre_pay/edit [post]
+func (rg *PrePaymentController) Edit(c *gin.Context) {
+	req := new(fms.ContractRegisterEditReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	claims, _ := c.Get("adminInfo")
+	adminInfo := claims.(*system.SysAdmin)
+
+	// 日期校验
+	startDate, e := time.ParseInLocation(utils.FormatDate, req.StartDate, time.Local)
+	if e != nil {
+		resp.FailMsg("合同开始日期格式有误", "合同开始日期格式有误, Err: "+e.Error(), c)
+		return
+	}
+	endDate, e := time.ParseInLocation(utils.FormatDate, req.EndDate, time.Local)
+	if e != nil {
+		resp.FailMsg("合同结束日期格式有误", "合同结束日期格式有误, Err: "+e.Error(), c)
+		return
+	}
+	signDate, _ := time.ParseInLocation(utils.FormatDate, "0000-00-00", time.Local)
+	if req.SignDate != "" {
+		signDateTime, e := time.ParseInLocation(utils.FormatDate, req.SignDate, time.Local)
+		if e != nil {
+			resp.FailMsg("合同签订日期格式有误", "合同签订日期格式有误, Err: "+e.Error(), c)
+			return
+		}
+		signDate = signDateTime
+	}
+
+	ob := new(fms.ContractRegister)
+	item, e := ob.Fetch(req.ContractRegisterId)
+	if e != nil {
+		if e == utils.ErrNoRow {
+			resp.Fail("登记记录不存在或已被删除", c)
+			return
+		}
+		resp.FailMsg("操作失败", "获取合同登记信息失败, Err:"+e.Error(), c)
+		return
+	}
+	// 是否存在相同合同编号的登记
+	existCond := `contract_code = ?`
+	existPars := make([]interface{}, 0)
+	existPars = append(existPars, req.ContractCode)
+	exist, e := ob.FetchByCondition(existCond, existPars)
+	if e != nil && e != utils.ErrNoRow {
+		resp.FailMsg("操作失败", "获取相同登记号失败, Err: "+e.Error(), c)
+		return
+	}
+	if exist != nil && exist.ContractRegisterId > 0 && exist.ContractRegisterId != item.ContractRegisterId {
+		resp.Fail("合同编号已存在", c)
+		return
+	}
+	originHasPayment := item.HasPayment
+
+	updateCols := []string{
+		"ContractCode", "RelateContractCode", "CrmContractId", "ContractSource", "CompanyName", "ActualCompanyName",
+		"SellerId", "SellerName", "ContractType", "ContractAmount", "StartDate", "EndDate", "SignDate", "AgreedPayTime",
+		"ContractStatus", "RegisterStatus", "Remark", "ServiceRemark", "HasPayment", "NewCompany", "ModifyTime",
+	}
+	nowTime := time.Now().Local()
+	item.ContractCode = req.ContractCode
+	item.RelateContractCode = req.RelateContractCode
+	item.CrmContractId = req.CrmContractId
+	item.ContractSource = req.ContractSource
+	item.CompanyName = req.CompanyName
+	item.ActualCompanyName = req.ActualCompanyName
+	item.SellerId = req.SellerId
+	item.SellerName = req.SellerName
+	item.ContractType = req.ContractType
+	item.ContractAmount = req.ContractAmount
+	item.StartDate = startDate
+	item.EndDate = endDate
+	item.SignDate = signDate
+	item.AgreedPayTime = req.AgreedPayTime
+	item.ContractStatus = req.ContractStatus
+	item.RegisterStatus = fms.ContractRegisterStatusIng
+	item.Remark = req.Remark
+	item.ServiceRemark = req.ServiceRemark
+	item.HasPayment = req.HasPayment
+	item.NewCompany = req.NewCompany
+	item.ModifyTime = nowTime
+
+	// 存在代付的直接完成登记, 且不允许进行开票/到款登记
+	if req.HasPayment == 1 {
+		item.RegisterStatus = fms.ContractRegisterStatusComplete
+		updateCols = append(updateCols, "RegisterStatus")
+	}
+
+	// 开票到款信息
+	invoiceOB := new(fms.ContractInvoice)
+	invoiceCond := `contract_register_id = ?`
+	invoicePars := make([]interface{}, 0)
+	invoicePars = append(invoicePars, req.ContractRegisterId)
+	invoiceList, e := invoiceOB.List(invoiceCond, invoicePars, "")
+	if e != nil {
+		resp.FailMsg("操作失败", "获取合同开票到款列表失败, Err: "+e.Error(), c)
+		return
+	}
+	invoiceUpdateCols := make([]string, 0)
+
+	// 开票到款操作类型: 0-无; 1-更新; 2-删除;
+	logRemark := req.Remark
+	invoiceHandleType := 0
+	if originHasPayment == 0 && req.HasPayment == 1 {
+		// 若从无代付修改为有代付, 则删除无代付期间新增的所有开票到款登记
+		invoiceHandleType = 2
+	} else {
+		// 修改了货币单位后,同步更新汇率及开票到款的换算金额
+		if req.CurrencyUnit != item.CurrencyUnit {
+			rateList, e := fmsService.GetTodayCurrencyRateList()
+			if e != nil {
+				resp.FailMsg("操作失败", "获取货币列表及汇率失败, Err: "+e.Error(), c)
+				return
+			}
+			var rate float64
+			for i := range rateList {
+				if rateList[i].Code == req.CurrencyUnit {
+					rate = rateList[i].RMBRate
+					break
+				}
+			}
+			if rate < 0 {
+				resp.FailMsg("操作失败", "货币汇率有误", c)
+				return
+			}
+			item.CurrencyUnit = req.CurrencyUnit
+			item.RMBRate = rate
+			updateCols = append(updateCols, "CurrencyUnit", "RMBRate")
+
+			// 调整开票到款换算后的金额, 保留两位小数
+			for i := range invoiceList {
+				invoiceList[i].CurrencyUnit = req.CurrencyUnit
+				a, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", invoiceList[i].OriginAmount/rate), 64)
+				invoiceList[i].Amount = a
+			}
+			invoiceUpdateCols = append(invoiceUpdateCols, "CurrencyUnit", "Amount")
+			invoiceHandleType = 1
+			logRemark = fmt.Sprintf("金额单位由%s修改为%s\n%s", item.CurrencyUnit, req.CurrencyUnit, logRemark)
+		}
+	}
+
+	// 套餐信息
+	serviceList, e := fmsService.HandleContractServiceAndDetail(req.ProductId, req.Services, true)
+	if e != nil {
+		resp.FailMsg("操作失败", "获取合同套餐详情失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 更新合同登记、套餐、开票到款
+	if e = fms.UpdateContractRegister(item, updateCols, serviceList, invoiceList, invoiceUpdateCols, invoiceHandleType); e != nil {
+		resp.FailMsg("操作失败", "更新合同及套餐失败, Err: "+e.Error(), c)
+		return
+	}
+
+	// 校验金额-是否修改状态
+	go fmsService.CheckContractRegisterAmount(item.ContractRegisterId)
+
+	// 操作日志
+	go func() {
+		opData := ""
+		opDataByte, e := json.Marshal(req)
+		if e != nil {
+			return
+		}
+		opData = string(opDataByte)
+
+		logItem := new(fms.ContractRegisterLog)
+		logItem.ContractRegisterId = item.ContractRegisterId
+		logItem.AdminId = int(adminInfo.AdminId)
+		logItem.AdminName = adminInfo.RealName
+		logItem.OpData = opData
+		logItem.OpType = fms.ContractRegisterOpTypeEdit
+		logItem.CreateTime = nowTime
+		logItem.Remark = logRemark
+		if e = logItem.Create(); e != nil {
+			return
+		}
+	}()
+	resp.Ok("操作成功", c)
+}
+
+// Del
+// @Title 删除到款预登记
+// @Description 删除到款预登记
+// @Param	request  body  fms.ContractRegisterDelReq  true  "type json string"
+// @Success 200 string "操作成功"
+// @router /contract/pre_pay/del [post]
+func (rg *PrePaymentController) Del(c *gin.Context) {
+	req := new(fms.ContractRegisterDelReq)
+	err := c.ShouldBind(&req)
+	if err != nil {
+		errs, ok := err.(validator.ValidationErrors)
+		if !ok {
+			resp.FailData("参数解析失败", "Err:"+err.Error(), c)
+			return
+		}
+		resp.FailData("参数解析失败", errs.Translate(global.Trans), c)
+		return
+	}
+	claims, _ := c.Get("adminInfo")
+	adminInfo := claims.(*system.SysAdmin)
+
+	ob := new(fms.ContractRegister)
+	item, e := ob.Fetch(req.ContractRegisterId)
+	if e != nil {
+		if e == utils.ErrNoRow {
+			resp.Fail("合同登记不存在或已被删除", c)
+			return
+		}
+		resp.FailMsg("获取合同登记失败", "Err:"+e.Error(), c)
+		return
+	}
+	nowTime := time.Now().Local()
+	item.IsDeleted = 1
+	item.ModifyTime = nowTime
+	updateCols := []string{"IsDeleted", "ModifyTime"}
+	if e = item.Update(updateCols); e != nil {
+		resp.FailMsg("操作失败", "更新合同登记失败, Err:"+e.Error(), c)
+		return
+	}
+
+	// 删除对应的开票到款登记
+	go func() {
+		if e = fms.DeleteContractInvoicesByRegisterId(item.ContractRegisterId); e != nil {
+			alarm_msg.SendAlarmMsg(fmt.Sprintf("删除合同登记%d后, 删除开票到款记录失败, ErrMsg: %s", item.ContractRegisterId, e.Error()), 3)
+			return
+		}
+		if e = fms.DeleteInvoicePaymentSummaryByRegisterId(item.ContractRegisterId); e != nil {
+			alarm_msg.SendAlarmMsg(fmt.Sprintf("删除合同登记%d后, 删除开票到款汇总数据失败, ErrMsg: %s", item.ContractRegisterId, e.Error()), 3)
+			return
+		}
+	}()
+
+	// 操作日志
+	go func() {
+		opData := ""
+		opDataByte, e := json.Marshal(req)
+		if e != nil {
+			return
+		}
+		opData = string(opDataByte)
+
+		logItem := new(fms.ContractRegisterLog)
+		logItem.ContractRegisterId = req.ContractRegisterId
+		logItem.AdminId = int(adminInfo.AdminId)
+		logItem.AdminName = adminInfo.RealName
+		logItem.OpData = opData
+		logItem.OpType = fms.ContractRegisterOpTypeDel
+		logItem.CreateTime = nowTime
+		if e = logItem.Create(); e != nil {
+			return
+		}
+	}()
+
+	resp.Ok("操作成功", c)
+}

+ 19 - 105
models/fms/contract_pre_payment.go

@@ -10,6 +10,7 @@ import (
 // ContractInvoice 合同开票表
 type ContractPrePayment struct {
 	PrePayId           int       `gorm:"primaryKey;column:pre_pay_id" json:"pre_pay_id" description:"预付款ID"`
+	CompanyName        string    `json:"company_name" description:"客户名称"`
 	ContractRegisterId int       `gorm:"column:contract_register_id" json:"contract_register_id" description:"登记ID"`
 	ContractCode       string    `gorm:"column:contract_code" json:"contract_code" description:"合同编号"`
 	Amount             float64   `gorm:"column:amount" json:"amount" description:"换算后的金额(人民币)"`
@@ -27,6 +28,7 @@ type ContractPrePayment struct {
 
 type ContractPrePaymentRespItem struct {
 	PrePayId           int     `gorm:"primaryKey;column:pre_pay_id" json:"pre_pay_id" description:"预付款ID"`
+	CompanyName        string  `json:"company_name" description:"客户名称"`
 	ContractRegisterId int     `gorm:"column:contract_register_id" json:"contract_register_id" description:"登记ID"`
 	ContractCode       string  `gorm:"column:contract_code" json:"contract_code" description:"合同编号"`
 	Amount             float64 `gorm:"column:amount" json:"amount" description:"换算后的金额(人民币)"`
@@ -47,111 +49,6 @@ func (c *ContractPrePayment) TableName() string {
 	return "contract_pre_payment"
 }
 
-//// ContractInvoiceItem 合同开票/到款
-//type ContractInvoiceItem struct {
-//	ContractInvoiceId  int     `gorm:"column:contract_invoice_id" json:"contract_invoice_id" description:"开票ID"`
-//	ContractRegisterId int     `gorm:"column:contract_register_id" json:"contract_register_id" description:"登记ID"`
-//	ContractCode       string  `gorm:"column:contract_code" json:"contract_code" description:"合同编号"`
-//	Amount             float64 `gorm:"column:amount" json:"amount" description:"换算金额"`
-//	OriginAmount       float64 `gorm:"column:origin_amount" json:"origin_amount" description:"开票/到款金额"`
-//	CurrencyUnit       string  `gorm:"column:currency_unit" json:"currency_unit" description:"货币国际代码"`
-//	UnitName           string  `json:"unit_name" description:"货币单位名称"`
-//	InvoiceType        int     `gorm:"column:invoice_type" json:"invoice_type" description:"类型: 1-开票登记; 2-到款登记"`
-//	InvoiceDate        string  `gorm:"column:invoice_time" json:"invoice_time" description:"开票日期/到款月"`
-//	SellerId           int     `gorm:"column:seller_id" json:"seller_id" description:"销售ID"`
-//	SellerName         string  `gorm:"column:seller_name" json:"seller_name" description:"销售名称"`
-//	PayType            int     `gorm:"column:pay_type" json:"pay_type" description:"付款方式:0-无;1-年付;2-半年付;3-季付;4-次付;5-异常"`
-//	Remark             string  `gorm:"column:remark" json:"remark" description:"备注信息"`
-//	CreateTime         string  `gorm:"column:create_time" json:"create_time" description:"创建时间"`
-//}
-//
-//func (c *ContractInvoice) Create() (err error) {
-//	err = global.DEFAULT_MYSQL.Create(c).Error
-//	return
-//}
-//
-//func (c *ContractInvoice) AddInBatches(list []*ContractInvoice) (err error) {
-//	err = global.DEFAULT_MYSQL.CreateInBatches(list, len(list)).Error
-//	return
-//}
-//
-//func (c *ContractInvoice) Update(updateCols []string) (err error) {
-//	err = global.DEFAULT_MYSQL.Model(c).Select(updateCols).Updates(c).Error
-//	return
-//}
-//
-//func (c *ContractInvoice) Fetch(id int) (item *ContractInvoice, err error) {
-//	err = global.DEFAULT_MYSQL.Model(c).Where("is_deleted = 0 AND contract_invoice_id = ?", id).First(&item).Error
-//	return
-//}
-//
-//func (c *ContractInvoice) Sum(field, condition string, pars []interface{}) (total float64, err error) {
-//	totalList := make([]float64, 0)
-//	err = global.DEFAULT_MYSQL.Model(c).
-//		Where("is_deleted = 0").
-//		Where(condition, pars...).
-//		Pluck(field, &totalList).Error
-//	for i := range totalList {
-//		total += totalList[i]
-//	}
-//	return
-//}
-//
-//func (c *ContractInvoice) List(condition string, pars []interface{}, orderRule string) (list []*ContractInvoice, err error) {
-//	list = make([]*ContractInvoice, 0)
-//	query := global.DEFAULT_MYSQL.Model(c).
-//		Where("is_deleted = 0").
-//		Where(condition, pars...)
-//	if orderRule != "" {
-//		query.Order(orderRule)
-//	} else {
-//		query.Order("contract_invoice_id ASC")
-//	}
-//	err = query.Find(&list).Error
-//	return
-//}
-//
-//func (c *ContractInvoice) PageList(page base.IPage, condition string, pars []interface{}) (count int64, results []*ContractInvoice, err error) {
-//	results = make([]*ContractInvoice, 0)
-//	query := global.DEFAULT_MYSQL.Model(c).
-//		Where("is_deleted = 0").
-//		Where(condition, pars...)
-//	query.Count(&count)
-//	if len(page.GetOrderItemsString()) > 0 {
-//		query = query.Order(page.GetOrderItemsString())
-//	}
-//	err = query.Limit(int(page.GetPageSize())).Offset(int(page.Offset())).Find(&results).Error
-//	return
-//}
-//
-//// DeleteAndCreateNewInvoice 删除并新增登记
-//func (c *ContractInvoice) DeleteAndCreateNewInvoice(contractRegisterId, invoiceType int, deleteInvoiceIds []int, invoices []*ContractInvoice) (err error) {
-//	tx := global.DEFAULT_MYSQL.Begin()
-//	defer func() {
-//		if err != nil {
-//			tx.Rollback()
-//		} else {
-//			tx.Commit()
-//		}
-//	}()
-//
-//	if len(deleteInvoiceIds) > 0 {
-//		err = tx.Model(c).
-//			Where("contract_register_id = ? AND invoice_type = ? AND contract_invoice_id IN (?)", contractRegisterId, invoiceType, deleteInvoiceIds).
-//			UpdateColumn("is_deleted", 1).Error
-//		if err != nil {
-//			return
-//		}
-//	}
-//	if len(invoices) > 0 {
-//		err = tx.CreateInBatches(invoices, len(invoices)).Error
-//		if err != nil {
-//			return
-//		}
-//	}
-//	return
-//}
-
 // ContractRegisterListReq 合同登记列表请求体
 type PrePayListReq struct {
 	Keyword   string `json:"keyword" form:"keyword" binding:"omitempty" description:"关键词"`
@@ -200,3 +97,20 @@ func formatPrePay2Item(item *ContractPrePayment) (formatItem *ContractPrePayment
 	formatItem.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, item.ModifyTime)
 	return
 }
+
+// PrepayAddReq 新增到款预登记请求体
+type PrepayAddReq struct {
+	CompanyName  string  `json:"company_name" binding:"required" description:"客户名称"`
+	SellerId     int     `json:"seller_id" binding:"required" description:"CRM系统-销售ID"`
+	SellerName   string  `json:"seller_name" binding:"required" description:"CRM系统-销售名称"`
+	Amount       float64 `json:"amount" binding:"required" description:"到款金额"`
+	CurrencyUnit string  `json:"currency_unit" binding:"required" description:"货币单位"`
+	StartDate    string  `json:"start_date" binding:"required" description:"约定开始日期"`
+	EndDate      string  `json:"end_date" binding:"required" description:"约定结束日期"`
+	Remark       string  `json:"remark" description:"备注信息"`
+}
+
+func (c *ContractPrePayment) Create() (err error) {
+	err = global.DEFAULT_MYSQL.Create(c).Error
+	return
+}

+ 3 - 0
routers/contract.go

@@ -38,4 +38,7 @@ func InitContract(rg *gin.RouterGroup) {
 	prepay := new(contract.PrePaymentController)
 	prepayGroup := rg.Group("pre_pay/").Use(middleware.Token())
 	prepayGroup.GET("list", prepay.List)
+	prepayGroup.POST("add", prepay.Add)
+	prepayGroup.POST("edit", prepay.Edit)
+	prepayGroup.POST("del", prepay.Del)
 }