Pārlūkot izejas kodu

撤销审批验证,已生成账单则不能撤销

zhangyao 1 mēnesi atpakaļ
vecāks
revīzija
e05ca999a0

+ 20 - 2
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/contractApproveController.java

@@ -164,7 +164,8 @@ public class contractApproveController {
     @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_recurring_services")
     public ResponseObject revokeRecurringServices(UserContext uc, String ids) throws SQLException {
         String result = contractService.getInstance().revokeRecurringServices(uc, ids);
-        if (StringUtils.isNotBlank(result)) return ResponseObject.newErrResponse(result);
+        if (StringUtils.isNotBlank(result))
+            return ResponseObject.newErrResponse(result);
 
         contractLogger.info("撤销定期服务成功");
         return ResponseObject.newOkResponse();
@@ -189,7 +190,8 @@ public class contractApproveController {
     @Mapping("com.awspaas.user.apps.donenow_ctt.revoke_cost")
     public ResponseObject revokeCost(UserContext uc, String ids) throws SQLException {
         String result = contractService.getInstance().revokeCost(uc, ids);
-        if (StringUtils.isNotBlank(result)) return ResponseObject.newErrResponse(result);
+        if (StringUtils.isNotBlank(result))
+            return ResponseObject.newErrResponse(result);
 
         contractLogger.info("撤销合同成本成功");
         return ResponseObject.newOkResponse();
@@ -944,6 +946,14 @@ public class contractApproveController {
             connUpdate.setAutoCommit(false);
             for (String id : ids.split(",")) {
                 BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
+
+                //判断是否已经生成 发票
+                if (StringUtils.isNotBlank(bo.getString("INVOICE_ID"))) {
+                    if (!DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
+                        return ResponseObject.newErrResponse("该服务已经生成发票,请先删除发票");
+                       // throw new RuntimeException("该服务已经生成发票,请先删除发票");
+                }
+
                 bo.set("CLOSED", 1);
                 dn.recordFormChanges.record(uc, bo, "撤销工时审批");
 
@@ -987,6 +997,14 @@ public class contractApproveController {
             connUpdate.setAutoCommit(false);
             for (String id : ids.split(",")) {
                 BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
+
+                //判断是否已经生成 发票
+                if (StringUtils.isNotBlank(bo.getString("INVOICE_ID"))) {
+                    if (!DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
+                        return ResponseObject.newErrResponse("该服务已经生成发票,请先删除发票");
+                    // throw new RuntimeException("该服务已经生成发票,请先删除发票");
+                }
+
                 bo.set("CLOSED", 1);
                 dn.recordFormChanges.record(uc, bo, "撤销费用审批");
 

+ 3 - 0
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/invoiceController.java

@@ -54,6 +54,9 @@ public class invoiceController {
 
         List<String> invoiceIds = InvoiceService.getInstance().processInvoice(uc, accDeduIds, invoiceDealDto, true);
 
+        if (invoiceIds == null || invoiceIds.isEmpty())
+            return ResponseObject.newErrResponse("已生成账单,不可重复生成");
+
         return ResponseObject.newOkResponse();
     }
 

+ 3 - 0
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/InvoiceService.java

@@ -64,6 +64,9 @@ public class InvoiceService {
 
         logger.info("账单个数:" + postedDataList.size());
 
+        if (postedDataList.isEmpty())
+            return null;
+
         // 统一Key为大写,避免字段名大小写不一致导致的NPE
         postedDataList.forEach(row -> row.forEach((key, value) -> {
             if (key.toUpperCase().equals("BILL_ACCOUNT_ID")) {

+ 15 - 1
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/contractService.java

@@ -2969,7 +2969,7 @@ public class contractService {
 
                 //判断是否已经生成 发票
                 if (StringUtils.isNotBlank(bo.getString("INVOICE_ID"))) {
-                    if (DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
+                    if (!DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
                         throw new RuntimeException("该服务已经生成发票,请先删除发票");
                 }
 
@@ -3030,6 +3030,13 @@ public class contractService {
 
             for (String id : ids.split(",")) {
                 BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
+
+                //判断是否已经生成 发票
+                if (StringUtils.isNotBlank(bo.getString("INVOICE_ID"))) {
+                    if (!DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
+                        throw new RuntimeException("该服务已经生成发票,请先删除发票");
+                }
+
                 if (bo.get("TYPE_ID").equals(cttConstant.ACCOUNT_DEDUCTION_TYPE_MILESTONES)) //类型:里程碑
                 {
                     BO ccm = SDK.getBOAPI().query("BO_EU_DNCTT_CONTRACT_MILESTONES").addQuery("CONTRACT_ID =", bo.getString("CONTRACT_ID")).addQuery("ID =", bo.getString("OBJECT_ID")).detail();
@@ -3071,6 +3078,13 @@ public class contractService {
             connUpdate.setAutoCommit(false);
             for (String id : ids.split(",")) {
                 BO bo = SDK.getBOAPI().get("BO_EU_DNCRM_ACCOUNT_DEDUCTION", id);
+
+                //判断是否已经生成 发票
+                if (StringUtils.isNotBlank(bo.getString("INVOICE_ID"))) {
+                    if (!DBSql.getString("select IS_VOIDED from BO_EU_DNCTT_INVOICE where ID=?", new Object[]{bo.getString("INVOICE_ID")}).equals("1"))
+                        throw new RuntimeException("该服务已经生成发票,请先删除发票");
+                }
+
                 bo.set("CLOSED", 1);
                 dn.recordFormChanges.record(uc, bo, "撤销成本审批");
 

+ 27 - 14
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/contractServiceAdj.java

@@ -838,24 +838,34 @@ public class contractServiceAdj {
     }
 
 
+    /**
+     * 将合同服务的采购成本按照服务周期进行分摊处理。
+     * <p>
+     * 该方法根据合同服务ID查询相关的付款计划和服务周期数据,
+     * 并根据不同服务类型(如一次性收费或分期服务)将付款金额分摊至各个服务周期中。
+     * 分摊结果会更新到服务周期表中的 PERIOD_COST 字段。
+     *
+     * @param uc 当前用户上下文信息,用于权限控制等用途(当前未使用)
+     * @param contractServiceId 合同服务ID,作为主键用于查询相关数据
+     */
     //合同服务采购成本平摊到服务周期上面
     public void paySplitServiceMonth(UserContext uc, String contractServiceId) {
 
         RowMap service = DBSql.getMap("select * from BO_EU_DNCTT_CONTRACT_SERVICE where ID=?", new Object[]{contractServiceId});
 
-        //付款计划
+        // 查询与该合同服务关联的所有付款计划,并按开始时间排序
         List<RowMap> payPlanList = DBSql.getMaps("select * from BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH where CONTRACT_SERVICE_ID=? ORDER BY PERIOD_BEGIN_DATE", new Object[]{contractServiceId});
 
         if (payPlanList.isEmpty() || payPlanList.size() == 0)
             return;
 
-        //收款
+        // 查询与该合同服务对应的服务周期记录,并按开始时间排序
         List<RowMap> contractServicePeriodList = DBSql.getMaps("select * from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD where CONTRACT_SERVICE_ID=? ORDER BY PERIOD_BEGIN_DATE", new Object[]{contractServiceId});
 
         if (contractServicePeriodList.isEmpty() || contractServicePeriodList.size() == 0)
             return;
 
-        //服务:一次性收费
+        // 处理“一次性收费”类型的合同服务:所有付款计划总和直接赋给第一个服务周期的成本
         if (service.getString("PERIOD_TYPE").equals("609")) {
             BigDecimal SUM_PLAN_AMOUNT = BigDecimal.ZERO;
             for (RowMap payPlan : payPlanList) {
@@ -867,37 +877,40 @@ public class contractServiceAdj {
             return;
         }
 
-        LocalDate LAST_PERIOD_END_DATE = null;
+        LocalDate LAST_DATE = null;
         for (RowMap servicePeriod : contractServicePeriodList) {
-            //服务周期
-            LocalDate PERIOD_BEGIN_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_BEGIN_DATE"), LocalDate.class);//开始日期
-            LocalDate PERIOD_END_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_END_DATE"), LocalDate.class);//结束日期
+            // 获取当前服务周期的结束日期
+            LocalDate PERIOD_END_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_END_DATE"), LocalDate.class);
 
             BigDecimal SUM_PLAN_AMOUNT = BigDecimal.ZERO;
             for (RowMap payPlan : payPlanList) {
-                LocalDate PAY_PERIOD_BEGIN_DATE = TypeUtil.convert(payPlan.get("PERIOD_BEGIN_DATE"), LocalDate.class);//开始日期
-                LocalDate PAY_PERIOD_END_DATE = TypeUtil.convert(payPlan.get("PERIOD_END_DATE"), LocalDate.class);//结束日期
+                LocalDate PAY_PERIOD_BEGIN_DATE = TypeUtil.convert(payPlan.get("PERIOD_BEGIN_DATE"), LocalDate.class);
 
-                if (PAY_PERIOD_END_DATE.isAfter(PERIOD_END_DATE)) {
+                // 跳过已处理过的付款计划(通过上一个周期末日期+1判断)
+                if (LAST_DATE != null && PAY_PERIOD_BEGIN_DATE.isBefore(LAST_DATE)) {
                     continue;
                 }
 
-                if (LAST_PERIOD_END_DATE != null && PAY_PERIOD_END_DATE.isAfter(LAST_PERIOD_END_DATE) == false) {
+                // 若付款计划起始日在当前服务周期之后,则跳过
+                if (PERIOD_END_DATE.isBefore(PAY_PERIOD_BEGIN_DATE)) {
                     continue;
                 }
 
-                //合计付款计划
+                // 累加符合时间段内的付款计划金额
                 SUM_PLAN_AMOUNT = SUM_PLAN_AMOUNT.add(TypeUtil.convert(payPlan.get("PLAN_AMOUNT"), BigDecimal.class));
 
             }
+            // 更新当前服务周期的成本字段
             DBSql.update("update BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD set PERIOD_COST=? where ID=? ", new Object[]{SUM_PLAN_AMOUNT, servicePeriod.getString("ID")});
 
-            contractServiceLogger.info("服务周期:" + servicePeriod.getString("ID") + ":" + SUM_PLAN_AMOUNT);
+            SDK.getLogAPI().consoleInfo("服务周期:" + servicePeriod.getString("ID") + ":" + SUM_PLAN_AMOUNT);
 
-            LAST_PERIOD_END_DATE = PERIOD_END_DATE;
+            // 设置下一轮比较的时间起点为当前周期结束后一天
+            LAST_DATE = PERIOD_END_DATE.plusDays(1);
         }
 
     }
 
 
+
 }

+ 29 - 18
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/service/PaymentPlanService.java

@@ -289,67 +289,78 @@ public class PaymentPlanService {
 
     /**
      * 分摊采购成本
-     * @param uc
-     * @param contractServiceId
+     * 将合同服务的采购成本按照服务周期进行分摊。对于一次性收费的服务,
+     * 直接将所有付款计划金额汇总后赋给唯一的服务周期;对于其他类型服务,
+     * 按照服务周期的时间范围匹配对应的付款计划,并计算该周期内的总费用。
+     *
+     * @param uc 当前用户上下文信息
+     * @param contractServiceId 合同服务ID,用于查询相关服务、付款计划和服务周期数据
      */
+    //合同服务采购成本平摊到服务周期上面
     public void paySplitServiceMonth(UserContext uc, String contractServiceId) {
 
         RowMap service = DBSql.getMap("select * from BO_EU_DNCTT_CONTRACT_SERVICE where ID=?", new Object[]{contractServiceId});
 
-
-        //付款计划
+        // 查询与该合同服务关联的所有付款计划,按开始时间排序
         List<RowMap> payPlanList = DBSql.getMaps("select * from BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH where CONTRACT_SERVICE_ID=? ORDER BY PERIOD_BEGIN_DATE", new Object[]{contractServiceId});
 
         if (payPlanList.isEmpty() || payPlanList.size() == 0)
             return;
 
-        //收款
+        // 查询与该合同服务关联的所有服务周期,按开始时间排序
         List<RowMap> contractServicePeriodList = DBSql.getMaps("select * from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD where CONTRACT_SERVICE_ID=? ORDER BY PERIOD_BEGIN_DATE", new Object[]{contractServiceId});
 
         if (contractServicePeriodList.isEmpty() || contractServicePeriodList.size() == 0)
             return;
 
-        //服务:一次性收费
+        // 处理“一次性收费”类型的合同服务(标识码为"609")
         if (service.getString("PERIOD_TYPE").equals("609")) {
             BigDecimal SUM_PLAN_AMOUNT = BigDecimal.ZERO;
             for (RowMap payPlan : payPlanList) {
-                //合计付款计划
                 SUM_PLAN_AMOUNT = SUM_PLAN_AMOUNT.add(TypeUtil.convert(payPlan.get("PLAN_AMOUNT"), BigDecimal.class));
             }
 
+            // 更新第一个也是唯一一个服务周期的成本字段
             DBSql.update("update BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD set PERIOD_COST=? where ID=? ", new Object[]{SUM_PLAN_AMOUNT, contractServicePeriodList.get(0).getString("ID")});
             return;
         }
 
-        LocalDate LAST_PERIOD_END_DATE = null;
+        LocalDate LAST_DATE = null;
         for (RowMap servicePeriod : contractServicePeriodList) {
-            //服务周期
-            LocalDate PERIOD_BEGIN_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_BEGIN_DATE"), LocalDate.class);//开始日期
-            LocalDate PERIOD_END_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_END_DATE"), LocalDate.class);//结束日期
+            // 获取当前服务周期的结束日期
+            LocalDate PERIOD_END_DATE = TypeUtil.convert(servicePeriod.get("PERIOD_END_DATE"), LocalDate.class);
 
             BigDecimal SUM_PLAN_AMOUNT = BigDecimal.ZERO;
             for (RowMap payPlan : payPlanList) {
-                LocalDate PAY_PERIOD_BEGIN_DATE = TypeUtil.convert(payPlan.get("PERIOD_BEGIN_DATE"), LocalDate.class);//开始日期
-                LocalDate PAY_PERIOD_END_DATE = TypeUtil.convert(payPlan.get("PERIOD_END_DATE"), LocalDate.class);//结束日期
+                // 获取付款计划开始日期
+                LocalDate PAY_PERIOD_BEGIN_DATE = TypeUtil.convert(payPlan.get("PERIOD_BEGIN_DATE"), LocalDate.class);
 
-                if (PAY_PERIOD_END_DATE.isAfter(PERIOD_END_DATE)) {
+                // 若上一处理周期已覆盖此付款计划起始日,则跳过
+                if (LAST_DATE != null && PAY_PERIOD_BEGIN_DATE.isBefore(LAST_DATE)) {
                     continue;
                 }
 
-                if (LAST_PERIOD_END_DATE != null && PAY_PERIOD_END_DATE.isAfter(LAST_PERIOD_END_DATE) == false) {
+                // 如果付款计划早于当前服务周期,则跳过
+                if (PERIOD_END_DATE.isBefore(PAY_PERIOD_BEGIN_DATE)) {
                     continue;
                 }
 
-                //合计付款计划
+                // 累加属于当前服务周期的付款计划金额
                 SUM_PLAN_AMOUNT = SUM_PLAN_AMOUNT.add(TypeUtil.convert(payPlan.get("PLAN_AMOUNT"), BigDecimal.class));
-
             }
+
+            // 更新当前服务周期的成本
             DBSql.update("update BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD set PERIOD_COST=? where ID=? ", new Object[]{SUM_PLAN_AMOUNT, servicePeriod.getString("ID")});
-            LAST_PERIOD_END_DATE = PERIOD_END_DATE;
+
+            SDK.getLogAPI().consoleInfo("服务周期:" + servicePeriod.getString("ID") + ":" + SUM_PLAN_AMOUNT);
+
+            // 设置下一个服务周期应排除的最早付款日期起点
+            LAST_DATE = PERIOD_END_DATE.plusDays(1);
         }
 
     }
 
+
     /**
      * 获取周期列表
      * @param RULE_CATE