Просмотр исходного кода

Merge branch 'master' of http://210.51.45.41:3000/itcat_admin/aws_donenow

HULEI 1 месяц назад
Родитель
Сommit
9ebdc320ac

+ 2 - 0
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/commissionController.java

@@ -85,4 +85,6 @@ public class commissionController {
     }
 
 
+    //合同销售佣金
+
 }

+ 27 - 3
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/controller/contractServiceController.java

@@ -14,6 +14,7 @@ import com.awspaas.user.apps.donenow_ctt.service.contractServiceAdj;
 import org.apache.commons.lang3.StringUtils;
 
 import java.time.LocalDate;
+import java.util.List;
 
 import static com.awspaas.user.apps.donenow_ctt.service.contractService.LocalDateYYYYMMDD;
 import static com.awspaas.user.apps.donenow_ctt.service.contractService.getLocalDate;
@@ -138,17 +139,40 @@ public class contractServiceController {
         }
 
 
-        if (contractServiceAdj.getInstance().execServicePurchaseAdj(uc, boId)) {
+        if (contractServiceAdj.getInstance().execServicePurchaseAdj(uc, boId, null)) {
             return ResponseObject.newOkResponse();
         }
         return ResponseObject.newOkResponse();
     }
 
+
+    @Mapping(value = "com.awspaas.user.apps.donenow_ctt.service_purchase_adjustTEST")
+    public ResponseObject editServicePurchaseTest(UserContext uc) {
+
+        List<String> serviceIds = DBSql.getList("SELECT ID FROM bo_eu_dnctt_contract_service where NEED_PURCHASE=1 AND ID in (SELECT CONTRACT_SERVICE_ID FROM bo_eu_dnctt_contract_service_period) ORDER BY CREATEDATE", String.class);
+
+        for (String serviceId : serviceIds) {
+            try {
+                //String bindid = contractServiceAdj.getInstance().editServicePurchase(uc, serviceId, "临时--分摊采购");
+                //String boId = DBSql.getString("SELECT ID FROM BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST where BINDID=?", new Object[]{bindid});
+                //contractServiceAdj.getInstance().execServicePurchaseAdj(uc, boId, null);
+
+                contractServiceAdj.getInstance().paySplitServiceMonth(uc, serviceId);
+
+            } catch (Exception ex) {
+
+            }
+
+        }
+
+        return ResponseObject.newOkResponse();
+    }
+
+
     @Mapping(value = "com.awspaas.user.apps.donenow_ctt.service_period_detail")
     public ResponseObject getServicePeriodDetail(UserContext uc, String serviceId) {
         String bindid = DBSql.getString("select BINDID from BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD_SHOW where CONTRACT_SERVICE_ID=?", new Object[]{serviceId});
-        if (StringUtils.isNotBlank(bindid))
-            return ResponseObject.newOkResponse().put("BINDID", bindid);
+        if (StringUtils.isNotBlank(bindid)) return ResponseObject.newOkResponse().put("BINDID", bindid);
 
         //新的调整单
         ProcessInstance contractInstance = SDK.getProcessAPI().createBOProcessInstance("obj_e70c97f1244c4107ae421f3b4a650518", uc.getUID(), serviceId);

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

@@ -42,6 +42,9 @@ public class invoiceController {
     public ResponseObject dealInvoice(UserContext uc, String accDeduIds, String startDate, String endDate) {
         InvoiceDealDto invoiceDealDto = new InvoiceDealDto();
         invoiceDealDto.setIds(accDeduIds);
+
+        SDK.getLogAPI().consoleInfo("处理账单:" + accDeduIds + "账单开始时间:" + startDate + "账单结束时间:" + endDate);
+
         invoiceDealDto.setDateRangeFromStr(startDate);
         invoiceDealDto.setDateRangeToStr(endDate);
 

+ 11 - 5
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/InvoiceDealDto.java

@@ -151,8 +151,7 @@ public class InvoiceDealDto {
     }
 
     public LocalDate getInvoiceDate() {
-        if (invoiceDate == null)
-            invoiceDate = LocalDate.now();
+        if (invoiceDate == null) invoiceDate = LocalDate.now();
         return invoiceDate;
     }
 
@@ -161,7 +160,7 @@ public class InvoiceDealDto {
     }
 
     public LocalDate getDateRangeFrom() {
-        return dateRangeFrom;
+        return this.dateRangeFrom;
     }
 
     public void setDateRangeFrom(LocalDate dateRangeFrom) {
@@ -170,9 +169,13 @@ public class InvoiceDealDto {
 
     public void setDateRangeFromStr(String dateRangeFrom) {
         try {
-            if (StringUtils.isNotBlank(dateRangeFrom))
+            if (StringUtils.isNotBlank(dateRangeFrom)) {
+                dateRangeFrom = dateRangeFrom.substring(0, 10);
                 this.dateRangeFrom = LocalDate.parse(dateRangeFrom);
+            }
+
         } catch (Exception e) {
+            e.printStackTrace();
             this.dateRangeFrom = null;
         }
     }
@@ -188,9 +191,12 @@ public class InvoiceDealDto {
 
     public void setDateRangeToStr(String dateRangeTo) {
         try {
-            if (StringUtils.isNotBlank(dateRangeTo))
+            if (StringUtils.isNotBlank(dateRangeTo)) {
+                dateRangeTo = dateRangeTo.substring(0, 10);
                 this.dateRangeTo = LocalDate.parse(dateRangeTo);
+            }
         } catch (Exception e) {
+            e.printStackTrace();
             this.dateRangeTo = null;
         }
     }

+ 16 - 7
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/InvoiceService.java

@@ -6,6 +6,7 @@ import com.actionsoft.bpms.commons.database.RowMap;
 import com.actionsoft.bpms.server.UserContext;
 import com.actionsoft.bpms.util.DBSql;
 import com.actionsoft.sdk.local.SDK;
+import com.actionsoft.sdk.local.api.Logger;
 import org.apache.commons.lang3.StringUtils;
 
 import java.time.LocalDateTime;
@@ -16,9 +17,11 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
- * 发票服务(单例模式,方法体≤5个)
+ * 发票服务
  */
 public class InvoiceService {
+
+    private static final Logger logger = SDK.getLogAPI().getLogger(InvoiceService.class);
     // 单例模式:双重校验锁保证线程安全
     private static volatile InvoiceService instance;
 
@@ -39,8 +42,9 @@ public class InvoiceService {
     // ====================== 1. 核心入口方法:处理发票生成 ======================
     public List<String> processInvoice(UserContext uc, String accDeduIds, InvoiceDealDto param, boolean isDeal) {
 
-        System.out.println("处理发票生成");
-        System.out.println("accDeduIds:" + accDeduIds);
+        logger.info("处理发票生成");
+        logger.info("accDeduIds:" + accDeduIds);
+        logger.info("日期范围:" + param.getDateRangeFrom() + "--" + param.getDateRangeTo());
 
         // 1. 基础校验:空值过滤
         if (StringUtils.isBlank(accDeduIds)) return new ArrayList<>();
@@ -57,6 +61,9 @@ public class InvoiceService {
                 "SELECT * FROM VIEW_EU_DNV_POSTED_ALL d WHERE d.ID IN " + sqlWhere + " AND (d.invoice_id is null OR d.invoice_id='' OR NOT EXISTS(SELECT 1 FROM bo_eu_dnctt_invoice i WHERE i.id=d.invoice_id AND IS_VOIDED=0))  AND  d.bill_account_id is NOT NULL AND d.ORGID='" + uc.getCompanyModel().getId() + "' ORDER BY ACCOUNT_ID,BILL_ACCOUNT_ID",
                 dedIdArr
         );
+
+        logger.info("账单个数:" + postedDataList.size());
+
         // 统一Key为大写,避免字段名大小写不一致导致的NPE
         postedDataList.forEach(row -> row.forEach((key, value) -> {
             if (key.toUpperCase().equals("BILL_ACCOUNT_ID")) {
@@ -133,7 +140,7 @@ public class InvoiceService {
                 }
             }
         }
-
+        logger.info("发票ID:" + invoiceIds.toString());
         return invoiceIds;
     }
 
@@ -302,7 +309,7 @@ public class InvoiceService {
     public boolean invoiceUpdate(UserContext uc, String invoiceIds, String dealStatus) {
         for (String invoiceId : invoiceIds.split(",")) {
             BO invoice = SDK.getBOAPI().get("BO_EU_DNCTT_INVOICE", invoiceId);
-            List<BO> invoiceDetails = SDK.getBOAPI().query("BO_EU_DNCTT_INVOICE_DETAIL").bindId(invoice.getBindId()).addQuery("INVOICE_ID=", invoiceId).orderBy("ACCOUNT_ID").orderBy("BILL_ACCOUNT_ID").list();
+            List<BO> invoiceDetails = SDK.getBOAPI().query("BO_EU_DNCTT_INVOICE_DETAIL").bindId(invoice.getBindId()).addQuery("INVOICE_ID =", invoiceId).orderBy("ACCOUNT_ID").orderBy("BILL_ACCOUNT_ID").list();
 
             boolean isDelete = true;
             int lineNo = 1;
@@ -360,14 +367,16 @@ public class InvoiceService {
             }
 
 
-            if (dealStatus.equals("作废发票")) {
-                List<BO> deductions = SDK.getBOAPI().query("BO_EU_DNCRM_ACCOUNT_DEDUCTION").addQuery("INVOICE_ID=", invoiceId).list();
+            if (isDelete || dealStatus.equals("作废发票")) {
+                List<BO> deductions = SDK.getBOAPI().query("BO_EU_DNCRM_ACCOUNT_DEDUCTION").addQuery("INVOICE_ID =", invoiceId).list();
                 for (BO deduction : deductions) {
                     deduction.set("INVOICE_ID", null);
                     deduction.set("INVOICE_LINE_ITEM_NO", 0);
                     dn.recordFormChanges.record(uc, deduction, "作废发票");
                     SDK.getBOAPI().update("BO_EU_DNCRM_ACCOUNT_DEDUCTION", deduction);
                 }
+
+                DBSql.update("UPDATE BO_EU_DNCRM_ACCOUNT_DEDUCTION SET INVOICE_ID=null,INVOICE_LINE_ITEM_NO=0 WHERE INVOICE_ID=?", new Object[]{invoiceId});
             }
         }
         return true;

+ 45 - 16
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/contractService.java

@@ -1140,13 +1140,14 @@ public class contractService {
         String PERIOD_TYPE = service.getString("PERIOD_TYPE");//服务周期类型
         String vendor_account_id = DBSql.getString(conn, "select VENDOR_ACCOUNT_ID from BO_EU_DNIVT_SERVICE where ID=?", new Object[]{service.getString("OBJECT_ID")});//供应商账号
 
-        BigDecimal SERVICE_UNIT_COST = service.get("UNIT_COST", BigDecimal.class);//服务单元成本
-        //需要采购
-        if (service.getString("NEED_PURCHASE").equals("1")) {
-            BigDecimal prate = GetPeriodRate(service.getString("PERIOD_TYPE"), service.getString("PURCHASE_PERIOD_TYPE"));
-            SERVICE_UNIT_COST = SERVICE_UNIT_COST.multiply(prate);
+        BigDecimal SERVICE_UNIT_COST = BigDecimal.ZERO;//服务单元成本
+        BigDecimal SERVICE_TOTAL_COST = BigDecimal.ZERO;//服务总成本
+        //无需采购
+        if (service.getString("NEED_PURCHASE").equals("1") == false) {
+            SERVICE_UNIT_COST = service.get("UNIT_COST", BigDecimal.class);//服务单元成本
+            SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, service.get("QUANTITY"));//服务总成本
         }
-        BigDecimal SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, service.get("QUANTITY"));//服务总成本
+
 
         BigDecimal SERVICE_UNIT_PRICE = service.get("UNIT_PRICE", BigDecimal.class);
         BigDecimal SERVICE_TOTAL_PRICE = multiply(SERVICE_UNIT_PRICE, service.get("QUANTITY"));
@@ -1181,7 +1182,6 @@ public class contractService {
                 }
             }
 
-
             for (PeriodCalculationUtil.Period period : periodList) {
                 BO csp = new BO();//服务周期
                 csp.set("CONTRACT_ID", contract.get("ID"));
@@ -1202,7 +1202,6 @@ public class contractService {
                 csp.setBindId(service.getString("BINDID"));
                 SDK.getBOAPI().createDataBO("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", csp, uc, conn);
 
-
                 if (service.getString("OBJECT_TYPE").equals("2"))//服务包
                 {
                     //本周期成本
@@ -1226,6 +1225,10 @@ public class contractService {
             service.set("PERIOD", PERIOD);
             service.set("ADJUST_PERIOD", StringUtils.EMPTY);
         }
+
+        //分摊成本
+        contractServiceAdj.getInstance().paySplitServiceMonth(uc, service.getString("ID"));
+
         return true;
     }
 
@@ -2646,7 +2649,7 @@ public class contractService {
                     if (bo != null) {
                         CONTRACT_SERVICE_ID = bo.getString("CONTRACT_SERVICE_ID");
                         CONTRACT_ID = bo.getString("CONTRACT_ID");
-
+                        cad.set("CONTRACT_ID", CONTRACT_ID);
                         bo.set("APPROVE_AND_POST_DATE", approveDate);
                         bo.set("SETUP_FEE_APPROVE_POST_USER_ID", uc.getUID());
                         SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", bo, connUpdate);
@@ -2662,14 +2665,18 @@ public class contractService {
 
                         cad.set("EXTENDED_PRICE", bo.get("PERIOD_ADJUSTED_PRICE"));
 
+ /*
                         String costCodeId = null;
                         if (bo.getString("OBJECT_TYPE").equals("1")) {
                             costCodeId = DBSql.getString("SELECT COST_CODE_ID FROM BO_EU_DNIVT_SERVICE WHERE ID = ?", new Object[]{bo.getString("OBJECT_ID")});
                         } else {
                             costCodeId = DBSql.getString("SELECT COST_CODE_ID FROM BO_EU_DNIVT_SERVICE_BUNDLE WHERE ID = ?", new Object[]{bo.getString("OBJECT_ID")});
                         }
+
                         Object taxCategoryId = DBSql.getString("select TAX_CATEGORY_ID from BO_EU_DND_COST_CODE where OID=? and ORGID=?", new Object[]{costCodeId, ORGID}); //SDK.getBOAPI().get("BO_EU_DND_COST_CODE", costCodeId, "TAX_CATEGORY_ID");
-                        if (taxCategoryId != null) TAX_CATEGORY_ID = taxCategoryId.toString();
+                        if (taxCategoryId != null)
+                            TAX_CATEGORY_ID = taxCategoryId.toString();
+                        */
                     }
 
                 }
@@ -2685,21 +2692,31 @@ public class contractService {
                     }
                 }
 
+                contractServiceLogger.info("TAX_CATEGORY_ID:" + TAX_CATEGORY_ID);
+
                 RowMap ca = DBSql.getMap("select NAME,TAX_REGION_ID,IS_TAX_EXEMPT from BO_EU_DNCRM_ACCOUNT where ID=?", new Object[]{cad.get("ACCOUNT_ID")});
                 String tax_category_name = null;//税收种类
                 String tax_region_name = null;//税区
                 double tax_rate = 0;//税率
 
                 if (StringUtils.isNotBlank(TAX_CATEGORY_ID)) {
-                    tax_category_name = DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()});
+
+                    RowMap taxcate = DBSql.getMap("SELECT NAME,EXT1 FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()});
+
+                    tax_category_name = taxcate.getString("NAME");
+
+                    tax_rate = taxcate.getDouble("EXT1");
                 }
 
                 if (ca.containsKey("TAX_REGION_ID") && StringUtils.isNotBlank(ca.getString("TAX_REGION_ID"))) {
                     tax_region_name = DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{ca.getString("TAX_REGION_ID"), uc.getCompanyModel().getId()});
                 }
 
+                //2025年11月19日 税率不需要再从税区上面获取
+                /*
                 if (tax_category_name != null && tax_region_name != null)
                     tax_rate = DBSql.getDouble("SELECT TOTAL_EFFECTIVE_TAX_RATE FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID='" + ca.getString("TAX_REGION_ID") + "' AND TAX_CATE_ID='" + TAX_CATEGORY_ID + "' AND ORGID='" + uc.getCompanyModel().getId() + "' ", "TOTAL_EFFECTIVE_TAX_RATE");
+                */
 
                 cad.set("POSTED_DATE", approveDate);
                 cad.set("TAX_CATEGORY_NAME", tax_category_name);
@@ -2715,7 +2732,7 @@ public class contractService {
                 contractServiceLogger.info("是否免税" + ca.get("IS_TAX_EXEMPT"));
                 contractServiceLogger.info(ca.getString("NAME") + cad.get("ACCOUNT_ID") + "是否免税" + ca.get("IS_TAX_EXEMPT"));
                 //是否免税
-                if (ca.get("IS_TAX_EXEMPT") != null && ca.getString("IS_TAX_EXEMPT").equals("1")) {
+                if (ca != null && ca.get("IS_TAX_EXEMPT") != null && ca.getString("IS_TAX_EXEMPT").equals("1")) {
 
                 } else {
 
@@ -2783,9 +2800,9 @@ public class contractService {
 
                     cad.set("OBJECT_ID", approveId);
                     cad.set("TAX_CATEGORY_ID", TAX_CATEGORY_ID);
-                    cad.set("TAX_CATEGORY_NAME", DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()}));
 
                     cad.set("TAX_REGION_ID", DBSql.getString("SELECT TAX_REGION_ID FROM BO_EU_DNCRM_ACCOUNT WHERE ID=(SELECT ACCOUNT_ID FROM BO_EU_DNCTT_CONTRACT WHERE ID=?)", new Object[]{bo.getString("CONTRACT_ID")}));
+
                     cad.set("TAX_REGION_NAME", DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{cad.get("TAX_REGION_ID"), uc.getCompanyModel().getId()}));
 
                     cad.set("ACCOUNT_ID", DBSql.getString("SELECT ACCOUNT_ID FROM BO_EU_DNCTT_CONTRACT WHERE ID=?", new Object[]{bo.getString("CONTRACT_ID")}));
@@ -2794,8 +2811,14 @@ public class contractService {
 
                     cad.set("CONTRACT_ID", bo.get("CONTRACT_ID"));
 
+                    // double tax_rate = DBSql.getDouble("SELECT TOTAL_EFFECTIVE_TAX_RATE FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID='" + cad.getString("TAX_REGION_ID") + "' AND TAX_CATE_ID='" + TAX_CATEGORY_ID + "' ", "TOTAL_EFFECTIVE_TAX_RATE");
+
+                    RowMap taxcate = DBSql.getMap("SELECT NAME,EXT1 FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()});
+
+                    cad.set("TAX_CATEGORY_NAME", taxcate.getString("NAME"));
+
+                    double tax_rate = taxcate.getDouble("EXT1");
 
-                    double tax_rate = DBSql.getDouble("SELECT TOTAL_EFFECTIVE_TAX_RATE FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID='" + cad.getString("TAX_REGION_ID") + "' AND TAX_CATE_ID='" + TAX_CATEGORY_ID + "' ", "TOTAL_EFFECTIVE_TAX_RATE");
                     cad.set("EFFECTIVE_TAX_RATE", tax_rate);
 
                     cad.set("EXTENDED_PRICE", bo.get("DOLLARS"));
@@ -2862,14 +2885,20 @@ public class contractService {
                     TAX_CATEGORY_ID = ccc.getString("TAX_CATEGORY_ID");
                 }
 
-                if (StringUtils.isNotBlank(TAX_CATEGORY_ID))
-                    tax_category_name = DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()});
+                if (StringUtils.isNotBlank(TAX_CATEGORY_ID)) {
+
+                    RowMap taxcate = DBSql.getMap("SELECT NAME,EXT1 FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{TAX_CATEGORY_ID, uc.getCompanyModel().getId()});
+                    tax_category_name = taxcate.getString("NAME");
+                    tax_rate = taxcate.getDouble("EXT1");
+                }
 
                 if (ca.get("TAX_REGION_ID") != null)
                     tax_region_name = DBSql.getString("SELECT NAME FROM BO_EU_DND_GENERAL WHERE OID = ? AND ORGID=?", new Object[]{ca.get("TAX_REGION_ID"), uc.getCompanyModel().getId()});
 
+                /*
                 if (StringUtils.isNotBlank(TAX_CATEGORY_ID) && ca.get("TAX_REGION_ID") != null)
                     tax_rate = DBSql.getDouble("SELECT TOTAL_EFFECTIVE_TAX_RATE FROM BO_EU_DND_TAX_REGION_CATE WHERE TAX_REGION_ID='" + ca.getString("TAX_REGION_ID") + "' AND TAX_CATE_ID='" + TAX_CATEGORY_ID + "' ", "TOTAL_EFFECTIVE_TAX_RATE");
+                */
 
                 BO cad = new BO();
                 cad.set("OBJECT_ID", ccc.getString("ID"));//成本表id

+ 167 - 31
com.awspaas.user.apps.donenow_ctt/src/com/awspaas/user/apps/donenow_ctt/service/contractServiceAdj.java

@@ -23,7 +23,6 @@ import java.util.List;
 import static com.awspaas.user.apps.donenow_ctt.PeriodCalculationUtil.GetPeriodMonth;
 import static com.awspaas.user.apps.donenow_ctt.PeriodCalculationUtil.getDateRate;
 import static com.awspaas.user.apps.donenow_ctt.service.contractService.*;
-import static com.awspaas.user.apps.donenow_ctt.service.contractService.LocalDateYYYYMMDD;
 
 public class contractServiceAdj {
     private static final Logger contractServiceLogger = SDK.getLogAPI().getLogger(contractServiceAdj.class);//记录日志
@@ -139,10 +138,21 @@ public class contractServiceAdj {
             BigDecimal SERVICE_UNIT_PRICE = null;
             BigDecimal SERVICE_TOTAL_PRICE = null;
 
+
+            BigDecimal SERVICE_UNIT_COST = BigDecimal.ZERO;//服务单元成本
+            BigDecimal SERVICE_TOTAL_COST = BigDecimal.ZERO;//服务总成本
+
+
             if (StringUtils.isNotBlank(lastPeriodId)) {
                 SERVICE_UNIT_PRICE = TypeUtil.convert(lastContractService.get("UNIT_PRICE"), BigDecimal.class);
                 SERVICE_TOTAL_PRICE = multiply(SERVICE_UNIT_PRICE, lastContractService.get("QUANTITY"));
 
+                //无需采购
+                if (orgContractService.getString("NEED_PURCHASE").equals("1") == false) {
+                    SERVICE_UNIT_COST = TypeUtil.convert(lastContractService.get("UNIT_COST"), BigDecimal.class);//服务单元成本
+                    SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, lastContractService.get("QUANTITY"));//服务总成本
+                }
+
                 BO lastServicePeriod = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", lastPeriodId);
 
                 LocalDate last_period_begin_date = getLocalDate(lastServicePeriod.get("PERIOD_BEGIN_DATE"));
@@ -154,6 +164,9 @@ public class contractServiceAdj {
                 lastServicePeriod.set("PERIOD_PRICE", multiply(SERVICE_TOTAL_PRICE, periodRate));
                 lastServicePeriod.set("PARTYA_PERIOD_PRICE", multiply(lastContractService.get("PARTYA_TOTAL_PRICE"), periodRate));
                 lastServicePeriod.set("PERIOD_ADJUSTED_PRICE", lastServicePeriod.get("PERIOD_PRICE"));
+
+                lastServicePeriod.set("PERIOD_COST", multiply(SERVICE_TOTAL_COST, periodRate));
+
                 SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", lastServicePeriod, conn);
 
             }
@@ -166,6 +179,12 @@ public class contractServiceAdj {
 
             SERVICE_TOTAL_PRICE = multiply(SERVICE_UNIT_PRICE, contractService.get("QUANTITY"));
 
+            //无需采购
+            if (orgContractService.getString("NEED_PURCHASE").equals("1") == false) {
+                SERVICE_UNIT_COST = contractService.get("UNIT_COST", BigDecimal.class);//服务单元成本
+                SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, contractService.get("QUANTITY"));//服务总成本
+            }
+
             String vendor_account_id = DBSql.getString(conn, "select VENDOR_ACCOUNT_ID from BO_EU_DNIVT_SERVICE where ID=?", new Object[]{orgContractService.getString("OBJECT_ID")});//供应商账号
 
             if (periodList != null && periodList.size() > 0) {
@@ -208,6 +227,8 @@ public class contractServiceAdj {
                     csp.set("PERIOD_ADJUSTED_PRICE", csp.get("PERIOD_PRICE"));
                     csp.set("PARTYA_PERIOD_PRICE", multiply(contractService.get("PARTYA_TOTAL_PRICE"), period.getRate()));//三方合同甲方含税总价
 
+                    csp.set("PERIOD_COST", period.getRate().multiply(SERVICE_TOTAL_COST));
+
                     csp.set("VENDOR_ACCOUNT_ID", vendor_account_id);
                     csp.setBindId(orgContractService.getString("BINDID"));
                     SDK.getBOAPI().createDataBO("BO_EU_DNCTT_CONTRACT_SERVICE_PERIOD", csp, uc, conn);
@@ -512,7 +533,7 @@ public class contractServiceAdj {
         //execServicePurchaseAdj(uc, adjBO.getId());
         //DBSql.update("update bo_eu_dnctt_contract_service set PURCHASE_END_DATE=? where ID=?", new Object[]{LocalDateYYYYMMDD(newEndDate), serviceId});
 
-        if (execServicePurchaseAdj(uc, adjBO.getId()) == false) {
+        if (execServicePurchaseAdj(uc, adjBO.getId(), null) == false) {
             DBSql.update("delete from BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST where ID=? AND IS_EFFECTIVE<>'已执行'", new Object[]{adjBO.getId()});
         } else {
             DBSql.update("update bo_eu_dnctt_contract_service set PURCHASE_END_DATE=? where ID=?", new Object[]{LocalDateYYYYMMDD(newEndDate), serviceId});
@@ -527,15 +548,43 @@ public class contractServiceAdj {
      * 执行服务调整--采购
      * @param uc
      * @param boId
+     * @param boName
      * @return
      */
-    public boolean execServicePurchaseAdj(UserContext uc, String boId) {
+    public boolean execServicePurchaseAdj(UserContext uc, String boId, String boName) {
         //调整 服务
         BO contractService = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST", boId);
 
-
+        if (StringUtils.isNotBlank(boName) && !boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH")) {
+            return false;
+        }
         String PERIOD_TYPE = contractService.getString("PURCHASE_PERIOD_TYPE");
 
+        int periodMonths;
+        switch (contractService.getString("PURCHASE_PERIOD_TYPE")) {
+            case "610":
+                periodMonths = 1; // 按月
+                break;
+            case "611":
+                periodMonths = 3; // 按季度
+                break;
+            case "612":
+                periodMonths = 6; // 按半年
+                break;
+            case "613":
+                periodMonths = 12; // 按年
+                break;
+            default:
+                periodMonths = 1;
+                break;
+        }
+
+        if (StringUtils.isBlank(boName)) {
+            boName = "BO_EU_DNIVT_ORDER_PAYMENT_PLAN";
+        } else {
+            PERIOD_TYPE = "610";//按月
+        }
+
         LocalDate EFFECTIVE_DATE = getLocalDate(contractService.get("PURCHASE_START_DATE"));//服务生效日期
         LocalDate EFFECTIVE_END_DATE = getLocalDate(contractService.get("PURCHASE_END_DATE"));//服务结束日期
 
@@ -551,9 +600,9 @@ public class contractServiceAdj {
             conn.setAutoCommit(false);
 
             //生效日期之后的服务周期删除
-            DBSql.update(conn, "DELETE FROM BO_EU_DNIVT_ORDER_PAYMENT_PLAN WHERE  CONTRACT_SERVICE_ID=? and PERIOD_BEGIN_DATE >=? and (PAY_AMOUNT=0 or PAY_AMOUNT is NULL)", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
+            DBSql.update(conn, "DELETE FROM " + boName + " WHERE  CONTRACT_SERVICE_ID=? and PERIOD_BEGIN_DATE >=? and (PAY_AMOUNT=0 or PAY_AMOUNT is NULL)", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
 
-            String lastPeriodId = DBSql.getString(conn, "select ID from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where CONTRACT_SERVICE_ID=? and PERIOD_END_DATE >=? order by PERIOD_BEGIN_DATE asc", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
+            String lastPeriodId = DBSql.getString(conn, "select ID from " + boName + " where CONTRACT_SERVICE_ID=? and PERIOD_END_DATE >=? order by PERIOD_BEGIN_DATE asc", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
 
             BigDecimal SERVICE_UNIT_COST = null;
             BigDecimal SERVICE_TOTAL_COST = null;
@@ -580,13 +629,9 @@ public class contractServiceAdj {
                         SERVICE_UNIT_COST = TypeUtil.convert(contractService.get("UNIT_COST_1STMONTH"), BigDecimal.class);
                         SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, contractService.get("QUANTITY"));
 
-                        //BigDecimal ratio = new BigDecimal(EFFECTIVE_DATE.getDayOfMonth()).divide(new BigDecimal(EFFECTIVE_DATE.lengthOfMonth()), 10, BigDecimal.ROUND_HALF_UP);
-                        // ratio = BigDecimal.ONE.subtract(ratio);
-
                         BigDecimal ratio = new BigDecimal(EFFECTIVE_DATE.lengthOfMonth() - EFFECTIVE_DATE.getDayOfMonth() + 1)
                                 .divide(new BigDecimal(EFFECTIVE_DATE.lengthOfMonth()), 10, BigDecimal.ROUND_HALF_UP);
 
-
                         COST_1STMONTH = SERVICE_TOTAL_COST.multiply(ratio);
 
                         EFFECTIVE_DATE = EFFECTIVE_DATE.plusMonths(1).withDayOfMonth(1);//下个月1号
@@ -600,11 +645,17 @@ public class contractServiceAdj {
                     SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, lastContractService.get("QUANTITY"));
                 } else {
                     SERVICE_UNIT_COST = TypeUtil.convert(lastContractService.get("UNIT_COST"), BigDecimal.class);
+
+                    //拆算成月成本
+                    if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH")) {
+                        SERVICE_UNIT_COST = SERVICE_UNIT_COST.divide(new BigDecimal(periodMonths), 10, BigDecimal.ROUND_HALF_UP);
+                    }
+
                     SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, lastContractService.get("QUANTITY"));
                 }
 
 
-                BO lastServicePeriod = SDK.getBOAPI().get("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", lastPeriodId);
+                BO lastServicePeriod = SDK.getBOAPI().get(boName, lastPeriodId);
 
                 LocalDate last_period_begin_date = getLocalDate(lastServicePeriod.get("PERIOD_BEGIN_DATE"));
 
@@ -615,13 +666,19 @@ public class contractServiceAdj {
                 lastServicePeriod.set("PLAN_AMOUNT", multiply(SERVICE_TOTAL_COST, periodRate));
                 lastServicePeriod.set("REMAIN_AMOUNT", lastServicePeriod.get("PLAN_AMOUNT"));
 
-                SDK.getBOAPI().update("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", lastServicePeriod, conn);
+                SDK.getBOAPI().update(boName, lastServicePeriod, conn);
             }
 
+
             //获取服务周期
             List<PeriodCalculationUtil.Period> periodList = PeriodCalculationUtil.getPeriodListByConfig(PERIOD_TYPE, START_DATE, EFFECTIVE_DATE, EFFECTIVE_END_DATE, contractService.getString("PURCHASE_CALC_METHOD_1STPERIOD"), "4638", contractService.getString("MONTH_1STQUARTER"));
 
+
             SERVICE_UNIT_COST = TypeUtil.convert(contractService.get("UNIT_COST"), BigDecimal.class);
+            //拆算成月成本
+            if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH")) {
+                SERVICE_UNIT_COST = SERVICE_UNIT_COST.divide(new BigDecimal(periodMonths), 10, BigDecimal.ROUND_HALF_UP);
+            }
 
             SERVICE_TOTAL_COST = multiply(SERVICE_UNIT_COST, contractService.get("QUANTITY"));
             RowMap costProduct = DBSql.getMap("select * from BO_EU_DNIVT_ORDER_PRODUCT where CONTRACT_SERVICE_ID=?", new Object[]{contractService.get("CONTRACT_SERVICE_ID")});
@@ -634,9 +691,7 @@ public class contractServiceAdj {
                 int i = 0;
                 for (PeriodCalculationUtil.Period period : periodList) {
                     i++;
-                    ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
                     BO paymentPlan = new BO();
-                    paymentPlan.setBindId(processInstance.getId());
                     paymentPlan.set("ORDER_ID", orderId);
                     paymentPlan.set("PLAN_DATE", period.getPeriodBeginDateStr());
                     paymentPlan.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
@@ -655,33 +710,43 @@ public class contractServiceAdj {
                     paymentPlan.set("CONTRACT_SERVICE_ID", orgContractService.getId());
                     paymentPlan.set("PAY_DESC", orgContractService.getString("NAME"));
                     paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
-                    SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc, conn);
+
+                    if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
+                        ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
+                        paymentPlan.setBindId(processInstance.getId());
+                        SDK.getBOAPI().create(boName, paymentPlan, processInstance, uc, conn);
+                    } else {
+                        SDK.getBOAPI().createDataBO(boName, paymentPlan, uc, conn);
+                    }
 
                     System.out.println("==== 创建付款计划:" + paymentPlan.get("PLAN_DATE") + ",金额:" + paymentPlan.get("PLAN_AMOUNT") + " ====");
                 }
             }
 
-            contractService.set("IS_EFFECTIVE", "已执行");
-            SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST", contractService, conn);
-            DBSql.update(conn, "update BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST set IS_EFFECTIVE='作废' where CONTRACT_SERVICE_ID=? and PURCHASE_START_DATE >?", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
+            if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
 
-            orgContractService.set("UNIT_COST", contractService.get("UNIT_COST"));
-            orgContractService.set("TOTAL_COST", contractService.get("TOTAL_COST"));
-            orgContractService.set("QUANTITY", contractService.get("QUANTITY"));
-            orgContractService.set("PURCHASE_CALC_METHOD_1STPERIOD", contractService.get("PURCHASE_CALC_METHOD_1STPERIOD"));
-            orgContractService.set("MONTH_1STQUARTER", contractService.get("MONTH_1STQUARTER"));
-            orgContractService.set("PURCHASE_PERIOD_TYPE", contractService.get("PURCHASE_PERIOD_TYPE"));
-            orgContractService.set("PURCHASE_END_DATE", contractService.get("PURCHASE_END_DATE"));
+                contractService.set("IS_EFFECTIVE", "已执行");
+                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST", contractService, conn);
+                DBSql.update(conn, "update BO_EU_DNCTT_CONTRACT_SERVICE_PURCHASE_ADJUST set IS_EFFECTIVE='作废' where CONTRACT_SERVICE_ID=? and PURCHASE_START_DATE >?", new Object[]{contractService.get("CONTRACT_SERVICE_ID"), LocalDateYYYYMMDD(EFFECTIVE_DATE)});
 
-            //如果合同服务上面的生效日期小于服务调整的生效日期,则将合同服务生效日期改为服务调整的生效日期
-            if (orgContractService.get("PURCHASE_START_DATE", LocalDate.class).compareTo(contractService.get("PURCHASE_START_DATE", LocalDate.class)) < 0)
-                orgContractService.set("PURCHASE_START_DATE", contractService.get("PURCHASE_START_DATE"));
+                orgContractService.set("UNIT_COST", contractService.get("UNIT_COST"));
+                orgContractService.set("TOTAL_COST", contractService.get("TOTAL_COST"));
+                orgContractService.set("QUANTITY", contractService.get("QUANTITY"));
+                orgContractService.set("PURCHASE_CALC_METHOD_1STPERIOD", contractService.get("PURCHASE_CALC_METHOD_1STPERIOD"));
+                orgContractService.set("MONTH_1STQUARTER", contractService.get("MONTH_1STQUARTER"));
+                orgContractService.set("PURCHASE_PERIOD_TYPE", contractService.get("PURCHASE_PERIOD_TYPE"));
+                orgContractService.set("PURCHASE_END_DATE", contractService.get("PURCHASE_END_DATE"));
 
-            SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE", orgContractService, conn);
+                //如果合同服务上面的生效日期小于服务调整的生效日期,则将合同服务生效日期改为服务调整的生效日期
+                if (orgContractService.get("PURCHASE_START_DATE", LocalDate.class).compareTo(contractService.get("PURCHASE_START_DATE", LocalDate.class)) < 0)
+                    orgContractService.set("PURCHASE_START_DATE", contractService.get("PURCHASE_START_DATE"));
+
+                SDK.getBOAPI().update("BO_EU_DNCTT_CONTRACT_SERVICE", orgContractService, conn);
 
+
+            }
             conn.commit();
 
-            return true;
         } catch (SQLException e) {
 
             e.printStackTrace();
@@ -690,12 +755,83 @@ public class contractServiceAdj {
             } catch (SQLException e1) {
                 e1.printStackTrace();
             }
-            return false;
+
         } finally {
             if (conn != null)
                 DBSql.close(conn);
         }
 
+        //生成每月的采购计划
+        if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
+            execServicePurchaseAdj(uc, boId, "BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH");
+
+            //分摊采购成本
+            paySplitServiceMonth(uc, contractService.getString("CONTRACT_SERVICE_ID"));
+        }
+
+        return true;
+    }
+
+
+    //合同服务采购成本平摊到服务周期上面
+    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) {
+
+                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;
+        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);//结束日期
+
+            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);//结束日期
+
+                if (PAY_PERIOD_END_DATE.isAfter(PERIOD_END_DATE)) {
+                    continue;
+                }
+
+                if (LAST_PERIOD_END_DATE != null && PAY_PERIOD_END_DATE.isAfter(LAST_PERIOD_END_DATE) == false) {
+                    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);
+
+            LAST_PERIOD_END_DATE = PERIOD_END_DATE;
+        }
+
     }
 
 

+ 23 - 2
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/controller/ivtOrderController.java

@@ -1054,7 +1054,7 @@ public class ivtOrderController {
             BigDecimal PLAN_AMOUNT0 = TypeUtil.convert(plan.get("PLAN_AMOUNT"), BigDecimal.class);
 
             //比较是否相等
-            if (PLAN_AMOUNT.compareTo(PLAN_AMOUNT0) != 0) {
+            if (isEqualUpToTwoDecimals(PLAN_AMOUNT, PLAN_AMOUNT0, RoundingMode.DOWN) == false) {
                 ivtLogger.info("付款计划已修改:" + plan.getString("PAY_DESC") + ":" + PLAN_AMOUNT0 + ":" + PLAN_AMOUNT);
                 sb.append(plan.getString("PAY_DESC")).append(":").append(PLAN_AMOUNT0).append(",");
             }
@@ -1090,8 +1090,9 @@ public class ivtOrderController {
 
             BigDecimal PLAN_AMOUNT0 = TypeUtil.convert(plan.get("PLAN_AMOUNT"), BigDecimal.class);
 
+
             //比较是否相等
-            if (PLAN_AMOUNT.compareTo(PLAN_AMOUNT0) != 0) {
+            if (isEqualUpToTwoDecimals(PLAN_AMOUNT, PLAN_AMOUNT0, RoundingMode.DOWN) == false) {
 
                 BO detailBO = SDK.getBOAPI().get("BO_EU_DNIVT_PAY_REQUEST_DETAIL", detail.getString("ID"));
 
@@ -1106,4 +1107,24 @@ public class ivtOrderController {
     }
 
 
+    /**
+     * 判断两个BigDecimal是否在小数点后两位及以上相等
+     * @param a 第一个BigDecimal
+     * @param b 第二个BigDecimal
+     * @param roundingMode 舍入模式(如截断、四舍五入等)
+     * @return 若小数点后两位及以上相等则返回true,否则返回false
+     */
+    public static boolean isEqualUpToTwoDecimals(BigDecimal a, BigDecimal b, RoundingMode roundingMode) {
+        // 处理null情况:都为null则相等,否则不等
+        if (a == null || b == null) {
+            return a == b;
+        }
+        // 统一保留两位小数
+        BigDecimal aScaled = a.setScale(2, roundingMode);
+        BigDecimal bScaled = b.setScale(2, roundingMode);
+        // 比较处理后的结果
+        return aScaled.compareTo(bScaled) == 0;
+    }
+
+
 }

+ 215 - 107
com.awspaas.user.apps.donenow_ivt/src/com/awspaas/user/apps/donenow_ivt/service/PaymentPlanService.java

@@ -2,8 +2,10 @@ package com.awspaas.user.apps.donenow_ivt.service;
 
 import com.actionsoft.bpms.bo.engine.BO;
 import com.actionsoft.bpms.bpmn.engine.model.run.delegate.ProcessInstance;
+import com.actionsoft.bpms.commons.database.RowMap;
 import com.actionsoft.bpms.server.UserContext;
 import com.actionsoft.bpms.util.DBSql;
+import com.actionsoft.bpms.util.TypeUtil;
 import com.actionsoft.sdk.local.SDK;
 import com.actionsoft.sdk.local.api.Logger;
 import com.awspaas.user.apps.donenow_ivt.constant.IVTConstant;
@@ -77,115 +79,9 @@ public class PaymentPlanService {
                             continue;
                         }
 
-                        logger.info("生成付款计划SERVICE_ID--" + SERVICE_ID);
-                        BO service = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE", SERVICE_ID);
-                        String RULE_CATE = service.getString("PURCHASE_PERIOD_TYPE");//采购周期
-                        LocalDate PERIOD_BEGIN_DATE = service.get("PURCHASE_START_DATE", LocalDate.class);
-                        BigDecimal TOTAL_COST = toBigDecimal(service.get("TOTAL_COST"));//周期成本
-                        if (RULE_CATE.equals("609")) {   //一次性付费
-
-                            ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
-
-                            BO paymentPlan = new BO();
-                            paymentPlan.setBindId(processInstance.getId());
-                            paymentPlan.set("ORDER_ID", orderId);
-                            paymentPlan.set("PLAN_DATE", PERIOD_BEGIN_DATE);
-                            paymentPlan.set("PLAN_AMOUNT", TOTAL_COST);
-                            paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
-                            paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
-                            paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
-                            paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));
-                            paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
-                            SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc, conn);
-                            continue;
-                        }
-
-                        // LocalDate START_DATE = TypeUtil.convert(DBSql.getString("select START_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);
-
-                        // LocalDate PERIOD_END_DATE = TypeUtil.convert(DBSql.getString("select END_DATE from BO_EU_DNCTT_CONTRACT where ID=?", new Object[]{service.getString("CONTRACT_ID")}).substring(0, 10), LocalDate.class);
-
-                        LocalDate START_DATE = PERIOD_BEGIN_DATE;
-                        LocalDate PERIOD_END_DATE = service.get("PURCHASE_END_DATE", LocalDate.class);//新增采购结束时间
-
-                        //采购单开始日期
-                    /*
-                    if (service.get("PURCHASE_START_DATE") != null) {
-                        START_DATE = TypeUtil.convert(service.get("PURCHASE_START_DATE").toString().substring(0, 10), LocalDate.class);
+                        createServicePaymentPlan(uc, orderId, SERVICE_ID, VENDOR_ACCOUNT_ID, orderProduct, "BO_EU_DNIVT_ORDER_PAYMENT_PLAN", conn);
                     }
-                     */
-
-                        String PURCHASE_CALC_METHOD_1STPERIOD = service.getString("PURCHASE_CALC_METHOD_1STPERIOD");
-
-                        if (StringUtils.isBlank(RULE_CATE) || StringUtils.isBlank(PURCHASE_CALC_METHOD_1STPERIOD)) {
-                            continue;
-                        }
-
-                        if (PERIOD_BEGIN_DATE == null || PERIOD_END_DATE == null || PERIOD_BEGIN_DATE.isAfter(PERIOD_END_DATE)) {
-                            continue;
-                        }
-
-
-                        if (DBSql.getInt(conn, "select count(1) as cnt from  BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=?  AND PAY_AMOUNT is NOT null AND PAY_AMOUNT<>0", new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID}) > 0) {
-                            continue;
-                        }
-
-                        String sql = "delete from BO_EU_DNIVT_ORDER_PAYMENT_PLAN where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=? and (PAY_AMOUNT is null or PAY_AMOUNT = 0)";
-                        DBSql.update(conn, sql, new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID});
-
-                        BigDecimal UNIT_COST_1STMONTH = BigDecimal.ZERO;
-                        String firstPeriodBeginDate = null;
-
-                        //首月单独计算
-                        if (RULE_CATE.equals("4598") || RULE_CATE.equals("4595") || RULE_CATE.equals("4592")) {
-                            //签约之日开始算周期,则不需要
-
-                        } else {
-                            UNIT_COST_1STMONTH = toBigDecimal(service.get("UNIT_COST_1STMONTH"));
-
-                            // 计算“日期当天到当月月底”的天数占当月总天数的比例(2025-6-25 对应 6/30)
-                            BigDecimal ratio = new BigDecimal(PERIOD_BEGIN_DATE.lengthOfMonth() - PERIOD_BEGIN_DATE.getDayOfMonth() + 1)
-                                    .divide(new BigDecimal(PERIOD_BEGIN_DATE.lengthOfMonth()), 10, BigDecimal.ROUND_HALF_UP);
 
-                            UNIT_COST_1STMONTH = ratio.multiply(UNIT_COST_1STMONTH);
-                            firstPeriodBeginDate = PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
-                            //下月一号
-                            PERIOD_BEGIN_DATE = PERIOD_BEGIN_DATE.plusMonths(1).withDayOfMonth(1);
-                        }
-
-                        List<PeriodCalculationUtil.Period> periods = PeriodCalculationUtil.getPeriodListByConfig(RULE_CATE, START_DATE, PERIOD_BEGIN_DATE, PERIOD_END_DATE, PURCHASE_CALC_METHOD_1STPERIOD, service.getString("CALC_METHOD_1STYEAR"), service.getString("MONTH_1STQUARTER"));
-
-                        int i = 0;
-                        for (PeriodCalculationUtil.Period period : periods) {
-                            total++;
-                            i++;
-                            ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
-
-                            BO paymentPlan = new BO();
-                            paymentPlan.setBindId(processInstance.getId());
-                            paymentPlan.set("ORDER_ID", orderId);
-                            paymentPlan.set("PLAN_DATE", period.getPeriodBeginDateStr());
-                            paymentPlan.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
-                            paymentPlan.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
-
-                            //第一条周期要加上首月成本
-                            if (i == 1 && UNIT_COST_1STMONTH.compareTo(BigDecimal.ZERO) > 0) {
-                                paymentPlan.set("PLAN_AMOUNT", TOTAL_COST.multiply(period.getRate()).add(UNIT_COST_1STMONTH));
-                                paymentPlan.set("PLAN_DATE", firstPeriodBeginDate);
-                                paymentPlan.set("PERIOD_BEGIN_DATE", firstPeriodBeginDate);
-                            } else {
-                                paymentPlan.set("PLAN_AMOUNT", TOTAL_COST.multiply(period.getRate()));
-                            }
-
-                            paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
-                            paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
-                            paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
-                            paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));
-                            paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
-                            SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc, conn);
-
-                            System.out.println("==== 创建付款计划:" + paymentPlan.get("PLAN_DATE") + ",金额:" + paymentPlan.get("PLAN_AMOUNT") + " ====");
-                        }
-                    }
                 }
             }
 
@@ -234,6 +130,218 @@ public class PaymentPlanService {
 
     }
 
+
+    public void createServicePaymentPlan(UserContext uc, String orderId, String SERVICE_ID, String VENDOR_ACCOUNT_ID, BO orderProduct, String boName, Connection conn) {
+
+        logger.info("生成付款计划SERVICE_ID--" + SERVICE_ID);
+        BO service = SDK.getBOAPI().get("BO_EU_DNCTT_CONTRACT_SERVICE", SERVICE_ID);
+        String RULE_CATE = service.getString("PURCHASE_PERIOD_TYPE");//采购周期
+
+
+        int periodMonths;
+        switch (service.getString("PURCHASE_PERIOD_TYPE")) {
+            case "610":
+                periodMonths = 1; // 按月
+                break;
+            case "611":
+                periodMonths = 3; // 按季度
+                break;
+            case "612":
+                periodMonths = 6; // 按半年
+                break;
+            case "613":
+                periodMonths = 12; // 按年
+                break;
+            default:
+                periodMonths = 1;
+                break;
+        }
+
+        if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH"))//按月采购
+            RULE_CATE = "610";
+
+        LocalDate PERIOD_BEGIN_DATE = service.get("PURCHASE_START_DATE", LocalDate.class);
+        BigDecimal TOTAL_COST = toBigDecimal(service.get("TOTAL_COST"));//周期成本
+
+
+        if (RULE_CATE.equals("609")) {   //一次性付费
+            BO paymentPlan = new BO();
+            paymentPlan.set("ORDER_ID", orderId);
+            paymentPlan.set("PLAN_DATE", PERIOD_BEGIN_DATE);
+            paymentPlan.set("PLAN_AMOUNT", TOTAL_COST);
+            paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
+            paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
+            paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
+            paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));
+            paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
+
+            if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
+                ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
+                paymentPlan.setBindId(processInstance.getId());
+                SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc, conn);
+            } else {
+                SDK.getBOAPI().createDataBO(boName, paymentPlan, uc, conn);
+            }
+
+            return;
+        }
+
+
+        LocalDate START_DATE = PERIOD_BEGIN_DATE;
+        LocalDate PERIOD_END_DATE = service.get("PURCHASE_END_DATE", LocalDate.class);//新增采购结束时间
+
+
+        String PURCHASE_CALC_METHOD_1STPERIOD = service.getString("PURCHASE_CALC_METHOD_1STPERIOD");
+
+        if (StringUtils.isBlank(RULE_CATE) || StringUtils.isBlank(PURCHASE_CALC_METHOD_1STPERIOD)) {
+            return;
+        }
+
+        if (PERIOD_BEGIN_DATE == null || PERIOD_END_DATE == null || PERIOD_BEGIN_DATE.isAfter(PERIOD_END_DATE)) {
+            return;
+        }
+
+
+        if (DBSql.getInt(conn, "select count(1) as cnt from  " + boName + " where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=?  AND PAY_AMOUNT is NOT null AND PAY_AMOUNT<>0", new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID}) > 0) {
+            return;
+        }
+
+        String sql = "delete from " + boName + " where ORDER_ID = ? and CONTRACT_COST_ID=? and CONTRACT_SERVICE_ID=? and (PAY_AMOUNT is null or PAY_AMOUNT = 0)";
+        DBSql.update(conn, sql, new Object[]{orderId, orderProduct.getString("CONTRACT_COST_ID"), SERVICE_ID});
+
+        BigDecimal UNIT_COST_1STMONTH = BigDecimal.ZERO;
+        String firstPeriodBeginDate = null;
+
+        //首月单独计算
+        if (RULE_CATE.equals("4598") || RULE_CATE.equals("4595") || RULE_CATE.equals("4592")) {
+            //签约之日开始算周期,则不需要
+
+        } else {
+            UNIT_COST_1STMONTH = toBigDecimal(service.get("UNIT_COST_1STMONTH"));
+
+            // 计算“日期当天到当月月底”的天数占当月总天数的比例(2025-6-25 对应 6/30)
+            BigDecimal ratio = new BigDecimal(PERIOD_BEGIN_DATE.lengthOfMonth() - PERIOD_BEGIN_DATE.getDayOfMonth() + 1)
+                    .divide(new BigDecimal(PERIOD_BEGIN_DATE.lengthOfMonth()), 10, BigDecimal.ROUND_HALF_UP);
+
+            UNIT_COST_1STMONTH = ratio.multiply(UNIT_COST_1STMONTH);
+            firstPeriodBeginDate = PERIOD_BEGIN_DATE.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+            //下月一号
+            PERIOD_BEGIN_DATE = PERIOD_BEGIN_DATE.plusMonths(1).withDayOfMonth(1);
+        }
+
+        List<PeriodCalculationUtil.Period> periods = PeriodCalculationUtil.getPeriodListByConfig(RULE_CATE, START_DATE, PERIOD_BEGIN_DATE, PERIOD_END_DATE, PURCHASE_CALC_METHOD_1STPERIOD, service.getString("CALC_METHOD_1STYEAR"), service.getString("MONTH_1STQUARTER"));
+
+        //拆成每月成本
+        if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH"))
+            TOTAL_COST = TOTAL_COST.divide(new BigDecimal(periodMonths), 10, BigDecimal.ROUND_HALF_UP);
+
+        int i = 0;
+        for (PeriodCalculationUtil.Period period : periods) {
+            i++;
+
+            BO paymentPlan = new BO();
+
+            paymentPlan.set("ORDER_ID", orderId);
+            paymentPlan.set("PLAN_DATE", period.getPeriodBeginDateStr());
+            paymentPlan.set("PERIOD_BEGIN_DATE", period.getPeriodBeginDateStr());
+            paymentPlan.set("PERIOD_END_DATE", period.getPeriodEndDateStr());
+
+            //第一条周期要加上首月成本
+            if (i == 1 && UNIT_COST_1STMONTH.compareTo(BigDecimal.ZERO) > 0) {
+                paymentPlan.set("PLAN_AMOUNT", TOTAL_COST.multiply(period.getRate()).add(UNIT_COST_1STMONTH));
+                paymentPlan.set("PLAN_DATE", firstPeriodBeginDate);
+                paymentPlan.set("PERIOD_BEGIN_DATE", firstPeriodBeginDate);
+            } else {
+                paymentPlan.set("PLAN_AMOUNT", TOTAL_COST.multiply(period.getRate()));
+            }
+
+            paymentPlan.set("REMAIN_AMOUNT", paymentPlan.get("PLAN_AMOUNT"));
+            paymentPlan.set("CONTRACT_COST_ID", orderProduct.getString("CONTRACT_COST_ID"));
+            paymentPlan.set("CONTRACT_SERVICE_ID", service.getId());
+            paymentPlan.set("PAY_DESC", orderProduct.getString("NAME"));
+            paymentPlan.set("ACCOUNT_PAYEE", VENDOR_ACCOUNT_ID);//收款单位
+
+            if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
+                ProcessInstance processInstance = SDK.getProcessAPI().createProcessInstance("obj_5cb4ae4a42944fd0a9a284ff4c64c65d", uc.getUID(), "付款计划");
+                paymentPlan.setBindId(processInstance.getId());
+                SDK.getBOAPI().create("BO_EU_DNIVT_ORDER_PAYMENT_PLAN", paymentPlan, processInstance, uc, conn);
+            } else {
+                SDK.getBOAPI().createDataBO(boName, paymentPlan, uc, conn);
+            }
+
+            System.out.println("==== 创建付款计划:" + paymentPlan.get("PLAN_DATE") + ",金额:" + paymentPlan.get("PLAN_AMOUNT") + " ====");
+        }
+
+        if (boName.equals("BO_EU_DNIVT_ORDER_PAYMENT_PLAN")) {
+            createServicePaymentPlan(uc, orderId, SERVICE_ID, VENDOR_ACCOUNT_ID, orderProduct, "BO_EU_DNIVT_ORDER_PAYMENT_PLAN_MONTH", conn);
+            paySplitServiceMonth(uc, SERVICE_ID);
+        }
+
+    }
+
+    /**
+     * 分摊采购成本
+     * @param uc
+     * @param contractServiceId
+     */
+    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) {
+                //合计付款计划
+                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;
+        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);//结束日期
+
+            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);//结束日期
+
+                if (PAY_PERIOD_END_DATE.isAfter(PERIOD_END_DATE)) {
+                    continue;
+                }
+
+                if (LAST_PERIOD_END_DATE != null && PAY_PERIOD_END_DATE.isAfter(LAST_PERIOD_END_DATE) == false) {
+                    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;
+        }
+
+    }
+
     /**
      * 获取周期列表
      * @param RULE_CATE