Performance.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146
  1. package controllers
  2. import (
  3. "ERP_salary/Nats/NatsServer"
  4. "ERP_salary/conf"
  5. "ERP_salary/dto"
  6. "ERP_salary/logs"
  7. "ERP_salary/models/Account"
  8. "ERP_salary/models/Performance"
  9. "ERP_salary/services"
  10. "encoding/json"
  11. "fmt"
  12. "io"
  13. "math"
  14. "net/http"
  15. "net/url"
  16. "strconv"
  17. "strings"
  18. "time"
  19. "github.com/robfig/cron/v3"
  20. "github.com/xuri/excelize/v2"
  21. beego "github.com/beego/beego/v2/server/web"
  22. userlibs "gogs.baozhida.cn/zoie/ERP_libs/User"
  23. "gogs.baozhida.cn/zoie/ERP_libs/lib"
  24. )
  25. type PerformanceController struct {
  26. beego.Controller
  27. User userlibs.User
  28. }
  29. // calculateTotalScore 计算总得分百分比
  30. func calculateTotalScore(perf Performance.Perf) float64 {
  31. if perf.T_assess_points == 0 {
  32. return 0
  33. }
  34. return (perf.T_workload / float64(perf.T_assess_points)) * 100
  35. }
  36. // calculatePerfTotal 计算应发绩效
  37. func calculatePerfTotal(perf Performance.Perf) float64 {
  38. score := calculateTotalScore(perf)
  39. if score >= 100 {
  40. return perf.T_perf
  41. }
  42. return (score / 100) * perf.T_perf
  43. }
  44. func (c *PerformanceController) Prepare() {
  45. c.User = *Account.User_r
  46. }
  47. func (c *PerformanceController) Points_List() {
  48. s := services.PerformancePoints{}
  49. reqData := dto.PerformancePointsPageReq{}
  50. if err := c.ParseForm(&reqData); err != nil {
  51. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  52. c.ServeJSON()
  53. return
  54. }
  55. if err := Validate(&reqData); err != nil {
  56. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  57. c.ServeJSON()
  58. return
  59. }
  60. R_List, R_cnt := s.GetPage(&reqData)
  61. var r_jsons lib.R_JSONS
  62. r_jsons.Num = R_cnt
  63. r_jsons.Data = R_List
  64. r_jsons.Page = reqData.Page
  65. r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize)))
  66. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
  67. c.ServeJSON()
  68. return
  69. }
  70. func (c *PerformanceController) Points_Add() {
  71. s := services.PerformancePoints{}
  72. reqData := dto.PerformancePointsInsertReq{}
  73. if err := c.ParseForm(&reqData); err != nil {
  74. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  75. c.ServeJSON()
  76. return
  77. }
  78. if err := Validate(&reqData); err != nil {
  79. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  80. c.ServeJSON()
  81. return
  82. }
  83. Id, err := s.Insert(&reqData)
  84. if err != nil {
  85. c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败"}
  86. c.ServeJSON()
  87. return
  88. }
  89. NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "添加", reqData)
  90. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id}
  91. c.ServeJSON()
  92. return
  93. }
  94. func (c *PerformanceController) Points_Edit() {
  95. s := services.PerformancePoints{}
  96. reqData := dto.PerformancePointsUpdateReq{}
  97. if err := c.ParseForm(&reqData); err != nil {
  98. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  99. c.ServeJSON()
  100. return
  101. }
  102. if err := Validate(&reqData); err != nil {
  103. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  104. c.ServeJSON()
  105. return
  106. }
  107. if err := s.Update(&reqData); err != nil {
  108. c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"}
  109. c.ServeJSON()
  110. return
  111. }
  112. NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "修改", reqData)
  113. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  114. c.ServeJSON()
  115. return
  116. }
  117. func (c *PerformanceController) Points_Del() {
  118. s := services.PerformancePoints{}
  119. reqData := dto.PerformancePointsDeleteReq{}
  120. if err := c.ParseForm(&reqData); err != nil {
  121. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  122. c.ServeJSON()
  123. return
  124. }
  125. if err := Validate(&reqData); err != nil {
  126. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  127. c.ServeJSON()
  128. return
  129. }
  130. if err := s.Delete(&reqData); err != nil {
  131. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  132. c.ServeJSON()
  133. return
  134. }
  135. NatsServer.AddUserLogs(c.User.T_uuid, "绩效点", "删除", strconv.Itoa(reqData.T_id))
  136. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  137. c.ServeJSON()
  138. return
  139. }
  140. func (c *PerformanceController) Target_List() {
  141. s := services.PerformanceTarget{}
  142. reqData := dto.PerformanceTargetPageReq{}
  143. if err := c.ParseForm(&reqData); err != nil {
  144. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  145. c.ServeJSON()
  146. return
  147. }
  148. if err := Validate(&reqData); err != nil {
  149. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  150. c.ServeJSON()
  151. return
  152. }
  153. R_List, R_cnt := s.GetPage(&reqData)
  154. var r_jsons lib.R_JSONS
  155. r_jsons.Num = R_cnt
  156. r_jsons.Data = R_List
  157. r_jsons.Page = reqData.Page
  158. r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize)))
  159. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
  160. c.ServeJSON()
  161. return
  162. }
  163. func (c *PerformanceController) Target_Add() {
  164. s := services.PerformanceTarget{}
  165. reqData := dto.PerformanceTargetInsertReq{}
  166. if err := c.ParseForm(&reqData); err != nil {
  167. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  168. c.ServeJSON()
  169. return
  170. }
  171. if err := Validate(&reqData); err != nil {
  172. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  173. c.ServeJSON()
  174. return
  175. }
  176. Id, err := s.Insert(&reqData)
  177. if err != nil {
  178. c.Data["json"] = lib.JSONS{Code: 202, Msg: "添加失败"}
  179. c.ServeJSON()
  180. return
  181. }
  182. NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "添加", reqData)
  183. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id}
  184. c.ServeJSON()
  185. return
  186. }
  187. func (c *PerformanceController) Target_Edit() {
  188. s := services.PerformanceTarget{}
  189. reqData := dto.PerformanceTargetUpdateReq{}
  190. if err := c.ParseForm(&reqData); err != nil {
  191. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  192. c.ServeJSON()
  193. return
  194. }
  195. if err := Validate(&reqData); err != nil {
  196. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  197. c.ServeJSON()
  198. return
  199. }
  200. if err := s.Update(&reqData); err != nil {
  201. c.Data["json"] = lib.JSONS{Code: 202, Msg: "修改失败"}
  202. c.ServeJSON()
  203. return
  204. }
  205. NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "修改", reqData)
  206. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  207. c.ServeJSON()
  208. return
  209. }
  210. func (c *PerformanceController) Target_Del() {
  211. s := services.PerformanceTarget{}
  212. reqData := dto.PerformanceTargetDeleteReq{}
  213. if err := c.ParseForm(&reqData); err != nil {
  214. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  215. c.ServeJSON()
  216. return
  217. }
  218. if err := Validate(&reqData); err != nil {
  219. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  220. c.ServeJSON()
  221. return
  222. }
  223. if err := s.Delete(&reqData); err != nil {
  224. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  225. c.ServeJSON()
  226. return
  227. }
  228. NatsServer.AddUserLogs(c.User.T_uuid, "绩效指标", "删除", strconv.Itoa(reqData.T_id))
  229. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  230. c.ServeJSON()
  231. return
  232. }
  233. // 绩效-用户
  234. func (c *PerformanceController) List() {
  235. s := services.Performance{}
  236. reqData := dto.PerformancePageReq{}
  237. if err := c.ParseForm(&reqData); err != nil {
  238. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  239. c.ServeJSON()
  240. return
  241. }
  242. if err := Validate(&reqData); err != nil {
  243. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  244. c.ServeJSON()
  245. return
  246. }
  247. userList, _ := NatsServer.Read_User_List_All()
  248. Account.Read_User_All_Map(userList)
  249. R_List, R_cnt := s.GetManagerPage(&reqData)
  250. var r_jsons lib.R_JSONS
  251. r_jsons.Num = R_cnt
  252. r_jsons.Data = R_List
  253. r_jsons.Page = reqData.Page
  254. r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize)))
  255. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
  256. c.ServeJSON()
  257. return
  258. }
  259. func (c *PerformanceController) Excel() {
  260. s := services.Performance{}
  261. reqData := dto.PerformancePageReq{}
  262. if err := c.ParseForm(&reqData); err != nil {
  263. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  264. c.ServeJSON()
  265. return
  266. }
  267. if err := Validate(&reqData); err != nil {
  268. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  269. c.ServeJSON()
  270. return
  271. }
  272. reqData.PageSize = 9999
  273. userList, _ := NatsServer.Read_User_List_All()
  274. Account.Read_User_All_Map(userList)
  275. R_List, R_cnt := s.GetManagerPage(&reqData)
  276. // 创建Excel文件
  277. f := excelize.NewFile()
  278. defer func() {
  279. if err := f.Close(); err != nil {
  280. logs.Error("关闭Excel文件失败: %s", err)
  281. }
  282. }()
  283. // 设置工作表名称
  284. sheetName := "绩效管理"
  285. index, err := f.NewSheet(sheetName)
  286. if err != nil {
  287. logs.Error("创建工作表失败: %s", err)
  288. c.Data["json"] = lib.JSONS{Code: 500, Msg: "创建Excel文件失败"}
  289. c.ServeJSON()
  290. return
  291. }
  292. f.SetActiveSheet(index)
  293. // 设置表头
  294. headers := []string{"序号", "姓名", "工资级别", "绩效工资(元)", "所属月份", "工作量", "考核工作量", "得分", "应发绩效"}
  295. for i, header := range headers {
  296. cell := fmt.Sprintf("%c1", 'A'+i)
  297. f.SetCellValue(sheetName, cell, header)
  298. }
  299. // 设置表头样式
  300. headerStyle, err := f.NewStyle(&excelize.Style{
  301. Font: &excelize.Font{
  302. Bold: true,
  303. },
  304. Alignment: &excelize.Alignment{
  305. Horizontal: "center",
  306. Vertical: "center",
  307. },
  308. Fill: excelize.Fill{
  309. Type: "pattern",
  310. Color: []string{"#E6F3FF"},
  311. Pattern: 1,
  312. },
  313. })
  314. if err == nil {
  315. f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), headerStyle)
  316. }
  317. // 填充数据
  318. for i, perf := range R_List {
  319. row := i + 2 // 从第2行开始(第1行是表头)
  320. // 序号
  321. f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), i+1)
  322. // 姓名
  323. f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), perf.T_submit_name)
  324. // 工资级别
  325. f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), perf.Target.T_name)
  326. // 绩效工资(元)
  327. f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), perf.T_perf)
  328. // 所属月份
  329. f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), perf.T_date)
  330. // 工作量
  331. f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), perf.T_workload)
  332. // 考核工作量
  333. f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), perf.T_assess_points)
  334. // 得分
  335. score := calculateTotalScore(perf)
  336. f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("%.1f%%", score))
  337. // 应发绩效
  338. perfTotal := calculatePerfTotal(perf)
  339. f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), fmt.Sprintf("%.2f", perfTotal))
  340. }
  341. // 设置列宽
  342. f.SetColWidth(sheetName, "A", "A", 8) // 序号
  343. f.SetColWidth(sheetName, "B", "B", 12) // 姓名
  344. f.SetColWidth(sheetName, "C", "C", 12) // 工资级别
  345. f.SetColWidth(sheetName, "D", "D", 15) // 绩效工资(元)
  346. f.SetColWidth(sheetName, "E", "E", 12) // 所属月份
  347. f.SetColWidth(sheetName, "F", "F", 12) // 工作量
  348. f.SetColWidth(sheetName, "G", "G", 15) // 考核工作量
  349. f.SetColWidth(sheetName, "H", "H", 12) // 得分
  350. f.SetColWidth(sheetName, "I", "I", 15) // 应发绩效
  351. // 设置数据区域样式
  352. dataStyle, err := f.NewStyle(&excelize.Style{
  353. Alignment: &excelize.Alignment{
  354. Horizontal: "center",
  355. Vertical: "center",
  356. },
  357. Border: []excelize.Border{
  358. {Type: "left", Color: "CCCCCC", Style: 1},
  359. {Type: "top", Color: "CCCCCC", Style: 1},
  360. {Type: "bottom", Color: "CCCCCC", Style: 1},
  361. {Type: "right", Color: "CCCCCC", Style: 1},
  362. },
  363. })
  364. if err == nil && len(R_List) > 0 {
  365. f.SetCellStyle(sheetName, "A2", fmt.Sprintf("I%d", len(R_List)+1), dataStyle)
  366. }
  367. // 生成文件名
  368. fileName := fmt.Sprintf("绩效管理_%s.xlsx", time.Now().Format("20060102_150405"))
  369. // 设置响应头
  370. c.Ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  371. c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
  372. c.Ctx.Output.Header("Content-Transfer-Encoding", "binary")
  373. // 写入响应
  374. if err := f.Write(c.Ctx.ResponseWriter); err != nil {
  375. logs.Error("写入Excel文件失败: %s", err)
  376. c.Data["json"] = lib.JSONS{Code: 500, Msg: "导出Excel失败"}
  377. c.ServeJSON()
  378. return
  379. }
  380. logs.Println(fmt.Sprintf("成功导出绩效管理Excel文件,共%d条记录", R_cnt))
  381. }
  382. func (c *PerformanceController) User_List() {
  383. s := services.Performance{}
  384. reqData := dto.PerformanceUserPageReq{}
  385. if err := c.ParseForm(&reqData); err != nil {
  386. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  387. c.ServeJSON()
  388. return
  389. }
  390. if err := Validate(&reqData); err != nil {
  391. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  392. c.ServeJSON()
  393. return
  394. }
  395. userList, _ := NatsServer.Read_User_List_All()
  396. Account.Read_User_All_Map(userList)
  397. reqData.T_submit = c.User.T_uuid
  398. R_List, R_cnt := s.GetPage(&reqData)
  399. var r_jsons lib.R_JSONS
  400. r_jsons.Num = R_cnt
  401. r_jsons.Data = R_List
  402. r_jsons.Page = reqData.Page
  403. r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(reqData.PageSize)))
  404. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
  405. c.ServeJSON()
  406. return
  407. }
  408. func (c *PerformanceController) User_Excel() {
  409. s := services.Performance{}
  410. reqData := dto.PerformanceUserPageReq{}
  411. if err := c.ParseForm(&reqData); err != nil {
  412. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  413. c.ServeJSON()
  414. return
  415. }
  416. if err := Validate(&reqData); err != nil {
  417. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  418. c.ServeJSON()
  419. return
  420. }
  421. reqData.PageSize = 9999
  422. reqData.T_submit = c.User.T_uuid
  423. userList, _ := NatsServer.Read_User_List_All()
  424. Account.Read_User_All_Map(userList)
  425. R_List, R_cnt := s.GetPage(&reqData)
  426. // 创建Excel文件
  427. f := excelize.NewFile()
  428. defer func() {
  429. if err := f.Close(); err != nil {
  430. logs.Error("关闭Excel文件失败: %s", err)
  431. }
  432. }()
  433. // 设置工作表名称
  434. sheetName := "绩效管理"
  435. index, err := f.NewSheet(sheetName)
  436. if err != nil {
  437. logs.Error("创建工作表失败: %s", err)
  438. c.Data["json"] = lib.JSONS{Code: 500, Msg: "创建Excel文件失败"}
  439. c.ServeJSON()
  440. return
  441. }
  442. f.SetActiveSheet(index)
  443. // 设置表头
  444. headers := []string{"序号", "姓名", "工资级别", "绩效工资(元)", "所属月份", "工作量", "考核工作量", "得分", "应发绩效"}
  445. for i, header := range headers {
  446. cell := fmt.Sprintf("%c1", 'A'+i)
  447. f.SetCellValue(sheetName, cell, header)
  448. }
  449. // 设置表头样式
  450. headerStyle, err := f.NewStyle(&excelize.Style{
  451. Font: &excelize.Font{
  452. Bold: true,
  453. },
  454. Alignment: &excelize.Alignment{
  455. Horizontal: "center",
  456. Vertical: "center",
  457. },
  458. Fill: excelize.Fill{
  459. Type: "pattern",
  460. Color: []string{"#E6F3FF"},
  461. Pattern: 1,
  462. },
  463. })
  464. if err == nil {
  465. f.SetCellStyle(sheetName, "A1", fmt.Sprintf("%c1", 'A'+len(headers)-1), headerStyle)
  466. }
  467. // 填充数据
  468. for i, perf := range R_List {
  469. row := i + 2 // 从第2行开始(第1行是表头)
  470. // 序号
  471. f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), i+1)
  472. // 姓名
  473. f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), perf.T_submit_name)
  474. // 工资级别
  475. f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), perf.Target.T_name)
  476. // 绩效工资(元)
  477. f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), perf.T_perf)
  478. // 所属月份
  479. f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), perf.T_date)
  480. // 工作量
  481. f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), perf.T_workload)
  482. // 考核工作量
  483. f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), perf.T_assess_points)
  484. // 得分
  485. score := calculateTotalScore(perf)
  486. f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), fmt.Sprintf("%.1f%%", score))
  487. // 应发绩效
  488. perfTotal := calculatePerfTotal(perf)
  489. f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), fmt.Sprintf("%.2f", perfTotal))
  490. }
  491. // 设置列宽
  492. f.SetColWidth(sheetName, "A", "A", 8) // 序号
  493. f.SetColWidth(sheetName, "B", "B", 12) // 姓名
  494. f.SetColWidth(sheetName, "C", "C", 12) // 工资级别
  495. f.SetColWidth(sheetName, "D", "D", 15) // 绩效工资(元)
  496. f.SetColWidth(sheetName, "E", "E", 12) // 所属月份
  497. f.SetColWidth(sheetName, "F", "F", 12) // 工作量
  498. f.SetColWidth(sheetName, "G", "G", 15) // 考核工作量
  499. f.SetColWidth(sheetName, "H", "H", 12) // 得分
  500. f.SetColWidth(sheetName, "I", "I", 15) // 应发绩效
  501. // 设置数据区域样式
  502. dataStyle, err := f.NewStyle(&excelize.Style{
  503. Alignment: &excelize.Alignment{
  504. Horizontal: "center",
  505. Vertical: "center",
  506. },
  507. Border: []excelize.Border{
  508. {Type: "left", Color: "CCCCCC", Style: 1},
  509. {Type: "top", Color: "CCCCCC", Style: 1},
  510. {Type: "bottom", Color: "CCCCCC", Style: 1},
  511. {Type: "right", Color: "CCCCCC", Style: 1},
  512. },
  513. })
  514. if err == nil && len(R_List) > 0 {
  515. f.SetCellStyle(sheetName, "A2", fmt.Sprintf("I%d", len(R_List)+1), dataStyle)
  516. }
  517. // 生成文件名
  518. fileName := fmt.Sprintf("绩效管理_%s.xlsx", time.Now().Format("20060102_150405"))
  519. // 设置响应头
  520. c.Ctx.Output.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  521. c.Ctx.Output.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", fileName))
  522. c.Ctx.Output.Header("Content-Transfer-Encoding", "binary")
  523. // 写入响应
  524. if err := f.Write(c.Ctx.ResponseWriter); err != nil {
  525. logs.Error("写入Excel文件失败: %s", err)
  526. c.Data["json"] = lib.JSONS{Code: 500, Msg: "导出Excel失败"}
  527. c.ServeJSON()
  528. return
  529. }
  530. logs.Println(fmt.Sprintf("成功导出绩效管理Excel文件,共%d条记录", R_cnt))
  531. }
  532. func (c *PerformanceController) Submit_User() {
  533. s := services.Performance{}
  534. page, _ := c.GetInt("page")
  535. if page < 1 {
  536. page = 1
  537. }
  538. page_z, _ := c.GetInt("page_z")
  539. if page_z < 1 {
  540. page_z = conf.Page_size
  541. }
  542. T_name := c.GetString("T_name")
  543. userList, _ := NatsServer.Read_User_List_All()
  544. Account.Read_User_All_Map(userList)
  545. uuidList := s.GetSubmitUserPage()
  546. R_List, R_cnt, err := NatsServer.Read_User_List_T_uuid(T_name, uuidList, page, page_z)
  547. if err != nil {
  548. c.Data["json"] = lib.JSONS{Code: 202, Msg: "查询失败"}
  549. c.ServeJSON()
  550. return
  551. }
  552. var U_List []userlibs.User
  553. for _, user := range R_List {
  554. U_List = append(U_List, user)
  555. }
  556. var r_jsons lib.R_JSONS
  557. r_jsons.Num = R_cnt
  558. r_jsons.Data = U_List
  559. r_jsons.Page = page
  560. r_jsons.Page_size = int(math.Ceil(float64(R_cnt) / float64(page_z)))
  561. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: r_jsons}
  562. c.ServeJSON()
  563. return
  564. }
  565. func (c *PerformanceController) Add() {
  566. s := services.Performance{}
  567. reqData := dto.PerformanceInsertReq{}
  568. if err := c.ParseForm(&reqData); err != nil {
  569. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  570. c.ServeJSON()
  571. return
  572. }
  573. if err := json.Unmarshal([]byte(reqData.Points), &reqData.PointList); err != nil {
  574. c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细 参数错误"}
  575. c.ServeJSON()
  576. return
  577. }
  578. if err := Validate(&reqData); err != nil {
  579. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  580. c.ServeJSON()
  581. return
  582. }
  583. reqData.T_submit = c.User.T_uuid
  584. // 如传入绩效点,则校验非空
  585. if len(reqData.PointList) == 0 {
  586. c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细不能为空"}
  587. c.ServeJSON()
  588. return
  589. }
  590. Id, err := s.Insert(&reqData)
  591. if err != nil {
  592. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  593. c.ServeJSON()
  594. return
  595. }
  596. NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "添加", reqData)
  597. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: Id}
  598. c.ServeJSON()
  599. return
  600. }
  601. func (c *PerformanceController) Edit() {
  602. s := services.Performance{}
  603. reqData := dto.PerformanceUpdateReq{}
  604. if err := c.ParseForm(&reqData); err != nil {
  605. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  606. c.ServeJSON()
  607. return
  608. }
  609. if err := json.Unmarshal([]byte(reqData.Points), &reqData.PointList); err != nil {
  610. c.Data["json"] = lib.JSONS{Code: 202, Msg: "绩效明细 参数错误"}
  611. c.ServeJSON()
  612. return
  613. }
  614. if err := Validate(&reqData); err != nil {
  615. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  616. c.ServeJSON()
  617. return
  618. }
  619. if err := s.Update(&reqData); err != nil {
  620. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  621. c.ServeJSON()
  622. return
  623. }
  624. NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "修改", reqData)
  625. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  626. c.ServeJSON()
  627. return
  628. }
  629. func (c *PerformanceController) Edit_Audit() {
  630. s := services.Performance{}
  631. reqData := dto.PerformanceUpdateAuditReq{}
  632. if err := c.ParseForm(&reqData); err != nil {
  633. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  634. c.ServeJSON()
  635. return
  636. }
  637. if err := Validate(&reqData); err != nil {
  638. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  639. c.ServeJSON()
  640. return
  641. }
  642. if err := s.UpdateAudit(&reqData); err != nil {
  643. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  644. c.ServeJSON()
  645. return
  646. }
  647. NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "修改状态", reqData)
  648. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  649. c.ServeJSON()
  650. return
  651. }
  652. func (c *PerformanceController) Del() {
  653. s := services.Performance{}
  654. reqData := dto.PerformanceDeleteReq{}
  655. if err := c.ParseForm(&reqData); err != nil {
  656. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  657. c.ServeJSON()
  658. return
  659. }
  660. if err := Validate(&reqData); err != nil {
  661. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  662. c.ServeJSON()
  663. return
  664. }
  665. if err := s.Delete(&reqData); err != nil {
  666. c.Data["json"] = lib.JSONS{Code: 202, Msg: err.Error()}
  667. c.ServeJSON()
  668. return
  669. }
  670. NatsServer.AddUserLogs(c.User.T_uuid, "绩效考核", "删除", strconv.Itoa(reqData.T_id))
  671. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!"}
  672. c.ServeJSON()
  673. return
  674. }
  675. // GetPerformanceDetail 根据ID获取绩效详情
  676. func (c *PerformanceController) GetPerformanceDetail() {
  677. s := services.Performance{}
  678. reqData := dto.PerformanceGetReq{}
  679. if err := c.ParseForm(&reqData); err != nil {
  680. c.Data["json"] = lib.JSONS{Code: 202, Msg: "参数错误"}
  681. c.ServeJSON()
  682. return
  683. }
  684. if reqData.T_id <= 0 {
  685. c.Data["json"] = lib.JSONS{Code: 202, Msg: "ID参数无效"}
  686. c.ServeJSON()
  687. return
  688. }
  689. perf, err := s.Get(reqData)
  690. if err != nil {
  691. c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取绩效详情失败: " + err.Error()}
  692. c.ServeJSON()
  693. return
  694. }
  695. // 获取关联的绩效点详情
  696. pointList, err := s.GetPerfPointsByPerfId(reqData.T_id)
  697. if err != nil {
  698. c.Data["json"] = lib.JSONS{Code: 202, Msg: "获取绩效点详情失败: " + err.Error()}
  699. c.ServeJSON()
  700. return
  701. }
  702. // 组装返回数据
  703. result := map[string]interface{}{
  704. "perf": perf,
  705. "pointList": pointList,
  706. }
  707. c.Data["json"] = lib.JSONS{Code: 200, Msg: "ok!", Data: result}
  708. c.ServeJSON()
  709. return
  710. }
  711. func Cron_Percentage() {
  712. //创建一个定时任务对象
  713. c := cron.New(cron.WithSeconds())
  714. //给对象增加定时任务 - 改为每月1日凌晨0点0分执行
  715. c.AddFunc("0 0 1 * *", SyncVerifyPercentage)
  716. //启动定时任务
  717. c.Start()
  718. defer c.Stop()
  719. //查询语句,阻塞,让main函数不退出,保持程序运行
  720. select {}
  721. }
  722. func SyncVerifyPercentage() {
  723. urls := "/openapi/task/list"
  724. signature, timestamp := lib.GenColdVerifySignature()
  725. // 构建请求数据
  726. var start_time, end_time string
  727. start_time = lib.GetFirstDayOfLastMonth() + " 00:00:00"
  728. end_time = lib.GetLastDayOfLastMonth() + " 23:59:59"
  729. // 使用标准HTTP库替换resty
  730. formData := url.Values{}
  731. formData.Set("T_reporting_pass_start_time", start_time)
  732. formData.Set("T_reporting_pass_end_time", end_time)
  733. formData.Set("X-API-KEY", lib.ColdVerify_OpenApi_Key)
  734. formData.Set("X-API-SIGNATURE", signature)
  735. formData.Set("X-API-TIMESTAMP", timestamp)
  736. // 构建完整URL
  737. fullURL := conf.ColdVerify_OpenApi_Host + urls
  738. // 创建HTTP客户端
  739. client := &http.Client{
  740. Timeout: 30 * time.Second,
  741. }
  742. // 创建POST请求
  743. req, err := http.NewRequest("POST", fullURL, strings.NewReader(formData.Encode()))
  744. if err != nil {
  745. logs.Error("创建HTTP请求失败: %v", err)
  746. return
  747. }
  748. // 设置请求头
  749. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  750. // 发送请求
  751. resp, err := client.Do(req)
  752. if err != nil {
  753. logs.Error("请求冷链验证任务列表接口失败: %v", err)
  754. return
  755. }
  756. defer resp.Body.Close()
  757. // 读取响应体
  758. body, err := io.ReadAll(resp.Body)
  759. if err != nil {
  760. logs.Error("读取响应体失败: %v", err)
  761. return
  762. }
  763. // 检查响应状态码
  764. if resp.StatusCode != http.StatusOK {
  765. logs.Error("请求冷链验证任务列表接口失败,状态码: %d", resp.StatusCode)
  766. return
  767. }
  768. // 解析响应
  769. type R_JSONS struct {
  770. //必须的大写开头
  771. Data []Performance.VerifyTask
  772. Code int64
  773. Msg string
  774. }
  775. var res R_JSONS
  776. if err = json.Unmarshal(body, &res); err != nil {
  777. logs.Error("解析响应数据失败: %v", err)
  778. return
  779. }
  780. pointsMap := GetPerformancePointsMap()
  781. coldVerifyUUIDMap := GetColdVerifyUUIDMap()
  782. // 分别为报告编写人员和数据采集人员创建统计映射
  783. reportingStat := map[string]map[int]int{} // 报告编写人员统计
  784. collectionStat := map[string]map[int]int{} // 数据采集人员统计
  785. // 遍历所有任务,分别统计报告编写人员和数据采集人员的工作量
  786. for _, task := range res.Data {
  787. verifyItem := GetPerformancePoints(Performance.DeviceTypeMap[task.T_device_type], task.T_verify_type, pointsMap)
  788. if verifyItem.Id == 0 {
  789. continue
  790. }
  791. // 报告编写人员统计
  792. reportingUserUUID := coldVerifyUUIDMap[task.T_reporting]
  793. if reportingUserUUID != "" {
  794. updateWorkloadStat(reportingStat, reportingUserUUID, verifyItem.Id)
  795. }
  796. // 数据采集人员统计
  797. collectionUserUUID := coldVerifyUUIDMap[task.T_collection]
  798. if collectionUserUUID != "" {
  799. updateWorkloadStat(collectionStat, collectionUserUUID, verifyItem.Id)
  800. }
  801. }
  802. Performance.Read_PerformanceTarget_All_Map()
  803. // 保存统计结果到数据库
  804. saveReportingStatsToDB(reportingStat, "reporting")
  805. saveCollectionStatsToDB(collectionStat, "collection")
  806. }
  807. // updateWorkloadStat 更新工作量统计的辅助函数
  808. func updateWorkloadStat(stat map[string]map[int]int, userUUID string, pointID int) {
  809. // 如果UUID为空则跳过
  810. if userUUID == "" {
  811. return
  812. }
  813. // 初始化用户映射表
  814. if stat[userUUID] == nil {
  815. stat[userUUID] = make(map[int]int)
  816. }
  817. // 增加工作量计数
  818. stat[userUUID][pointID]++
  819. }
  820. // saveReportingStatsToDB 保存报告编写人员统计结果到数据库
  821. func saveReportingStatsToDB(stat map[string]map[int]int, workType string) {
  822. s := services.Performance{}
  823. // 获取当前日期(用于T_date字段)
  824. currentDate := time.Now().Format("2006-01")
  825. // 遍历统计结果并保存到数据库
  826. for userUUID, points := range stat {
  827. // 计算总工作量
  828. totalWorkload := 0.0
  829. totalPoints := 0 // 总绩效点
  830. // 收集所有绩效点信息用于创建PerfPoint列表
  831. var pointList []Performance.PerfPoint
  832. for pointID, count := range points {
  833. // 获取绩效点信息以计算工作量
  834. pointsInfo := getPerformancePointsInfo(pointID)
  835. if pointsInfo.Id > 0 {
  836. // 计算工作量:T_points_numerator/T_points_denominator*统计出来的工作量
  837. workload := float64(pointsInfo.T_points_numerator) / float64(pointsInfo.T_points_denominator) * float64(count)
  838. totalWorkload += workload
  839. // 累计总绩效点和总数量
  840. totalPoints += pointsInfo.T_points_numerator
  841. // 创建绩效点记录
  842. point := Performance.PerfPoint{
  843. T_performance_points_id: pointID,
  844. T_quantity: count,
  845. T_points_numerator: pointsInfo.T_points_numerator,
  846. T_points_denominator: pointsInfo.T_points_denominator,
  847. T_type: workType,
  848. T_remark: fmt.Sprintf("报告编写工作量统计: %d项", count),
  849. }
  850. pointList = append(pointList, point)
  851. }
  852. }
  853. User := Account.Read_User_Get(userUUID)
  854. target := Performance.Read_PerformanceTarget_Get(User.T_verify_perf_target)
  855. // 创建Perf记录
  856. perf := Performance.Perf{
  857. T_date: currentDate,
  858. T_submit: userUUID,
  859. T_workload: totalWorkload,
  860. T_audit: 1, // 待提交状态
  861. T_State: 1, // 正常状态
  862. T_assess_points: target.T_assess_points, // 考核绩效点
  863. T_perf: target.T_perf, // 考核绩效点
  864. T_performance_target_id: target.Id, // 考核绩效点
  865. }
  866. // 保存到数据库
  867. _, err := s.InsertFromStats(&perf, pointList)
  868. if err != nil {
  869. logs.Error("保存报告编写人员统计结果失败: %v", err)
  870. } else {
  871. logs.Info("成功保存报告编写人员 %s 的统计结果", userUUID)
  872. }
  873. }
  874. }
  875. // saveCollectionStatsToDB 保存数据采集人员统计结果到数据库
  876. func saveCollectionStatsToDB(stat map[string]map[int]int, workType string) {
  877. s := services.Performance{}
  878. // 获取当前日期(用于T_date字段)
  879. currentDate := time.Now().AddDate(0, -1, 0).Format("2006-01")
  880. // 遍历统计结果并保存到数据库
  881. for userUUID, points := range stat {
  882. // 计算总工作量
  883. totalWorkload := 0.0
  884. totalPoints := 0 // 总绩效点
  885. totalCount := 0 // 总数量
  886. // 收集所有绩效点信息用于创建PerfPoint列表
  887. var pointList []Performance.PerfPoint
  888. for pointID, count := range points {
  889. // 获取绩效点信息以计算工作量
  890. pointsInfo := getPerformancePointsInfo(pointID)
  891. if pointsInfo.Id > 0 {
  892. // 计算工作量:T_points_numerator/T_points_denominator*统计出来的工作量
  893. workload := float64(pointsInfo.T_points_numerator) / float64(pointsInfo.T_points_denominator) * float64(count)
  894. totalWorkload += workload
  895. // 累计总绩效点和总数量
  896. totalPoints += pointsInfo.T_points_numerator
  897. totalCount += count
  898. // 创建绩效点记录
  899. point := Performance.PerfPoint{
  900. T_performance_points_id: pointID,
  901. T_quantity: count,
  902. T_points_numerator: pointsInfo.T_points_numerator,
  903. T_points_denominator: pointsInfo.T_points_denominator,
  904. T_type: workType,
  905. T_remark: fmt.Sprintf("数据采集工作量统计: %d项", count),
  906. }
  907. pointList = append(pointList, point)
  908. }
  909. }
  910. User := Account.Read_User_Get(userUUID)
  911. target := Performance.Read_PerformanceTarget_Get(User.T_verify_perf_target)
  912. // 创建Perf记录
  913. perf := Performance.Perf{
  914. T_date: currentDate,
  915. T_submit: userUUID,
  916. T_workload: totalWorkload,
  917. T_audit: 1, // 待提交状态
  918. T_State: 1, // 正常状态
  919. T_assess_points: target.T_assess_points, // 考核绩效点
  920. T_perf: target.T_perf, // 考核绩效
  921. T_performance_target_id: target.Id, // 工资级别id
  922. }
  923. // 保存到数据库
  924. _, err := s.InsertFromStats(&perf, pointList)
  925. if err != nil {
  926. logs.Error("保存数据采集人员统计结果失败: %v", err)
  927. } else {
  928. logs.Info(fmt.Sprintf("成功保存数据采集人员 %s 的统计结果", userUUID))
  929. }
  930. }
  931. }
  932. // getPerformancePointsInfo 获取绩效点信息
  933. func getPerformancePointsInfo(pointID int) Performance.PerformancePoints {
  934. s := services.PerformancePoints{}
  935. points, err := s.Get(pointID)
  936. if err != nil {
  937. logs.Error("获取绩效点信息失败: %v", err)
  938. return Performance.PerformancePoints{}
  939. }
  940. return points
  941. }
  942. func GetPerformancePointsMap() map[string]Performance.PerformancePoints {
  943. s := services.PerformancePoints{}
  944. reqData := dto.PerformancePointsPageReq{}
  945. reqData.PageSize = 9999
  946. performancePointsList, _ := s.GetPage(&reqData)
  947. var pointsMap = make(map[string]Performance.PerformancePoints) // 实施
  948. for _, item := range performancePointsList {
  949. pointsMap[item.T_name] = item
  950. }
  951. return pointsMap
  952. }
  953. func GetColdVerifyUUIDMap() (uuidMap map[string]string) {
  954. uuidMap = make(map[string]string)
  955. userList, _ := NatsServer.Read_User_List_All()
  956. for _, user := range userList {
  957. uuidMap[user.T_verify_cold_uuid] = user.T_uuid
  958. }
  959. return uuidMap
  960. }
  961. // 获取实施提成金额
  962. func GetPerformancePoints(T_device_type, T_verify_type string, pointsMap map[string]Performance.PerformancePoints) (money Performance.PerformancePoints) {
  963. if strings.Contains(T_device_type, "箱") {
  964. return pointsMap["箱"]
  965. }
  966. if strings.Contains(T_device_type, "车") {
  967. if strings.Contains(T_verify_type, "空载") {
  968. return pointsMap["车(空载)"]
  969. } else {
  970. return pointsMap["车(满载)"]
  971. }
  972. }
  973. if strings.Contains(T_device_type, "柜") {
  974. if strings.Contains(T_verify_type, "空载") {
  975. return pointsMap["库(空载)"]
  976. } else {
  977. return pointsMap["库(满载)"]
  978. }
  979. }
  980. if strings.Contains(T_device_type, "库") {
  981. if strings.Contains(T_verify_type, "空载") {
  982. return pointsMap["库(空载)"]
  983. } else {
  984. return pointsMap["库(满载)"]
  985. }
  986. }
  987. if strings.Contains(T_device_type, "系统") {
  988. return pointsMap["系统"]
  989. }
  990. if strings.Contains(T_device_type, "位置") {
  991. return pointsMap["位置"]
  992. }
  993. if strings.Contains(T_device_type, "巡检") {
  994. return pointsMap["巡检"]
  995. }
  996. if strings.Contains(T_device_type, "培训") {
  997. return pointsMap["培训"]
  998. }
  999. return Performance.PerformancePoints{}
  1000. }