领域驱动设计 用DDD重构会计凭证生成(下)( 四 )


可以看到 , 一个具体的生成规则是通过()来实现的 , 也就是说 , 定义新的规则只需继续给用put()这个链式调用添加即可 , 本质上仍遵循了OCP , 只是将扩展的维度从类换成了方法 , 好处是有效避免了类的膨胀 。
设计原则的核心意图是降低软件开发的复杂度 , 所以当你做出设计决策或想要遵循某个设计原则时先想想是否有利于这个核心意图 , 有时如果适度的放宽原则可获利更多 , 那当然也是可以接受的 , 它们像是处于天平两端的砝码 , 找到那个平衡点才是最重要的 。
在完成上述规则定义后 , 为了在不发布代码和重启服务的情况下使新定义的规则生效 , 于是采用自定义从Git库中加载上传的规则字节码的方式 , 实现了凭证生成规则快速 , 稳定上线的目的 , 大大提升了开发和测试的效率 。门面微服务的多个部署节点间是通过UDP组播方式通知未加载新规则的节点来加载新上传的规则字节码 。
重构凭证生成方法
完成了凭证生成规则的代码化后 , 接下来就是如何获取到规则并依据其生成凭证 。重构前是由凭证微服务接收门面微服务经过复杂的业务逻辑处理后发送的单据数据 , 然后凭证微服务根据单据类型等属性从数据库中获取匹配的规则 。
@Service@Slf4jpublic class AdCreateBuilderNewExpense extends AbstractAdCreateBuilder {@Autowiredprivate DepositService depositService;@Autowiredprivate ExpenseFeesService expenseFeesService;@Autowiredprivate SafeListService writeOffService;@Autowiredprivate DepositPayService depositPayService;@Autowiredprivate DepositDeductionService depositDeductionService;@Autowiredprivate ExpenseExtendService expenseExtendService;@Autowiredprivate ExpensePurchaseService expensePurchaseService;@Autowiredprivate ExpenseInvoiceService expenseInvoiceService;@Autowiredprivate FeeItemsService feeItemsService;@Autowiredprivate NewExpenseBillFormLogic newExpenseBillFormLogic;@Overrideprotected void prepareBillData(BillPO bill) {//getExpenseFeesPOListif (CollectionUtils.isEmpty(bill.getExpenseFeesPOList())) {bill.setExpenseFeesPOList(this.getFeeListByBillNo4Voucher(bill.getBillNo()));}//getSafeListPOListif (CollectionUtils.isEmpty(bill.getSafeListPOList())) {bill.setSafeListPOList(writeOffService.getListByBillId(bill.getId()));}//getDepositPayPOListif (CollectionUtils.isEmpty(bill.getDepositPayPOList())) {bill.setDepositPayPOList(depositPayService.getPayListByBillId(bill.getId()));}//getDepositDeductionPOListif (CollectionUtils.isEmpty(bill.getDepositDeductionPOList())) {bill.setDepositDeductionPOList(depositDeductionService.getPOAndDetailByBillNo(bill.getBillNo()));}if (bill.getExpenseExtendPO() == null) {ExpenseExtendPO expenseExtend = expenseExtendService.getByBillId(bill.getId());bill.setPayFlag(expenseExtend.getPayForInvoiceFlag() + "");bill.setPrepayFlag(expenseExtend.getPrePayFlag() + "");bill.setRepReceiveFlag(expenseExtend.getRepReceiveFlag());bill.setPlanPaymentDate(expenseExtend.getPlanPayTime());bill.setDepositDeductionFlag(expenseExtend.getDepositDeductionFlag());bill.setPaymentMode(expenseExtend.getPaymentMode());bill.setRelatedParty(expenseExtend.getRelatedParty());//关联方交易, 0:是, 1:否}//发票信息页 20190603if (CollectionUtils.isEmpty(bill.getInvoicePOList())) {bill.setInvoicePOList(expenseInvoiceService.getInvoiceListByBillId(bill.getId()));}bill.setRelatedParty(expenseExtendService.getByBillId(bill.getId()).getRelatedParty());}/*** 根据单据生成凭证生成请求的公共部分币种信息设置为什么不在父类中写** @param bill单据* @param adRequest 凭证生成请求* @param billType*/@Overrideprotected void buildAdCreateRequestCommonInfo(BillPO bill, AdCreateRequestVO adRequest, BillTypePO billType) {super.buildAdCreateRequestCommonInfo(bill, adRequest, billType);if (adRequest.getCompanyBaseCurrencyId() != null) {CurrencyPO companyBaseCurrency = this.currencyRemoteService.getById(adRequest.getCompanyBaseCurrencyId());adRequest.setCompanyBaseCurrencyCode(companyBaseCurrency.getCode());adRequest.setCompanyBaseCurrencyName(companyBaseCurrency.getCcyName());}if (adRequest.getSupplierBaseCurrencyId() != null) {CurrencyPO supplierBaseCurrency = this.currencyRemoteService.getById(adRequest.getSupplierBaseCurrencyId());adRequest.setSupplierBaseCurrencyCode(supplierBaseCurrency.getCode());adRequest.setSupplierBaseCurrencyName(supplierBaseCurrency.getCcyName());}}@Overridepublic void buildAdCreateRequestFees(BillPO bill, AdCreateRequestVO adRequest) {//衍生单时 ,  有关联单据编号if (BillConstants.BILL_SYSTEM_FLAG_MAKE_PAIR.equals(bill.getSystemFlag())) {adRequest.setMakePairFlag(BooleanConstants.YES);}//代收时 , 有付款信息的供应商if (BooleanConstants.YES.equals(bill.getRepReceiveFlag())) {adRequest.setRepReceiveFlag(BooleanConstants.YES);if (bill.getPayInfoPO() != null) {adRequest.setPaySupplierId(bill.getPayInfoPO().getSupplierId());}}// 费用明细行this.buildAdCreateRequestFeesForFee(bill, adRequest);// 押金明细行this.buildAdCreateRequestFeesForDeposit(bill, adRequest);// 抵扣明细行this.buildAdCreateRequestFeesForDepositDeduction(bill, adRequest);// 20190605 发票行this.buildAdCreateRequestFeesForInvoice(bill, adRequest);}@Overridepublic void buildAdCreateRequestAmounts(BillPO bill, AdCreateRequestVO adRequest) {if ("0".equals(bill.getRelatedParty())) {//关联方交易buildAdCreateRequestAmounts_RelatedParty(bill, adRequest);} else {//非关联方交易buildAdCreateRequestAmounts_common(bill, adRequest);}}/*** 非关联方交易生成凭证** @param bill* @param adRequest*/private void buildAdCreateRequestAmounts_common(BillPO bill, AdCreateRequestVO adRequest) {// 构建生成凭证需要的amountsList amounts = new ArrayList();AdCreateAmountRequestVO amount;//单据金额if (bill.getTotalAmount() != null && bill.getTotalAmount().compareTo(BigDecimal.ZERO) != 0) {amount = super.buildAdCreateAmountRequestVO(AmountTypeEnum.BILL_AMOUNT, bill.getTotalAmount());amounts.add(amount);}//核销金额List safeListPOList = bill.getSafeListPOList();if (!CollectionUtils.isEmpty(safeListPOList)) {BigDecimal safeAmount = BigDecimal.ZERO;for (SafeListPO po : safeListPOList) {safeAmount = safeAmount.add(po.getSafeAmount());}if (safeAmount.compareTo(BigDecimal.ZERO) != 0) {amount = this.buildAdCreateAmountRequestVO(AmountTypeEnum.SAFE_AMOUNT, safeAmount);amounts.add(amount);}}//押金金额存在时 支付金额需去掉押金金额BigDecimal depositPayAmout = BigDecimal.ZERO;List