ソースを参照

test 合同登记导出

hsun 2 年 前
コミット
08093bdd69

+ 281 - 1
controller/contract/register.go

@@ -1,16 +1,21 @@
 package contract
 
 import (
+	"bytes"
 	"encoding/json"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"github.com/go-playground/validator/v10"
+	"github.com/tealeg/xlsx"
 	"hongze/fms_api/controller/resp"
 	"hongze/fms_api/global"
 	"hongze/fms_api/models/base"
+	"hongze/fms_api/models/crm"
 	"hongze/fms_api/models/fms"
 	"hongze/fms_api/models/system"
 	fmsService "hongze/fms_api/services/fms"
 	"hongze/fms_api/utils"
+	"net/http"
 	"time"
 )
 
@@ -48,7 +53,7 @@ func (rg *RegisterController) List(c *gin.Context) {
 		pars = append(pars, kw, kw, kw)
 	}
 	if req.StartDate != "" && req.EndDate != "" {
-		cond += ` AND (start_time >= ? AND end_time <= ?)`
+		cond += ` AND (create_time BETWEEN ? AND ?)`
 		pars = append(pars, req.StartDate, req.EndDate)
 	}
 	if req.ContractType != 0 {
@@ -552,6 +557,9 @@ func (rg *RegisterController) UpdateStatus(c *gin.Context) {
 		return
 	}
 
+	// 校验金额-是否修改状态
+	go fmsService.CheckContractRegisterAmount(req.ContractRegisterId)
+
 	// 操作日志
 	go func() {
 		opData := ""
@@ -665,5 +673,277 @@ func (rg *RegisterController) Invoice(c *gin.Context) {
 
 // 导出
 func (rg *RegisterController) Export(c *gin.Context) {
+	// 获取小套餐品种
+	cpCond := `product_id = ? AND permission_name <> ?`
+	cpPars := make([]interface{}, 0)
+	cpPars = append(cpPars, crm.CompanyProductFicc, crm.ChartPermissionStrategyName)
+	cp := new(crm.ChartPermission)
+	permissionList, e := cp.List(cpCond, cpPars)
+	if e != nil {
+		resp.FailData("获取小套餐品种失败", "Err:"+e.Error(), c)
+		return
+	}
+	permissionLen := len(permissionList)
+
+	// 获取套餐服务
+	//serviceList, e := fms.GetContractServiceTemplateMapByProductId(crm.CompanyProductFicc)
+	//if e != nil {
+	//	resp.FailData("获取套餐服务失败", "Err:"+e.Error(), c)
+	//	return
+	//}
+
+	// 获取列表数据
+	cond := ``
+	pars := make([]interface{}, 0)
+	cr := new(fms.ContractRegister)
+	list, e := cr.List(cond, pars)
+	if e != nil {
+		resp.FailData("获取合同列表失败", "Err:"+e.Error(), c)
+		return
+	}
+	registerIds := make([]int, 0)
+	for i := range list {
+		registerIds = append(registerIds, list[i].ContractRegisterId)
+	}
+
+	// 套餐/开票/到款列表
+	serviceMap := make(map[int][]*fms.ContractService)
+	invoiceMap := make(map[int][]*fms.ContractInvoice)
+	paymentMap := make(map[int][]*fms.ContractInvoice)
+	maxInvoice := 0
+	maxPayment := 0
+	if len(registerIds) > 0 {
+		// 获取套餐信息
+		csCond := `contract_register_id IN ?`
+		csPars := make([]interface{}, 0)
+		csPars = append(csPars, registerIds)
+		cs := new(fms.ContractService)
+		serviceList, e := cs.List(csCond, csPars)
+		if e != nil {
+			resp.FailData("获取合同套餐列表失败", "Err:"+e.Error(), c)
+			return
+		}
+		for i := range serviceList {
+			cid := serviceList[i].ContractRegisterId
+			if serviceMap[cid] == nil {
+				serviceMap[cid] = make([]*fms.ContractService, 0)
+			}
+			serviceMap[cid] = append(serviceMap[cid], serviceList[i])
+		}
+
+		// TODO:获取小套餐权限
+
+		// 获取开票/到款详情, 并取最大的开票/到款数(用于动态扩展第二列表头)
+		ci := new(fms.ContractInvoice)
+		invoiceList, e := ci.List(csCond, csPars)
+		if e != nil {
+			resp.FailData("获取开票/到款列表失败", "Err:"+e.Error(), c)
+			return
+		}
+		for k := range invoiceList {
+			cid := invoiceList[k].ContractRegisterId
+			if invoiceMap[cid] == nil {
+				invoiceMap[cid] = make([]*fms.ContractInvoice, 0)
+			}
+			if paymentMap[cid] == nil {
+				paymentMap[cid] = make([]*fms.ContractInvoice, 0)
+			}
+			if invoiceList[k].InvoiceType == fms.ContractInvoiceTypeMake {
+				invoiceMap[cid] = append(invoiceMap[cid], invoiceList[k])
+				continue
+			}
+			if invoiceList[k].InvoiceType == fms.ContractInvoiceTypePay {
+				paymentMap[cid] = append(paymentMap[cid], invoiceList[k])
+				continue
+			}
+		}
+		// 取最大开票/到款数
+		for j := range invoiceMap {
+			if len(invoiceMap[j]) > maxInvoice {
+				maxInvoice = len(invoiceMap[j])
+			}
+		}
+		for p := range paymentMap {
+			if len(paymentMap[p]) > maxPayment {
+				maxPayment = len(paymentMap[p])
+			}
+		}
+	}
+
+	// 生成Excel文件
+	//dir, err := os.Executable()
+	//exPath := filepath.Dir(dir)
+	//filePath := exPath + "/" + time.Now().Format(utils.FormatDateTimeUnSpace) + ".xlsx"
+	xlsxFile := xlsx.NewFile()
+	//if err != nil {
+	//	resp.FailData("生成文件失败", "Err:"+err.Error(), c)
+	//	return
+	//}
+	style := xlsx.NewStyle()
+	alignment := xlsx.Alignment{
+		Horizontal: "center",
+		Vertical:   "center",
+		WrapText:   true,
+	}
+	style.Alignment = alignment
+	style.ApplyAlignment = true
+
+	sheet, err := xlsxFile.AddSheet("合同登记")
+	if err != nil {
+		resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
+		return
+	}
+	//_ = sheet.SetColWidth(0, 0, 60)
+	//_ = sheet.SetColWidth(4, 10, 60)
+	// 1行表头
+	titleRow := sheet.AddRow()
+	titleRow.SetHeight(40)
+	// 1行1列-右合并两格
+	cell1 := titleRow.AddCell()
+	cell1.HMerge = 2
+	cell1.SetValue("FICC客户签约表  2022")
+	cell1.SetStyle(style)
+	// 右增两列空白格用于第一列合并, 否则后续单元格合并会有问题
+	titleRow.AddCell().SetValue("")
+	titleRow.AddCell().SetValue("")
+
+	// 1行2列
+	cell2 := titleRow.AddCell()
+	cell2.SetValue("商品大套餐")
+	cell2.SetStyle(style)
+
+	// 1行3列-右合并小套餐数
+	if permissionLen >= 1 {
+		cell3 := titleRow.AddCell()
+		cell3.HMerge = permissionLen - 1
+		cell3.SetValue("商品小套餐")
+		cell3.SetStyle(style)
+		// 同上右增单元格小套餐数-1的空白单元格用于合并
+		for i := 0; i < permissionLen-1; i++ {
+			titleRow.AddCell().SetValue("")
+		}
+	}
+	cell4 := titleRow.AddCell()
+	cell4.SetValue("市场策略")
+	cell4.SetStyle(style)
+	cell5 := titleRow.AddCell()
+	cell5.SetValue("财富管理")
+	cell5.SetStyle(style)
+
+	// 第二行表头
+	titleRow2 := sheet.AddRow()
+	titleRow2.SetHeight(60)
+	row2Title := make([]string, 0)
+	row2Title = append(row2Title, "客户名称", "续约-0\n新增-1", "销售", "商品大套餐")
+	for i := range permissionList {
+		row2Title = append(row2Title, permissionList[i].PermissionName)
+	}
+	row2Title = append(row2Title, "市场策略", "财富管理", "开始时间", "到期时间", "2022年合同金额", "约定付款时间", "签订日",
+		"签订月", "合同状态", "合同编号", "备注")
+	for i := range row2Title {
+		v := titleRow2.AddCell()
+		v.SetValue(row2Title[i])
+		v.SetStyle(style)
+	}
+
+	// 第二行表头-开票/收款(动态添加)
+	for i := 0; i < maxInvoice; i++ {
+		n := i + 1
+		c1 := titleRow2.AddCell()
+		t1 := fmt.Sprintf("%s%d", "开票日", n)
+		c1.SetValue(t1)
+		c1.SetStyle(style)
+		c2 := titleRow2.AddCell()
+		t2 := fmt.Sprintf("%s%d", "开票金额", n)
+		c2.SetValue(t2)
+		c2.SetStyle(style)
+		row2Title = append(row2Title, t1, t2)
+	}
+	for i := 0; i < maxPayment; i++ {
+		n := i + 1
+		c1 := titleRow2.AddCell()
+		t1 := fmt.Sprintf("%s%d", "收款月", n)
+		c1.SetValue(t1)
+		c1.SetStyle(style)
+		c2 := titleRow2.AddCell()
+		t2 := fmt.Sprintf("%s%d", "收款金额", n)
+		c2.SetValue(t2)
+		c2.SetStyle(style)
+		row2Title = append(row2Title, t1, t2)
+	}
+
+	contractTMap := map[int]int{
+		fms.ContractTypeNew:   1,
+		fms.ContractTypeRenew: 0,
+	}
+	for _, v := range list {
+		k := -1
+		dataRow := sheet.AddRow()
+		dataRow.SetHeight(20)
+		dataRow.AddCell().SetString(v.CompanyName)
+		dataRow.AddCell().SetString(fmt.Sprint(contractTMap[v.ContractType]))
+		dataRow.AddCell().SetString(v.SellerName)
+		k += 3
+		// TODO:大套餐
+		svList := serviceMap[v.ContractRegisterId]
+		if svList != nil && len(svList) > 0 {
+
+		}
+		// TODO: 财富管理/市场策略
+		dataRow.AddCell().SetString("大套餐占位1")
+		dataRow.AddCell().SetString("大套餐占位2")
+		dataRow.AddCell().SetString("大套餐占位3")
+
+		// TODO:小套餐
+		for i := 0; i < permissionLen; i++ {
+			dataRow.AddCell().SetString("小套餐占位")
+		}
+
+		// 其他信息
+		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.StartDate)) // 开始时间
+		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.EndDate))   // 到期时间
+		dataRow.AddCell().SetString(fmt.Sprint("¥", v.ContractAmount))                   // 2022年合同金额
+		dataRow.AddCell().SetString(v.AgreedPayTime)                                     // 约定付款时间
+		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.SignDate))  // 签订日
+		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01", v.SignDate))     // 签订月
+		dataRow.AddCell().SetString(fms.ContractStatusKeyNameMap[v.ContractStatus])      // 合同状态
+		dataRow.AddCell().SetString(v.ContractCode)                                      // 合同编号
+		dataRow.AddCell().SetString(v.Remark)                                            // 备注
+
+		// 开票/到款信息
+		ivList := invoiceMap[v.ContractRegisterId]
+		if ivList != nil && len(ivList) > 0 {
+			for ia := range ivList {
+				dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", ivList[ia].InvoiceDate)) // 开票日
+				dataRow.AddCell().SetString(fmt.Sprint(ivList[ia].Amount))                                  // 开票金额
+			}
+		}
+		pyList := paymentMap[v.ContractRegisterId]
+		if pyList != nil && len(pyList) > 0 {
+			for ib := range pyList {
+				dataRow.AddCell().SetString(utils.TimeTransferString("2006年01月", pyList[ib].InvoiceDate)) // 收款月
+				dataRow.AddCell().SetString(fmt.Sprint(pyList[ib].Amount))                                // 收款金额
+			}
+		}
+	}
+
 
