report.go 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. package home
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "math"
  7. "time"
  8. contDao "dashoo.cn/micro/app/dao/contract"
  9. platDao "dashoo.cn/micro/app/dao/plat"
  10. projDao "dashoo.cn/micro/app/dao/proj"
  11. "dashoo.cn/micro/app/model/home"
  12. "dashoo.cn/micro/app/model/plat"
  13. "dashoo.cn/micro/app/service"
  14. contractService "dashoo.cn/micro/app/service/contract"
  15. platService "dashoo.cn/micro/app/service/plat"
  16. projSrv "dashoo.cn/micro/app/service/proj"
  17. "dashoo.cn/opms_libary/micro_srv"
  18. "dashoo.cn/opms_libary/myerrors"
  19. "github.com/gogf/gf/database/gdb"
  20. "github.com/gogf/gf/frame/g"
  21. "github.com/gogf/gf/os/gtime"
  22. "github.com/gogf/gf/util/gconv"
  23. )
  24. // getPersonalContractReportData 获取个人数据
  25. // dataType:collection为回款;其他为合同
  26. func getPersonalContractReportData(ctx context.Context, dataType string, params *map[string]interface{}) (*home.ReportData, error) {
  27. var reportData home.ReportData
  28. targetMap := make(map[int]gdb.Record, 0)
  29. realMap := make(map[int][]*gdb.Record, 0)
  30. targetField := "sales_target"
  31. realField := "contract_amount"
  32. year := gtime.Now().Format("Y")
  33. if params != nil && (*params)["year"] != nil {
  34. year = gconv.String((*params)["year"])
  35. }
  36. // 统计字段
  37. if dataType == "COLLECTION" {
  38. targetField = "collection_target"
  39. realField = "collection_amount"
  40. }
  41. srv, err := contractService.NewCtrContractService(ctx)
  42. if err != nil {
  43. return nil, err
  44. }
  45. // 获取用户信息
  46. userInfo, err := micro_srv.GetUserInfo(ctx)
  47. if err != nil {
  48. return nil, fmt.Errorf("获取用户信息异常:%s", err.Error())
  49. }
  50. targets, err := srv.Dao.DB.Model("rpt_sales_target").Where("sale_user_id", userInfo.Id).Order("monthly ASC").FindAll()
  51. if err != nil && err != sql.ErrNoRows {
  52. return nil, err
  53. }
  54. for index, target := range targets {
  55. targetMap[target["monthly"].Int()] = targets[index]
  56. }
  57. // 统计12个月份的数据
  58. // 统计目标值
  59. for index := 1; index <= 12; index++ {
  60. reportData.XData = append(reportData.XData, fmt.Sprintf("%v月", index))
  61. if target, ok := targetMap[index]; ok {
  62. reportData.YDataTarget = append(reportData.YDataTarget, target[targetField].Float64())
  63. } else {
  64. reportData.YDataTarget = append(reportData.YDataTarget, 0)
  65. }
  66. }
  67. // 统计合同值
  68. contractModel := srv.Dao.DB.Model("ctr_contract").Where("ctr_contract.incharge_id", userInfo.Id)
  69. if dataType != "COLLECTION" {
  70. contracts, err := contractModel.Where("ctr_contract.contract_start_time LIKE ?", year+"-%").Order("ctr_contract.contract_start_time ASC").FindAll()
  71. if err != nil && err != sql.ErrNoRows {
  72. return nil, err
  73. }
  74. for index, contract := range contracts {
  75. realMap[contract["contract_start_time"].GTime().Month()] = append(realMap[contract["contract_start_time"].GTime().Month()], &contracts[index])
  76. }
  77. } else {
  78. // 回款数据统计
  79. collections, err := contractModel.InnerJoin("ctr_contract_collection", "ctr_contract.id=ctr_contract_collection.contract_id").Where("ctr_contract_collection.appro_status", "20").Where("ctr_contract_collection.collection_datetime LIKE ?", year+"-%").Order("ctr_contract_collection.collection_datetime ASC").Fields("ctr_contract_collection.*").FindAll()
  80. if err != nil && err != sql.ErrNoRows {
  81. return nil, err
  82. }
  83. for index, collection := range collections {
  84. realMap[collection["collection_datetime"].GTime().Month()] = append(realMap[collection["collection_datetime"].GTime().Month()], &collections[index])
  85. }
  86. }
  87. // 统计12个月份的数据
  88. // 统计实际值
  89. for index := 1; index <= 12; index++ {
  90. if realData, ok := realMap[index]; ok {
  91. realAmount := float64(0)
  92. for _, data := range realData {
  93. realAmount += (*data)[realField].Float64()
  94. }
  95. reportData.YDataReal = append(reportData.YDataReal, realAmount)
  96. } else {
  97. reportData.YDataReal = append(reportData.YDataReal, 0)
  98. }
  99. if reportData.YDataTarget[index-1] == 0 {
  100. reportData.PercentData = append(reportData.PercentData, 0)
  101. } else {
  102. reportData.PercentData = append(reportData.PercentData, reportData.YDataReal[index-1]*100/reportData.YDataTarget[index-1])
  103. }
  104. }
  105. return &reportData, nil
  106. }
  107. // getCompanyContractReportData 获取总部数据
  108. // dataType:collection为回款;其他为合同
  109. func getCompanyContractReportData(ctx context.Context, dataType string, params *map[string]interface{}) (*home.ReportData, error) {
  110. var reportData home.ReportData
  111. realMap := make(map[int]gdb.Record, 0)
  112. targetField := "sales_target"
  113. realField := "contract_amount"
  114. dateWhere1 := "" // 查询条件
  115. dateWhere2 := "" // 查询条件
  116. dateWhere3 := ""
  117. date := gtime.Now()
  118. if params != nil && (*params)["date"] != nil {
  119. date = gconv.GTime((*params)["date"])
  120. }
  121. dateWhere1 = fmt.Sprintf("ctr_contract.contract_start_time LIKE '%v'", date.Format("Y")+"-%")
  122. dateWhere2 = fmt.Sprintf("ctr_contract_collection.collection_datetime LIKE '%v'", date.Format("Y")+"-%")
  123. if params != nil && (*params)["searchType"] != nil {
  124. searchType := gconv.String((*params)["searchType"])
  125. if searchType == "month" {
  126. dateWhere1 = fmt.Sprintf("ctr_contract.contract_start_time LIKE '%v'", date.Format("Y-m")+"-%")
  127. dateWhere2 = fmt.Sprintf("ctr_contract_collection.collection_datetime LIKE '%v'", date.Format("Y-m")+"-%")
  128. dateWhere3 = fmt.Sprintf("monthly=%v AND created_time LIKE '%v%%'", date.Month(), date.Format("Y"))
  129. } else if searchType == "quarter" {
  130. dateWhere1 = getQuarterWhere(date, "ctr_contract.contract_start_time")
  131. dateWhere2 = getQuarterWhere(date, "ctr_contract_collection.collection_datetime")
  132. dateWhere3 = getQuarterMonthWhere(date, "monthly") + fmt.Sprintf(" AND created_time LIKE '%v%%'", date.Format("Y"))
  133. }
  134. }
  135. // 统计字段
  136. if dataType == "COLLECTION" {
  137. targetField = "collection_target"
  138. realField = "collection_amount"
  139. }
  140. srv, err := contractService.NewCtrContractService(ctx)
  141. if err != nil {
  142. return nil, err
  143. }
  144. targets, err := srv.Dao.DB.Model("rpt_sales_target").Where(dateWhere3).Order("sale_user_id ASC").Group("sale_user_id").Fields(fmt.Sprintf("sale_user_id, sale_user_name, SUM(%v) %v", targetField, targetField)).FindAll()
  145. if err != nil && err != sql.ErrNoRows {
  146. return nil, err
  147. }
  148. // 统计合同值
  149. contractModel := srv.Dao.DB.Model("ctr_contract").Group("ctr_contract.incharge_id").Order("ctr_contract.incharge_id ASC")
  150. if dataType != "COLLECTION" {
  151. contracts, err := contractModel.Where(dateWhere1).Fields("ctr_contract.incharge_id, ctr_contract.incharge_name, count(ctr_contract.contract_amount) contract_amount").FindAll()
  152. if err != nil && err != sql.ErrNoRows {
  153. return nil, err
  154. }
  155. for index, contract := range contracts {
  156. realMap[contract["incharge_id"].Int()] = contracts[index]
  157. }
  158. } else {
  159. // 回款数据统计
  160. collections, err := contractModel.InnerJoin("ctr_contract_collection", "ctr_contract.id=ctr_contract_collection.contract_id").Where("ctr_contract_collection.appro_status", "20").Where(dateWhere2).Fields("ctr_contract.incharge_id, ctr_contract.incharge_name, SUM(ctr_contract_collection.collection_amount) collection_amount").FindAll()
  161. if err != nil && err != sql.ErrNoRows {
  162. return nil, err
  163. }
  164. for index, collection := range collections {
  165. realMap[collection["incharge_id"].Int()] = collections[index]
  166. }
  167. }
  168. // 过滤掉已删除的销售
  169. normalUserMap := make(map[int]bool)
  170. normalUsers, err := srv.Dao.DB.Model("sys_user").Where("status='10'").FindAll()
  171. if err != nil && err != sql.ErrNoRows {
  172. return nil, err
  173. }
  174. for _, user := range normalUsers {
  175. normalUserMap[user["id"].Int()] = true
  176. }
  177. // 统计目标值和实际值
  178. var index int
  179. for _, target := range targets {
  180. // 过滤掉已删除的销售
  181. if !normalUserMap[target["sale_user_id"].Int()] {
  182. continue
  183. }
  184. reportData.XData = append(reportData.XData, target["sale_user_name"].String())
  185. reportData.YDataTarget = append(reportData.YDataTarget, target[targetField].Float64())
  186. if realData, ok := realMap[target["sale_user_id"].Int()]; ok {
  187. reportData.YDataReal = append(reportData.YDataReal, realData[realField].Float64())
  188. } else {
  189. reportData.YDataReal = append(reportData.YDataReal, 0)
  190. }
  191. if reportData.YDataTarget[index] == 0 {
  192. reportData.PercentData = append(reportData.PercentData, 0)
  193. } else {
  194. reportData.PercentData = append(reportData.PercentData, reportData.YDataReal[index]*100/reportData.YDataTarget[index])
  195. }
  196. index++
  197. }
  198. return &reportData, nil
  199. }
  200. func getQuarterGoalReportData(ctx context.Context, dataType string, params *map[string]interface{}) (*home.ReportData, error) {
  201. if params == nil {
  202. return nil, fmt.Errorf("请输入年度")
  203. }
  204. p := *params
  205. year := gconv.Int(p["year"])
  206. quarter := gconv.Int(p["quarter"])
  207. if year == 0 {
  208. return nil, fmt.Errorf("请输入年度")
  209. }
  210. srv, err := contractService.NewCtrContractService(ctx)
  211. if err != nil {
  212. return nil, err
  213. }
  214. goal := map[string]float64{}
  215. goaldao := srv.GoalDao.Where("year = ?", year).Where("goal_type = ?", dataType)
  216. if quarter != 0 {
  217. goaldao = goaldao.Where("quarter = ?", quarter)
  218. } else {
  219. goaldao = goaldao.Where("quarter = 1 || quarter = 2 || quarter = 3 || quarter = 4")
  220. }
  221. goalent, err := goaldao.All()
  222. if err != nil {
  223. return nil, err
  224. }
  225. for _, ent := range goalent {
  226. goal[ent.ProductLine] += ent.Amount
  227. }
  228. got := map[string]float64{}
  229. ctrdao := srv.Dao.As("a").InnerJoin("sys_user b", "a.incharge_id=b.id").Where("b.status='10'").Where("year(a.created_time) = ?", year)
  230. if quarter != 0 {
  231. if quarter == 1 {
  232. ctrdao = ctrdao.Where("month(a.created_time) in (1,2,3)")
  233. }
  234. if quarter == 2 {
  235. ctrdao = ctrdao.Where("month(a.created_time) in (4,5,6)")
  236. }
  237. if quarter == 3 {
  238. ctrdao = ctrdao.Where("month(a.created_time) in (7,8,9)")
  239. }
  240. if quarter == 4 {
  241. ctrdao = ctrdao.Where("month(a.created_time) in (10,11,12)")
  242. }
  243. }
  244. ctrent, err := ctrdao.All()
  245. if err != nil {
  246. return nil, err
  247. }
  248. for _, ent := range ctrent {
  249. if dataType == "10" {
  250. got[ent.ProductLine] += ent.ContractAmount
  251. }
  252. if dataType == "20" {
  253. got[ent.ProductLine] += ent.CollectedAmount
  254. }
  255. }
  256. productLine, err := service.GetDictDataByType(ctx, "sys_product_line")
  257. if err != nil {
  258. return nil, err
  259. }
  260. productLineCode := []string{}
  261. productLineName := []string{}
  262. for k, v := range productLine {
  263. productLineCode = append(productLineCode, k)
  264. productLineName = append(productLineName, v)
  265. }
  266. var reportData home.ReportData
  267. for _, c := range productLineCode {
  268. reportData.XData = append(reportData.XData, productLine[c])
  269. reportData.YDataTarget = append(reportData.YDataTarget, goal[c])
  270. reportData.YDataReal = append(reportData.YDataReal, got[c]/10000)
  271. }
  272. return &reportData, nil
  273. }
  274. // 客户现场打卡频次
  275. func getClockfrequency(ctx context.Context, dataType string, params *map[string]interface{}) (*home.ReportData, error) {
  276. var reportData home.ReportData
  277. realMap := make(map[int]gdb.Record, 0)
  278. dateWhere1 := "" // 查询条件
  279. date := gtime.Now()
  280. nowTime := gtime.Datetime()
  281. if params != nil && (*params)["date"] != nil {
  282. date = gconv.GTime((*params)["date"])
  283. }
  284. if params != nil && (*params)["searchType"] != nil {
  285. searchType := gconv.String((*params)["searchType"])
  286. if searchType == "month" {
  287. dateWhere1 = fmt.Sprintf("plat_punch_records.punch_time LIKE '%v'", date.Format("Y-m")+"-%")
  288. } else if searchType == "week" {
  289. weekday := transferWeekday(date.Weekday())
  290. fmt.Println(weekday)
  291. beforeTime := gtime.NewFromStr(nowTime).AddDate(0, 0, -gconv.Int(weekday)).String()
  292. endTime := gtime.NewFromStr(nowTime).AddDate(0, 0, 7-gconv.Int(weekday)).String()
  293. dateWhere1 = fmt.Sprintf("plat_punch_records.punch_time between '%v' and '%v'", beforeTime, endTime)
  294. }
  295. }
  296. srv, err := platService.NewPunchRecordsService(ctx)
  297. if err != nil {
  298. return nil, err
  299. }
  300. platpunchrecords, err := srv.Dao.DB.Model("plat_punch_records").Where(dateWhere1).Fields("plat_punch_records.user_nick_name,Count(plat_punch_records.user_nick_name) as punch_sum").Group("plat_punch_records.user_nick_name").FindAll()
  301. if err != nil && err != sql.ErrNoRows {
  302. return nil, err
  303. }
  304. // 过滤掉已删除的销售
  305. normalUserMap := make(map[int]bool)
  306. normalUsers, err := srv.Dao.DB.Model("sys_user").Where("status='10'").FindAll()
  307. if err != nil && err != sql.ErrNoRows {
  308. return nil, err
  309. }
  310. for _, user := range normalUsers {
  311. normalUserMap[user["id"].Int()] = true
  312. }
  313. // 赋值实际值
  314. var index int
  315. for _, target := range platpunchrecords {
  316. // 过滤掉已删除的销售
  317. if !normalUserMap[target["user_id"].Int()] {
  318. continue
  319. }
  320. reportData.XData = append(reportData.XData, target["user_nick_name"].String())
  321. reportData.YDataTarget = append(reportData.YDataTarget, target["punch_sum"].Float64())
  322. if realData, ok := realMap[target["punch_sum"].Int()]; ok {
  323. reportData.YDataReal = append(reportData.YDataReal, realData["punch_sum"].Float64())
  324. } else {
  325. reportData.YDataReal = append(reportData.YDataReal, 0)
  326. }
  327. if reportData.YDataTarget[index] == 0 {
  328. reportData.PercentData = append(reportData.PercentData, 0)
  329. } else {
  330. reportData.PercentData = append(reportData.PercentData, reportData.YDataReal[index]*100/reportData.YDataTarget[index])
  331. }
  332. index++
  333. }
  334. return &reportData, nil
  335. }
  336. // 销售工程师跟进记录的打卡频次
  337. func getFollowUpRecord(ctx context.Context, dataType string, params *map[string]interface{}) ([]plat.Statistics, error) {
  338. now := time.Now()
  339. date := gconv.Int(gtime.Now().Month())
  340. if params != nil && (*params)["date"] != nil {
  341. date = gconv.Int((*params)["date"])
  342. }
  343. // 获取本月的第一天
  344. firstOfMonth := time.Date(now.Year(), time.Month(date), 1, 0, 0, 0, 0, now.Location())
  345. // 获取本月的最后一天
  346. lastOfMonth := firstOfMonth.AddDate(0, 1, -1)
  347. l, _ := time.LoadLocation("Asia/Shanghai")
  348. startTime, _ := time.ParseInLocation("2006-01-02", firstOfMonth.Format("2006-01-02"), l)
  349. endTime, _ := time.ParseInLocation("2006-01-02", lastOfMonth.Format("2006-01-02"), l)
  350. datas := GroupByWeekDate(startTime, endTime)
  351. var Follows []plat.Followlist
  352. srv, err := platService.NewFollowupService(ctx)
  353. if err != nil {
  354. return nil, err
  355. }
  356. var stats []plat.Statistics
  357. for _, d := range datas {
  358. err = srv.Dao.DB.Model("plat_followup").
  359. Where("follow_date>=? and follow_date<=?", d.StartTime.Format("2006-01-02"), d.EndTime.Format("2006-01-02")).Fields("count(follow_type)as num ,follow_type").
  360. Group("date_format(follow_date,'%v'),follow_type").Scan(&Follows)
  361. if err != nil && err != sql.ErrNoRows {
  362. return nil, err
  363. }
  364. if len(Follows) > 0 {
  365. var stat plat.Statistics
  366. for _, val := range Follows {
  367. if val.FollowType == "10" {
  368. stat.Phone = gconv.Int(val.Num)
  369. } else if val.FollowType == "20" {
  370. stat.Mail = gconv.Int(val.Num)
  371. } else if val.FollowType == "30" {
  372. stat.PayVisit = gconv.Int(val.Num)
  373. }
  374. }
  375. stat.Total = stat.Phone + stat.Mail + stat.PayVisit
  376. stat.Week = d.WeekTh + "周"
  377. stats = append(stats, stat)
  378. }
  379. }
  380. return stats, nil
  381. }
  382. func getQuarterWhere(date *gtime.Time, field string) string {
  383. if date.Month() >= 1 && date.Month() <= 3 {
  384. return fmt.Sprintf("%v >= '%v' AND %v < '%v'", field, date.Format("Y-")+"01-01 00:00:00", field, date.Format("Y-")+"04-01 00:00:00")
  385. } else if date.Month() >= 4 && date.Month() <= 6 {
  386. return fmt.Sprintf("%v >= '%v' AND %v < '%v'", field, date.Format("Y-")+"04-01 00:00:00", field, date.Format("Y-")+"07-01 00:00:00")
  387. } else if date.Month() >= 7 && date.Month() <= 9 {
  388. return fmt.Sprintf("%v >= '%v' AND %v < '%v'", field, date.Format("Y-")+"07-01 00:00:00", field, date.Format("Y-")+"10-01 00:00:00")
  389. } else if date.Month() >= 10 && date.Month() <= 12 {
  390. return fmt.Sprintf("%v >= '%v' AND %v <= '%v'", field, date.Format("Y-")+"10-01 00:00:00", field, date.Format("Y-")+"12-31 23:59:59")
  391. }
  392. return ""
  393. }
  394. func getQuarterMonthWhere(date *gtime.Time, field string) string {
  395. if date.Month() >= 1 && date.Month() <= 3 {
  396. return fmt.Sprintf("%v >= %v AND %v < %v", field, 1, field, 4)
  397. } else if date.Month() >= 4 && date.Month() <= 6 {
  398. return fmt.Sprintf("%v >= %v AND %v < %v", field, 4, field, 7)
  399. } else if date.Month() >= 7 && date.Month() <= 9 {
  400. return fmt.Sprintf("%v >= %v AND %v < %v", field, 7, field, 10)
  401. } else if date.Month() >= 10 && date.Month() <= 12 {
  402. return fmt.Sprintf("%v >= %v AND %v <= %v", field, 10, field, 12)
  403. }
  404. return ""
  405. }
  406. func transferWeekday(day time.Weekday) string {
  407. switch day {
  408. case time.Monday:
  409. return "1"
  410. case time.Tuesday:
  411. return "2"
  412. case time.Wednesday:
  413. return "3"
  414. case time.Thursday:
  415. return "4"
  416. case time.Friday:
  417. return "5"
  418. case time.Saturday:
  419. return "6"
  420. case time.Sunday:
  421. return "7"
  422. default:
  423. return ""
  424. }
  425. }
  426. // 判断时间是当年的第几周
  427. func WeekByDate(t time.Time) string {
  428. yearDay := t.YearDay()
  429. yearFirstDay := t.AddDate(0, 0, -yearDay+1)
  430. firstDayInWeek := int(yearFirstDay.Weekday())
  431. //今年第一周有几天
  432. firstWeekDays := 1
  433. if firstDayInWeek != 0 {
  434. firstWeekDays = 7 - firstDayInWeek + 1
  435. }
  436. var week int
  437. Weeks := WeekByDates(t)
  438. if yearDay <= firstWeekDays {
  439. week = 1
  440. } else {
  441. week = (yearDay-firstWeekDays)/7 + 2
  442. }
  443. return fmt.Sprintf("%d", week-gconv.Int(Weeks)+1)
  444. }
  445. func WeekByDates(now time.Time) int {
  446. l, _ := time.LoadLocation("Asia/Shanghai")
  447. // 获取本月的第一天
  448. firstOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
  449. endTime, _ := time.ParseInLocation("2006-01-02", firstOfMonth.Format("2006-01-02"), l)
  450. t := endTime
  451. yearDay := t.YearDay()
  452. yearFirstDay := t.AddDate(0, 0, -yearDay+1)
  453. firstDayInWeek := int(yearFirstDay.Weekday())
  454. //今年第一周有几天
  455. firstWeekDays := 1
  456. if firstDayInWeek != 0 {
  457. firstWeekDays = 7 - firstDayInWeek + 1
  458. }
  459. var week int
  460. if yearDay <= firstWeekDays {
  461. week = 1
  462. } else {
  463. week = (yearDay-firstWeekDays)/7 + 2
  464. }
  465. return week
  466. }
  467. // 将开始时间和结束时间分割为周为单位
  468. func GroupByWeekDate(startTime, endTime time.Time) []plat.WeekDate {
  469. weekDate := make([]plat.WeekDate, 0)
  470. diffDuration := endTime.Sub(startTime)
  471. days := int(math.Ceil(float64(diffDuration/(time.Hour*24)))) + 1
  472. currentWeekDate := plat.WeekDate{}
  473. currentWeekDate.WeekTh = WeekByDate(endTime)
  474. currentWeekDate.EndTime = endTime
  475. currentWeekDay := int(endTime.Weekday())
  476. if currentWeekDay == 0 {
  477. currentWeekDay = 7
  478. }
  479. currentWeekDate.StartTime = endTime.AddDate(0, 0, -currentWeekDay+1)
  480. nextWeekEndTime := currentWeekDate.StartTime
  481. weekDate = append(weekDate, currentWeekDate)
  482. for i := 0; i < (days-currentWeekDay)/7; i++ {
  483. weekData := plat.WeekDate{}
  484. weekData.EndTime = nextWeekEndTime
  485. weekData.StartTime = nextWeekEndTime.AddDate(0, 0, -7)
  486. weekData.WeekTh = WeekByDate(weekData.StartTime)
  487. nextWeekEndTime = weekData.StartTime
  488. weekDate = append(weekDate, weekData)
  489. }
  490. if lastDays := (days - currentWeekDay) % 7; lastDays > 0 {
  491. lastData := plat.WeekDate{}
  492. lastData.EndTime = nextWeekEndTime
  493. lastData.StartTime = nextWeekEndTime.AddDate(0, 0, -lastDays)
  494. lastData.WeekTh = WeekByDate(lastData.StartTime)
  495. weekDate = append(weekDate, lastData)
  496. }
  497. return weekDate
  498. }
  499. type BusCount struct {
  500. NboType string `json:"nboType"`
  501. ProductLine string `json:"productLine"`
  502. Count int `json:"count"`
  503. Remark string `json:"remark"`
  504. }
  505. // 报表数据 三大产品线,新增以及转化项目(C转B、B转A、A转签约、C转A、C转签约、B转签约、储备转A/B/C/签约)数量, 按周和月
  506. // params 10:周 20:月
  507. func (s *HomeService) getNewAndConvertBusiness(productLine []string, params *map[string]interface{}) (interface{}, error) {
  508. if params == nil {
  509. return nil, myerrors.TipsError("请求参数传递不正确")
  510. }
  511. searchType, ok := (*params)["searchType"]
  512. if !ok {
  513. return nil, myerrors.TipsError("请求查询类型参数传递错误")
  514. }
  515. currentTime := gtime.Now()
  516. weekStart, weekEnd := currentTime.StartOfWeek(), currentTime.EndOfWeek()
  517. // monthStart, monthEnd := currentTime.StartOfMonth(), currentTime.EndOfMonth()
  518. monthStr, ok := (*params)["month"]
  519. if !ok {
  520. return nil, myerrors.TipsError("请求查询类型参数传递错误")
  521. }
  522. m := gconv.Int(monthStr)
  523. now := time.Now()
  524. firstOfMonth := time.Date(now.Year(), time.Month(m), 1, 0, 0, 0, 0, now.Location()) // 获取本月的第一天
  525. lastOfMonth := firstOfMonth.AddDate(0, 1, -1) // 获取本月的最后一天
  526. l, _ := time.LoadLocation("Asia/Shanghai")
  527. startTime, _ := time.ParseInLocation("2006-01-02", firstOfMonth.Format("2006-01-02"), l)
  528. endTime, _ := time.ParseInLocation("2006-01-02", lastOfMonth.Format("2006-01-02"), l)
  529. businessDao := projDao.NewProjBusinessDao(s.Tenant)
  530. busDynamicsDao := projDao.NewProjBusinessDynamicsDao(s.Tenant)
  531. contractDao := contDao.NewCtrContractDao(s.Tenant)
  532. // 获取三大产品线新增项目
  533. getAddBusCount := func(searchType string) (addCount []BusCount, err error) {
  534. commonDb := businessDao.DataScope(s.Ctx, "sale_id").Group(businessDao.C.ProductLine).OrderAsc(businessDao.C.ProductLine).
  535. Fields("product_line, count(id) as count")
  536. if searchType == "week" {
  537. err = commonDb.WhereGTE(businessDao.C.FilingTime, weekStart).WhereLTE(businessDao.C.FilingTime, weekEnd).Scan(&addCount)
  538. }
  539. if searchType == "month" {
  540. err = commonDb.WhereGTE(businessDao.C.FilingTime, startTime).WhereLTE(businessDao.C.FilingTime, endTime).Scan(&addCount)
  541. }
  542. return addCount, err
  543. }
  544. addCount, err := getAddBusCount(searchType.(string))
  545. if err != nil {
  546. return nil, err
  547. }
  548. // 获取三大产品线签约项目
  549. getSignBusCount := func(searchType string) (signCount []BusCount, err error) {
  550. commonDb := contractDao.As("contract").DataScope(s.Ctx, "incharge_id").LeftJoin(businessDao.Table, "bus", "bus.id=contract.nbo_id").
  551. Fields("bus.product_line, bus.nbo_type, count(contract.id) as count").
  552. Group("bus.product_line, bus.nbo_type").Order("bus.product_line ASC, bus.nbo_type ASC")
  553. if searchType == "week" {
  554. err = commonDb.WhereGTE("contract."+contractDao.C.CreatedTime, weekStart).WhereLTE("contract."+contractDao.C.CreatedTime, weekEnd).Scan(&signCount)
  555. }
  556. if searchType == "month" {
  557. err = commonDb.WhereGTE("contract."+contractDao.C.CreatedTime, startTime).WhereLTE("contract."+contractDao.C.CreatedTime, endTime).Scan(&signCount)
  558. }
  559. return signCount, err
  560. }
  561. signCount, err := getSignBusCount(searchType.(string))
  562. if err != nil {
  563. return nil, err
  564. }
  565. // 获取三大产品线转化项目(C转B、B转A、A转签约、C转A、C转签约、B转签约、储备转A/B/C/签约)数量
  566. getConvertBusData := func(searchType string) (convertData []BusCount, err error) {
  567. commonDb := busDynamicsDao.As("dy").LeftJoin(businessDao.Table, "bus", "bus.id=dy.bus_id").DataScope(s.Ctx, "sale_id", "bus").
  568. Where("dy."+busDynamicsDao.C.OpnType, projSrv.OpnUpgradeApproval).WhereNot("dy."+busDynamicsDao.C.Remark, "").
  569. Fields("bus.product_line, dy.remark").OrderAsc("bus.product_line")
  570. if searchType == "week" {
  571. err = commonDb.WhereGTE("dy."+busDynamicsDao.C.CreatedTime, weekStart).WhereLTE("dy."+busDynamicsDao.C.CreatedTime, weekEnd).Scan(&convertData)
  572. }
  573. if searchType == "month" {
  574. err = commonDb.WhereGTE("dy."+busDynamicsDao.C.CreatedTime, startTime).WhereLTE("dy."+busDynamicsDao.C.CreatedTime, endTime).Scan(&convertData)
  575. }
  576. return convertData, err
  577. }
  578. convertBusData, err := getConvertBusData(searchType.(string))
  579. if err != nil {
  580. return nil, err
  581. }
  582. // 处理数据
  583. result := make([][]int, len(productLine))
  584. for i, pl := range productLine {
  585. result[i] = make([]int, 8)
  586. for _, item := range addCount {
  587. if item.ProductLine == pl {
  588. result[i][0] = item.Count
  589. }
  590. }
  591. for _, item := range signCount {
  592. if item.ProductLine != pl {
  593. continue
  594. }
  595. switch item.NboType {
  596. case projSrv.StatusA:
  597. result[i][3] += item.Count
  598. case projSrv.StatusB:
  599. result[i][6] += item.Count
  600. case projSrv.StatusC:
  601. result[i][5] += item.Count
  602. case projSrv.StatusReserve:
  603. result[i][7] += item.Count
  604. }
  605. }
  606. for _, item := range convertBusData {
  607. if item.ProductLine != pl {
  608. continue
  609. }
  610. info := gconv.Map(item.Remark)
  611. if info["origNboType"] == projSrv.StatusC && info["nboType"] == projSrv.StatusB {
  612. result[i][1] += 1
  613. }
  614. if info["origNboType"] == projSrv.StatusB && info["nboType"] == projSrv.StatusA {
  615. result[i][2] += 1
  616. }
  617. if info["origNboType"] == projSrv.StatusC && info["nboType"] == projSrv.StatusA {
  618. result[i][4] += 1
  619. }
  620. if info["origNboType"] == projSrv.StatusReserve {
  621. result[i][7] += 1
  622. }
  623. }
  624. }
  625. return result, nil
  626. }
  627. // 报表数据 三大产品线,AB类项目出货金额
  628. func (s *HomeService) getShipmentAmount(productLine, nboType []string) (interface{}, error) {
  629. businessDao := projDao.NewProjBusinessDao(s.Tenant)
  630. data, err := businessDao.As("a").InnerJoin("sys_user b", "a.sale_id=b.id").Fields("a.product_line, a.nbo_type, SUM(a.est_trans_price) as est_trans_price").Where("b.status='10'").
  631. WhereIn("a.product_line", productLine).WhereIn("a.nbo_type", nboType).
  632. Group("a.product_line, a.nbo_type").Order("a.product_line ASC, a.nbo_type ASC").DataScope(s.Ctx, "a.sale_id").All()
  633. if err != nil {
  634. return nil, err
  635. }
  636. result := make([][]float64, len(productLine))
  637. for i, pl := range productLine {
  638. result[i] = make([]float64, len(nboType))
  639. for j, t := range nboType {
  640. for _, item := range data {
  641. if item.ProductLine == pl && item.NboType == t {
  642. result[i][j] = item.EstTransPrice
  643. }
  644. }
  645. }
  646. }
  647. return arrayReversal(result), nil
  648. }
  649. // 报表数据 三大产品线,当月和累计的签约、回款额
  650. func (s *HomeService) getProductLineSignedAndBackAmount(productLine []string) (interface{}, error) {
  651. currentTime := gtime.Now()
  652. monthStart := currentTime.StartOfMonth()
  653. monthEnd := currentTime.EndOfMonth()
  654. contractDao := contDao.NewCtrContractDao(s.Tenant)
  655. commonDao := contractDao.As("a").InnerJoin("sys_user b", "a.incharge_id=b.id").DataScope(s.Ctx, "incharge_id").WhereIn(contractDao.C.ProductLine, productLine).Where("b.status='10'").
  656. Group(contractDao.C.ProductLine).OrderAsc(contractDao.C.ProductLine)
  657. //累计签约合同金额 contract_amount
  658. allContractAmount, err := commonDao.Fields("a.product_line, SUM(a.contract_amount) as contract_amount").All()
  659. if err != nil {
  660. return nil, err
  661. }
  662. //累计回款金额 collected_amount
  663. allCollectedAmount, err := commonDao.Fields("a.product_line, SUM(a.collected_amount) as collected_amount").All()
  664. if err != nil {
  665. return nil, err
  666. }
  667. //当月签约合同金额(维度:月)
  668. monthContractAmount, err := commonDao.WhereGTE(contractDao.C.ContractStartTime, monthStart).WhereLTE(contractDao.C.ContractStartTime, monthEnd).
  669. Fields("a.product_line, SUM(a.contract_amount) as contract_amount").All()
  670. if err != nil {
  671. return nil, err
  672. }
  673. //当月回款金额(维度:月)
  674. monthCollectedAmount, err := commonDao.WhereGTE(contractDao.C.ContractStartTime, monthStart).WhereLTE(contractDao.C.ContractStartTime, monthEnd).
  675. Fields("a.product_line, SUM(a.collected_amount) as collected_amount").All()
  676. if err != nil {
  677. return nil, err
  678. }
  679. result := make([][]float64, len(productLine))
  680. for i, pl := range productLine {
  681. result[i] = make([]float64, 4)
  682. for _, item := range monthContractAmount {
  683. if item.ProductLine == pl {
  684. result[i][0] = item.ContractAmount
  685. }
  686. }
  687. for _, item := range allContractAmount {
  688. if item.ProductLine == pl {
  689. result[i][1] = item.ContractAmount
  690. }
  691. }
  692. for _, item := range monthCollectedAmount {
  693. if item.ProductLine == pl {
  694. result[i][2] = item.CollectedAmount
  695. }
  696. }
  697. for _, item := range allCollectedAmount {
  698. if item.ProductLine == pl {
  699. result[i][3] = item.CollectedAmount
  700. }
  701. }
  702. }
  703. return arrayReversal(result), nil
  704. }
  705. // 二维数组反转
  706. func arrayReversal(result [][]float64) [][]float64 {
  707. if len(result) == 0 {
  708. return [][]float64{}
  709. }
  710. data := make([][]float64, len(result[0]))
  711. for k, v := range result {
  712. for m, n := range v {
  713. if k == 0 {
  714. data[m] = make([]float64, len(result))
  715. }
  716. data[m][k] = n
  717. }
  718. }
  719. return data
  720. }
  721. type FollowUpCount struct {
  722. CreatedBy int `json:"createdBy"`
  723. CreatedName string `json:"createdName"`
  724. FollowType string `json:"followType"`
  725. Count int `json:"count"`
  726. }
  727. // QuerySalesEngineerFollowUpNum 查询销售工程师跟进记录频次
  728. func (s *HomeService) QuerySalesEngineerFollowUpNum(day *gtime.Time) (interface{}, error) {
  729. weekData := GetMonthWeekDay(day)
  730. followUpDao := platDao.NewPlatFollowupDao(s.Tenant)
  731. followUpMonthData := make([][]FollowUpCount, 0)
  732. for _, item := range weekData {
  733. data := make([]FollowUpCount, 0)
  734. err := followUpDao.Fields("created_by, created_name, follow_type, COUNT(id) as count").
  735. WhereGTE(followUpDao.C.FollowDate, item[0]).WhereLTE(followUpDao.C.FollowDate, item[1]).
  736. Group("created_by, follow_type").Order("created_by ASC, follow_type ASC").Scan(&data)
  737. if err != nil {
  738. return nil, err
  739. }
  740. followUpMonthData = append(followUpMonthData, data)
  741. }
  742. // 409022238
  743. userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer"}, 100)
  744. if err != nil {
  745. return nil, err
  746. }
  747. followMethod, err := service.GetDictDataTreeByType(s.Ctx, "plat_follow_method")
  748. if err != nil {
  749. return nil, err
  750. }
  751. header, data := make([]g.Map, 0), make([]g.Map, 0)
  752. header = append(header, g.Map{"prop": "userName", "label": "销售工程师"})
  753. header = append(header, g.Map{"prop": "followType", "label": "跟进方式"})
  754. for k, _ := range weekData {
  755. header = append(header, g.Map{"prop": fmt.Sprintf("W%d", k+1), "label": fmt.Sprintf("第%d周", k+1)})
  756. }
  757. header = append(header, g.Map{"prop": "monthTotal", "label": "月度合计"})
  758. for userName, id := range userList {
  759. for _, key := range followMethod.Keys() {
  760. data = append(data, followUpReportDataConvert(g.Map{
  761. "userName": userName,
  762. "userId": id,
  763. "followTypeKey": key,
  764. "followType": followMethod.Get(key),
  765. }, followUpMonthData))
  766. }
  767. }
  768. return g.Map{"header": header, "data": data}, nil
  769. }
  770. type PunchRecordsCount struct {
  771. UserId int `json:"userId"`
  772. UserNickName string `json:"userNickName"`
  773. PunchType string `json:"punchType"`
  774. Count int `json:"count"`
  775. }
  776. // QueryPunchRecordsNum 打卡记录数据统计
  777. func (s *HomeService) QueryPunchRecordsNum(day *gtime.Time) (interface{}, error) {
  778. weekData := GetMonthWeekDay(day)
  779. punchRecordsDao := platDao.NewPlatPunchRecordsDao(s.Tenant)
  780. punchRecordsMonthData := make([][]PunchRecordsCount, 0)
  781. for _, item := range weekData {
  782. data := make([]PunchRecordsCount, 0)
  783. err := punchRecordsDao.Fields("user_id, user_nick_name, punch_type, COUNT(id) as count").
  784. WhereGTE(punchRecordsDao.C.PunchTime, item[0]).WhereLTE(punchRecordsDao.C.PunchTime, item[1]).
  785. Group("user_id, punch_type").Order("user_id ASC, punch_type ASC").Scan(&data)
  786. if err != nil {
  787. return nil, err
  788. }
  789. punchRecordsMonthData = append(punchRecordsMonthData, data)
  790. }
  791. // 409022238
  792. userList, err := service.GetUsersByRoleCode(s.Ctx, []string{"SalesEngineer"}, 100)
  793. if err != nil {
  794. return nil, err
  795. }
  796. // 打卡类型(10居家20客户30经销商40代理商)
  797. var punchTypes = []string{"10", "20", "30", "40"}
  798. var punchTypeNames = []string{"居家", "客户", "经销商", "代理商"}
  799. header, data := make([]g.Map, 0), make([]g.Map, 0)
  800. header = append(header, g.Map{"prop": "userName", "label": "销售工程师"})
  801. header = append(header, g.Map{"prop": "punchType", "label": "打卡方式"})
  802. for k, _ := range weekData {
  803. header = append(header, g.Map{"prop": fmt.Sprintf("W%d", k+1), "label": fmt.Sprintf("第%d周", k+1)})
  804. }
  805. header = append(header, g.Map{"prop": "monthTotal", "label": "月度合计"})
  806. // 打卡类型(10居家20客户30经销商40代理商)
  807. for userName, id := range userList {
  808. for index, key := range punchTypes {
  809. data = append(data, punchRecordsDataConvert(g.Map{
  810. "userName": userName,
  811. "userId": id,
  812. "punchTypeKey": key,
  813. "punchType": punchTypeNames[index],
  814. }, punchRecordsMonthData))
  815. }
  816. }
  817. return g.Map{"header": header, "data": data}, nil
  818. }
  819. func followUpReportDataConvert(data g.Map, followUpMonthData [][]FollowUpCount) g.Map {
  820. var total int
  821. for k, items := range followUpMonthData {
  822. data[fmt.Sprintf("W%d", k+1)] = 0
  823. for _, item := range items {
  824. if item.CreatedBy == data["userId"] && item.FollowType == data["followTypeKey"] {
  825. data[fmt.Sprintf("W%d", k+1)] = item.Count
  826. total += item.Count
  827. break
  828. }
  829. }
  830. }
  831. data["monthTotal"] = total
  832. return data
  833. }
  834. func punchRecordsDataConvert(data g.Map, punchRecordsCMonthData [][]PunchRecordsCount) g.Map {
  835. var total int
  836. for k, items := range punchRecordsCMonthData {
  837. data[fmt.Sprintf("W%d", k+1)] = 0
  838. for _, item := range items {
  839. if item.UserId == data["userId"] && item.PunchType == data["punchTypeKey"] {
  840. data[fmt.Sprintf("W%d", k+1)] = item.Count
  841. total += item.Count
  842. break
  843. }
  844. }
  845. }
  846. data["monthTotal"] = total
  847. return data
  848. }
  849. // GetMonthWeekDay 获取月份下的每周日期
  850. func GetMonthWeekDay(day *gtime.Time) [][]*gtime.Time {
  851. fmt.Println(day)
  852. result := make([][]*gtime.Time, 0)
  853. monthStart, monthEnd := day.StartOfMonth(), day.EndOfMonth()
  854. startWeekS, startWeekE := monthStart.StartOfWeek(), monthStart.EndOfWeek()
  855. endWeekS, endWeekE := monthEnd.StartOfWeek(), monthEnd.EndOfWeek()
  856. // 计算开始
  857. if startWeekS.Before(monthStart) || startWeekS.Equal(monthStart) {
  858. result = append(result, []*gtime.Time{monthStart, startWeekE})
  859. }
  860. // 计算整周
  861. sub := int(endWeekS.Sub(startWeekE).Hours() / 24 / 7)
  862. forDay := startWeekE.AddDate(0, 0, 1)
  863. for i := 1; i <= sub; i++ {
  864. result = append(result, []*gtime.Time{forDay.StartOfDay(), forDay.EndOfWeek()})
  865. forDay = forDay.AddDate(0, 0, 7)
  866. }
  867. // 计算结束
  868. if endWeekE.After(monthEnd) || endWeekE.Equal(monthEnd) {
  869. result = append(result, []*gtime.Time{endWeekS, monthEnd})
  870. }
  871. return result
  872. }