Răsfoiți Sursa

Merge branch 'dev/2.1' into debug

hsun 2 ani în urmă
părinte
comite
6e29347202

+ 85 - 3
controller/census/invoice_payment.go

@@ -197,7 +197,7 @@ func (ct *InvoicePaymentController) List(c *gin.Context) {
 			respList = append(respList, v)
 		}
 
-		// 开票到款金额合计
+		// 开票到款金额合计(换算后)
 		amountTotalCond := `contract_register_id IN ?`
 		amountTotalPars := make([]interface{}, 0)
 		amountTotalPars = append(amountTotalPars, registerIds)
@@ -211,14 +211,66 @@ func (ct *InvoicePaymentController) List(c *gin.Context) {
 			amountTotalMap[amountTotalList[i].InvoiceType] = amountTotalList[i].TotalAmount
 		}
 
+		// 分币种金额统计
+		currencyOB := new(fms.CurrencyUnit)
+		currencyCond := `enable = 1`
+		currencyPars := make([]interface{}, 0)
+		currencyList, e := currencyOB.List(currencyCond, currencyPars)
+		if e != nil {
+			resp.FailMsg("获取失败", "获取货币列表失败, Err: "+e.Error(), c)
+			return
+		}
+		unitMap := make(map[string]string)
+		invoiceCurrencyTotals := make([]*fms.InvoiceListCurrencyTotal, 0)
+		paymentCurrencyTotals := make([]*fms.InvoiceListCurrencyTotal, 0)
+		for i := range currencyList {
+			unitMap[currencyList[i].Code] = currencyList[i].UnitName
+			invoiceCurrencyTotals = append(invoiceCurrencyTotals, &fms.InvoiceListCurrencyTotal{
+				Name:     currencyList[i].Name,
+				UnitName: currencyList[i].UnitName,
+				Code:     currencyList[i].Code,
+				FlagImg:  currencyList[i].FlagImg,
+			})
+			paymentCurrencyTotals = append(paymentCurrencyTotals, &fms.InvoiceListCurrencyTotal{
+				Name:     currencyList[i].Name,
+				UnitName: currencyList[i].UnitName,
+				Code:     currencyList[i].Code,
+				FlagImg:  currencyList[i].FlagImg,
+			})
+		}
+		sumList, e := fms.GetInvoiceListCurrencySum(cond, pars, "currency_unit, invoice_type")
+		if e != nil {
+			resp.FailMsg("获取失败", "获取商品到款统计货币合计金额失败, Err: "+e.Error(), c)
+			return
+		}
+		invoiceSumMap := make(map[string]float64)
+		paymentSumMap := make(map[string]float64)
+		for i := range sumList {
+			if sumList[i].InvoiceType == fms.ContractInvoiceTypeMake {
+				invoiceSumMap[sumList[i].CurrencyUnit] = sumList[i].OriginAmountTotal
+				continue
+			}
+			if sumList[i].InvoiceType == fms.ContractInvoiceTypePay {
+				paymentSumMap[sumList[i].CurrencyUnit] = sumList[i].OriginAmountTotal
+			}
+		}
+		for i := range invoiceCurrencyTotals {
+			invoiceCurrencyTotals[i].Amount = invoiceSumMap[invoiceCurrencyTotals[i].Code]
+		}
+		for i := range paymentCurrencyTotals {
+			paymentCurrencyTotals[i].Amount = paymentSumMap[paymentCurrencyTotals[i].Code]
+		}
+
 		results.DataList = respList
 		results.InvoiceTotal = amountTotalMap[fms.ContractInvoiceTypeMake]
 		results.PaymentTotal = amountTotalMap[fms.ContractInvoiceTypePay]
+		results.InvoiceCurrencyTotal = invoiceCurrencyTotals
+		results.PaymentCurrencyTotal = paymentCurrencyTotals
 	}
 
 	// 是否导出
 	if req.IsExport == 1 {
-		ExportInvoicePaymentCensusList(c, results.DataList)
+		ExportInvoicePaymentCensusList(c, results)
 		return
 	}
 	page.SetTotal(total)
@@ -229,7 +281,13 @@ func (ct *InvoicePaymentController) List(c *gin.Context) {
 }
 
 // ExportInvoicePaymentCensusList 导出商品到款统计列表