+	// 输出文件
+	var buffer bytes.Buffer
+	_ = xlsxFile.Write(&buffer)
+	content := bytes.NewReader(buffer.Bytes())
+	//err = xlsxFile.Save(filePath)
+	//if err != nil {
+	//	resp.FailData("保存文件失败", "Err:"+err.Error(), c)
+	//	return
+	//}
+	//defer func() {
+	//	_ = os.Remove(filePath)
+	//}()
+	randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
+	fileName := "财务列表_" + randStr + ".xlsx"
+
+	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
+	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
+	http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
 }

+ 1 - 0
go.mod

@@ -26,6 +26,7 @@ require (
 	github.com/spf13/viper v1.9.0
 	github.com/swaggo/gin-swagger v1.3.3
 	github.com/swaggo/swag v1.7.4
+	github.com/tealeg/xlsx v1.0.5
 	golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
 	golang.org/x/image v0.0.0-20190802002840-cff245a6509b
 	gorm.io/driver/mysql v1.1.3

+ 9 - 0
models/crm/chart_permission.go

@@ -32,6 +32,15 @@ func (cp *ChartPermission) TableName() string {
 	return "chart_permission"
 }
 
+func (cp *ChartPermission) List(condition string, pars []interface{}) (list []*ChartPermission, err error) {
+	list = make([]*ChartPermission, 0)
+	err = global.MYSQL["report"].Model(cp).
+		Where(condition, pars...).
+		Order("sort ASC").
+		Find(&list).Error
+	return
+}
+
 type PermissionSetResp struct {
 	List []*PermissionSetList
 }

+ 2 - 0
models/crm/constants.go

@@ -35,6 +35,8 @@ const (
 	CompanyProductFiccName = "ficc"
 	CompanyProductRaiName  = "权益"
 
+	ChartPermissionStrategyName = "策略"
+
 	// 合同类型
 	ContractTypeNew   = "新签合同" // 新签
 	ContractTypeRenew = "续约合同" // 续约

+ 6 - 0
models/fms/constants.go

@@ -25,3 +25,9 @@ const (
 	ContractInvoiceTypeMake = 1 // 开票登记
 	ContractInvoiceTypePay  = 2 // 到款登记
 )
+
+var ContractStatusKeyNameMap = map[int]string{
+	ContractStatusApproved:    "已审批",
+	ContractStatusSendOut:     "单章寄出",
+	ContractStatusCheckedBack: "已签回",
+}

+ 1 - 0
models/fms/contract_invoice.go

@@ -56,6 +56,7 @@ func (c *ContractInvoice) List(condition string, pars []interface{}) (list []*Co
 	err = global.DEFAULT_MYSQL.Model(c).
 		Where("is_deleted = 0").
 		Where(condition, pars...).
+		Order("contract_invoice_id ASC").
 		Find(&list).Error
 	return
 }

+ 1 - 1
routers/contract.go

@@ -16,7 +16,7 @@ func InitContract(rg *gin.RouterGroup) {
 	crGroup.POST("del", cr.Del)
 	crGroup.GET("detail", cr.Detail)
 	crGroup.POST("update_status", cr.UpdateStatus)
-	crGroup.POST("export", cr.Export)
+	crGroup.GET("export", cr.Export)
 	crGroup.POST("invoice", cr.Invoice)
 	crGroup.POST("payment", cr.Invoice) // 与开票登记用同一个func, 路由作区分划分权限
 

+ 1 - 1
services/fms/contract_register.go

@@ -55,7 +55,7 @@ func CheckContractRegisterAmount(registerId int) {
 
 	// 核对金额是否相等, 并更新状态
 	status := fms.ContractRegisterStatusIng
-	if amount.Equal(invoiceAmount) && invoiceAmount.Equal(paymentAmount) {
+	if amount.Equal(invoiceAmount) && invoiceAmount.Equal(paymentAmount) && item.ContractStatus == fms.ContractStatusCheckedBack {
 		status = fms.ContractRegisterStatusComplete
 	}
 	updateCols := []string{"InvoicedAmount", "PaymentAmount", "RegisterStatus", "ModifyTime"}