seller.go 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012
  1. package census
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/gin-gonic/gin"
  6. "github.com/go-playground/validator/v10"
  7. "github.com/shopspring/decimal"
  8. "github.com/tealeg/xlsx"
  9. "hongze/fms_api/controller/resp"
  10. "hongze/fms_api/global"
  11. "hongze/fms_api/models"
  12. "hongze/fms_api/models/base"
  13. "hongze/fms_api/models/crm"
  14. "hongze/fms_api/models/fms"
  15. "hongze/fms_api/services/alarm_msg"
  16. crmService "hongze/fms_api/services/crm"
  17. "hongze/fms_api/utils"
  18. "net/http"
  19. "strconv"
  20. "strings"
  21. "time"
  22. )
  23. // SellerController 销售统计
  24. type SellerController struct{}
  25. // GroupInvoiceList
  26. // @Title 销售组开票统计列表
  27. // @Description 销售组开票统计列表
  28. // @Param StartDate query string false "开始日期"
  29. // @Param EndDate query string false "结束日期"
  30. // @Param SortField query int false "排序字段: 1-开票金额; 2-组别占比"
  31. // @Param SortType query int false "排序方式: 1-正序; 2-倒序"
  32. // @Param IsExport query int false "是否导出: 0-否; 1-是"
  33. // @Success 200 {object} fms.CensusSellerGroupInvoiceItem
  34. // @router /census/seller/group_invoice_list [get]
  35. func (ct *SellerController) GroupInvoiceList(c *gin.Context) {
  36. var req fms.CensusSellerGroupInvoiceListReq
  37. if e := c.BindQuery(&req); e != nil {
  38. err, ok := e.(validator.ValidationErrors)
  39. if !ok {
  40. resp.FailData("参数解析失败", "Err:"+e.Error(), c)
  41. return
  42. }
  43. resp.FailData("参数解析失败", err.Translate(global.Trans), c)
  44. return
  45. }
  46. var departmentId int
  47. if req.SellerType == 1 {
  48. departmentId = crm.SellerDepartmentId
  49. }else if req.SellerType == 2 {
  50. departmentId = crm.RaiSellerDepartmentId
  51. }else if req.SellerType == 0 {
  52. resp.Fail("请选择销售类型", c)
  53. return
  54. }else {
  55. resp.Fail("请选择正确的销售类型", c)
  56. return
  57. }
  58. outCond := ` department_id = %d AND parent_id = 0 `
  59. outCond = fmt.Sprintf(outCond, departmentId)
  60. cond := ` (invoice_type = %d OR invoice_type = %d) AND a.is_deleted = 0 AND a.seller_id != 0 `
  61. cond = fmt.Sprintf(cond, fms.ContractInvoiceTypeMake, fms.ContractInvoiceTypePreMake)
  62. //adminCond := ` (invoice_type = %d OR invoice_type = %d) AND is_deleted = 0 AND seller_group_id != 0 `
  63. //adminCond = fmt.Sprintf(cond, fms.ContractInvoiceTypeMake, fms.ContractInvoiceTypePreMake)
  64. pars := make([]interface{}, 0)
  65. // 开票日期
  66. if req.StartDate != "" && req.EndDate != "" {
  67. st := fmt.Sprint(req.StartDate, " 00:00:00")
  68. ed := fmt.Sprint(req.EndDate, " 23:59:59")
  69. cond += ` AND (invoice_time BETWEEN '%s' AND '%s')`
  70. cond = fmt.Sprintf(cond, st, ed)
  71. //adminCond += ` AND (invoice_time BETWEEN '%s' AND '%s')`
  72. //adminCond = fmt.Sprintf(cond, st, ed)
  73. }
  74. if req.CompanyType == 1 {
  75. cond += ` AND b.contract_type = 1 `
  76. //historyCond += ` AND new_company = 1 `
  77. } else if req.CompanyType == 2 {
  78. cond += ` AND b.contract_type IN (2,3,4) `
  79. //historyCond += ` AND new_company = 0 `
  80. }
  81. page := new(base.Page)
  82. page.SetPageSize(req.PageSize)
  83. page.SetCurrent(req.Current)
  84. // 排序, 默认开票金额倒序
  85. sortFieldMap := map[int]string{0: "invoice_amount", 1: "invoice_amount", 2: "group_rate"}
  86. sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
  87. page.AddOrderItem(base.OrderItem{Column: sortFieldMap[req.SortField], Asc: sortTypeMap[req.SortType]})
  88. if req.IsExport == 1 {
  89. page.SetPageSize(10000)
  90. page.SetCurrent(1)
  91. }
  92. // 查询开票金额总和(减少子查询)
  93. invOB := new(fms.ContractInvoice)
  94. sumCond := cond
  95. sumPars := make([]interface{}, 0)
  96. invSum, e := invOB.Sum("amount", sumCond, sumPars)
  97. if e != nil {
  98. resp.FailMsg("获取失败", "获取开票金额总和失败, Err: "+e.Error(), c)
  99. return
  100. }
  101. // 查询列表
  102. groupOB := new(crm.SysGroup)
  103. //totalCond := outCond
  104. //totalPars := make([]interface{}, 0)
  105. //total, e := groupOB.Count(totalCond, totalPars)
  106. //if e != nil {
  107. // resp.FailMsg("获取失败", "获取销售组开票统计列表总数失败, Err: "+e.Error(), c)
  108. // return
  109. //}
  110. //list, e := fms.GetCensusSellerGroupInvoicePageList(page, cond, outCond, pars, invSum)
  111. //if e != nil {
  112. // resp.FailMsg("获取失败", "获取销售组开票统计列表失败, Err: "+e.Error(), c)
  113. // return
  114. //}
  115. groupCond := ` department_id = %d AND parent_id = 0 `
  116. groupCond = fmt.Sprintf(groupCond, departmentId)
  117. groupPars := make([]interface{}, 0)
  118. groupList, e := groupOB.List(groupCond, groupPars)
  119. if e != nil {
  120. resp.FailMsg("获取失败", "获取组别列表失败, Err: "+e.Error(), c)
  121. return
  122. }
  123. //total := len(groupList)
  124. groupMap := make(map[int]*crm.SysGroup)
  125. groupIdSlice := make([]string,0)
  126. for i := range groupList {
  127. groupMap[groupList[i].GroupId] = groupList[i]
  128. groupIdSlice = append(groupIdSlice, strconv.Itoa(groupList[i].GroupId))
  129. }
  130. groupStr := strings.Join(groupIdSlice, ",")
  131. total, list, e := fms.GetCensusSellerGroupInvoicePageListV2(page, groupStr, cond, pars, invSum)
  132. if e != nil {
  133. resp.FailMsg("获取失败", "获取销售组开票统计列表失败, Err: "+e.Error(), c)
  134. return
  135. }
  136. for _, v := range list {
  137. if group, ok := groupMap[v.GroupId]; ok{
  138. v.GroupName = group.GroupName
  139. }
  140. }
  141. // 处理百分比, 乘100并保留两位小数
  142. mulNum := decimal.NewFromFloat(100)
  143. for i := range list {
  144. d := decimal.NewFromFloat(list[i].GroupRate)
  145. d = d.Mul(mulNum).Round(2)
  146. a, _ := d.Float64()
  147. list[i].GroupRate = a
  148. }
  149. // 是否导出
  150. if req.IsExport == 1 {
  151. ExportGroupInvoiceList(c, list, req)
  152. return
  153. }
  154. page.SetTotal(int64(total))
  155. baseData := new(base.BaseData)
  156. baseData.SetPage(page)
  157. baseData.SetList(list)
  158. resp.OkData("获取成功", baseData, c)
  159. }
  160. // ExportGroupInvoiceList 导出销售组开票统计列表
  161. func ExportGroupInvoiceList(c *gin.Context, list []*fms.CensusSellerGroupInvoiceItem, req fms.CensusSellerGroupInvoiceListReq) {
  162. // 生成Excel文件
  163. xlsxFile := xlsx.NewFile()
  164. style := xlsx.NewStyle()
  165. alignment := xlsx.Alignment{
  166. Horizontal: "center",
  167. Vertical: "center",
  168. WrapText: true,
  169. }
  170. style.Alignment = alignment
  171. style.ApplyAlignment = true
  172. sheetName := "销售组开票统计"
  173. sheet, err := xlsxFile.AddSheet(sheetName)
  174. if err != nil {
  175. resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
  176. return
  177. }
  178. // 存在筛选则前两行显示时间信息
  179. if req.StartDate != "" && req.EndDate != "" {
  180. timeData := fmt.Sprintf("时间:%s至%s", req.StartDate, req.EndDate)
  181. rowA := sheet.AddRow()
  182. cellAA := rowA.AddCell()
  183. cellAA.SetString("销售统计表")
  184. cellAA.SetStyle(style)
  185. rowB := sheet.AddRow()
  186. rowB.AddCell().SetString(timeData)
  187. // 第三行空出
  188. sheet.AddRow()
  189. }
  190. // 数据表头
  191. rowTitle := []string{"排名", "销售组别", "收入金额(元)", "组别占比"}
  192. titleRow := sheet.AddRow()
  193. for i := range rowTitle {
  194. v := titleRow.AddCell()
  195. v.SetString(rowTitle[i])
  196. v.SetStyle(style)
  197. }
  198. // 填充数据
  199. for k, v := range list {
  200. dataRow := sheet.AddRow()
  201. dataRow.AddCell().SetString(fmt.Sprint(k + 1)) // 排名
  202. dataRow.AddCell().SetString(v.GroupName) // 销售组别
  203. dataRow.AddCell().SetString(fmt.Sprint(v.InvoiceAmount)) // 开票金额
  204. dataRow.AddCell().SetString(fmt.Sprint(v.GroupRate, "%")) // 组别占比
  205. }
  206. // 输出文件
  207. var buffer bytes.Buffer
  208. _ = xlsxFile.Write(&buffer)
  209. content := bytes.NewReader(buffer.Bytes())
  210. randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
  211. fileName := sheetName + randStr + ".xlsx"
  212. c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
  213. c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  214. http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
  215. }
  216. // InvoiceList
  217. // @Title 销售开票统计列表
  218. // @Description 销售开票统计列表
  219. // @Param GroupId query int false "组别ID"
  220. // @Param StartDate query string false "开始日期"
  221. // @Param EndDate query string false "结束日期"
  222. // @Param SortField query int false "排序字段: 1-开票金额; 2-组别占比; 3-全员占比"
  223. // @Param SortType query int false "排序方式: 1-正序; 2-倒序"
  224. // @Param IsExport query int false "是否导出: 0-否; 1-是"
  225. // @Success 200 {object} fms.CensusSellerInvoiceListReq
  226. // @router /census/seller/invoice_list [get]
  227. func (ct *SellerController) InvoiceList(c *gin.Context) {
  228. var req fms.CensusSellerInvoiceListReq
  229. if e := c.BindQuery(&req); e != nil {
  230. err, ok := e.(validator.ValidationErrors)
  231. if !ok {
  232. resp.FailData("参数解析失败", "Err:"+e.Error(), c)
  233. return
  234. }
  235. resp.FailData("参数解析失败", err.Translate(global.Trans), c)
  236. return
  237. }
  238. var departmentId int
  239. if req.SellerType == 1 {
  240. departmentId = crm.SellerDepartmentId
  241. }else if req.SellerType == 2 {
  242. departmentId = crm.RaiSellerDepartmentId
  243. }else if req.SellerType == 0 {
  244. resp.Fail("请选择销售类型", c)
  245. return
  246. }else {
  247. resp.Fail("请选择正确的销售类型", c)
  248. return
  249. }
  250. pars := make([]interface{}, 0)
  251. adminPars := make([]interface{}, 0)
  252. outCond := ` a.department_id = %d `
  253. outCond = fmt.Sprintf(outCond, departmentId)
  254. adminCond := ` department_id = %d `
  255. adminCond = fmt.Sprintf(adminCond, departmentId)
  256. totalCond := ` department_id = %d `
  257. totalCond = fmt.Sprintf(totalCond, departmentId)
  258. totalPars := make([]interface{}, 0)
  259. if !req.ShowResign {
  260. adminCond += ` AND enabled = 1 `
  261. }
  262. if req.GroupId > 0 {
  263. // 筛选组别时, 查询当前组别的下级组(因为admin表存的group_id, 有三级的存的是子ID, 只有二级的存的才是父ID =_=!)
  264. groupCond := `parent_id = ?`
  265. groupPars := make([]interface{}, 0)
  266. groupPars = append(groupPars, req.GroupId)
  267. groupOB := new(crm.SysGroup)
  268. groupList, e := groupOB.List(groupCond, groupPars)
  269. if e != nil {
  270. resp.FailMsg("获取失败", "获取组别下级组列表失败, Err: "+e.Error(), c)
  271. return
  272. }
  273. groupIds := make([]int, 0)
  274. groupIds = append(groupIds, req.GroupId)
  275. for i := range groupList {
  276. groupIds = append(groupIds, groupList[i].GroupId)
  277. }
  278. outCond += ` AND a.group_id IN (?) `
  279. pars = append(pars, groupIds)
  280. adminCond += ` AND group_id IN (?) `
  281. adminPars = append(adminPars, groupIds)
  282. totalCond += ` AND group_id IN (?) `
  283. totalPars = append(totalPars, groupIds)
  284. }
  285. sumCond := ` (invoice_type = ? OR invoice_type = ? ) AND a.is_deleted = 0 AND a.seller_id != 0 `
  286. sumPars := make([]interface{}, 0)
  287. sumPars = append(sumPars, fms.ContractInvoiceTypeMake, fms.ContractInvoiceTypePreMake)
  288. cond := ` (c.invoice_type = %d OR c.invoice_type = %d) AND c.is_deleted = 0 AND c.seller_id != 0 `
  289. inCond := ` (invoice_type = %d OR invoice_type = %d) AND is_deleted = 0 AND seller_id != 0 `
  290. cond = fmt.Sprintf(cond, fms.ContractInvoiceTypeMake, fms.ContractInvoiceTypePreMake)
  291. inCond = fmt.Sprintf(inCond, fms.ContractInvoiceTypeMake, fms.ContractInvoiceTypePreMake)
  292. if req.CompanyType == 1 {
  293. cond += ` AND b.contract_type = 1 `
  294. //historyCond += ` AND new_company = 1 `
  295. } else if req.CompanyType == 2 {
  296. cond += ` AND b.contract_type IN (2,3,4) `
  297. //historyCond += ` AND new_company = 0 `
  298. }
  299. // 开票日期
  300. if req.StartDate != "" && req.EndDate != "" {
  301. st := fmt.Sprint(req.StartDate, " 00:00:00")
  302. ed := fmt.Sprint(req.EndDate, " 23:59:59")
  303. cond += ` AND (c.invoice_time BETWEEN '%s' AND '%s')`
  304. inCond += ` AND (invoice_time BETWEEN '%s' AND '%s')`
  305. cond = fmt.Sprintf(cond, st, ed)
  306. inCond = fmt.Sprintf(inCond, st, ed)
  307. sumCond += ` AND (invoice_time BETWEEN ? AND ?)`
  308. sumPars = append(sumPars, st, ed)
  309. }
  310. page := new(base.Page)
  311. page.SetPageSize(req.PageSize)
  312. page.SetCurrent(req.Current)
  313. // 排序, 默认开票金额倒序
  314. sortFieldMap := map[int]string{0: "invoice_amount", 1: "invoice_amount", 2: "group_rate", 3: "seller_rate"}
  315. sortTypeMap := map[int]bool{0: false, 1: true, 2: false}
  316. page.AddOrderItem(base.OrderItem{Column: sortFieldMap[req.SortField], Asc: sortTypeMap[req.SortType]})
  317. if req.IsExport == 1 {
  318. page.SetPageSize(10000)
  319. page.SetCurrent(1)
  320. }
  321. // 查询开票金额总和(减少子查询)
  322. invOB := new(fms.ContractInvoice)
  323. invSum, e := invOB.Sum("amount", sumCond, sumPars)
  324. if e != nil {
  325. resp.FailMsg("获取失败", "获取开票金额总和失败, Err: "+e.Error(), c)
  326. return
  327. }
  328. // 查询列表
  329. adminOB := new(crm.Admin)
  330. //total, e := adminOB.Count(totalCond, totalPars)
  331. //if e != nil {
  332. // resp.FailMsg("获取失败", "获取销售开票统计列表总数失败, Err: "+e.Error(), c)
  333. // return
  334. //}
  335. //list, e := fms.GetCensusSellerInvoicePageList(page, cond, outCond, pars, invSum)
  336. //if e != nil {
  337. // resp.FailMsg("获取失败", "获取销售开票统计列表失败, Err: "+e.Error(), c)
  338. // return
  339. //}
  340. adminList, e := adminOB.List(adminCond, adminPars)
  341. if e != nil {
  342. resp.FailMsg("获取失败", "获取销售列表失败, Err: "+e.Error(), c)
  343. return
  344. }
  345. //total := len(adminList)
  346. adminIdSlice := make([]string,0)
  347. sellerMap := make(map[int]*crm.Admin)
  348. for i := range adminList {
  349. sellerMap[adminList[i].AdminId] = adminList[i]
  350. adminIdSlice = append(adminIdSlice, strconv.Itoa(adminList[i].AdminId))
  351. }
  352. adminStr := strings.Join(adminIdSlice, ",")
  353. total, list, e := fms.GetCensusSellerInvoicePageListV2(page, adminStr, inCond, cond, pars, invSum)
  354. if e != nil {
  355. resp.FailMsg("获取失败", "获取销售开票统计列表失败, Err: "+e.Error(), c)
  356. return
  357. }
  358. for _, v := range list {
  359. if admin, ok := sellerMap[v.SellerId]; ok{
  360. v.GroupName = admin.GroupName
  361. v.SellerName = admin.RealName
  362. v.GroupId = admin.GroupId
  363. }
  364. }
  365. // 分组信息, list的groupId可能是三级的ID, 要转为对应的二级
  366. groupMap, e := crmService.GetSellerTeamGroupMap()
  367. if e != nil {
  368. resp.FailMsg("获取失败", "获取组别对应信息失败, Err: "+e.Error(), c)
  369. return
  370. }
  371. mulNum := decimal.NewFromFloat(100)
  372. for i := range list {
  373. g := groupMap[list[i].GroupId]
  374. if g != nil {
  375. list[i].GroupId = g.GroupId
  376. list[i].GroupName = g.GroupName
  377. }
  378. // 处理百分比, 乘100并保留两位小数
  379. d := decimal.NewFromFloat(list[i].GroupRate)
  380. d = d.Mul(mulNum).Round(2)
  381. a, _ := d.Float64()
  382. list[i].GroupRate = a
  383. d2 := decimal.NewFromFloat(list[i].SellerRate)
  384. d2 = d2.Mul(mulNum).Round(2)
  385. a2, _ := d2.Float64()
  386. list[i].SellerRate = a2
  387. }
  388. // 是否导出
  389. if req.IsExport == 1 {
  390. ExportInvoiceList(c, list, req)
  391. return
  392. }
  393. page.SetTotal(int64(total))
  394. baseData := new(base.BaseData)
  395. baseData.SetPage(page)
  396. baseData.SetList(list)
  397. resp.OkData("获取成功", baseData, c)
  398. }
  399. // ExportInvoiceList 导出销售开票统计列表
  400. func ExportInvoiceList(c *gin.Context, list []*fms.CensusSellerInvoiceItem, req fms.CensusSellerInvoiceListReq) {
  401. // 生成Excel文件
  402. xlsxFile := xlsx.NewFile()
  403. style := xlsx.NewStyle()
  404. alignment := xlsx.Alignment{
  405. Horizontal: "center",
  406. Vertical: "center",
  407. WrapText: true,
  408. }
  409. style.Alignment = alignment
  410. style.ApplyAlignment = true
  411. sheetName := "销售开票统计"
  412. sheet, err := xlsxFile.AddSheet(sheetName)
  413. if err != nil {
  414. resp.FailData("新增Sheet失败", "Err:"+err.Error(), c)
  415. return
  416. }
  417. // 存在筛选则前两行显示时间信息
  418. if req.StartDate != "" && req.EndDate != "" {
  419. timeData := fmt.Sprintf("时间:%s至%s", req.StartDate, req.EndDate)
  420. rowA := sheet.AddRow()
  421. cellAA := rowA.AddCell()
  422. cellAA.SetString("销售统计表")
  423. cellAA.SetStyle(style)
  424. rowB := sheet.AddRow()
  425. rowB.AddCell().SetString(timeData)
  426. // 第三行空出
  427. sheet.AddRow()
  428. }
  429. // 数据表头
  430. rowTitle := []string{"排名", "销售员", "销售组别", "收入金额(元)", "小组占比", "全员占比"}
  431. titleRow := sheet.AddRow()
  432. for i := range rowTitle {
  433. v := titleRow.AddCell()
  434. v.SetString(rowTitle[i])
  435. v.SetStyle(style)
  436. }
  437. // 填充数据
  438. for k, v := range list {
  439. dataRow := sheet.AddRow()
  440. dataRow.AddCell().SetString(fmt.Sprint(k + 1)) // 排名
  441. dataRow.AddCell().SetString(v.SellerName) // 销售员
  442. dataRow.AddCell().SetString(v.GroupName) // 销售组别
  443. dataRow.AddCell().SetString(fmt.Sprint(v.InvoiceAmount)) // 开票金额
  444. dataRow.AddCell().SetString(fmt.Sprint(v.GroupRate, "%")) // 小组占比
  445. dataRow.AddCell().SetString(fmt.Sprint(v.SellerRate, "%")) // 全员占比
  446. }
  447. // 输出文件
  448. var buffer bytes.Buffer
  449. _ = xlsxFile.Write(&buffer)
  450. content := bytes.NewReader(buffer.Bytes())
  451. randStr := time.Now().Format(utils.FormatDateTimeUnSpace)
  452. fileName := sheetName + randStr + ".xlsx"
  453. c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
  454. c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  455. http.ServeContent(c.Writer, c.Request, fileName, time.Now(), content)
  456. }
  457. func (this *SellerController) GroupInvoiceListV2(c *gin.Context) {
  458. var req fms.IncomeListReq
  459. if e := c.BindQuery(&req); e != nil {
  460. err, ok := e.(validator.ValidationErrors)
  461. if !ok {
  462. resp.FailData("参数解析失败", "Err:"+e.Error(), c)
  463. return
  464. }
  465. resp.FailData("参数解析失败", err.Translate(global.Trans), c)
  466. return
  467. }
  468. //收入统计
  469. var incomeList models.CensusIncomeChartResp
  470. ch := make(chan models.CensusIncomeChartResp, 1)
  471. go getGroupInvoiceList(ch, req)
  472. for v := range ch {
  473. incomeList = v
  474. close(ch)
  475. }
  476. // 是否导出
  477. if req.IsExport == 1 {
  478. ExportIncomeList(c, incomeList.DataList)
  479. return
  480. }
  481. resp.OkData("获取成功", incomeList, c)
  482. }
  483. func getGroupInvoiceList(ch chan models.CensusIncomeChartResp, req fms.IncomeListReq) (incomeChart models.CensusIncomeChartResp, err error) {
  484. defer func() {
  485. if err != nil {
  486. global.LOG.Error(err)
  487. if err != utils.ErrNoRow {
  488. go alarm_msg.SendAlarmMsg("获取业务收入金额统计数据异常,Err:"+err.Error(), 3)
  489. }
  490. }
  491. ch <- incomeChart
  492. }()
  493. //获取最新的开票到款日期
  494. cond := ``
  495. historyCond := ``
  496. pars := make([]interface{}, 0)
  497. historyPars := make([]interface{}, 0)
  498. //if req.SellerIds != "" {
  499. // sellerIds := strings.Split(req.SellerIds, ",")
  500. // cond += ` AND (a.seller_id in ? ) `
  501. // historyCond += ` AND (seller_id in ? ) `
  502. // pars = append(pars, sellerIds)
  503. // historyPars = append(historyPars, sellerIds)
  504. //}
  505. if req.CompanyType == 1 {
  506. cond += ` AND b.contract_type = 1 `
  507. historyCond += ` AND new_company = 1 `
  508. } else if req.CompanyType == 2 {
  509. cond += ` AND b.contract_type IN (2,3,4) `
  510. historyCond += ` AND new_company = 0 `
  511. }
  512. var latestTime time.Time
  513. invoiceItem, err := fms.GetLatestIncome(cond, pars)
  514. if err != nil && err != utils.ErrNoRow {
  515. err = fmt.Errorf("获取最新的开票或到款日期, Err: %s", err.Error())
  516. return
  517. }
  518. latestTime = invoiceItem.InvoiceDate
  519. if err == utils.ErrNoRow {
  520. historyItem, e := fms.GetLatestHistoryIncome(historyCond, historyPars)
  521. if e != nil && e != utils.ErrNoRow {
  522. err = fmt.Errorf("获取最新的历史开票或到款日期, Err: %s", e.Error())
  523. return
  524. }
  525. latestTime = historyItem.InvoiceDate
  526. }
  527. if latestTime.IsZero() {
  528. latestTime = time.Now()
  529. }
  530. latestTime = latestTime.AddDate(0, 0, -latestTime.Day()+1)
  531. var dateSlice []string
  532. var totalMoneySlice, prevTotalMoneySlice []float64
  533. var yoySlice []string
  534. var yearNum, monthNum int
  535. var reqStartDate, reqEndDate time.Time
  536. historyTime, _ := time.Parse(utils.FormatDate, "2023-04-01")
  537. if req.StartDate != "" && req.EndDate != "" {
  538. st := fmt.Sprint(req.StartDate, "-01 00:00:00")
  539. ed := fmt.Sprint(req.EndDate, "-01 23:59:59")
  540. reqStartDate, _ = time.Parse(utils.FormatDateTime, st)
  541. reqEndDate, _ = time.Parse(utils.FormatDateTime, ed)
  542. if reqEndDate.After(latestTime) {
  543. yearNum = latestTime.Year() - reqStartDate.Year()
  544. monthNum = int(latestTime.Month() - reqStartDate.Month())
  545. } else {
  546. yearNum = reqEndDate.Year() - reqStartDate.Year()
  547. monthNum = int(reqEndDate.Month() - reqStartDate.Month())
  548. }
  549. } else {
  550. yearNum = latestTime.Year() - 2020
  551. monthNum = int(latestTime.Month() - 1)
  552. }
  553. if yearNum < 0 {
  554. yearNum = -yearNum
  555. }
  556. if monthNum < 0 {
  557. monthNum = -monthNum
  558. }
  559. numMonth := yearNum*12 + monthNum //共存在多少个月
  560. // 累计值
  561. var accumulate float64
  562. var partAccumulate float64
  563. var historyAccumulate float64
  564. var partHistoryAccumulate float64
  565. //dataList := make([]*fms.IncomeSummaryItem, 0)
  566. //historydataList := make([]*fms.IncomeSummaryItem, 0)
  567. fmt.Println("numMonth:", numMonth)
  568. fmt.Println("InvoiceDate:", latestTime)
  569. var j int
  570. for i := 0; i <= numMonth; i++ {
  571. //timeNow, _ := time.Parse("2006-01", time.Now().Format("2006-01"))
  572. var endDateTime time.Time
  573. var prevEndDateTime time.Time
  574. var prevStartDate, prevEndDate string
  575. var startDate, endDate string
  576. //开始日期
  577. if req.StartDate != "" && req.EndDate != "" {
  578. startDate = reqStartDate.AddDate(0, i, 0).Format("2006-01")
  579. prevStartDate = reqStartDate.AddDate(-1, i, 0).Format("2006-01")
  580. } else {
  581. startDate = latestTime.AddDate(0, i-numMonth, 0).Format("2006-01")
  582. prevStartDate = latestTime.AddDate(-1, i-numMonth, 0).Format("2006-01")
  583. }
  584. startDate = fmt.Sprint(startDate, "-01")
  585. prevStartDate = fmt.Sprint(prevStartDate, "-01")
  586. startDateTime, _ := time.Parse(utils.FormatDate, startDate)
  587. prevStartDateTime, _ := time.Parse(utils.FormatDate, prevStartDate)
  588. //结束日期
  589. if req.StartDate != "" && req.EndDate != "" {
  590. endDateTime = reqStartDate.AddDate(0, i+1, -1)
  591. prevEndDateTime = reqStartDate.AddDate(-1, i+1, -1)
  592. if reqEndDate.After(latestTime) {
  593. endDateTime = latestTime.AddDate(0, i-numMonth+1, -1)
  594. prevEndDateTime = latestTime.AddDate(-1, i-numMonth+1, -1)
  595. }
  596. } else {
  597. endDateTime = latestTime.AddDate(0, i-numMonth+1, -1)
  598. prevEndDateTime = latestTime.AddDate(-1, i-numMonth+1, -1)
  599. }
  600. endDate = endDateTime.Format(utils.FormatDate)
  601. prevEndDate = prevEndDateTime.Format(utils.FormatDate)
  602. cond := `1 = 1`
  603. histrtyCond := `1 = 1`
  604. pars := make([]interface{}, 0)
  605. historyPars := make([]interface{}, 0)
  606. prevCond := `1 = 1`
  607. prevHistoryCond := `1 = 1`
  608. prevPars := make([]interface{}, 0)
  609. prevHistoryPars := make([]interface{}, 0)
  610. if req.CompanyType == 1 {
  611. cond += ` AND b.contract_type = 1 `
  612. prevCond += ` AND b.contract_type = 1 `
  613. histrtyCond += ` AND new_company = 1 `
  614. prevHistoryCond += ` AND new_company = 1 `
  615. } else if req.CompanyType == 2 {
  616. cond += ` AND b.contract_type IN (2,3,4) `
  617. prevCond += ` AND b.contract_type IN (2,3,4) `
  618. histrtyCond += ` AND new_company = 0 `
  619. prevHistoryCond += ` AND new_company = 0 `
  620. }
  621. //if req.SellerIds != "" {
  622. // sellerIds := strings.Split(req.SellerIds, ",")
  623. // cond += ` AND (c.seller_id in ? OR d.seller_id in ?)`
  624. // pars = append(pars, sellerIds, sellerIds)
  625. // prevCond += ` AND (c.seller_id in ? OR d.seller_id in ?)`
  626. // prevPars = append(prevPars, sellerIds, sellerIds)
  627. // histrtyCond += ` AND seller_id in ? `
  628. // prevHistoryCond += ` AND seller_id in ? `
  629. // historyPars = append(historyPars, sellerIds)
  630. // prevHistoryPars = append(prevHistoryPars, sellerIds)
  631. //}
  632. {
  633. //本期
  634. st := fmt.Sprint(startDate, " 00:00:00")
  635. ed := fmt.Sprint(endDate, " 23:59:59")
  636. //校验日期,分段查询
  637. if startDateTime.After(historyTime) || startDateTime.Equal(historyTime) {
  638. //全部走新查询
  639. //fmt.Println("新查询")
  640. cond += ` AND ((c.invoice_time BETWEEN ? AND ?) or (d.invoice_time BETWEEN ? AND ?))`
  641. pars = append(pars, st, ed, st, ed)
  642. summaryIds, e := fms.GetInvoicePaymentCensusSummaryDataIds(cond, pars)
  643. if e != nil {
  644. return
  645. }
  646. // 开票到款金额合计(换算后)
  647. var amountTotal float64
  648. if len(summaryIds) > 0 {
  649. amountCond := `a.id IN ? `
  650. amountPars := make([]interface{}, 0)
  651. amountPars = append(amountPars, summaryIds)
  652. if req.SellerIds != "" {
  653. sellerIds := strings.Split(req.SellerIds, ",")
  654. amountCond += ` AND (( b.seller_id IN ? AND a.invoice_id <> 0 AND b.invoice_time BETWEEN ? AND ?)`
  655. amountCond += `OR ( d.seller_id IN ? AND a.payment_id <> 0 AND a.invoice_id = 0 AND d.invoice_time BETWEEN ? AND ?)) `
  656. amountPars = append(amountPars, sellerIds, st, ed, sellerIds, st, ed)
  657. } else {
  658. amountCond += ` AND ((a.invoice_id <> 0 AND b.invoice_time BETWEEN ? AND ?)`
  659. amountCond += `OR (a.payment_id <> 0 AND a.invoice_id = 0 AND d.invoice_time BETWEEN ? AND ?))`
  660. amountPars = append(amountPars, st, ed, st, ed)
  661. }
  662. results, e := fms.GetContractSummaryIncomeAmount(amountCond, amountPars)
  663. if e != nil {
  664. err = fmt.Errorf("获取汇总数据失败, Err: %s", e.Error())
  665. return
  666. }
  667. //dataList = append(dataList, results...)
  668. var amountSum float64
  669. for _, result := range results {
  670. incomeChart.DataList = append(incomeChart.DataList, result)
  671. amountSum += result.Amount
  672. fmt.Println("result.Amount:", result.Amount)
  673. }
  674. amountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountSum), 64)
  675. accumulate += amountTotal
  676. partAccumulate += amountTotal
  677. }
  678. if i == j || i == numMonth {
  679. if req.ListParam == "4" {
  680. totalMoneySlice = append(totalMoneySlice, accumulate)
  681. if startDateTime.Month() == 12 {
  682. accumulate = 0
  683. }
  684. } else if req.ListParam == "0" {
  685. totalMoneySlice = append(totalMoneySlice, amountTotal)
  686. } else if i > 0 || i == numMonth {
  687. totalMoneySlice = append(totalMoneySlice, partAccumulate)
  688. fmt.Println("partAccumulate:", partAccumulate)
  689. partAccumulate = 0.0
  690. }
  691. }
  692. } else if endDateTime.Before(historyTime) || endDateTime.Equal(historyTime) {
  693. //全部走旧查询
  694. //fmt.Println("旧查询")
  695. //fmt.Println("st:",st)
  696. //fmt.Println("ed:",ed)
  697. histrtyCond += ` AND (invoice_time BETWEEN ? AND ? )`
  698. historyPars = append(historyPars, st, ed)
  699. //fmt.Println("st:",st)
  700. //fmt.Println("ed:",ed)
  701. // 开票到款金额合计(换算后)
  702. var amountTotal float64
  703. results, e := fms.GetIncomeHistory(histrtyCond, historyPars)
  704. if e != nil {
  705. err = fmt.Errorf("获取汇总数据失败, Err: %s", e.Error())
  706. return
  707. }
  708. var amountSum float64
  709. //dataList = append(dataList, results...)
  710. for _, result := range results {
  711. incomeChart.DataList = append(incomeChart.DataList, result)
  712. amountSum += result.Amount
  713. }
  714. amountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountSum), 64)
  715. accumulate += amountTotal
  716. partAccumulate += amountTotal
  717. if i == j || i == numMonth {
  718. if req.ListParam == "4" {
  719. totalMoneySlice = append(totalMoneySlice, accumulate)
  720. if startDateTime.Month() == 12 {
  721. accumulate = 0
  722. }
  723. } else if req.ListParam == "0" {
  724. totalMoneySlice = append(totalMoneySlice, amountTotal)
  725. } else if i > 0 || i == numMonth {
  726. totalMoneySlice = append(totalMoneySlice, partAccumulate)
  727. partAccumulate = 0.0
  728. }
  729. }
  730. //fmt.Println("partAccumulate:",partAccumulate)
  731. }
  732. }
  733. { // 去年同期,用于计算同比值
  734. prevSt := fmt.Sprint(prevStartDate, " 00:00:00") // 格式化上一年同一天的开始时间
  735. prevEd := fmt.Sprint(prevEndDate, " 23:59:59") // 格式化上一年同一天的结束时间
  736. // 校验日期,分段查询
  737. if prevStartDateTime.After(historyTime) || prevStartDateTime.Equal(historyTime) {
  738. // 全部走新查询
  739. prevCond += ` AND ((b.invoice_time BETWEEN ? AND ?) or (d.invoice_time BETWEEN ? AND ?))` // 查询条件加入新的时间范围
  740. prevPars = append(prevPars, prevSt, prevEd, prevSt, prevEd) // 添加时间参数到参数列表
  741. prevSummaryIds, e := fms.GetInvoicePaymentCensusSummaryDataIds(prevCond, prevPars) // 获取摘要ID列表
  742. if e != nil {
  743. return
  744. }
  745. // 开票到款金额合计(换算后)
  746. var prevAmountTotal float64
  747. if len(prevSummaryIds) > 0 {
  748. amountCond := `a.id IN ? ` // 查询条件为ID在给定的摘要ID列表中
  749. amountPars := make([]interface{}, 0)
  750. amountPars = append(amountPars, prevSummaryIds) // 将摘要ID列表添加到参数列表
  751. if req.SellerIds != "" {
  752. sellerIds := strings.Split(req.SellerIds, ",")
  753. amountCond += ` AND (( b.seller_id IN ? AND a.invoice_id <> 0 AND b.invoice_time BETWEEN ? AND ?)`
  754. amountCond += `OR ( d.seller_id IN ? AND a.payment_id <> 0 AND a.invoice_id = 0 AND d.invoice_time BETWEEN ? AND ?)) ` // 根据卖家ID和发票/支付状态筛选时间范围
  755. amountPars = append(amountPars, sellerIds, prevSt, prevEd, sellerIds, prevSt, prevEd) // 将卖家ID列表添加到参数列表
  756. } else {
  757. amountCond += ` AND ((a.invoice_id <> 0 AND b.invoice_time BETWEEN ? AND ?)`
  758. amountCond += `OR (a.payment_id <> 0 AND a.invoice_id = 0 AND d.invoice_time BETWEEN ? AND ?))` // 根据发票/支付状态筛选时间范围
  759. amountPars = append(amountPars, prevSt, prevEd)
  760. }
  761. results, e := fms.GetContractSummaryIncomeAmount(amountCond, amountPars) // 获取合同摘要收入金额数据
  762. if e != nil {
  763. err = fmt.Errorf("获取汇总数据失败, Err: %s", e.Error())
  764. return
  765. }
  766. var amountSum float64
  767. //historydataList = append(historydataList, results...)
  768. for _, result := range results {
  769. amountSum += result.Amount // 累计收入金额
  770. }
  771. prevAmountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountSum), 64) // 将累计金额转换为浮点数
  772. historyAccumulate += prevAmountTotal // 累计历史金额
  773. partHistoryAccumulate += prevAmountTotal // 累计部分历史金额
  774. }
  775. if i == j || i == numMonth {
  776. if req.ListParam == "4" {
  777. prevTotalMoneySlice = append(prevTotalMoneySlice, historyAccumulate) // 将累计金额添加到总金额切片中
  778. if prevStartDateTime.Month() == 12 {
  779. historyAccumulate = 0 // 如果是去年的12月份,则将历史金额清零
  780. }
  781. } else if req.ListParam == "0" {
  782. prevTotalMoneySlice = append(prevTotalMoneySlice, prevAmountTotal) // 将部分历史金额添加到总金额切片中
  783. } else if i > 0 || i == numMonth {
  784. prevTotalMoneySlice = append(prevTotalMoneySlice, partHistoryAccumulate) // 将部分历史金额添加到总金额切片中
  785. fmt.Println("partHistoryAccumulate:", partHistoryAccumulate)
  786. partHistoryAccumulate = 0.0 // 清零部分历史金额
  787. }
  788. }
  789. } else if prevEndDateTime.Before(historyTime) || prevEndDateTime.Equal(historyTime) {
  790. // 全部走旧查询
  791. fmt.Println("prevSt:", prevSt)
  792. fmt.Println("prevEd:", prevEd)
  793. prevHistoryCond += ` AND (invoice_time BETWEEN ? AND ?)` // 查询条件加入旧的时间范围
  794. prevHistoryPars = append(prevHistoryPars, prevSt, prevEd) // 添加时间参数到参数列表
  795. // 开票到款金额合计(换算后)
  796. var amountTotal float64
  797. results, e := fms.GetIncomeHistory(prevHistoryCond, prevHistoryPars) // 获取历史收入数据
  798. if e != nil {
  799. err = fmt.Errorf("获取汇总数据失败, Err: %s", e.Error())
  800. return
  801. }
  802. //historydataList = append(historydataList, results...)
  803. var amountSum float64
  804. for _, result := range results {
  805. amountSum += result.Amount // 累计收入金额
  806. }
  807. amountTotal, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", amountSum), 64) // 将累计金额转换为浮点数
  808. historyAccumulate += amountTotal // 累计历史金额
  809. partHistoryAccumulate += amountTotal // 累计部分历史金额
  810. if i == j || i == numMonth {
  811. if req.ListParam == "4" {
  812. prevTotalMoneySlice = append(prevTotalMoneySlice, historyAccumulate) // 将累计金额添加到总金额切片中
  813. if prevStartDateTime.Month() == 12 {
  814. historyAccumulate = 0 // 如果是去年的12月份,则将历史金额清零
  815. }
  816. } else if req.ListParam == "0" {
  817. prevTotalMoneySlice = append(prevTotalMoneySlice, amountTotal) // 将历史金额添加到总金额切片中
  818. } else if i > 0 || i == numMonth {
  819. prevTotalMoneySlice = append(prevTotalMoneySlice, partHistoryAccumulate) // 将部分历史金额添加到总金额切片中
  820. fmt.Println("partHistoryAccumulate:", partHistoryAccumulate)
  821. partHistoryAccumulate = 0.0 // 清零部分历史金额
  822. }
  823. }
  824. if req.ListParam == "1" && i == j {
  825. if i == 0 {
  826. dateSlice = append(dateSlice, startDateTime.AddDate(0, 2, 0).Format("06/01")) // 添加下一个月份的开始日期到日期切片中
  827. j = j + 2
  828. } else {
  829. dateSlice = append(dateSlice, startDateTime.AddDate(0, 3, 0).Format("06/01")) // 添加下一季度的开始日期到日期切片中
  830. j = j + 3
  831. }
  832. } else if req.ListParam == "2" && i == j {
  833. if i == 0 {
  834. dateSlice = append(dateSlice, startDateTime.AddDate(0, 5, 0).Format("06/01")) // 添加下五个月份的开始日期到日期切片中
  835. j = j + 5
  836. } else {
  837. dateSlice = append(dateSlice, startDateTime.AddDate(0, 6, 0).Format("06/01")) // 添加下半年的开始日期到日期切片中
  838. j = j + 6
  839. }
  840. } else if req.ListParam == "3" && i == j {
  841. if i == 0 {
  842. dateSlice = append(dateSlice, startDateTime.AddDate(0, 11, 0).Format("06/01")) // 添加下十一个月份的开始日期到日期切片中
  843. j = j + 11
  844. } else {
  845. dateSlice = append(dateSlice, startDateTime.AddDate(0, 12, 0).Format("06/01")) // 添加下一季度的开始日期到日期切片中
  846. j = j + 12
  847. }
  848. } else if i == j {
  849. dateSlice = append(dateSlice, startDateTime.Format("06/01")) // 添加当月开始日期到日期切片中
  850. j++
  851. }
  852. }
  853. if req.ListParam == "1" && i == j {
  854. if i == 0 {
  855. dateSlice = append(dateSlice, startDateTime.AddDate(0, 2, 0).Format("06/01")) // 添加下一个月份的开始日期到日期切片中
  856. j = j + 2
  857. } else {
  858. dateSlice = append(dateSlice, startDateTime.AddDate(0, 3, 0).Format("06/01")) // 添加下一季度的开始日期到日期切片中
  859. j = j + 3
  860. }
  861. } else if req.ListParam == "2" && i == j {
  862. if i == 0 {
  863. dateSlice = append(dateSlice, startDateTime.AddDate(0, 5, 0).Format("06/01")) // 添加下五个月份的开始日期到日期切片中
  864. j = j + 5
  865. } else {
  866. dateSlice = append(dateSlice, startDateTime.AddDate(0, 6, 0).Format("06/01")) // 添加下半年的开始日期到日期切片中
  867. j = j + 6
  868. }
  869. } else if req.ListParam == "3" && i == j {
  870. if i == 0 {
  871. dateSlice = append(dateSlice, startDateTime.AddDate(0, 11, 0).Format("06/01"))
  872. j = j + 11
  873. } else {
  874. dateSlice = append(dateSlice, startDateTime.AddDate(0, 12, 0).Format("06/01"))
  875. j = j + 12
  876. }
  877. } else if i == j {
  878. dateSlice = append(dateSlice, startDateTime.Format("06/01"))
  879. j++
  880. }
  881. }
  882. }
  883. fmt.Println("prevTotalMoneySlice:", len(prevTotalMoneySlice))
  884. fmt.Println("totalMoneySlice:", len(totalMoneySlice))
  885. if req.CompanyType != 3 {
  886. //计算同比值
  887. for i := range prevTotalMoneySlice {
  888. var yoy float64
  889. var yoyStr string
  890. totalMoneySlice[i], _ = strconv.ParseFloat(fmt.Sprintf("%.2f", totalMoneySlice[i]), 64)
  891. if prevTotalMoneySlice[i] != 0 && totalMoneySlice[i] != 0 {
  892. yoy = (totalMoneySlice[i] - prevTotalMoneySlice[i]) / prevTotalMoneySlice[i]
  893. yoyStr = fmt.Sprintf("%.4f", yoy)
  894. if i == len(prevTotalMoneySlice)-1 && i > 0 && req.ListParam == "3" {
  895. fmt.Println("totalMoneySlice[i-1]:", totalMoneySlice[i-1])
  896. yoy = (totalMoneySlice[i] - totalMoneySlice[i-1]) / totalMoneySlice[i-1]
  897. yoyStr = fmt.Sprintf("%.4f", yoy)
  898. }
  899. }
  900. yoySlice = append(yoySlice, yoyStr)
  901. }
  902. } else {
  903. // 当筛选条件是”月度“时,并且客户是”未续约“客户,展示柱形图和曲线图
  904. // 当筛选条件是”季度“、”半年度“、”年度“、”月度统计“时,并且客户是”未续约“时,仅展示柱形图,无曲线图
  905. // 未续约收入金额=去年同期总收入金额(新客户+老客户)-当期老客户收入金额
  906. // 移动平均值:若是10月份,计算8月,9月,10月,这三个月的收入金额平均值
  907. for i := range prevTotalMoneySlice {
  908. totalMoneySlice[i], _ = strconv.ParseFloat(fmt.Sprintf("%.2f", prevTotalMoneySlice[i]-totalMoneySlice[i]), 64)
  909. var yoy float64
  910. var yoyStr string
  911. if i > 1 && req.ListParam == "0" {
  912. // 前俩月没有
  913. yoy = (totalMoneySlice[i] + totalMoneySlice[i-1] + totalMoneySlice[i-2]) / 3
  914. yoyStr = fmt.Sprintf("%.4f", yoy)
  915. yoySlice = append(yoySlice, yoyStr)
  916. } else {
  917. yoySlice = append(yoySlice, "")
  918. }
  919. }
  920. }
  921. incomeChart.Title = "开票到款统计图"
  922. incomeChart.Date = dateSlice
  923. incomeChart.TotalMoney = totalMoneySlice
  924. incomeChart.PrevTotalMoney = prevTotalMoneySlice
  925. incomeChart.Yoy = yoySlice
  926. return
  927. }