-func ExportInvoicePaymentCensusList(c *gin.Context, list []*fms.InvoicePaymentCensusItem) {
+func ExportInvoicePaymentCensusList(c *gin.Context, results *fms.InvoicePaymentCensusResp) {
+	list := results.DataList
+	if len(list) == 0 {
+		resp.Fail("列表数据为空", c)
+		return
+	}
+
 	// 生成Excel文件
 	xlsxFile := xlsx.NewFile()
 	style := xlsx.NewStyle()
@@ -249,6 +307,30 @@ func ExportInvoicePaymentCensusList(c *gin.Context, list []*fms.InvoicePaymentCe
 	_ = sheet.SetColWidth(1, 1, 30)
 	_ = sheet.SetColWidth(3, 3, 30)
 
+	// 前三行-开票金额合计
+	rowA := sheet.AddRow()
+	cellAA := rowA.AddCell()
+	cellAA.SetString(fmt.Sprintf("已开票合计金额(换算后):%.2f(元)", results.InvoiceTotal))
+	rowBData := "已开票金额:"
+	for _, v := range results.InvoiceCurrencyTotal {
+		rowBData += fmt.Sprintf("%s%.2f(%s)  ", v.Name, v.Amount, v.UnitName)
+	}
+	rowB := sheet.AddRow()
+	rowB.AddCell().SetString(rowBData)
+	sheet.AddRow()
+
+	// 四至六-到款金额合计
+	rowD := sheet.AddRow()
+	cellDA := rowD.AddCell()
+	cellDA.SetString(fmt.Sprintf("已到款合计金额(换算后):%.2f(元)", results.PaymentTotal))
+	rowEData := "已到款金额:"
+	for _, v := range results.PaymentCurrencyTotal {
+		rowEData += fmt.Sprintf("%s%.2f(%s)  ", v.Name, v.Amount, v.UnitName)
+	}
+	rowE := sheet.AddRow()
+	rowE.AddCell().SetString(rowEData)
+	sheet.AddRow()
+
 	// 表头, 套餐动态获取
 	rowTitle := []string{"序号", "客户名称", "是否新客户", "合同有效期", "开票日", "开票金额", "到款日", "到款金额", "付款方式", "销售",
 		"组别"}

+ 2 - 2
controller/census/seller.go

@@ -148,7 +148,7 @@ func ExportGroupInvoiceList(c *gin.Context, list []*fms.CensusSellerGroupInvoice
 	}
 
 	// 数据表头
-	rowTitle := []string{"排名", "销售组别", "开票金额", "组别占比"}
+	rowTitle := []string{"排名", "销售组别", "收入金额(元)", "组别占比"}
 	titleRow := sheet.AddRow()
 	for i := range rowTitle {
 		v := titleRow.AddCell()
@@ -346,7 +346,7 @@ func ExportInvoiceList(c *gin.Context, list []*fms.CensusSellerInvoiceItem, req
 	}
 
 	// 数据表头
-	rowTitle := []string{"排名", "销售员", "销售组别", "开票金额", "小组占比", "全员占比"}
+	rowTitle := []string{"排名", "销售员", "销售组别", "收入金额(元)", "小组占比", "全员占比"}
 	titleRow := sheet.AddRow()
 	for i := range rowTitle {
 		v := titleRow.AddCell()

+ 173 - 93
controller/contract/register.go

@@ -217,6 +217,24 @@ func (rg *RegisterController) Add(c *gin.Context) {
 		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
+	}
+
 	nowTime := time.Now().Local()
 	ob.ContractCode = req.ContractCode
 	ob.RelateContractCode = req.RelateContractCode
@@ -229,6 +247,8 @@ func (rg *RegisterController) Add(c *gin.Context) {
 	ob.SellerName = req.SellerName
 	ob.ContractType = req.ContractType
 	ob.ContractAmount = req.ContractAmount
+	ob.CurrencyUnit = req.CurrencyUnit
+	ob.RMBRate = rate
 	ob.StartDate = startDate
 	ob.EndDate = endDate
 	ob.SignDate = signDate
@@ -348,6 +368,11 @@ func (rg *RegisterController) Edit(c *gin.Context) {
 		return
 	}
 	originHasPayment := item.HasPayment
+	// TODO:确认是否允许修改货币单位,若可修改货币单位则需要相应的处理开票到款
+	if req.CurrencyUnit != item.CurrencyUnit {
+		resp.Fail("暂不允许修改货币单位", c)
+		return
+	}
 
 	updateCols := []string{
 		"ContractCode", "RelateContractCode", "CrmContractId", "ContractSource", "CompanyName", "ActualCompanyName",
@@ -676,12 +701,13 @@ func (rg *RegisterController) Invoice(c *gin.Context) {
 		resp.Fail("合同存在代付不允许添加开票/到款登记", c)
 		return
 	}
-	// 合同有效时长
-	dayDiff := item.EndDate.Sub(item.StartDate).Hours() / 24
 
 	noChangeInvoiceIds := make([]int, 0)
 	newInvoice := make([]*fms.ContractInvoice, 0)
 	if len(req.AmountList) > 0 {
+		// 合同有效时长(计算付款方式)
+		dayDiff := item.EndDate.Sub(item.StartDate).Hours() / 24
+
 		// 获取销售分组信息
 		sellerList, e := crmService.GetSellerDepartmentListWithGroupAndTeam()
 		if e != nil {
@@ -714,12 +740,15 @@ func (rg *RegisterController) Invoice(c *gin.Context) {
 			}
 			if req.AmountList[i].InvoiceId > 0 {
 				noChangeInvoiceIds = append(noChangeInvoiceIds, req.AmountList[i].InvoiceId)
+				continue
 			}
 			if req.AmountList[i].InvoiceId == 0 {
 				v := &fms.ContractInvoice{
 					ContractRegisterId: req.ContractRegisterId,
 					ContractCode:       item.ContractCode,
 					Amount:             req.AmountList[i].Amount,
+					OriginAmount:       req.AmountList[i].OriginAmount,
+					CurrencyUnit:       item.CurrencyUnit,
 					InvoiceType:        req.InvoiceType,
 					InvoiceDate:        t,
 					AdminId:            int(adminInfo.AdminId),
@@ -1070,7 +1099,7 @@ func (rg *RegisterController) Export(c *gin.Context) {
 	for i := range otherService {
 		row2Title = append(row2Title, otherService[i].Title)
 	}
-	row2Title = append(row2Title, "套餐备注", "开始时间", "到期时间", "2022年合同金额", "约定付款时间", "签订日", "合同状态",
+	row2Title = append(row2Title, "套餐备注", "开始时间", "到期时间", "2022年合同金额", "金额单位", "约定付款时间", "签订日", "合同状态",
 		"合同编号", "合规备注")
 
 	// 设置表头
@@ -1175,6 +1204,7 @@ func (rg *RegisterController) Export(c *gin.Context) {
 		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.CurrencyUnit)                                      // 货币单位
 		dataRow.AddCell().SetString(v.AgreedPayTime)                                     // 约定付款时间
 		dataRow.AddCell().SetString(utils.TimeTransferString("2006/01/02", v.SignDate))  // 签订日
 		dataRow.AddCell().SetString(fms.ContractStatusKeyNameMap[v.ContractStatus])      // 合同状态
@@ -1239,6 +1269,7 @@ func (rg *RegisterController) Export(c *gin.Context) {
 // @Param   EndDate			query	string	false	"结束日期"
 // @Param   MinAmount		query	float64	false	"开票金额区间-最小值"
 // @Param   MaxAmount		query	float64	false	"开票金额区间-最大值"
+// @Param   IsExport		query	int		false	"是否导出: 0-否; 1-是"
 // @Success 200 {object} fms.ContractInvoiceItem
 // @router /contract/register/invoice_list [get]
 func (rg *RegisterController) InvoiceList(c *gin.Context) {
@@ -1267,8 +1298,13 @@ func (rg *RegisterController) InvoiceList(c *gin.Context) {
 	// 合同编号
 	if req.ContractCode != "" {
 		kw := fmt.Sprint("%", req.ContractCode, "%")
-		cond += ` AND contract_code LIKE ?`
 		pars = append(pars, kw)
+		// 开票列表同时模糊查询销售名称
+		if req.InvoiceType == fms.ContractInvoiceTypeMake {
+			cond += ` AND (contract_code LIKE ? OR seller_name LIKE ?)`
+		} else {
+			cond += ` AND contract_code LIKE ?`
+		}
 	}
 	if req.StartDate != "" && req.EndDate != "" {
 		st := fmt.Sprint(req.StartDate, " 00:00:00")
@@ -1285,103 +1321,96 @@ func (rg *RegisterController) InvoiceList(c *gin.Context) {
 		pars = append(pars, req.MaxAmount)
 	}
 
+	// 货币列表
+	currencyOB := new(fms.CurrencyUnit)
+	currencyCond := `enable = 1`
+	currencyPars := make([]interface{}, 0)
+	currencyList, e := currencyOB.List(currencyCond, currencyPars)
+	if e != nil {
+		resp.FailMsg("获取失败", "获取货币列表失败, Err: "+e.Error(), c)
+		return
+	}
+	unitMap := make(map[string]string)
+	currencyTotals := make([]*fms.InvoiceListCurrencyTotal, 0)
+	for i := range currencyList {
+		unitMap[currencyList[i].Code] = currencyList[i].UnitName
+		currencyTotals = append(currencyTotals, &fms.InvoiceListCurrencyTotal{
+			Name:     currencyList[i].Name,
+			UnitName: currencyList[i].UnitName,
+			Code:     currencyList[i].Code,
+			FlagImg:  currencyList[i].FlagImg,
+		})
+	}
+
 	page := new(base.Page)
 	page.SetPageSize(pageSize)
 	page.SetCurrent(pageIndex)
 	page.AddOrderItem(base.OrderItem{Column: "invoice_time", Asc: false})
+	if req.IsExport == 1 {
+		page.SetPageSize(10000)
+		page.SetCurrent(1)
+	}
 	total, list, e := fms.GetContractInvoiceItemPageList(page, cond, pars)
 	if e != nil {
 		resp.FailMsg("获取失败", "获取合同开票/到款列表失败, Err: "+e.Error(), c)
 		return
 	}
 	page.SetTotal(total)
+	for i := range list {
+		list[i].UnitName = unitMap[list[i].CurrencyUnit]
+	}
 
-	// 金额合计
-	ob := new(fms.ContractInvoice)
-	amountTotal, e := ob.Sum("amount", cond, pars)
+	// 分币种合计金额
+	var amountTotal float64
+	sumList, e := fms.GetInvoiceListCurrencySum(cond, pars, "currency_unit")
 	if e != nil {
-		resp.FailMsg("获取失败", "获取合同开票/到款列表合计金额失败, Err: "+e.Error(), c)
+		resp.FailMsg("获取失败", "获取开票/到款列表合计金额失败, Err: "+e.Error(), c)
 		return
 	}
-	amountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountTotal), 64)
-
-	type RespData struct {
-		Page        *base.Page  `json:"page"`
-		List        interface{} `json:"list"`
-		AmountTotal float64     `json:"amount_total"`
-	}
-	respData := &RespData{
-		Page:        page,
-		List:        list,
-		AmountTotal: amountTotal,
-	}
-	resp.OkData("获取成功", respData, c)
-}
-
-// InvoiceExport
-// @Title 开票/到款列表-导出
-// @Description 合同登记-导出
-// @Param   InvoiceType		query	int		false	"类型: 1-开票登记; 2-到款登记"
-// @Param   ContractCode	query	string	false	"合同编号"
-// @Param   StartDate		query	string	false	"开始日期"
-// @Param   EndDate			query	string	false	"结束日期"
-// @Param   MinAmount		query	float64	false	"开票金额区间-最小值"
-// @Param   MaxAmount		query	float64	false	"开票金额区间-最大值"
-// @Success 200 string "操作成功"
-// @router /contract/register/invoice_export [get]
-func (rg *RegisterController) InvoiceExport(c *gin.Context) {
-	var req fms.ContractInvoiceListReq
-	if e := c.BindQuery(&req); e != nil {
-		err, ok := e.(validator.ValidationErrors)
-		if !ok {
-			resp.FailData("参数解析失败", "Err:"+e.Error(), c)
-			return
+	sumMap := make(map[string]float64)
+	for i := range sumList {
+		if sumList[i].CurrencyUnit == fms.BaseCurrencyCode {
+			amountTotal = sumList[i].AmountTotal
 		}
-		resp.FailData("参数解析失败", err.Translate(global.Trans), c)
-		return
+		sumMap[sumList[i].CurrencyUnit] = sumList[i].OriginAmountTotal
 	}
-	listName := "开票"
-	if req.InvoiceType == fms.ContractInvoiceTypePay {
-		listName = "到款"
+	for i := range currencyTotals {
+		currencyTotals[i].Amount = sumMap[currencyTotals[i].Code]
 	}
 
-	cond := `invoice_type = ?`
-	pars := make([]interface{}, 0)
-	pars = append(pars, req.InvoiceType)
-	// 合同编号
-	if req.ContractCode != "" {
-		kw := fmt.Sprint("%", req.ContractCode, "%")
-		cond += ` AND contract_code LIKE ?`
-		pars = append(pars, kw)
+	respData := &fms.InvoiceListRespData{
+		Page:          page,
+		List:          list,
+		AmountTotal:   amountTotal,
+		CurrencyTotal: currencyTotals,
 	}
-	if req.StartDate != "" && req.EndDate != "" {
-		st := fmt.Sprint(req.StartDate, " 00:00:00")
-		ed := fmt.Sprint(req.EndDate, " 23:59:59")
-		cond += ` AND (invoice_time BETWEEN ? AND ?)`
-		pars = append(pars, st, ed)
-	}
-	if req.MinAmount > 0 {
-		cond += ` AND amount >= ?`
-		pars = append(pars, req.MinAmount)
-	}
-	if req.MaxAmount > 0 {
-		cond += ` AND amount <= ?`
-		pars = append(pars, req.MaxAmount)
+	// 是否导出
+	if req.IsExport == 1 {
+		ExportInvoiceList(c, req, respData)
+		return
 	}
+	resp.OkData("获取成功", respData, c)
+}
 
-	// 获取列表数据
-	cr := new(fms.ContractInvoice)
-	orderRule := `invoice_time DESC`
-	list, e := cr.List(cond, pars, orderRule)
-	if e != nil {
-		resp.FailData(fmt.Sprintf("获取%s列表失败", listName), "Err:"+e.Error(), c)
+// ExportInvoiceList 导出开票/到款列表
+func ExportInvoiceList(c *gin.Context, req fms.ContractInvoiceListReq, results *fms.InvoiceListRespData) {
+	list := make([]*fms.ContractInvoiceItem, 0)
+	if val, ok := results.List.([]*fms.ContractInvoiceItem); ok {
+		list = val
+	} else {
+		resp.Fail("列表数据有误", c)
 		return
 	}
 	if len(list) == 0 {
-		resp.Fail("无有效数据可导出", c)
+		resp.Fail("列表数据为空", c)
 		return
 	}
 
+	listName := "开票"
+	if req.InvoiceType == fms.ContractInvoiceTypePay {
+		listName = "到款"
+	}
+
 	// 生成Excel文件
 	xlsxFile := xlsx.NewFile()
 	style := xlsx.NewStyle()
@@ -1399,25 +1428,40 @@ func (rg *RegisterController) InvoiceExport(c *gin.Context) {
 		return
 	}
 
-	// 表头
+	// 前两行显示合计金额, 第三行空出与列表数据隔一行
+	rowA := sheet.AddRow()
+	cellAA := rowA.AddCell()
+	cellAA.SetString(fmt.Sprintf("已开票合计金额(换算后):%.2f(元)", results.AmountTotal))
+	rowBData := "已开票金额:"
+	for _, v := range results.CurrencyTotal {
+		rowBData += fmt.Sprintf("%s%.2f(%s)  ", v.Name, v.Amount, v.UnitName)
+	}
+	rowB := sheet.AddRow()
+	rowB.AddCell().SetString(rowBData)
+	sheet.AddRow()
+
+	// 列表数据表头
+	titles := []string{"合同编号", fmt.Sprintf("%s金额", listName), "金额单位", "换算金额(元)",
+		fmt.Sprintf("%s日期", listName), "销售", "备注"}
 	titleRow := sheet.AddRow()
 	titleRow.SetHeight(40)
-	cell1 := titleRow.AddCell()
-	cell1.SetString("合同编号")
-	cell1.SetStyle(style)
-	cell2 := titleRow.AddCell()
-	cell2.SetValue(fmt.Sprintf("%s金额", listName))
-	cell2.SetStyle(style)
-	cell3 := titleRow.AddCell()
-	cell3.SetValue(fmt.Sprintf("%s日期", listName))
-	cell3.SetStyle(style)
+	for i := range titles {
+		c := titleRow.AddCell()
+		c.SetString(titles[i])
+		c.SetStyle(style)
+	}
 
+	// 单元格赋值
 	for _, v := range list {
 		dataRow := sheet.AddRow()
 		dataRow.SetHeight(20)
-		dataRow.AddCell().SetString(v.ContractCode)
-		dataRow.AddCell().SetString(fmt.Sprint(v.Amount))
-		dataRow.AddCell().SetString(utils.TimeTransferString("2006-01-02", v.InvoiceDate))
+		dataRow.AddCell().SetString(v.ContractCode)             // 合同编号
+		dataRow.AddCell().SetString(fmt.Sprint(v.OriginAmount)) // 开票金额
+		dataRow.AddCell().SetString(v.UnitName)                 // 金额单位
+		dataRow.AddCell().SetString(fmt.Sprint(v.Amount))       // 换算金额(元)
+		dataRow.AddCell().SetString(v.InvoiceDate)              // 开票日
+		dataRow.AddCell().SetString(v.SellerName)               // 销售
+		dataRow.AddCell().SetString(v.Remark)                   // 备注
 	}
 
 	// 输出文件
@@ -1524,6 +1568,17 @@ func (rg *RegisterController) Import(c *gin.Context) {
 		serviceTempNameMap[serviceTempList[i].Title] = serviceTempList[i]
 	}
 
+	// 获取货币列表及汇率(汇率为导入日的汇率)
+	rateList, e := fmsService.GetTodayCurrencyRateList()
+	if e != nil {
+		resp.FailData("获取货币列表及汇率失败", "Err:"+e.Error(), c)
+		return
+	}
+	rateMap := make(map[string]float64)
+	for i := range rateList {
+		rateMap[rateList[i].Code] = rateList[i].RMBRate
+	}
+
 	titleMap := make(map[int]string)
 	newIds := make([]int, 0)
 	newCompanyArr := []string{"0", "1"}
@@ -1776,13 +1831,24 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						rowRegister.ContractAmount = amount
 						continue
 					}
-					// 约定付款日期
+					// 金额单位
 					if k == 37 {
+						rate := rateMap[v]
+						if rate <= 0 {
+							resp.Fail(fmt.Sprintf("第%d行金额单位有误, 请按模板导入", i+1), c)
+							return
+						}
+						rowRegister.CurrencyUnit = v
+						rowRegister.RMBRate = rate
+						continue
+					}
+					// 约定付款日期
+					if k == 38 {
 						rowRegister.AgreedPayTime = v
 						continue
 					}
 					// 签订日
-					if k == 38 {
+					if k == 39 {
 						va := cell.Value
 						if va == "" {
 							continue
@@ -1804,7 +1870,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合同状态
-					if k == 39 {
+					if k == 40 {
 						rowRegister.ContractStatus = fms.ContractStatusNameKeyMap[v]
 						if rowRegister.ContractStatus == 0 {
 							resp.Fail(fmt.Sprintf("第%d行合同状态不匹配, 请按模板导入", i+1), c)
@@ -1813,7 +1879,7 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合同编号
-					if k == 40 {
+					if k == 41 {
 						rowContractCode := v
 						if rowContractCode == "" {
 							resp.Fail(fmt.Sprintf("第%d行合同编号不可为空, 请按模板导入", i+1), c)
@@ -1828,12 +1894,12 @@ func (rg *RegisterController) Import(c *gin.Context) {
 						continue
 					}
 					// 合规备注
-					if k == 41 {
+					if k == 42 {
 						rowRegister.Remark = v
 						continue
 					}
 					// 开票列表
-					k2 := 41
+					k2 := 42
 					for ir := 0; ir < invoiceMax; ir++ {
 						n := ir + 1
 						// 开票日
@@ -2016,3 +2082,17 @@ func (rg *RegisterController) Import(c *gin.Context) {
 
 	resp.Ok("操作成功", c)
 }
+
+// CurrencyList
+// @Title 货币单位列表
+// @Description 货币单位列表
+// @Success 200 {object} fms.CurrencyUnitItem
+// @router /contract/register/currency_list [get]
+func (rg *RegisterController) CurrencyList(c *gin.Context) {
+	list, e := fmsService.GetTodayCurrencyRateList()
+	if e != nil {
+		resp.FailData("获取失败", "获取今日货币汇率列表失败, Err: "+e.Error(), c)
+		return
+	}
+	resp.OkData("获取成功", list, c)
+}

+ 1 - 1
controller/crm/contract.go

@@ -239,7 +239,7 @@ func (rg *ContractController) ServiceDetail(c *gin.Context) {
 		return
 	}
 
-	// 获取合同服务中的权限ID失败
+	// 获取合同服务中的权限ID, 填充contractDetail.Service.ChartPermissionIds字段
 	_, e = crmService.GetServicePermissionMap(contractDetail.Service)
 	if e != nil {
 		resp.FailMsg("获取失败", "获取合同服务中的权限ID失败, Err: "+e.Error(), c)

+ 3 - 0
models/fms/constants.go

@@ -35,6 +35,9 @@ const (
 	ContractPaymentPayTypeQuarter  = 3 // 季付
 	ContractPaymentPayTypeOther    = 4 // 次付
 	ContractPaymentPayTypeAbnormal = 5 // 异常
+
+	// 基础货币代码(人民币)
+	BaseCurrencyCode = "CNY"
 )
 
 var ContractStatusKeyNameMap = map[int]string{

+ 63 - 11
models/fms/contract_invoice.go

@@ -13,7 +13,9 @@ type ContractInvoice struct {
 	ContractInvoiceId  int       `gorm:"primaryKey;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:"金额"`
+	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:"货币国际代码"`
 	InvoiceType        int       `gorm:"column:invoice_type" json:"invoice_type" description:"类型: 1-开票登记; 2-到款登记"`
 	InvoiceDate        time.Time `gorm:"column:invoice_time" json:"invoice_time" description:"开票日期/到款月"`
 	SellerId           int       `gorm:"column:seller_id" json:"seller_id" description:"销售ID"`
@@ -39,7 +41,10 @@ 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:"金额"`
+	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"`
@@ -143,13 +148,14 @@ type ContractInvoiceSaveReq struct {
 	AmountList         []*ContractInvoiceSaveItem `json:"amount_list"`
 }
 
-// ContractInvoiceSaveReq 合同开票数据
+// ContractInvoiceSaveItem 合同开票数据
 type ContractInvoiceSaveItem struct {
-	InvoiceId   int     `json:"invoice_id" description:"开票ID"`
-	Amount      float64 `json:"amount" description:"开票金额/到款金额"`
-	InvoiceDate string  `json:"invoice_date" description:"开票日期/到款月"`
-	Remark      string  `json:"remark" description:"备注"`
-	SellerId    int     `json:"seller_id" description:"销售ID"`
+	InvoiceId    int     `json:"invoice_id" description:"开票ID"`
+	OriginAmount float64 `json:"origin_amount" description:"开票(到款)金额"`
+	Amount       float64 `json:"amount" description:"换算后的金额"`
+	InvoiceDate  string  `json:"invoice_date" description:"开票日期/到款月"`
+	Remark       string  `json:"remark" description:"备注"`
+	SellerId     int     `json:"seller_id" description:"销售ID"`
 }
 
 // GetContractInvoiceItemList 获取开票到款列表
@@ -176,6 +182,8 @@ func formatContractInvoice2ItemList(list []*ContractInvoice) (itemList []*Contra
 			ContractRegisterId: list[i].ContractRegisterId,
 			ContractCode:       list[i].ContractCode,
 			Amount:             list[i].Amount,
+			OriginAmount:       list[i].OriginAmount,
+			CurrencyUnit:       list[i].CurrencyUnit,
 			InvoiceType:        list[i].InvoiceType,
 			InvoiceDate:        utils.TimeTransferString(utils.FormatDate, list[i].InvoiceDate),
 			SellerId:           list[i].SellerId,
@@ -196,6 +204,7 @@ type ContractInvoiceListReq struct {
 	EndDate      string  `json:"end_date" form:"end_date" binding:"omitempty,datetime=2006-01-02" description:"结束日期"`
 	MinAmount    float64 `json:"min_amount" form:"min_amount" description:"开票金额区间-最小值"`
 	MaxAmount    float64 `json:"max_amount" form:"max_amount" description:"开票金额区间-最大值"`
+	IsExport     int     `json:"is_export" form:"is_export" description:"是否导出: 0-否; 1-是"`
 	base.PageReq
 }
 
@@ -226,8 +235,13 @@ func formatContractInvoice2Item(item *ContractInvoice) (formatItem *ContractInvo
 	formatItem.ContractRegisterId = item.ContractRegisterId
 	formatItem.ContractCode = item.ContractCode
 	formatItem.Amount = item.Amount
+	formatItem.OriginAmount = item.OriginAmount
+	formatItem.CurrencyUnit = item.CurrencyUnit
 	formatItem.InvoiceType = item.InvoiceType
 	formatItem.InvoiceDate = utils.TimeTransferString(utils.FormatDate, item.InvoiceDate)
+	formatItem.SellerId = item.SellerId
+	formatItem.SellerName = item.SellerName
+	formatItem.PayType = item.PayType
 	formatItem.Remark = item.Remark
 	formatItem.CreateTime = utils.TimeTransferString(utils.FormatDateTime, item.CreateTime)
 	return
@@ -283,9 +297,11 @@ func GetInvoicePaymentCensusPageList(page base.IPage, condition string, pars []i
 
 // InvoicePaymentCensusResp 商品到款统计响应体
 type InvoicePaymentCensusResp struct {
-	DataList     []*InvoicePaymentCensusItem `json:"data_list"`
-	InvoiceTotal float64                     `json:"invoice_total" description:"开票总金额"`
-	PaymentTotal float64                     `json:"payment_total" description:"到款总金额"`
+	DataList             []*InvoicePaymentCensusItem `json:"data_list"`
+	InvoiceTotal         float64                     `json:"invoice_total" description:"开票总金额(换算后)"`
+	PaymentTotal         float64                     `json:"payment_total" description:"到款总金额(换算后)"`
+	InvoiceCurrencyTotal []*InvoiceListCurrencyTotal `json:"invoice_currency_total" description:"开票-分币种总金额"`
+	PaymentCurrencyTotal []*InvoiceListCurrencyTotal `json:"payment_currency_total" description:"到款-分币种总金额"`
 }
 
 // InvoicePaymentCensusItem 商品到款统计信息
@@ -425,3 +441,39 @@ func GetCensusSellerInvoicePageList(page base.IPage, condition, outCond string,
 	err = global.DEFAULT_MYSQL.Raw(sql, pars...).Scan(&results).Error
 	return
 }
+
+// InvoiceListRespData 开票/到款列表响应体
+type InvoiceListRespData struct {
+	Page          *base.Page                  `json:"page"`
+	List          interface{}                 `json:"list"`
+	AmountTotal   float64                     `json:"amount_total"`
+	CurrencyTotal []*InvoiceListCurrencyTotal `json:"currency_total"`
+}
+
+// InvoiceListCurrencyTotal 开票/到款列表分币种合计信息
+type InvoiceListCurrencyTotal struct {
+	Name     string  `json:"name" description:"货币名称"`
+	UnitName string  `json:"unit_name" description:"单位名称"`
+	Code     string  `json:"code" description:"国际代码"`
+	Amount   float64 `json:"amount" description:"金额"`
+	FlagImg  string  `json:"flag_img" description:"国旗图标"`
+}
+
+// InvoiceListCurrencySum 开票/到款列表分币种总和
+type InvoiceListCurrencySum struct {
+	CurrencyUnit      string  `json:"currency_unit" description:"货币代码"`
+	InvoiceType       int     `json:"invoice_type" description:"开票类型:1-开票; 2-到款"`
+	AmountTotal       float64 `json:"amount_total" description:"换算后合计金额"`
+	OriginAmountTotal float64 `json:"origin_amount_total" description:"原合计金额"`
+}
+
+// GetInvoiceListCurrencySum 获取开票/到款分货币合计
+func GetInvoiceListCurrencySum(condition string, pars []interface{}, groupRule string) (results []*InvoiceListCurrencySum, err error) {
+	query := global.DEFAULT_MYSQL.Table("contract_invoice").
+		Select("currency_unit, invoice_type, SUM(amount) AS amount_total, SUM(origin_amount) AS origin_amount_total").
+		Where("is_deleted = 0").
+		Where(condition, pars...).
+		Group(groupRule)
+	err = query.Find(&results).Error
+	return
+}

+ 7 - 0
models/fms/contract_register.go

@@ -23,6 +23,8 @@ type ContractRegister struct {
 	ContractAmount     float64   `gorm:"column:contract_amount" json:"contract_amount" description:"合同金额"`
 	InvoicedAmount     float64   `gorm:"column:invoiced_amount" json:"invoiced_amount" description:"开票金额"`
 	PaymentAmount      float64   `gorm:"column:payment_amount" json:"payment_amount" description:"到款金额"`
+	CurrencyUnit       string    `gorm:"column:currency_unit" json:"currency_unit" description:"货币国际代码"`
+	RMBRate            float64   `gorm:"column:rmb_rate" json:"rmb_rate" description:"人民币汇率(create_time当日)"`
 	StartDate          time.Time `gorm:"column:start_date" json:"start_date" description:"合同开始日期"`
 	EndDate            time.Time `gorm:"column:end_date" json:"end_date" description:"合同结束日期"`
 	SignDate           time.Time `gorm:"column:sign_date" json:"sign_date" description:"合同签订日期"`
@@ -117,6 +119,8 @@ type ContractRegisterItem struct {
 	ContractAmount     float64 `json:"contract_amount" description:"合同金额"`
 	InvoicedAmount     float64 `json:"invoiced_amount" description:"开票金额"`
 	PaymentAmount      float64 `json:"payment_amount" description:"到款金额"`
+	CurrencyUnit       string  `json:"currency_unit" description:"货币国际代码"`
+	RMBRate            float64 `json:"rmb_rate" description:"人民币汇率(create_time当日)"`
 	StartDate          string  `json:"start_date" description:"合同开始日期"`
 	EndDate            string  `json:"end_date" description:"合同结束日期"`
 	SignDate           string  `json:"sign_date" description:"合同签订日期"`
@@ -161,6 +165,7 @@ type ContractRegisterAddReq struct {
 	SellerName         string                  `json:"seller_name" binding:"required" description:"CRM系统-销售名称"`
 	ContractType       int                     `json:"contract_type" binding:"oneof=1 2 3 4" description:"合同类型: 1-新签; 2-续约; 3-代付; 4-补充协议"`
 	ContractAmount     float64                 `json:"contract_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:"合同结束日期"`
 	SignDate           string                  `json:"sign_date" description:"合同签订日期"`
@@ -345,6 +350,8 @@ func formatContractRegister2Item(item *ContractRegister) (formatItem *ContractRe
 	formatItem.ContractAmount = item.ContractAmount
 	formatItem.InvoicedAmount = item.InvoicedAmount
 	formatItem.PaymentAmount = item.PaymentAmount
+	formatItem.CurrencyUnit = item.CurrencyUnit
+	formatItem.RMBRate = item.RMBRate
 	formatItem.StartDate = utils.TimeTransferString(utils.FormatDate, item.StartDate)
 	formatItem.EndDate = utils.TimeTransferString(utils.FormatDate, item.EndDate)
 	formatItem.SignDate = utils.TimeTransferString(utils.FormatDate, item.SignDate)

+ 35 - 0
models/fms/currency_unit.go

@@ -0,0 +1,35 @@
+package fms
+
+import "hongze/fms_api/global"
+
+// CurrencyUnit 货币单位表
+type CurrencyUnit struct {
+	CurrencyUnitId int    `gorm:"primaryKey;column:currency_unit_id" json:"-" description:"货币ID"`
+	Name           string `gorm:"column:name" json:"name" description:"货币名称"`
+	UnitName       string `gorm:"unit_name" json:"unit_name" description:"单位名称"`
+	Code           string `gorm:"code" json:"code" description:"国际代码"`
+	Enable         int    `gorm:"enable" json:"enable" description:"状态: 0-禁用; 1-启用"`
+	FlagImg        string `gorm:"flag_img" json:"flag_img" description:"国旗图片"`
+}
+
+func (m *CurrencyUnit) TableName() string {
+	return "currency_unit"
+}
+
+func (m *CurrencyUnit) List(condition string, pars []interface{}) (list []*CurrencyUnit, err error) {
+	list = make([]*CurrencyUnit, 0)
+	query := global.DEFAULT_MYSQL.Model(m).
+		Where(condition, pars...).
+		Order("currency_unit_id ASC")
+	err = query.Find(&list).Error
+	return
+}
+
+type CurrencyUnitItem struct {
+	Name     string  `json:"name" description:"货币名称"`
+	UnitName string  `json:"unit_name" description:"单位名称"`
+	Code     string  `json:"code" description:"国际代码"`
+	Enable   int     `json:"enable" description:"状态: 0-禁用; 1-启用"`
+	RMBRate  float64 `json:"rmb_rate" description:"当日对人民币汇率"`
+	FlagImg  string  `json:"flag_img" description:"国旗图片"`
+}

+ 1 - 1
routers/contract.go

@@ -20,8 +20,8 @@ func InitContract(rg *gin.RouterGroup) {
 	crGroup.POST("invoice", cr.Invoice)
 	crGroup.POST("payment", cr.Invoice) // 与开票登记用同一个func, 路由作区分划分权限
 	crGroup.GET("invoice_list", cr.InvoiceList)
-	crGroup.GET("invoice_export", cr.InvoiceExport)
 	crGroup.POST("import", cr.Import)
+	crGroup.GET("currency_list", cr.CurrencyList)
 
 	// 合同套餐
 	sr := new(contract.ServiceController)

+ 169 - 0
services/fms/currency_rate.go

@@ -0,0 +1,169 @@
+package fms
+
+import (
+	"context"
+	"encoding/json"
+	"fmt"
+	jsoniter "github.com/json-iterator/go"
+	"hongze/fms_api/global"
+	"hongze/fms_api/models/fms"
+	"hongze/fms_api/services/alarm_msg"
+	"hongze/fms_api/utils"
+	"strconv"
+	"time"
+)
+
+const (
+	CurrencyRateApiHost        = "https://jisuhuilv.market.alicloudapi.com"
+	CurrencyRateExchangeSingle = "/exchange/single"
+	CurrencyRateApiAppCode     = "22553c4ba74545568aba70ac6cfd441d"
+	CurrencyRateApiAppKey      = "203889624"
+	CurrencyRateApiAppSecret   = "voampGGl0yGNx5xA1sZdmZlV2EiBct2P"
+)
+
+type CurrencyRateApiResp struct {
+	Status int    `json:"status"`
+	Msg    string `json:"msg"`
+	Result struct {
+		Currency string `json:"currency"`
+		Name     string `json:"name"`
+		List     map[string]struct {
+			Name       string `json:"name"`
+			Rate       string `json:"rate"`
+			UpdateTime string `json:"updatetime"`
+		} `json:"list"`
+	} `json:"result"`
+}
+
+type CurrencyRateItem struct {
+	Name       string    `json:"name"`
+	Code       string    `json:"code"`
+	Rate       float64   `json:"rate"`
+	UpdateTime time.Time `json:"update_time"`
+}
+
+// CurlCurrencyRateApi 请求货币汇率接口
+func CurlCurrencyRateApi() (resList []*CurrencyRateItem, err error) {
+	defer func() {
+		if err != nil {
+			go alarm_msg.SendAlarmMsg("请求汇率接口失败, Err: "+err.Error(), 3)
+		}
+	}()
+
+	// 请求汇率接口
+	query := "?currency=CNY"
+	reqUrl := fmt.Sprint(CurrencyRateApiHost, CurrencyRateExchangeSingle, query)
+	auth := fmt.Sprintf("APPCODE %s", CurrencyRateApiAppCode)
+	resultByte, e := utils.PublicGetRequest(reqUrl, auth)
+	if e != nil {
+		err = fmt.Errorf("HttpCurrencyRateApi errMsg: %s", e.Error())
+		return
+	}
+	if len(resultByte) == 0 {
+		err = fmt.Errorf("HttpCurrencyRateApi empty data")
+		return
+	}
+
+	// 汇率结果
+	results := new(CurrencyRateApiResp)
+	if e := json.Unmarshal(resultByte, &results); e != nil {
+		err = fmt.Errorf("rate api result unmarshal err: %s", e.Error())
+		return
+	}
+	if results.Status != 0 {
+		err = fmt.Errorf("curl rate api errMsg: %s", results.Msg)
+		return
+	}
+	list := results.Result.List
+	if list == nil {
+		err = fmt.Errorf("rate api list is empty")
+		return
+	}
+	resList = make([]*CurrencyRateItem, 0)
+	for k, v := range list {
+		item := new(CurrencyRateItem)
+		item.Code = k
+		item.Name = v.Name
+		f, e := strconv.ParseFloat(v.Rate, 64)
+		if e != nil {
+			err = fmt.Errorf("rate api rate parse err: %v", e)
+			return
+		}
+		item.Rate = f
+		t, e := time.ParseInLocation(utils.FormatDateTime, v.UpdateTime, time.Local)
+		if e != nil {
+			err = fmt.Errorf("rate api time parse err: %v", e)
+			return
+		}
+		item.UpdateTime = t
+		resList = append(resList, item)
+	}
+	return
+}
+
+// GetTodayCurrencyRateList 获取今日货币及汇率列表
+func GetTodayCurrencyRateList() (list []*fms.CurrencyUnitItem, err error) {
+	list = make([]*fms.CurrencyUnitItem, 0)
+	// 货币列表
+	ob := new(fms.CurrencyUnit)
+	cond := `enable = 1`
+	pars := make([]interface{}, 0)
+	currencyList, e := ob.List(cond, pars)
+	if e != nil {
+		err = fmt.Errorf("获取货币列表失败, Err: %s", e.Error())
+		return
+	}
+
+	rateMap := make(map[string]float64)
+	rateList := make([]*CurrencyRateItem, 0)
+
+	// 读取缓存
+	cacheJson, _ := global.Redis.Get(context.TODO(), utils.CACHE_KEY_CURRENCY_RMB_RATE).Result()
+	if cacheJson != "" {
+		if e = jsoniter.UnmarshalFromString(cacheJson, &rateList); e != nil {
+			err = fmt.Errorf("解析汇率缓存数据失败, Err: %s", e.Error())
+			return
+		}
+	}
+
+	// 请求汇率接口
+	if cacheJson == "" {
+		rateList, e = CurlCurrencyRateApi()
+		if e != nil {
+			err = fmt.Errorf("请求汇率接口失败, Err: %s", e.Error())
+			return
+		}
+		if len(rateList) == 0 {
+			err = fmt.Errorf("汇率接口返回数据为空")
+			return
+		}
+		newCache, e := jsoniter.MarshalToString(rateList)
+		if e != nil {
+			err = fmt.Errorf("写入汇率缓存失败, Err: %s", e.Error())
+			return
+		}
+		now := time.Now()
+		todayLast := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, time.Local)
+		sub := todayLast.Sub(now)
+		_ = global.Redis.SetEX(context.TODO(), utils.CACHE_KEY_CURRENCY_RMB_RATE, newCache, sub)
+	}
+
+	for i := range rateList {
+		rateMap[rateList[i].Code] = rateList[i].Rate
+	}
+	for i := range currencyList {
+		r := rateMap[currencyList[i].Code]
+		if currencyList[i].Code == fms.BaseCurrencyCode {
+			r = 1
+		}
+		list = append(list, &fms.CurrencyUnitItem{
+			Name:     currencyList[i].Name,
+			UnitName: currencyList[i].UnitName,
+			Code:     currencyList[i].Code,
+			Enable:   currencyList[i].Enable,
+			RMBRate:  r,
+			FlagImg:  currencyList[i].FlagImg,
+		})
+	}
+	return
+}

+ 32 - 6
utils/common.go

@@ -13,6 +13,7 @@ import (
 	"image"
 	"image/png"
 	"io"
+	"io/ioutil"
 	"math"
 	"math/rand"
 	"net"
@@ -48,7 +49,7 @@ func GenToken(account string) (accessToken string, err error) {
 	return
 }
 
-//随机数种子
+// 随机数种子
 var rnd = rand.New(rand.NewSource(time.Now().UnixNano()))
 
 // GetRandString 获取随机字符串
@@ -406,8 +407,8 @@ func TrimHtml(src string) string {
 	return strings.TrimSpace(src)
 }
 
-//1556164246  ->  2019-04-25 03:50:46 +0000
-//timestamp
+// 1556164246  ->  2019-04-25 03:50:46 +0000
+// timestamp
 // TimeToTimestamp
 func TimeToTimestamp() {
 	fmt.Println(time.Unix(1556164246, 0).Format(FormatDateTime))
@@ -467,7 +468,7 @@ func GetWilsonScore(p, n float64) float64 {
 	return toFixed(((p+1.9208)/(p+n)-1.96*math.Sqrt(p*n/(p+n)+0.9604)/(p+n))/(1+3.8416/(p+n)), 2)
 }
 
-//将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
+// 将中文数字转化成数字,比如 第三百四十五章,返回第345章 不支持一亿及以上
 func ChangeWordsToNum(str string) (numStr string) {
 	words := ([]rune)(str)
 	num := 0
@@ -643,7 +644,7 @@ func GetMonthStartAndEnd(myYear string, myMonth string) (startDate, endDate stri
 	return t1, t2
 }
 
-//TrimStr 移除字符串中的空格
+// TrimStr 移除字符串中的空格
 func TrimStr(str string) (str2 string) {
 	return strings.Replace(str, " ", "", -1)
 }
@@ -1072,4 +1073,29 @@ func InArrayByStr(idStrList []string, searchId string) (has bool) {
 		}
 	}
 	return
-}
+}
+
+// PublicGetRequest 公共Get请求方法
+func PublicGetRequest(url, authorization string) (body []byte, err error) {
+	method := "GET"
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, nil)
+	if err != nil {
+		return
+	}
+	if authorization != "" {
+		req.Header.Add("Authorization", authorization)
+	}
+	res, err := client.Do(req)
+	if err != nil {
+		return
+	}
+	defer func() {
+		_ = res.Body.Close()
+	}()
+	body, err = ioutil.ReadAll(res.Body)
+	if err != nil {
+		return
+	}
+	return
+}

+ 3 - 2
utils/constants.go

@@ -1,6 +1,6 @@
 package utils
 
-//常量定义
+// 常量定义
 const (
 	FormatTime            = "15:04:05"                //时间格式
 	FormatDate            = "2006-01-02"              //日期格式
@@ -17,7 +17,7 @@ const (
 	PageSize30            = 30
 )
 
-//手机号,电子邮箱正则
+// 手机号,电子邮箱正则
 const (
 	RegularMobile = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0-9])|(17[0-9])|(16[0-9])|(19[0-9]))\\d{8}$" //手机号码
 	RegularEmail  = `\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`                                             //匹配电子邮箱
@@ -34,6 +34,7 @@ const (
 	SYSTEM_LOGIN_TOKEN          = "fms:login:token:"
 	SYSTEM_LOGIN_TOKEN_NO_TRUST = "fms:login:no_trust:" //管理后台登录(不可信登录态)
 	SYSTEM_LOGIN_ADMINID_IP     = "fms:login:admin_id:"
+	CACHE_KEY_CURRENCY_RMB_RATE = "fms:currency:rmb:rate" // 汇率接口
 )
 
 // OSS