auto_export_business.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. // Copyright 2019 getensh.com. All rights reserved.
  2. // Use of this source code is governed by getensh.com.
  3. package crontab
  4. import (
  5. "gd_crontab/apis"
  6. "gd_crontab/errors"
  7. "fmt"
  8. "time"
  9. "gd_crontab/common.in/config"
  10. "gd_crontab/common.in/utils"
  11. "github.com/astaxie/beego/orm"
  12. "github.com/tealeg/xlsx"
  13. "go.uber.org/zap"
  14. )
  15. type TGdBusinessReport struct {
  16. Id int64
  17. Date string `json:"date"`
  18. ApiName string `json:"api_name"`
  19. MerchantName string
  20. Total int `json:"total"`
  21. Valid int `json:"valid"`
  22. DistinctCount int `json:"distinct_count" description:"去重调用量"`
  23. ApiId int64 `json:"api_id"`
  24. MerchantId int64 `json:"merchant_id"`
  25. Charge int `json:"charge"`
  26. UnvalidRedundant int `json:"unvalid_redundant" description:"无效中的重复调用,即失败-失败里的去重调用"`
  27. ArgsFormatError int `json:"args_format_error"`
  28. ArgsUnsupport int `json:"args_unsupport"`
  29. ChargeReuse int `json:"charge_reuse"`
  30. NoRecord int `json:"no_record"`
  31. ProviderError int `json:"provider_error"`
  32. PlatformError int `json:"platform_error"`
  33. TimeoutConf string `json:"timeout_conf"`
  34. TimeoutCount int `json:"timeout_count"`
  35. }
  36. // makeXlsxBusinessHeader 构建日报明细表头
  37. func makeXlsxBusinessHeader(sheet *xlsx.Sheet) {
  38. row := sheet.AddRow()
  39. dateCell := row.AddCell()
  40. dateCell.Value = "日期"
  41. dateCell.VMerge = 1
  42. sheet.SetColWidth(0, 0, 20)
  43. merchantCell := row.AddCell()
  44. merchantCell.VMerge = 1
  45. sheet.SetColWidth(1, 1, 10)
  46. merchantCell.Value = "商户"
  47. apiCell := row.AddCell()
  48. apiCell.VMerge = 1
  49. sheet.SetColWidth(2, 2, 24)
  50. apiCell.Value = "api"
  51. totalInfoCell := row.AddCell()
  52. totalInfoCell.Value = "总调用详情"
  53. totalInfoCell.HMerge = 5
  54. for i := 0; i < 5; i++ {
  55. row.AddCell()
  56. }
  57. unvalidInfoCell := row.AddCell()
  58. unvalidInfoCell.Value = "无效调用分析"
  59. unvalidInfoCell.HMerge = 2
  60. for i := 0; i < 2; i++ {
  61. row.AddCell()
  62. }
  63. queryInfoCell := row.AddCell()
  64. queryInfoCell.Value = "查得分析"
  65. queryInfoCell.HMerge = 1
  66. row.AddCell()
  67. norecordInfoCell := row.AddCell()
  68. norecordInfoCell.Value = "查无及异常分析"
  69. norecordInfoCell.HMerge = 2
  70. for i := 0; i < 2; i++ {
  71. row.AddCell()
  72. }
  73. timeoutInfoCell := row.AddCell()
  74. timeoutInfoCell.Value = "时效性分析"
  75. timeoutInfoCell.HMerge = 2
  76. for i := 0; i < 2; i++ {
  77. row.AddCell()
  78. }
  79. row = sheet.AddRow()
  80. for i := 0; i < 3; i++ {
  81. row.AddCell()
  82. }
  83. totalCell := row.AddCell()
  84. totalCell.Value = "总调用量"
  85. distinctCell := row.AddCell()
  86. distinctCell.Value = "去重调用量"
  87. validCell := row.AddCell()
  88. validCell.Value = "有效调用量"
  89. validRateCell := row.AddCell()
  90. validRateCell.Value = "有效调用率"
  91. chargeCell := row.AddCell()
  92. chargeCell.Value = "计费量"
  93. chargeRateCell := row.AddCell()
  94. chargeRateCell.Value = "计费率"
  95. redundantCell := row.AddCell()
  96. redundantCell.Value = "重复调用"
  97. argsFormatCell := row.AddCell()
  98. argsFormatCell.Value = "入参格式错误"
  99. argsUnsupportCell := row.AddCell()
  100. argsUnsupportCell.Value = "不支持的查询参数"
  101. chargeReuseCell := row.AddCell()
  102. chargeReuseCell.Value = "计费复用量"
  103. chargeReuseRateCell := row.AddCell()
  104. chargeReuseRateCell.Value = "计费复用率"
  105. norecordCell := row.AddCell()
  106. norecordCell.Value = "接口查无"
  107. providerErrorCell := row.AddCell()
  108. providerErrorCell.Value = "数据源异常"
  109. systemErrorCell := row.AddCell()
  110. systemErrorCell.Value = "平台限制"
  111. timeoutConfCell := row.AddCell()
  112. timeoutConfCell.Value = "超时设置"
  113. timeoutCountCell := row.AddCell()
  114. timeoutCountCell.Value = "超时数量"
  115. timeoutRateCell := row.AddCell()
  116. timeoutRateCell.Value = "超时率"
  117. }
  118. func converDataToBusinessReport(info apis.LogQueryUserAcessBusinessExport) TGdBusinessReport {
  119. ret := TGdBusinessReport{}
  120. ret.TimeoutCount = info.TimeoutCount
  121. ret.TimeoutConf = info.TimeoutConf
  122. ret.PlatformError = info.PlatformError
  123. ret.ProviderError = info.ProviderError
  124. ret.NoRecord = info.NoRecord
  125. ret.ChargeReuse = info.ChargeReuse
  126. ret.ArgsUnsupport = info.ArgsUnsupport
  127. ret.ArgsFormatError = info.ArgsFormatError
  128. ret.UnvalidRedundant = info.UnvalidRedundant
  129. ret.Valid = info.Valid
  130. ret.Charge = info.Charge
  131. ret.DistinctCount = info.DistinctCount
  132. ret.Total = info.Total
  133. ret.ApiName = info.ApiName
  134. ret.Date = info.Date
  135. ret.ApiId = info.ApiId
  136. ret.MerchantId = info.MerchantId
  137. ret.MerchantName = info.MerchantName
  138. return ret
  139. }
  140. func getBusinessDataFromReport(start, end string) ([]apis.LogQueryUserAcessBusinessExport, error) {
  141. sql := fmt.Sprintf("select date, merchant_id, api_id, merchant_name, api_name, timeout_conf,"+
  142. "sum(total) as total,"+
  143. "sum(distinct_count) as distinct_count,"+
  144. "sum(valid) as valid,"+
  145. "sum(charge) as charge,"+
  146. "sum(unvalid_redundant) as unvalid_redundant,"+
  147. "sum(args_format_error) as args_format_error,"+
  148. "sum(args_unsupport) as args_unsupport,"+
  149. "sum(charge_reuse) as charge_reuse,"+
  150. "sum(no_record) as no_record,"+
  151. "sum(provider_error) as provider_error,"+
  152. "sum(platform_error) as platform_error,"+
  153. "sum(timeout_count) as timeout_count"+
  154. " from t_gd_business_report where date >= '%s' and date <= '%s' group by merchant_id, api_id ", start, end)
  155. o := orm.NewOrm()
  156. ret := []apis.LogQueryUserAcessBusinessExport{}
  157. _, err := o.Raw(sql).QueryRows(&ret)
  158. if err != nil && err != orm.ErrNoRows {
  159. return nil, errors.DataBaseError
  160. }
  161. for i, v := range ret {
  162. ret[i].Date = fmt.Sprintf("%s至%s", start, end)
  163. ret[i].ValidRate = computeBusinessPercent(float64(v.Valid), float64(v.Total))
  164. ret[i].ChargeRate = computeBusinessPercent(float64(v.Charge), float64(v.Valid))
  165. ret[i].ChargeReuseRate = computeBusinessPercent(float64(v.ChargeReuse), float64(v.Charge))
  166. ret[i].TimeoutRate = computeBusinessPercent(float64(v.TimeoutCount), float64(v.Total))
  167. }
  168. return ret, nil
  169. }
  170. func parseBusinessDetail(sheet *xlsx.Sheet, infos []apis.LogQueryUserAcessBusinessExport, reports []TGdBusinessReport, merchant string) []TGdBusinessReport {
  171. for _, v := range infos {
  172. row := sheet.AddRow()
  173. dateCell := row.AddCell()
  174. dateCell.Value = v.Date
  175. merchantCell := row.AddCell()
  176. merchantCell.Value = merchant
  177. apiCell := row.AddCell()
  178. apiCell.Value = v.ApiName
  179. totalCell := row.AddCell()
  180. totalCell.SetInt(v.Total)
  181. distinctCell := row.AddCell()
  182. distinctCell.SetInt(v.DistinctCount)
  183. validCell := row.AddCell()
  184. validCell.SetInt(v.Valid)
  185. validRateCell := row.AddCell()
  186. SetPercentForXlsx(v.ValidRate, validRateCell)
  187. chargeCell := row.AddCell()
  188. chargeCell.SetInt(v.Charge)
  189. chargeRateCell := row.AddCell()
  190. SetPercentForXlsx(v.ChargeRate, chargeRateCell)
  191. redundantCell := row.AddCell()
  192. redundantCell.SetInt(v.UnvalidRedundant)
  193. argsFormatCell := row.AddCell()
  194. argsFormatCell.SetInt(v.ArgsFormatError)
  195. argsUnsupportCell := row.AddCell()
  196. argsUnsupportCell.SetInt(v.ArgsUnsupport)
  197. chargeReuseCell := row.AddCell()
  198. chargeReuseCell.SetInt(v.ChargeReuse)
  199. chargeReuseRateCell := row.AddCell()
  200. SetPercentForXlsx(v.ChargeReuseRate, chargeReuseRateCell)
  201. norecordCell := row.AddCell()
  202. norecordCell.SetInt(v.NoRecord)
  203. providerErrorCell := row.AddCell()
  204. providerErrorCell.SetInt(v.ProviderError)
  205. systemErrorCell := row.AddCell()
  206. systemErrorCell.SetInt(v.PlatformError)
  207. timeoutConfCell := row.AddCell()
  208. timeoutConfCell.Value = v.TimeoutConf
  209. timeoutCountCell := row.AddCell()
  210. timeoutCountCell.SetInt(v.TimeoutCount)
  211. timeoutRateCell := row.AddCell()
  212. SetPercentForXlsx(v.TimeoutRate, timeoutRateCell)
  213. if reports != nil {
  214. reports = append(reports, converDataToBusinessReport(v))
  215. }
  216. }
  217. return reports
  218. }
  219. func insertBusinessReports(reports []TGdBusinessReport, date string, merchantId int64, apiId int64) error {
  220. if len(reports) == 0 {
  221. return nil
  222. }
  223. sql := fmt.Sprintf("delete from t_gd_business_report where date='%s'", date)
  224. if merchantId > 0 {
  225. sql = fmt.Sprintf("%s and merchant_id=%d", sql, merchantId)
  226. }
  227. if apiId > 0 {
  228. sql = fmt.Sprintf("%s and api_id=%d", sql, apiId)
  229. }
  230. o := orm.NewOrm()
  231. o.Begin()
  232. if _, err := o.Raw(sql).Exec(); err != nil {
  233. o.Rollback()
  234. }
  235. if _, err := o.InsertMulti(len(reports), &reports); err != nil {
  236. o.Rollback()
  237. }
  238. o.Commit()
  239. return nil
  240. }
  241. func sortBusiness(datas []apis.LogQueryUserAcessBusinessExport) ([]apis.LogQueryUserAcessBusinessExport) {
  242. if len(datas) == 0 {
  243. return datas
  244. }
  245. for i := 0; i < len(datas); i++ {
  246. for j := 0; j < len(datas) - i - 1; j++ {
  247. if datas[j].Total < datas[j+1].Total {
  248. tmp := datas[j]
  249. datas[j] = datas[j+1]
  250. datas[j+1] = tmp
  251. }
  252. }
  253. }
  254. return datas
  255. }
  256. type MerchantTotalInfo struct {
  257. MerchantId int64
  258. Total int
  259. }
  260. func sortMerchant(m map[int64]int) []MerchantTotalInfo{
  261. if len(m) == 0 {
  262. return nil
  263. }
  264. array := make([]MerchantTotalInfo, len(m))
  265. i := 0
  266. for k, v := range m {
  267. array[i].Total = v
  268. array[i].MerchantId = k
  269. i++
  270. }
  271. for i = 0; i < len(array); i++ {
  272. for j := 0; j < len(array) - i - 1; j++ {
  273. if array[j].Total < array[j+1].Total {
  274. tmp := array[j]
  275. array[j] = array[j+1]
  276. array[j+1] = tmp
  277. }
  278. }
  279. }
  280. return array
  281. }
  282. // exportBusinessDay商务日报
  283. func exportBusinessDay(start, end, merchantId, apiId int64, isInsert bool) (string, error) {
  284. file := xlsx.NewFile()
  285. date := time.Unix(start, 0).Format("2006-01-02")
  286. detailSheet, err := file.AddSheet("商务报表" + date)
  287. if err != nil {
  288. l.Error("func",
  289. zap.String("call", "file.AddSheet"),
  290. zap.String("args", "明细"),
  291. zap.String("error", err.Error()))
  292. return "", err
  293. }
  294. makeXlsxBusinessHeader(detailSheet)
  295. reports := []TGdBusinessReport{}
  296. //merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  297. //lastMerchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  298. mreq := apis.LogQueryUserAccessBusinessExportReq{}
  299. reply := apis.LogQueryUserAccessBusinessExportReply{}
  300. mreq.StartTimestamp = start
  301. mreq.EndTimestamp = end
  302. mreq.MerchantId = merchantId
  303. if apiId != 0 {
  304. mreq.ApiIdList = append(mreq.ApiIdList, apiId)
  305. }
  306. if time.Now().Unix()-start < 3600*26 {
  307. mreq.TabName = "t_gd_access_log_day"
  308. }
  309. err = LogQueryUserAccessBusinessExport(&mreq, &reply)
  310. if err != nil {
  311. l.Error("func",
  312. zap.String("call", "LogQueryUserAccessBusinessExport"),
  313. zap.String("args", utils.MarshalJsonString(mreq)),
  314. zap.String("error", err.Error()))
  315. return "", err
  316. }
  317. merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  318. merchantTotalMap := map[int64]int{}
  319. for _, v := range reply.LogQueryUserAcessBusiness {
  320. if value, ok := merchantTotalMap[v.MerchantId]; ok {
  321. merchantTotalMap[v.MerchantId] = value + v.Total
  322. } else {
  323. merchantTotalMap[v.MerchantId] = v.Total
  324. }
  325. merchantMap[v.MerchantId] = append(merchantMap[v.MerchantId], v)
  326. }
  327. merchantSorted := sortMerchant(merchantTotalMap)
  328. for _, v := range merchantSorted {
  329. array, ok := merchantMap[v.MerchantId]
  330. if !ok {
  331. continue
  332. }
  333. array = sortBusiness(array)
  334. if len(array) == 0 {
  335. continue
  336. }
  337. reports = parseBusinessDetail(detailSheet, array, reports, array[0].MerchantName)
  338. }
  339. if isInsert {
  340. err = insertBusinessReports(reports, date, merchantId, apiId)
  341. if err != nil {
  342. return "", err
  343. }
  344. }
  345. filename := fmt.Sprintf("gd商务日报-%s", time.Unix(start, 0).Format("2006-01-02"))
  346. path := config.Conf.ReportLocalDir + filename + ".xlsx"
  347. setAllCells(file)
  348. err = file.Save(path)
  349. if err != nil {
  350. l.Error("func",
  351. zap.String("call", "save excel"),
  352. zap.String("file_name", path),
  353. zap.String("error", err.Error()))
  354. }
  355. return path, err
  356. }
  357. // exportBusinessWeek 商务周报
  358. func exportBusinessWeek(weekStart string) (string, error) {
  359. start, end := getWeekExportTimestamp(weekStart)
  360. startDate := time.Unix(start, 0).Format("2006-01-02")
  361. endDate := time.Unix(end-1, 0).Format("2006-01-02")
  362. file := xlsx.NewFile()
  363. date := time.Unix(start, 0).Format("2006-01-02")
  364. detailSheet, err := file.AddSheet("商务报表周报" + date)
  365. if err != nil {
  366. l.Error("func",
  367. zap.String("call", "file.AddSheet"),
  368. zap.String("args", "明细"),
  369. zap.String("error", err.Error()))
  370. return "", err
  371. }
  372. makeXlsxBusinessHeader(detailSheet)
  373. //merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  374. //lastMerchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  375. datas, err := getBusinessDataFromReport(startDate, endDate)
  376. if err != nil {
  377. l.Error("func",
  378. zap.String("call", "getBusinessDataFromReport"),
  379. zap.String("args", ""),
  380. zap.String("error", err.Error()))
  381. return "", err
  382. }
  383. merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  384. merchantTotalMap := map[int64]int{}
  385. for _, v := range datas {
  386. if value, ok := merchantTotalMap[v.MerchantId]; ok {
  387. merchantTotalMap[v.MerchantId] = value + v.Total
  388. } else {
  389. merchantTotalMap[v.MerchantId] = v.Total
  390. }
  391. merchantMap[v.MerchantId] = append(merchantMap[v.MerchantId], v)
  392. }
  393. merchantSorted := sortMerchant(merchantTotalMap)
  394. for _, v := range merchantSorted {
  395. array, ok := merchantMap[v.MerchantId]
  396. if !ok {
  397. continue
  398. }
  399. array = sortBusiness(array)
  400. if len(array) == 0 {
  401. continue
  402. }
  403. parseBusinessDetail(detailSheet, array, nil, array[0].MerchantName)
  404. }
  405. filename := fmt.Sprintf("gd商务周报-%s-%s", startDate, endDate)
  406. path := config.Conf.ReportLocalDir + filename + ".xlsx"
  407. setAllCells(file)
  408. err = file.Save(path)
  409. if err != nil {
  410. l.Error("func",
  411. zap.String("call", "save excel"),
  412. zap.String("file_name", path),
  413. zap.String("error", err.Error()))
  414. }
  415. return path, err
  416. }
  417. // exportBusinessMonth商务月报
  418. func exportBusinessMonth(monthStart string) (string, error) {
  419. start, end := getMonthExportTimestamp(monthStart)
  420. startDate := time.Unix(start, 0).Format("2006-01-02")
  421. endDate := time.Unix(end-1, 0).Format("2006-01-02")
  422. file := xlsx.NewFile()
  423. date := time.Unix(start, 0).Format("2006-01-02")
  424. detailSheet, err := file.AddSheet("商务报表月报" + date)
  425. if err != nil {
  426. l.Error("func",
  427. zap.String("call", "file.AddSheet"),
  428. zap.String("args", "明细"),
  429. zap.String("error", err.Error()))
  430. return "", err
  431. }
  432. makeXlsxBusinessHeader(detailSheet)
  433. //merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  434. //lastMerchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  435. datas, err := getBusinessDataFromReport(startDate, endDate)
  436. if err != nil {
  437. l.Error("func",
  438. zap.String("call", "getBusinessDataFromReport"),
  439. zap.String("args", ""),
  440. zap.String("error", err.Error()))
  441. return "", err
  442. }
  443. merchantMap := map[int64][]apis.LogQueryUserAcessBusinessExport{}
  444. merchantTotalMap := map[int64]int{}
  445. for _, v := range datas {
  446. if value, ok := merchantTotalMap[v.MerchantId]; ok {
  447. merchantTotalMap[v.MerchantId] = value + v.Total
  448. } else {
  449. merchantTotalMap[v.MerchantId] = v.Total
  450. }
  451. merchantMap[v.MerchantId] = append(merchantMap[v.MerchantId], v)
  452. }
  453. merchantSorted := sortMerchant(merchantTotalMap)
  454. for _, v := range merchantSorted {
  455. array, ok := merchantMap[v.MerchantId]
  456. if !ok {
  457. continue
  458. }
  459. array = sortBusiness(array)
  460. if len(array) == 0 {
  461. continue
  462. }
  463. parseBusinessDetail(detailSheet, array, nil, array[0].MerchantName)
  464. }
  465. filename := fmt.Sprintf("gd商务月报-%s-%s", startDate, endDate)
  466. path := config.Conf.ReportLocalDir + filename + ".xlsx"
  467. setAllCells(file)
  468. err = file.Save(path)
  469. if err != nil {
  470. l.Error("func",
  471. zap.String("call", "save excel"),
  472. zap.String("file_name", path),
  473. zap.String("error", err.Error()))
  474. }
  475. return path, err
  476. }