From aca18e8a6b49f0c9aeb1707d55f70509a4e0d94d Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Sat, 22 Aug 2026 23:19:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=8F=E5=AE=9E=E6=8A=A5=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CanteenReportSupplierAllocSaveDTO.java | 26 ++ .../CanteenReportSupplierAllocEntity.java | 50 +++ .../report/CanteenReportConstants.java | 5 + .../CanteenReportSupplierAllocRowVO.java | 25 ++ .../CanteenReportSupplierAllocTableVO.java | 42 ++ .../controller/CanteenReportController.java | 17 + .../CanteenReportFaceImportController.java | 7 + .../CanteenReportSupplierAllocMapper.java | 12 + .../CanteenReportFaceImportService.java | 3 + .../CanteenReportSupplierAllocService.java | 14 + .../CanteenReportFaceImportServiceImpl.java | 32 ++ ...CanteenReportSupplierAllocServiceImpl.java | 408 ++++++++++++++++++ .../CanteenReportSupplierAllocMapper.xml | 9 + 13 files changed, 650 insertions(+) create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/report/CanteenReportSupplierAllocSaveDTO.java create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenReportSupplierAllocEntity.java create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocRowVO.java create mode 100644 pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocTableVO.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenReportSupplierAllocMapper.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportSupplierAllocService.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportSupplierAllocServiceImpl.java create mode 100644 pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenReportSupplierAllocMapper.xml diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/report/CanteenReportSupplierAllocSaveDTO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/report/CanteenReportSupplierAllocSaveDTO.java new file mode 100644 index 000000000..ff7f9f337 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/dto/report/CanteenReportSupplierAllocSaveDTO.java @@ -0,0 +1,26 @@ +package com.bsd.pjcloud.canteen.dto.report; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.List; + +@Data +@Schema(description = "供应商分摊保存") +public class CanteenReportSupplierAllocSaveDTO { + + @Schema(description = "业务月") + private String bizMonth; + + @Schema(description = "分配单元") + private List cells = new ArrayList<>(); + + @Data + public static class Cell { + private String costCenter; + private String supplier; + private BigDecimal amount; + } +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenReportSupplierAllocEntity.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenReportSupplierAllocEntity.java new file mode 100644 index 000000000..c210ba8ab --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/entity/CanteenReportSupplierAllocEntity.java @@ -0,0 +1,50 @@ +package com.bsd.pjcloud.canteen.entity; + +import com.baomidou.mybatisplus.annotation.*; +import com.baomidou.mybatisplus.extension.activerecord.Model; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Data +@TableName("canteen_report_supplier_alloc") +@EqualsAndHashCode(callSuper = true) +@Schema(description = "食堂报表-供应商分摊手工分配") +public class CanteenReportSupplierAllocEntity extends Model { + + @TableId(type = IdType.ASSIGN_ID) + private Long id; + + @Schema(description = "业务月份 yyyy-MM") + private String bizMonth; + + @Schema(description = "成本中心") + private String costCenter; + + @Schema(description = "供应商") + private String supplier; + + @Schema(description = "分配金额(元)") + private BigDecimal amount; + + @TableField(fill = FieldFill.INSERT) + private String createBy; + + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + @TableField(fill = FieldFill.INSERT_UPDATE) + private String updateBy; + + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + @TableLogic + @TableField(fill = FieldFill.INSERT) + private String delFlag; + + private Long tenantId; +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/report/CanteenReportConstants.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/report/CanteenReportConstants.java index 7440a5529..2251105bc 100644 --- a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/report/CanteenReportConstants.java +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/report/CanteenReportConstants.java @@ -58,6 +58,11 @@ public final class CanteenReportConstants { "食材", "能耗", "外协" )); + /** 供应商分摊右侧表:最末手填列(无固定开票额,参与行差额) */ + public static final List SUPPLIER_ALLOC_MANUAL_COLS = Collections.unmodifiableList(Arrays.asList( + "招待费" + )); + public static final List COST_CENTERS = Collections.unmodifiableList(Arrays.asList( "嘉兴敏华", "嘉兴敏惠-铝件", diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocRowVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocRowVO.java new file mode 100644 index 000000000..9320e926a --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocRowVO.java @@ -0,0 +1,25 @@ +package com.bsd.pjcloud.canteen.vo.report; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.LinkedHashMap; +import java.util.Map; + +@Data +@Schema(description = "供应商分摊-分配行") +public class CanteenReportSupplierAllocRowVO { + + @Schema(description = "成本中心") + private String costCenter; + + @Schema(description = "开票小计(来自左侧成本分摊开票金额)") + private BigDecimal invoiceSubtotal = BigDecimal.ZERO; + + @Schema(description = "各供应商分配金额") + private Map supplierAmounts = new LinkedHashMap<>(); + + @Schema(description = "差额=开票小计-各供应商之和") + private BigDecimal diff = BigDecimal.ZERO; +} diff --git a/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocTableVO.java b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocTableVO.java new file mode 100644 index 000000000..dfcdf77bc --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-api/src/main/java/com/bsd/pjcloud/canteen/vo/report/CanteenReportSupplierAllocTableVO.java @@ -0,0 +1,42 @@ +package com.bsd.pjcloud.canteen.vo.report; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +@Data +@Schema(description = "供应商分摊右侧表") +public class CanteenReportSupplierAllocTableVO { + + @Schema(description = "供应商列顺序") + private List suppliers = new ArrayList<>(); + + @Schema(description = "右侧手填列(招待费等,无固定开票上限)") + private List manualColumns = new ArrayList<>(); + + @Schema(description = "供应商固定开票合计(食材能耗汇总)") + private Map supplierTotals = new LinkedHashMap<>(); + + @Schema(description = "供应商开票总计") + private BigDecimal grandTotal = BigDecimal.ZERO; + + @Schema(description = "成本中心开票小计合计") + private BigDecimal invoiceGrandTotal = BigDecimal.ZERO; + + @Schema(description = "分配行") + private List rows = new ArrayList<>(); + + @Schema(description = "小计行(各列合计)") + private CanteenReportSupplierAllocRowVO subtotalRow; + + @Schema(description = "检查行:列合计-固定开票,应≤0防止填超") + private Map checkRow = new LinkedHashMap<>(); + + @Schema(description = "检查-开票小计列:已分配合计-开票小计合计") + private BigDecimal checkInvoiceSubtotal = BigDecimal.ZERO; +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportController.java index 26b0f5ad9..e8a96d2cf 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportController.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportController.java @@ -3,7 +3,9 @@ package com.bsd.pjcloud.canteen.controller; import com.bsd.pjcloud.canteen.dto.report.CanteenReportBusinessExportExcel; import com.bsd.pjcloud.canteen.dto.report.CanteenReportIncomeExportExcel; import com.bsd.pjcloud.canteen.dto.report.CanteenReportShareExportExcel; +import com.bsd.pjcloud.canteen.dto.report.CanteenReportSupplierAllocSaveDTO; import com.bsd.pjcloud.canteen.service.CanteenReportCalcService; +import com.bsd.pjcloud.canteen.service.CanteenReportSupplierAllocService; import com.bsd.pjcloud.canteen.vo.report.CanteenReportBusinessRowVO; import com.bsd.pjcloud.canteen.vo.report.CanteenReportIncomeRowVO; import com.bsd.pjcloud.canteen.vo.report.CanteenReportShareRowVO; @@ -15,6 +17,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpHeaders; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @@ -32,6 +36,7 @@ import java.util.Map; public class CanteenReportController { private final CanteenReportCalcService calcService; + private final CanteenReportSupplierAllocService supplierAllocService; @Operation(summary = "汇总校验") @GetMapping("/summary") @@ -57,6 +62,18 @@ public class CanteenReportController { return R.ok(calcService.supplierShareAudit(bizMonth)); } + @Operation(summary = "供应商分摊-右侧开票分配表") + @GetMapping("/supplierShare/alloc") + public R supplierShareAlloc(@RequestParam String bizMonth) { + return R.ok(supplierAllocService.buildTable(bizMonth)); + } + + @Operation(summary = "保存供应商分摊开票分配") + @PutMapping("/supplierShare/alloc") + public R saveSupplierShareAlloc(@RequestBody CanteenReportSupplierAllocSaveDTO dto) { + return supplierAllocService.saveAlloc(dto); + } + @Operation(summary = "经营报表") @GetMapping("/business") public R business(@RequestParam String bizMonth) { diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportFaceImportController.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportFaceImportController.java index 2086fd33a..eec4756fd 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportFaceImportController.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/controller/CanteenReportFaceImportController.java @@ -39,6 +39,13 @@ public class CanteenReportFaceImportController { return R.ok(faceImportService.getById(id)); } + @SysLog("删除人脸消费导入记录") + @Operation(summary = "删除导入日志及该批明细(含曾按该批写入的 FACE 刷卡行)") + @DeleteMapping("/log") + public R removeLog(@RequestBody Long[] ids) { + return faceImportService.deleteImportLogs(java.util.Arrays.asList(ids)); + } + @Operation(summary = "人脸逐笔明细分页") @GetMapping("/detail/page") public R detailPage(@ParameterObject Page page, diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenReportSupplierAllocMapper.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenReportSupplierAllocMapper.java new file mode 100644 index 000000000..d50f1feee --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/mapper/CanteenReportSupplierAllocMapper.java @@ -0,0 +1,12 @@ +package com.bsd.pjcloud.canteen.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.bsd.pjcloud.canteen.entity.CanteenReportSupplierAllocEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +@Mapper +public interface CanteenReportSupplierAllocMapper extends BaseMapper { + + int deletePhysicallyByBizMonth(@Param("bizMonth") String bizMonth); +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportFaceImportService.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportFaceImportService.java index 1b8857ec3..eff5b15e1 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportFaceImportService.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportFaceImportService.java @@ -38,4 +38,7 @@ public interface CanteenReportFaceImportService extends IService orgLevel2s); List listOrgLevel2(String bizMonth, Long importLogId); + + /** 删除导入日志及该批人脸明细;若曾按该批汇总,同步删除关联 FACE 刷卡行 */ + R deleteImportLogs(List ids); } diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportSupplierAllocService.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportSupplierAllocService.java new file mode 100644 index 000000000..378854f8b --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/CanteenReportSupplierAllocService.java @@ -0,0 +1,14 @@ +package com.bsd.pjcloud.canteen.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.bsd.pjcloud.canteen.dto.report.CanteenReportSupplierAllocSaveDTO; +import com.bsd.pjcloud.canteen.entity.CanteenReportSupplierAllocEntity; +import com.bsd.pjcloud.canteen.vo.report.CanteenReportSupplierAllocTableVO; +import com.bsd.pjcloud.common.core.util.R; + +public interface CanteenReportSupplierAllocService extends IService { + + CanteenReportSupplierAllocTableVO buildTable(String bizMonth); + + R saveAlloc(CanteenReportSupplierAllocSaveDTO dto); +} diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportFaceImportServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportFaceImportServiceImpl.java index d851f9c73..dd78aa6b5 100644 --- a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportFaceImportServiceImpl.java +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportFaceImportServiceImpl.java @@ -75,6 +75,38 @@ public class CanteenReportFaceImportServiceImpl extends ServiceImpl ids) { + if (CollUtil.isEmpty(ids)) { + return R.failed("请选择要删除的导入记录"); + } + int logCount = 0; + int detailRows = 0; + int swipeRows = 0; + for (Long id : ids) { + if (id == null) { + continue; + } + CanteenReportImportLogEntity logEntity = getById(id); + if (logEntity == null) { + continue; + } + if ("RUNNING".equals(logEntity.getStatus())) { + return R.failed(String.format("「%s」仍在导入中,请完成或失败后再删除", StrUtil.blankToDefault(logEntity.getFileName(), "导入任务"))); + } + detailRows += faceDetailMapper.deletePhysicallyByImportLogId(id); + swipeRows += swipeMapper.deletePhysicallyByImportLogId(id); + removeById(id); + logCount++; + } + if (logCount == 0) { + return R.failed("未找到可删除的导入记录"); + } + return R.ok(null, String.format("已删除 %d 条导入记录;人脸明细 %d 行,关联 FACE 刷卡 %d 行", logCount, detailRows, + swipeRows)); + } + @Override public Page pageDetails(Page page, String bizMonth, Long importLogId, String empNo, String payMethod, String deviceName, String empName, String phone, List orgLevel2s) { diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportSupplierAllocServiceImpl.java b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportSupplierAllocServiceImpl.java new file mode 100644 index 000000000..9c28a80b1 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/java/com/bsd/pjcloud/canteen/service/impl/CanteenReportSupplierAllocServiceImpl.java @@ -0,0 +1,408 @@ +package com.bsd.pjcloud.canteen.service.impl; + + + +import cn.hutool.core.collection.CollUtil; + +import cn.hutool.core.util.StrUtil; + +import com.baomidou.mybatisplus.core.toolkit.Wrappers; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; + +import com.bsd.pjcloud.canteen.dto.report.CanteenReportSupplierAllocSaveDTO; + +import com.bsd.pjcloud.canteen.entity.CanteenReportFoodEnergyEntity; + +import com.bsd.pjcloud.canteen.entity.CanteenReportSupplierAllocEntity; + +import com.bsd.pjcloud.canteen.mapper.CanteenReportSupplierAllocMapper; + +import com.bsd.pjcloud.canteen.report.CanteenReportConstants; + +import com.bsd.pjcloud.canteen.service.CanteenReportCalcService; + +import com.bsd.pjcloud.canteen.service.CanteenReportFoodEnergyService; + +import com.bsd.pjcloud.canteen.service.CanteenReportSupplierAllocService; + +import com.bsd.pjcloud.canteen.vo.report.CanteenReportShareRowVO; + +import com.bsd.pjcloud.canteen.vo.report.CanteenReportSupplierAllocRowVO; + +import com.bsd.pjcloud.canteen.vo.report.CanteenReportSupplierAllocTableVO; + +import com.bsd.pjcloud.common.core.util.R; + +import lombok.RequiredArgsConstructor; + +import org.springframework.stereotype.Service; + +import org.springframework.transaction.annotation.Transactional; + + + +import java.math.BigDecimal; + +import java.math.RoundingMode; + +import java.util.ArrayList; + +import java.util.Comparator; + +import java.util.HashMap; + +import java.util.LinkedHashMap; + +import java.util.List; + +import java.util.Map; + +import java.util.stream.Collectors; + + + +@Service + +@RequiredArgsConstructor + +public class CanteenReportSupplierAllocServiceImpl + + extends ServiceImpl + + implements CanteenReportSupplierAllocService { + + + + private static final int SCALE = 2; + + + + private final CanteenReportCalcService calcService; + + private final CanteenReportFoodEnergyService foodEnergyService; + + + + @Override + + public CanteenReportSupplierAllocTableVO buildTable(String bizMonth) { + + Map supplierTotals = loadSupplierTotals(bizMonth); + + List suppliers = supplierTotals.keySet().stream() + + .sorted(Comparator.comparing((String s) -> supplierTotals.get(s)).reversed() + + .thenComparing(String::compareTo)) + + .collect(Collectors.toList()); + + List manualCols = new ArrayList<>(CanteenReportConstants.SUPPLIER_ALLOC_MANUAL_COLS); + + List allCols = new ArrayList<>(suppliers); + + allCols.addAll(manualCols); + + + + BigDecimal grandTotal = supplierTotals.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add) + + .setScale(SCALE, RoundingMode.HALF_UP); + + + + Map saved = loadSavedMap(bizMonth); + + List shareRows = calcService.supplierShareReport(bizMonth); + + + + List rows = new ArrayList<>(); + + Map colSums = new LinkedHashMap<>(); + + for (String col : allCols) { + + colSums.put(col, BigDecimal.ZERO); + + } + + BigDecimal invoiceGrand = BigDecimal.ZERO; + + BigDecimal allocGrand = BigDecimal.ZERO; + + + + for (CanteenReportShareRowVO share : shareRows) { + + String center = share.getCostCenter(); + + if (isMetaRow(center)) { + + continue; + + } + + CanteenReportSupplierAllocRowVO row = buildRow(center, nz(share.getInvoiceAmount()), allCols, saved); + + rows.add(row); + + invoiceGrand = invoiceGrand.add(row.getInvoiceSubtotal()); + + for (Map.Entry e : row.getSupplierAmounts().entrySet()) { + + colSums.merge(e.getKey(), nz(e.getValue()), BigDecimal::add); + + allocGrand = allocGrand.add(nz(e.getValue())); + + } + + } + + + + CanteenReportSupplierAllocRowVO subtotalRow = new CanteenReportSupplierAllocRowVO(); + + subtotalRow.setCostCenter("小计"); + + subtotalRow.setInvoiceSubtotal(invoiceGrand.setScale(SCALE, RoundingMode.HALF_UP)); + + Map subMap = new LinkedHashMap<>(); + + for (String col : allCols) { + + subMap.put(col, nz(colSums.get(col)).setScale(SCALE, RoundingMode.HALF_UP)); + + } + + subtotalRow.setSupplierAmounts(subMap); + + subtotalRow.setDiff(invoiceGrand.subtract(allocGrand).setScale(SCALE, RoundingMode.HALF_UP)); + + + + Map checkRow = new LinkedHashMap<>(); + + for (String sup : suppliers) { + + BigDecimal sum = nz(colSums.get(sup)); + + BigDecimal fixed = nz(supplierTotals.get(sup)); + + checkRow.put(sup, sum.subtract(fixed).setScale(SCALE, RoundingMode.HALF_UP)); + + } + + + + CanteenReportSupplierAllocTableVO vo = new CanteenReportSupplierAllocTableVO(); + + vo.setSuppliers(suppliers); + + vo.setManualColumns(manualCols); + + vo.setSupplierTotals(roundMap(supplierTotals)); + + vo.setGrandTotal(grandTotal); + + vo.setInvoiceGrandTotal(invoiceGrand.setScale(SCALE, RoundingMode.HALF_UP)); + + vo.setRows(rows); + + vo.setSubtotalRow(subtotalRow); + + vo.setCheckRow(checkRow); + + vo.setCheckInvoiceSubtotal(allocGrand.subtract(invoiceGrand).setScale(SCALE, RoundingMode.HALF_UP)); + + return vo; + + } + + + + @Override + + @Transactional(rollbackFor = Exception.class) + + public R saveAlloc(CanteenReportSupplierAllocSaveDTO dto) { + + if (dto == null || StrUtil.isBlank(dto.getBizMonth())) { + + return R.failed("业务月不能为空"); + + } + + String bizMonth = dto.getBizMonth().trim(); + // 逻辑删除无法释放 uk(biz_month,cost_center,supplier),保存前须物理清空该月 + baseMapper.deletePhysicallyByBizMonth(bizMonth); + + if (CollUtil.isEmpty(dto.getCells())) { + return R.ok(null, "已清空该月供应商分摊"); + } + + Map dedup = new LinkedHashMap<>(); + for (CanteenReportSupplierAllocSaveDTO.Cell cell : dto.getCells()) { + if (cell == null || StrUtil.isBlank(cell.getCostCenter()) || StrUtil.isBlank(cell.getSupplier())) { + continue; + } + String center = cell.getCostCenter().trim(); + String supplier = cell.getSupplier().trim(); + if (isMetaRow(center)) { + continue; + } + BigDecimal amt = nz(cell.getAmount()).setScale(SCALE, RoundingMode.HALF_UP); + if (amt.compareTo(BigDecimal.ZERO) == 0) { + continue; + } + String key = center + "|" + supplier; + CanteenReportSupplierAllocEntity entity = new CanteenReportSupplierAllocEntity(); + entity.setBizMonth(bizMonth); + entity.setCostCenter(center); + entity.setSupplier(supplier); + entity.setAmount(amt); + dedup.put(key, entity); + } + List batch = new ArrayList<>(dedup.values()); + if (!batch.isEmpty()) { + saveBatch(batch, 500); + } + + + + CanteenReportSupplierAllocTableVO table = buildTable(bizMonth); + + boolean over = table.getCheckRow().values().stream().anyMatch(v -> nz(v).compareTo(BigDecimal.ZERO) > 0); + + String msg = over ? "已保存;部分供应商分配合计超过固定开票额,请查看检查行" : "保存成功"; + + return R.ok(table, msg); + + } + + + + private Map loadSupplierTotals(String bizMonth) { + + List foods = foodEnergyService.list( + + Wrappers.lambdaQuery() + + .eq(CanteenReportFoodEnergyEntity::getBizMonth, bizMonth)); + + Map totals = new LinkedHashMap<>(); + + for (CanteenReportFoodEnergyEntity f : foods) { + + String classify = StrUtil.blankToDefault(f.getClassify(), "食材").trim(); + + if (!CanteenReportConstants.SHARE_FOOD_CLASSIFY.contains(classify)) { + + continue; + + } + + String supplier = StrUtil.blankToDefault(f.getSupplier(), "未知供应商").trim(); + + totals.merge(supplier, nz(f.getSettleAmount()), BigDecimal::add); + + } + + return totals; + + } + + + + private Map loadSavedMap(String bizMonth) { + + List list = list( + + Wrappers.lambdaQuery() + + .eq(CanteenReportSupplierAllocEntity::getBizMonth, bizMonth)); + + Map map = new HashMap<>(); + + for (CanteenReportSupplierAllocEntity e : list) { + + map.put(e.getCostCenter() + "|" + e.getSupplier(), nz(e.getAmount())); + + } + + return map; + + } + + + + private CanteenReportSupplierAllocRowVO buildRow(String center, BigDecimal invoiceSubtotal, List columns, + + Map saved) { + + CanteenReportSupplierAllocRowVO row = new CanteenReportSupplierAllocRowVO(); + + row.setCostCenter(center); + + row.setInvoiceSubtotal(invoiceSubtotal.setScale(SCALE, RoundingMode.HALF_UP)); + + Map amounts = new LinkedHashMap<>(); + + BigDecimal rowSum = BigDecimal.ZERO; + + for (String col : columns) { + + BigDecimal amt = nz(saved.get(center + "|" + col)).setScale(SCALE, RoundingMode.HALF_UP); + + amounts.put(col, amt); + + rowSum = rowSum.add(amt); + + } + + row.setSupplierAmounts(amounts); + + row.setDiff(invoiceSubtotal.subtract(rowSum).setScale(SCALE, RoundingMode.HALF_UP)); + + return row; + + } + + + + private static boolean isMetaRow(String center) { + + return "小计".equals(center) || "开票调整(全局)".equals(center) + + || (center != null && center.startsWith("检查")); + + } + + + + private static BigDecimal nz(BigDecimal v) { + + return v == null ? BigDecimal.ZERO : v; + + } + + + + private static Map roundMap(Map src) { + + Map out = new LinkedHashMap<>(); + + for (Map.Entry e : src.entrySet()) { + + out.put(e.getKey(), nz(e.getValue()).setScale(SCALE, RoundingMode.HALF_UP)); + + } + + return out; + + } + +} + + diff --git a/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenReportSupplierAllocMapper.xml b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenReportSupplierAllocMapper.xml new file mode 100644 index 000000000..955e55627 --- /dev/null +++ b/pjcloud-canteen/pjcloud-canteen-biz/src/main/resources/mapper/CanteenReportSupplierAllocMapper.xml @@ -0,0 +1,9 @@ + + + + + + DELETE FROM canteen_report_supplier_alloc WHERE biz_month = #{bizMonth} + + +