| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- package com.malk.controller;
- import com.malk.service.workhours.WorkHoursCalcService;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RequestParam;
- import org.springframework.web.bind.annotation.RestController;
- import java.time.LocalDate;
- import java.util.LinkedHashMap;
- import java.util.Map;
- /**
- * 应填报工时临时接口(验证用)
- */
- @Slf4j
- @RestController
- @RequestMapping("/workhours")
- public class WorkHoursController {
- @Autowired
- private WorkHoursCalcService workHoursCalcService;
- /**
- * 批量删除全部应填报工时数据
- * GET /workhours/delete-all
- */
- @GetMapping("/delete-all")
- public Map<String, Object> deleteAll() {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- workHoursCalcService.deleteAllRequiredHours();
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", "应填报工时数据已清空");
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("删除失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 单员工单日验证写入(清空后做一条验证,确认归属公司等字段正确带入)
- * GET /workhours/sync-one?userId=xxx&date=2026-04-22
- */
- @GetMapping("/sync-one")
- public Map<String, Object> syncOne(@RequestParam String userId,
- @RequestParam String date) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- LocalDate workDay = LocalDate.parse(date);
- Map<String, Object> data = workHoursCalcService.syncOneEmployeeOneDay(userId, workDay);
- long cost = System.currentTimeMillis() - start;
- Object ok = data.get("success");
- result.put("success", Boolean.TRUE.equals(ok));
- result.put("message", Boolean.TRUE.equals(ok) ? "单条验证写入完成" : "单条验证写入失败");
- result.put("data", data);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("单条验证失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 小批量同步:前 N 个内部员工 × 当月工作日(默认 count=5)
- * GET /workhours/sync-batch?count=5&month=2026-04
- */
- @GetMapping("/sync-batch")
- public Map<String, Object> syncBatch(@RequestParam(defaultValue = "5") int count,
- @RequestParam(required = false) String month) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- LocalDate targetMonth = null;
- if (month != null && !month.isEmpty()) {
- targetMonth = LocalDate.parse(month + "-01");
- }
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.syncBatchEmployees(count, targetMonth);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", "小批量同步完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("小批量同步失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 回填存量应填报工时的「是否cf员工」字段(textField_mpp7a2k7),值取自人员档案
- * GET /workhours/backfill-cf (实际更新)
- * GET /workhours/backfill-cf?dryRun=true(仅扫描预览,不更新)
- */
- @GetMapping("/backfill-cf")
- public Map<String, Object> backfillCf(@RequestParam(defaultValue = "false") boolean dryRun) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.backfillCfEmployee(dryRun);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", dryRun ? "cf字段回填预览完成(未更新)" : "cf字段回填完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("cf字段回填失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 回填存量应填报工时的「归属公司」+「属性」两字段, 值取自人员档案
- * ppExt: 一次性接口, 不设定时; 主流程 upsertDailyHours 已带最新两字段, 后续变动自动同步, 老记录靠本接口一次对齐
- * GET /workhours/backfill-company-attr (实际更新)
- * GET /workhours/backfill-company-attr?dryRun=true(仅扫描预览, 不更新)
- */
- @GetMapping("/backfill-company-attr")
- public Map<String, Object> backfillCompanyAttr(@RequestParam(defaultValue = "false") boolean dryRun) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.backfillCompanyAndAttribute(dryRun);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", dryRun ? "公司+属性回填预览完成(未更新)" : "公司+属性回填完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("公司+属性回填失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 清理同一员工同一日期的重复应填报工时(一次性接口,默认仅预览)
- * GET /workhours/cleanup-duplicates (仅预览)
- * GET /workhours/cleanup-duplicates?dryRun=false(实际删除)
- */
- @GetMapping("/cleanup-duplicates")
- public Map<String, Object> cleanupDuplicates(@RequestParam(defaultValue = "true") boolean dryRun) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.cleanupDuplicateHours(dryRun);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", dryRun ? "重复工时清理预览完成(未删除)" : "重复工时清理完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("重复工时清理失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 清理已离职员工「离职日之后」的历史应报工时(一次性接口)
- * GET /workhours/cleanup-after-offline (实际删除)
- * GET /workhours/cleanup-after-offline?dryRun=true(仅统计不删除)
- */
- @GetMapping("/cleanup-after-offline")
- public Map<String, Object> cleanupAfterOffline(@RequestParam(defaultValue = "false") boolean dryRun) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.cleanupAfterOffline(dryRun);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", dryRun ? "离职后工时清理预览完成(未删除)" : "离职后工时清理完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("离职后工时清理失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 清理已写入的"未来"应报工时 (workDay > cutoff, cutoff 缺省 today)
- * GET /workhours/cleanup-future (实际删除, cutoff=today)
- * GET /workhours/cleanup-future?dryRun=true (仅预览)
- * GET /workhours/cleanup-future?cutoff=2026-07-15 (指定保留截止日)
- */
- @GetMapping("/cleanup-future")
- public Map<String, Object> cleanupFuture(@RequestParam(required = false) String cutoff,
- @RequestParam(defaultValue = "false") boolean dryRun) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- LocalDate cutoffDate = (cutoff == null || cutoff.isEmpty()) ? null : LocalDate.parse(cutoff);
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.cleanupFutureHours(cutoffDate, dryRun);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", dryRun ? "未来工时清理预览完成(未删除)" : "未来工时清理完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("未来工时清理失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 项目变更审批增量同步(手动触发;定时器 ProjectChangeSyncTimer 定期跑)
- * GET /workhours/sync-project-changes?daysBack=7
- * 只更新变更时间未来的应报工时 Manager, 变更前记录一律不动
- */
- @GetMapping("/sync-project-changes")
- public Map<String, Object> syncProjectChanges(@RequestParam(defaultValue = "7") int daysBack) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.syncProjectChanges(daysBack);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", "项目变更增量同步完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("项目变更同步失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- /**
- * 全量同步当月应填报工时
- * GET /workhours/sync?month=2026-04
- */
- @GetMapping("/sync")
- public Map<String, Object> sync(@RequestParam(required = false) String month) {
- Map<String, Object> result = new LinkedHashMap<>();
- try {
- LocalDate targetMonth = null;
- if (month != null && !month.isEmpty()) {
- targetMonth = LocalDate.parse(month + "-01");
- }
- long start = System.currentTimeMillis();
- Map<String, Object> stats = workHoursCalcService.calculateAndSyncMonthlyHours(targetMonth);
- long cost = System.currentTimeMillis() - start;
- result.put("success", true);
- result.put("message", "全量同步完成");
- result.put("stats", stats);
- result.put("costMs", cost);
- } catch (Exception e) {
- log.error("同步失败", e);
- result.put("success", false);
- result.put("message", e.getMessage());
- }
- return result;
- }
- }
|