request.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. package offlineactivity
  2. import (
  3. "encoding/csv"
  4. "fmt"
  5. "go-common/library/time"
  6. "math"
  7. "strconv"
  8. time2 "time"
  9. )
  10. const (
  11. dateFmt = "20060102"
  12. dateTimeFmt = "20060102_150405"
  13. filenamePre = "活动"
  14. )
  15. func round(num float64) int {
  16. return int(num + math.Copysign(0.5, num))
  17. }
  18. //ToFixed fix float precision
  19. func ToFixed(num float64, precision int) float64 {
  20. output := math.Pow(10, float64(precision))
  21. return float64(round(num*output)) / output // since go 1.9 doesn't have a math.Round function...
  22. }
  23. //ExportArg export arg
  24. type ExportArg struct {
  25. Export string `form:"export"`
  26. }
  27. //ExportFormat export format
  28. func (e *ExportArg) ExportFormat() string {
  29. return e.Export
  30. }
  31. //BonusInfo bonus struct
  32. type BonusInfo struct {
  33. TotalMoney float64 `json:"total_money"`
  34. MemberCount int64 `json:"member_count"`
  35. Mids string `json:"mids"`
  36. MidList []int64 `json:"-"` // 存储转换后的mids
  37. Filename string `json:"filename"` // 如果有文件名,优先使用文件
  38. }
  39. //AddActivityArg add activity arg
  40. type AddActivityArg struct {
  41. Title string `json:"title"`
  42. Link string `json:"link"`
  43. BonusType int8 `json:"bonus_type"`
  44. Memo string `json:"memo"`
  45. BonusList []*BonusInfo `json:"bonus_list"`
  46. Creator string `json:"-"`
  47. }
  48. //PreAddActivityResult result, nothing to return
  49. type PreAddActivityResult struct {
  50. BonusType int8 `json:"bonus_type"`
  51. MemberCount int64 `json:"member_count"`
  52. TotalMoney float64 `json:"total_money"`
  53. }
  54. //AddActivityResult result, nothing to return
  55. type AddActivityResult struct {
  56. }
  57. //PageArg page arg
  58. type PageArg struct {
  59. Page int `form:"page"`
  60. Size int `form:"size"`
  61. }
  62. //CheckPageValidation check the page validte, return limit offset
  63. func (arg *PageArg) CheckPageValidation() (limit, offset int) {
  64. if arg.Page < 1 {
  65. arg.Page = 1
  66. }
  67. if arg.Size > 100 || arg.Size <= 0 {
  68. arg.Size = 10
  69. }
  70. limit = arg.Size
  71. offset = (arg.Page - 1) * limit
  72. return
  73. }
  74. //ToPageResult cast to page result
  75. func (arg *PageArg) ToPageResult(total int) (res PageResult) {
  76. res.TotalCount = total
  77. res.Page = arg.Page
  78. return
  79. }
  80. //PageResult page result
  81. type PageResult struct {
  82. Page int `json:"page"`
  83. TotalCount int `json:"total_count"`
  84. }
  85. //QueryActivityByIDArg arg
  86. type QueryActivityByIDArg struct {
  87. FromDate string `form:"from_date"` // 20180101
  88. ToDate string `form:"to_date"` // 20180102 closed interval [20180101, 20180102]
  89. ID int64 `form:"id"` // activity id, if not 0, FromDate and toDate not used
  90. PageArg
  91. ExportArg
  92. }
  93. //QueryActivityInfo activity info
  94. type QueryActivityInfo struct {
  95. OfflineActivityInfo
  96. CreateTime string `json:"create_time"`
  97. TotalMoney float64 `json:"total_money"`
  98. MemberCount uint32 `json:"member_count"`
  99. PayDate string `json:"pay_date"`
  100. }
  101. //QueryActivityResult result
  102. type QueryActivityResult struct {
  103. Result []*QueryActivityInfo `json:"result"`
  104. PageResult
  105. }
  106. //GetFileName get file name
  107. func (q *QueryActivityResult) GetFileName() string {
  108. return fmt.Sprintf("%s-%s_%s.csv", filenamePre, "按活动", time2.Now().Format(dateTimeFmt))
  109. }
  110. //ToCsv to buffer
  111. func (q *QueryActivityResult) ToCsv(writer *csv.Writer) {
  112. var title = []string{
  113. "添加日期",
  114. "活动id",
  115. "活动标题",
  116. "活动链接",
  117. "支出金额",
  118. "中奖人数",
  119. "付款日期",
  120. "发奖状态"}
  121. writer.Write(title)
  122. if q == nil {
  123. return
  124. }
  125. for _, v := range q.Result {
  126. var record []string
  127. record = append(record,
  128. v.CreateTime,
  129. strconv.Itoa(int(v.ID)),
  130. v.Title,
  131. v.Link,
  132. fmt.Sprintf("%0.2f", v.TotalMoney),
  133. strconv.Itoa(int(v.MemberCount)),
  134. v.PayDate,
  135. StateToString(int(v.State)),
  136. )
  137. writer.Write(record)
  138. }
  139. }
  140. //CopyFromActivityDB copy from db
  141. func (q *QueryActivityInfo) CopyFromActivityDB(v *OfflineActivityInfo) {
  142. q.OfflineActivityInfo = *v
  143. q.CreateTime = v.CTime.Time().Format(dateFmt)
  144. q.PayDate = q.CreateTime
  145. }
  146. //QueryUpBonusByMidArg arg
  147. type QueryUpBonusByMidArg struct {
  148. Mid int64 `form:"mid"` // activity id, if not 0, FromDate and toDate not used
  149. PageArg
  150. ExportArg
  151. }
  152. //UpSummaryBonusInfo bonus for one up info
  153. type UpSummaryBonusInfo struct {
  154. Mid int64 `json:"mid"`
  155. BilledMoney float64 `json:"billed_money"`
  156. UnbilledMoney float64 `json:"unbilled_money"`
  157. LastBillTime string `json:"last_bill_time"` // 20180101, 最近结算时间
  158. TmpBillTime time.Time `json:"-"` // 用来计算LastBillTime
  159. TotalBonusMoney float64 `json:"total_bonus_money"` // 所有的中奖金额
  160. ActivityID int64 `json:"activity_id"` // 中奖活动ID
  161. }
  162. //Finish finish it before send back
  163. func (s *UpSummaryBonusInfo) Finish() {
  164. if s.TmpBillTime > 0 {
  165. s.LastBillTime = s.TmpBillTime.Time().Format(dateFmt)
  166. }
  167. s.BilledMoney = ToFixed(s.BilledMoney, 2)
  168. s.UnbilledMoney = ToFixed(s.UnbilledMoney, 2)
  169. s.TotalBonusMoney = ToFixed(s.TotalBonusMoney, 2)
  170. }
  171. //QueryUpBonusByMidResult query result
  172. type QueryUpBonusByMidResult struct {
  173. Result []*UpSummaryBonusInfo `json:"result"`
  174. PageResult
  175. }
  176. //GetFileName get file name
  177. func (q *QueryUpBonusByMidResult) GetFileName() string {
  178. return fmt.Sprintf("%s-%s_%s.csv", filenamePre, "结算记录", time2.Now().Format(dateTimeFmt))
  179. }
  180. //ToCsv to buffer
  181. func (q *QueryUpBonusByMidResult) ToCsv(writer *csv.Writer) {
  182. var title = []string{
  183. "UID",
  184. "已结算",
  185. "未结算",
  186. "最近结算时间"}
  187. writer.Write(title)
  188. if q == nil {
  189. return
  190. }
  191. for _, v := range q.Result {
  192. var record []string
  193. record = append(record,
  194. intFormat(v.Mid),
  195. floatFormat(v.BilledMoney),
  196. floatFormat(v.UnbilledMoney),
  197. v.LastBillTime,
  198. )
  199. writer.Write(record)
  200. }
  201. }
  202. //QueryUpBonusByActivityResult use same result, we define another type, because we need to implement interface again
  203. type QueryUpBonusByActivityResult QueryUpBonusByMidResult
  204. //GetFileName get file name
  205. func (q *QueryUpBonusByActivityResult) GetFileName() string {
  206. return fmt.Sprintf("%s-%s_%s.csv", filenamePre, "详细信息", time2.Now().Format(dateTimeFmt))
  207. }
  208. //ToCsv to buffer
  209. func (q *QueryUpBonusByActivityResult) ToCsv(writer *csv.Writer) {
  210. var title = []string{
  211. "UID",
  212. "中奖活动id",
  213. "中奖金额",
  214. "结算日期",
  215. "结算收入",
  216. "未结算收入"}
  217. writer.Write(title)
  218. if q == nil {
  219. return
  220. }
  221. for _, v := range q.Result {
  222. var record []string
  223. record = append(record,
  224. intFormat(v.Mid),
  225. intFormat(v.ActivityID),
  226. floatFormat(v.TotalBonusMoney),
  227. v.LastBillTime,
  228. floatFormat(v.BilledMoney),
  229. floatFormat(v.UnbilledMoney),
  230. )
  231. writer.Write(record)
  232. }
  233. }
  234. //QueryActvityMonthArg arg
  235. type QueryActvityMonthArg struct {
  236. ExportArg
  237. PageArg
  238. FromDate string `form:"from_date"`
  239. ToDate string `form:"to_date"`
  240. }
  241. //ActivityMonthInfo info
  242. type ActivityMonthInfo struct {
  243. CreateTime string `json:"create_time"`
  244. ActivityCount int64 `json:"activity_count"`
  245. MemberCount uint32 `json:"member_count"`
  246. AverageMoneyMember float64 `json:"average_money_member"`
  247. AverageMoneyActivity float64 `json:"average_money_activity"`
  248. TotalBonusMoneyMonth float64 `json:"total_bonus_money"` // 所有的中奖金额
  249. TotalMoneyAccumulate float64 `json:"total_money_accumulate"`
  250. GenerateDay string `json:"generate_day"` // 生成日期
  251. activityMap map[int64]struct{} // 用来保存活动数
  252. }
  253. //AddBonus 增加bonus信息
  254. func (s *ActivityMonthInfo) AddBonus(v *OfflineActivityBonus) {
  255. s.MemberCount += v.MemberCount
  256. s.TotalBonusMoneyMonth += GetMoneyFromDb(v.TotalMoney)
  257. if s.activityMap == nil {
  258. s.activityMap = make(map[int64]struct{})
  259. }
  260. s.activityMap[v.ActivityID] = struct{}{}
  261. }
  262. //Finish finish
  263. func (s *ActivityMonthInfo) Finish() {
  264. if s.MemberCount > 0 {
  265. s.AverageMoneyMember = ToFixed(s.TotalBonusMoneyMonth/float64(s.MemberCount), 2)
  266. }
  267. s.ActivityCount = int64(len(s.activityMap))
  268. if s.ActivityCount > 0 {
  269. s.AverageMoneyActivity = ToFixed(s.TotalBonusMoneyMonth/float64(s.ActivityCount), 2)
  270. }
  271. }
  272. //QueryActivityMonthResult result
  273. type QueryActivityMonthResult struct {
  274. PageResult
  275. Result []*ActivityMonthInfo `json:"result"`
  276. }
  277. //GetFileName get file name
  278. func (q *QueryActivityMonthResult) GetFileName() string {
  279. return fmt.Sprintf("%s-%s_%s.csv", filenamePre, "按月", time2.Now().Format(dateTimeFmt))
  280. }
  281. func floatFormat(f float64) string {
  282. return strconv.FormatFloat(f, 'f', 2, 64)
  283. }
  284. func intFormat(i int64) string {
  285. return strconv.Itoa(int(i))
  286. }
  287. //ToCsv to csv
  288. func (q *QueryActivityMonthResult) ToCsv(writer *csv.Writer) {
  289. var title = []string{
  290. "月份",
  291. "最新数据截止日期",
  292. "月支出",
  293. "活动数",
  294. "中奖人数",
  295. "人均支出",
  296. "活动均支出",
  297. "累计支出"}
  298. writer.Write(title)
  299. if q == nil {
  300. return
  301. }
  302. for _, v := range q.Result {
  303. var record []string
  304. record = append(record,
  305. v.CreateTime,
  306. v.GenerateDay,
  307. floatFormat(v.TotalBonusMoneyMonth),
  308. intFormat(v.ActivityCount),
  309. intFormat(int64(v.MemberCount)),
  310. floatFormat(v.AverageMoneyMember),
  311. floatFormat(v.AverageMoneyActivity),
  312. floatFormat(v.TotalMoneyAccumulate),
  313. )
  314. writer.Write(record)
  315. }
  316. }