UNPKG

yonbip-code-gen-mcp

Version:

YonBIP高级版代码生成MCP

879 lines (828 loc) 42.4 kB
# 采购订单生成付款计划时追加制单人信息 1. 业务处理要求 * 在`getPayPlanBillVOData`方法中将采购订单制单人(billmaker)设置给付款计划制单人上(billmaker) 2. 高级版2505版本源码如下 ```java package nc.pubitf.pu.m21p.util; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import nc.impl.scmpub.payterm.AbstractRecvPayPlan; import nc.vo.bd.payment.IPaymentUtil; import nc.vo.pu.m21.entity.OrderHeaderVO; import nc.vo.pu.m21.entity.OrderItemVO; import nc.vo.pu.m21.entity.OrderPaymentVO; import nc.vo.pu.m21.entity.OrderVO; import nc.vo.pu.m21.entity.PayPlanBillVO; import nc.vo.pu.m21.entity.PayPlanItemVO; import nc.vo.pu.m21.entity.PayPlanVO; import nc.vo.pu.m21p.pub.RelationCalculateToolsFor21PUtils; import nc.vo.pu.pub.constant.PUParaValue; import nc.vo.pu.pub.util.PUSysParamUtil; import nc.vo.pu.pub.util.PubSysParamUtil; import nc.vo.pub.lang.UFBoolean; import nc.vo.pub.lang.UFDate; import nc.vo.pub.lang.UFDouble; import nc.vo.pubapp.AppContext; import nc.vo.pubapp.pattern.pub.MathTool; import nc.vo.pubapp.scale.ScaleUtils; import nc.vo.scmpub.payterm.pay.AbstractPayPlanVO; import nc.vo.scmpub.res.billtype.POBillType; import nc.vo.scmpub.res.para.NCPara; import nc.vo.scmpub.util.BillBodySortUtils; import nc.vo.scmpub.util.CollectionUtils; import nc.vo.scmpub.util.StringUtil; import nc.vo.scmpub.util.payterm.PayTermUtil; import nccloud.commons.lang.ArrayUtils; /** * @description 采购订单审批生成采购订单付款计划工具类 * @author yinl * @date 2022年8月25日 下午1:46:04 * @version ncc1.0 */ public class PayPlanBillVODataUtil { /** * 金额字段数组(下标要和orderBidToSub中对应的金额字段下标一直) * 0-税额-NTAX,1-本币金额-NMNY,2-无税金额-NORDERORIGMNY, * 3-本币无税金额-NORDERMNY,4-价税合计-NORIGTAXMNY, * 5-计税金额-NCALTAXMNY,6-计成本金额-NCALCOSTMNY, * 7-不可抵扣税额-NNOSUBTAX,8-全局本币无税金额-NGLOBALMNY, * 9-全局本币价税合计-NGLOBALTAXMNY,10-集团本币无税金额-NGROUPMNY, * 11-集团本币价税合计-NGROUPTAXMNY */ private String[] mnyArrs = new String[] { PayPlanItemVO.NTAX, PayPlanItemVO.NMNY, PayPlanItemVO.NORDERORIGMNY, PayPlanItemVO.NORDERMNY, PayPlanItemVO.NORIGTAXMNY, PayPlanItemVO.NCALTAXMNY, PayPlanItemVO.NCALCOSTMNY, PayPlanItemVO.NNOSUBTAX, PayPlanItemVO.NGLOBALMNY, PayPlanItemVO.NGLOBALTAXMNY, PayPlanItemVO.NGROUPMNY, PayPlanItemVO.NGROUPTAXMNY }; /** * Map<付款计划金额字段,订单表体金额字段> * 用于找到付款计划表体和订单表体金额对应的关系,获取订单上的金额字段,计算尾差使用 */ private Map<String, String> planToOrderMnyKeys = new HashMap<String, String>(); /** * 单价字段 * 0-主本币无税单价,1-主无税单价,2- 主含税单价,3- 主本币含税单价 * * 用于恢复付款计划单价使用,付款计划表体的单价金额算法,以原币金额驱动,由于数量是计算过的,单价可能会变动, * 但是,生成付款计划的时候,单价是不变的才对,这里做个备份,计算完成之后,付款计划子表单价恢复成订单单价 */ public String[] priceArrs = new String[] { PayPlanItemVO.NORDERPRICE, PayPlanItemVO.NORDERORIGPRICE, PayPlanItemVO.NORDERORIGTAXPRICE, PayPlanItemVO.NORDERTAXPRICE }; /** * Map<付款计划单价字段,订单单价字段> * 用于恢复付款计划单价使用,付款计划表体的单价金额算法,以原币金额驱动,由于数量是计算过的,单价可能会变动, * 但是,生成付款计划的时候,单价是不变的才对,这里做个备份,计算完成之后,付款计划子表单价恢复成订单单价 */ private Map<String, String> planToOrderPriceKeys = new HashMap<String, String>(); /** 原币金额字段集合,用于设置金额字段精度使用 */ private List<String> oriMnyKeyList = new ArrayList<String>(); /** 金额字段集合,用于设置金额字段精度使用 */ private List<String> mnyKeyList = new ArrayList<String>(); /** 金额字段集合,用于设置金额字段精度使用 */ private List<String> glogalAndGroupMnyKeyList = new ArrayList<String>(); public PayPlanBillVODataUtil() { // 原币金额字段 oriMnyKeyList.add(PayPlanItemVO.NORDERORIGMNY);// 2-无税金额-NORDERORIGMNY oriMnyKeyList.add(PayPlanItemVO.NORIGTAXMNY);// 4-价税合计-NORIGTAXMNY // 本币金额字段 mnyKeyList.add(PayPlanItemVO.NTAX);// 0-税额-NTAX mnyKeyList.add(PayPlanItemVO.NMNY);// 1-本币金额-NMNY mnyKeyList.add(PayPlanItemVO.NORDERMNY);// 3-本币无税金额-NORDERMNY mnyKeyList.add(PayPlanItemVO.NCALTAXMNY);// 5-计税金额-NCALTAXMNY mnyKeyList.add(PayPlanItemVO.NCALCOSTMNY);// 6-计成本金额-NCALCOSTMNY mnyKeyList.add(PayPlanItemVO.NNOSUBTAX);// 7-不可抵扣税额-NNOSUBTAX mnyKeyList.add(PayPlanItemVO.NGLOBALMNY);// 8-全局本币无税金额-NGLOBALMNY mnyKeyList.add(PayPlanItemVO.NGLOBALTAXMNY);// // 9-全局本币价税合计-NGLOBALTAXMNY mnyKeyList.add(PayPlanItemVO.NGROUPMNY);// // 10-集团本币无税金额-NGROUPMNY mnyKeyList.add(PayPlanItemVO.NGROUPTAXMNY);// 11-集团本币价税合计-NGROUPTAXMNY // 全局、集团本币字段 glogalAndGroupMnyKeyList.add(PayPlanItemVO.NGLOBALMNY);// 8-全局本币无税金额-NGLOBALMNY glogalAndGroupMnyKeyList.add(PayPlanItemVO.NGLOBALTAXMNY);// 9-全局本币价税合计-NGLOBALTAXMNY glogalAndGroupMnyKeyList.add(PayPlanItemVO.NGROUPMNY);// 10-集团本币无税金额-NGROUPMNY glogalAndGroupMnyKeyList.add(PayPlanItemVO.NGROUPTAXMNY);// 11-集团本币价税合计-NGROUPTAXMNY // 设置集合Map<付款计划金额字段,订单表体金额字段>,用于计算尾差 planToOrderMnyKeys.put(PayPlanItemVO.NTAX, OrderItemVO.NTAX);// 0-本币税额 planToOrderMnyKeys.put(PayPlanItemVO.NMNY, OrderItemVO.NTAXMNY);// 1-本币金额 planToOrderMnyKeys.put(PayPlanItemVO.NORDERORIGMNY, OrderItemVO.NORIGMNY);// 2-无税金额 planToOrderMnyKeys.put(PayPlanItemVO.NORDERMNY, OrderItemVO.NMNY);// 3-无税金额 planToOrderMnyKeys.put(PayPlanItemVO.NORIGTAXMNY, OrderItemVO.NORIGTAXMNY);// 4-价税合计 planToOrderMnyKeys.put(PayPlanItemVO.NCALTAXMNY, OrderItemVO.NCALTAXMNY);// 5-计税金额 planToOrderMnyKeys.put(PayPlanItemVO.NCALCOSTMNY, OrderItemVO.NCALCOSTMNY);// 6-记成本金额 planToOrderMnyKeys.put(PayPlanItemVO.NNOSUBTAX, OrderItemVO.NNOSUBTAX);// 7-不可抵扣税额 planToOrderMnyKeys.put(PayPlanItemVO.NGLOBALMNY, OrderItemVO.NGLOBALMNY);// 8-全局本币无税金额 planToOrderMnyKeys.put(PayPlanItemVO.NGLOBALTAXMNY, OrderItemVO.NGLOBALTAXMNY);// 9-全局本币价税合计 planToOrderMnyKeys.put(PayPlanItemVO.NGROUPMNY, OrderItemVO.NGROUPMNY);// 10-集团本币无税金额 planToOrderMnyKeys.put(PayPlanItemVO.NGROUPTAXMNY, OrderItemVO.NGROUPTAXMNY);// 11-集团本币价税合计 // Map<付款计划单价字段,订单单价字段> planToOrderPriceKeys.put(PayPlanItemVO.NORDERPRICE, OrderItemVO.NPRICE);// 0-主本币无税单价 planToOrderPriceKeys.put(PayPlanItemVO.NORDERORIGPRICE, OrderItemVO.NORIGPRICE); // 1-主无税单价 planToOrderPriceKeys.put(PayPlanItemVO.NORDERORIGTAXPRICE, OrderItemVO.NORIGTAXPRICE);// 2- 主含税单价 planToOrderPriceKeys.put(PayPlanItemVO.NORDERTAXPRICE, OrderItemVO.NTAXPRICE);// 3- 主本币含税单价 } /** * 里程碑采购添加,获取聚合的采购订单付款计划vo * @param vos 采购订单VO * @return 采购订单付款计划聚合VO * */ public PayPlanBillVO[] getPayPlanBillVOData(OrderVO[] vos) { List<PayPlanBillVO> payPlanBillList = new ArrayList<PayPlanBillVO>(); for (OrderVO vo : vos) { /** 1、获取订单的数据,用来组装采购订单付款计划 */ OrderHeaderVO orderHVO = vo.getHVO(); // 采购订单表头 OrderItemVO[] orderItemVOs = vo.getBVO(); // 采购订单表体 OrderPaymentVO[] orderPaymentVOs = vo.getPaymentVO(); // 采购订单付款协议 if (ArrayUtils.isEmpty(orderPaymentVOs)) { orderPaymentVOs = new OrderPaymentVO[] { new OrderPaymentVO() }; // 结算方式 orderPaymentVOs[0].setPk_balatype(orderHVO.getPk_balatype()); // 设置默认账期号为1 orderPaymentVOs[0].setShoworder(Integer.valueOf(1)); } /** 2、通过采购订单,生成采购订单付款计划 */ PayPlanBillVO[] payPlanBillVOs = this.splitByPtch(orderHVO, orderItemVOs, orderPaymentVOs); if (ArrayUtils.isEmpty(payPlanBillVOs)) { continue; } else { // 根据付款计划的付款方式(整单付款、明细付款) // 采购订单付款计划付款 PUParaValue.po95 po95 = PUSysParamUtil.getPO95(orderHVO.getPk_org()); for (PayPlanBillVO payPlanBillVO : payPlanBillVOs) { PayPlanVO hvo = payPlanBillVO.getHVO(); // 采购订单付款计划->付款单 付款方式是否为整单付款 if(po95.equals(PUParaValue.po95.BILLPAYMENT)){ hvo.setBbillpay(UFBoolean.TRUE); }else if (po95.equals(PUParaValue.po95.DETAILPAYMENT)){ hvo.setBbillpay(UFBoolean.FALSE); } payPlanBillList.add(payPlanBillVO); } } } return payPlanBillList.toArray(new PayPlanBillVO[payPlanBillList.size()]); } /** * 里程碑采购添加,获取聚合的采购订单付款计划vo * 1、先按照采购订单明细行,拆分付款协议,每一个物料行都有一套付款协议 * 2、汇总采购订单付款计划子表信息,形成汇总数据 * 3、组装聚合vo,并设置到list集合中 * @param vos 采购订单VO * @return 采购订单付款计划聚合VO * */ private PayPlanBillVO[] splitByPtch(OrderHeaderVO orderHVO, OrderItemVO[] orderItemVOs, OrderPaymentVO[] orderPaymentVOs) { if (CollectionUtils.isNullForAllTElements(orderItemVOs)) { return null; } /** 1、排序处理,以便后续计算尾差顺序是对的 */ BillBodySortUtils.sort(orderItemVOs); BillBodySortUtils.sort(orderPaymentVOs, OrderPaymentVO.SHOWORDER); /** 2、生成付款计划子表数据,先按照采购订单明细行,拆分付款协议,每一个物料行都有一套付款协议,用以组装采购订单付款计划子表信息 */ // 按照采购订单明细行拆分付款计划子表的集合,即每一个明细行都有一套付款计划 Map<String, List<PayPlanItemVO>> payPlanBVOMap = new HashMap<String, List<PayPlanItemVO>>(); // 付款时点主键结合,用于整理汇总付款计划表头数据使用 List<String> pk_payments = new ArrayList<String>(); // Map<订单表体主键,订单表体vo> - 用于计算尾差使用 Map<String, OrderItemVO> orderBidToBvo = new HashMap<String, OrderItemVO>(); // 生成付款计划子表信息,并整理一些后续需要的集合 // payPlanBVOMap,付款计划子表信息 // pk_payments,付款时点主键集合 this.getPayPlanBVOs(orderHVO, orderItemVOs, orderPaymentVOs, payPlanBVOMap, pk_payments, orderBidToBvo); /** 3、获取付款计划组装好的主子表vo */ PayPlanBillVO[] bills = this.getPayPlanVOs(orderHVO, payPlanBVOMap, pk_payments); // 价格金额算法,计算全局、集团本位币金额等字段 /** 4、进行单价金额算法*/ for (PayPlanBillVO bill : bills) { new RelationCalculateToolsFor21PUtils().calculate(bill, PayPlanItemVO.NORIGMNY); } /** 5、计算尾差,单价金额算法结束后,处理税额、无税金额、价税合计的尾差,并汇总表头的本币金额*/ this.processLastDiff(bills, orderBidToBvo); /** 6、汇总表头本币金额 */ this.sumHeadMny(bills); return bills; } /** * 获取账期到账日 * @param dbegindate 起算日期 * @param orderPaymentVO 付款协议 * @param paymentday 账期天数 * @return * */ private UFDate getDenddate(UFDate dbegindate, OrderPaymentVO orderPaymentVO) { // 固定结账日 Integer checkdata = orderPaymentVO.getCheckdata(); Integer accountDate = orderPaymentVO.getAccountday(); Integer effectmonth = orderPaymentVO.getEffectmonth(); Integer effectaddmonth = orderPaymentVO.getEffectaddmonth(); Integer iitermdays = orderPaymentVO.getPaymentday(); return PayTermUtil.getEndDate(dbegindate, iitermdays, checkdata, accountDate, effectmonth, effectaddmonth); } /** * 生成付款计划子表信息 * @param orderHVO 订单表头vo * @param orderItemVOs 订单明细表体vo * @param orderPaymentVOs 订单付款协议表体vo * @param payPlanBVOMap 生成的付款计划子表,Map<付款时点,List<付款计划子表>> * @param pk_payments 付款时点主键(付款计划表头是按照付款时点主键汇总的) * @param orderBidToSub Map<订单明细表体主键,[需要计算尾差的各字段数组]> * 需要计算尾差的各字段数组的结构: * [0-税额,1-本币金额,2-无税金额,3-本币无税金额, * 4-价税合计,5-计税金额 ,6-计成本金额,7-不可抵扣税额, * 8-全局本币无税金额,9-全局本币价税合计,10-集团本币无税金额,11-集团本币价税合计] * @param orderBidToPrice Map<采购订单表体主键,[单价数组]> * 单价数组结构: * [0-订单行主本币无税单价,1-付款计划订单行主无税单价, * 2-订单行主含税单价,3-订单行主本币含税单价] * */ public void getPayPlanBVOs(OrderHeaderVO orderHVO, OrderItemVO[] orderItemVOs, OrderPaymentVO[] orderPaymentVOs, Map<String, List<PayPlanItemVO>> payPlanBVOMap, List<String> pk_payments, Map<String, OrderItemVO> orderBidToBvo) { for (OrderItemVO orderItem : orderItemVOs) { // 获取订单表体主键 String pk_order_b = orderItem.getPk_order_b(); // NCC-365240 赠品行不生成付款计划子表 begin UFBoolean largess = orderItem.getBlargess(); if(UFBoolean.TRUE.equals(largess)){ continue; } // NCC-365240 赠品行不生成付款计划子表 end // 遍历采购订单付款协议,生成采购订单付款计划子表 UFDouble accNum = UFDouble.ZERO_DBL;// 数量,用于最后一行价税合计倒挤 UFDouble accOrimny = UFDouble.ZERO_DBL;// 金额和值,用于最后一行金额倒挤时使用 UFDouble accNoTaxmny = UFDouble.ZERO_DBL;// 无税金额和值,用于最后一行无税金额倒挤使用 // 设置需要计算尾差的map集合 begin orderBidToBvo.put(pk_order_b, orderItem); // 设置需要计算尾差的map集合 end // 创建精度处理工具 String pk_group = AppContext.getInstance().getPkGroup(); ScaleUtils scale = new ScaleUtils(pk_group); // 原币币种 String corigcurrencyid = orderHVO.getCorigcurrencyid(); for (int i = 0; i < orderPaymentVOs.length; i++) { PayPlanItemVO payPlanItem = new PayPlanItemVO(); // 设置一些不需要计算的付款计划子表字段(非付款协议获取数据的字段) payPlanItem = PayPlanPubUtils.getPayPlanBVOs(orderHVO, orderItem, payPlanItem); // 采购订单付款协议主键 String pk_payment = orderPaymentVOs[i].getPk_payment(); if (!pk_payments.contains(pk_payment)) { pk_payments.add(pk_payment); } payPlanItem.setPk_paymentch(pk_payment); // 备注 payPlanItem.setVmemo(orderItem.getVbmemo()); // 账期号 payPlanItem.setIaccounttermno(orderPaymentVOs[i].getShoworder()); // 起算依据 String effectdata = orderPaymentVOs[i].getPk_payperiod(); payPlanItem.setFeffdatetype(effectdata); // 起算日期(原逻辑取采购订单的审批日期),需要根据起算日期延迟天数计算出真正的起算日期 UFDate dbegindate = null; if (IPaymentUtil.PURCHASE_ORDER_APPROVE_DATE.equals(effectdata)) { UFBoolean breturn = orderHVO.getBreturn(); if (UFBoolean.FALSE.equals(breturn)) { // 退货不需要更新起算日期 dbegindate = orderHVO.getTaudittime(); } } // 起效日期延迟天数 Integer effectdateadddate = orderPaymentVOs[i].getEffectdateadddate(); payPlanItem.setEffectdateadddate(effectdateadddate); // 根据起算日期延迟天数继续计算起算日期 dbegindate = PayTermUtil.getEffectDate(dbegindate, effectdateadddate); payPlanItem.setDbegindate(dbegindate); // 账期天数 Integer paymentday = orderPaymentVOs[i].getPaymentday(); payPlanItem.setIitermdays(paymentday); // 账期到账日 payPlanItem.setDenddate(this.getDenddate(dbegindate, orderPaymentVOs[i])); // 预付款 UFBoolean prepayment = orderPaymentVOs[i].getPrepayment(); if (prepayment == null) { prepayment = UFBoolean.FALSE; } payPlanItem.setBpreflag(prepayment); // 价税合计, 总价税合计(总付款金额)应该是表头的信息 (orderHVO.getNtotalorigmny()); UFDouble norigtaxmny = orderItem.getNorigtaxmny(); UFDouble norigmny = orderItem.getNorigmny();// 无税金额 // 比率 UFDouble rate = orderPaymentVOs[i].getAccrate(); if (rate == null) { rate = new UFDouble(100); } payPlanItem.setNrate(rate); // 订单的价税合计(付款计划的原币金额) UFDouble mny = norigtaxmny.multiply(MathTool.nvl(rate) .div(AbstractRecvPayPlan.UF100, UFDouble.DEFAULT_POWER)); mny = scale.adjustMnyScale(mny, corigcurrencyid); // 无税金额 UFDouble noTaxMny = norigmny.multiply(MathTool.nvl(rate) .div(AbstractRecvPayPlan.UF100, UFDouble.DEFAULT_POWER)); noTaxMny = scale.adjustMnyScale(noTaxMny, corigcurrencyid); if (i < orderPaymentVOs.length - 1) { // 计算金额 payPlanItem.setNorigmny(mny); payPlanItem.setNorigtaxmny(mny);// 价税合计 accOrimny = MathTool.add(accOrimny, mny); accNoTaxmny = MathTool.add(accNoTaxmny, noTaxMny); } else { // 最后一行倒挤 payPlanItem.setNorigmny(MathTool.sub(norigtaxmny, accOrimny)); payPlanItem.setNorigtaxmny(MathTool.sub(norigtaxmny, accOrimny));// 价税合计 payPlanItem.setLastAccoutTerm(true); payPlanItem.setNorderorigmny(MathTool.sub(norigmny, accNoTaxmny));// 无税金额 } // 序号 payPlanItem.setCrowno(String.valueOf(10 * (i + 1))); // 质保金 payPlanItem.setIsdeposit(orderPaymentVOs[i].getIsdeposit()); // 结算方式 payPlanItem.setPk_balatype(orderPaymentVOs[i].getPk_balatype()); // 订单行主数量 UFDouble orderItemNnum = orderItem.getNnum(); // NCC-171729 主数量(本次确认主数量) 这里处理进度,和采购发票保持一致 begin UFDouble nnum = orderItemNnum.multiply(MathTool.nvl(rate) .div(AbstractRecvPayPlan.UF100, UFDouble.DEFAULT_POWER)); UFDouble updateNum = UFDouble.ZERO_DBL; String cunitid = orderItem.getCunitid(); if (i < orderPaymentVOs.length - 1) { updateNum = scale.adjustNumScale(nnum, cunitid); accNum = MathTool.add(accNum, updateNum); } else { // 求尾差 updateNum = MathTool.sub(orderItemNnum, accNum); } payPlanItem.setNnum(updateNum); // NCC-171729 主数量(本次确认主数量) 这里处理进度,和采购发票保持一致 end // 价格金额算法 if (payPlanBVOMap.containsKey(pk_payment)) { payPlanBVOMap.get(pk_payment).add(payPlanItem); } else { // 采购订单付款计划子表List集合 List<PayPlanItemVO> payPlanBVOList = new ArrayList<PayPlanItemVO>(); payPlanBVOList.add(payPlanItem); payPlanBVOMap.put(pk_payment, payPlanBVOList); } } } } /** * 获取付款计划主子表 * @param orderHVO 订单表头数据 * @param payPlanBVOMap 生成的付款计划子表,Map<付款时点,List<付款计划子表>> * @param pk_payments 付款时点主键(付款计划表头是按照付款时点主键汇总的) * @return */ public PayPlanBillVO[] getPayPlanVOs(OrderHeaderVO orderHVO, Map<String, List<PayPlanItemVO>> payPlanBVOMap, List<String> pk_payments) { List<PayPlanBillVO> panPlanList = new ArrayList<PayPlanBillVO>(); int hvoCrowno = 0;// 采购订单付款计划表头的序号基数,后面会乘以10 for (int i = 0; i < pk_payments.size(); i++) { String pk_paymentList = pk_payments.get(i); PayPlanBillVO payPlan = new PayPlanBillVO(); // 设置采购订单付款计划子表信息 List<PayPlanItemVO> payPlanBVOs = payPlanBVOMap.get(pk_paymentList); PayPlanItemVO[] payPlanItems = payPlanBVOs.toArray(new PayPlanItemVO[payPlanBVOs.size()]); payPlan.setBVO(payPlanItems); // 设置采购订单付款计划表头信息(汇总信息) PayPlanVO payPlanHVO = this.getPayPlanHVO(pk_paymentList, orderHVO, payPlanItems, ++hvoCrowno); payPlan.setHVO(payPlanHVO); /** 4、组装聚合vo,并设置到list集合中,用以返回组装好的采购订单付款计划聚合vo数据 */ // 将设置好的聚合VO设置到返回的list中 panPlanList.add(payPlan); } PayPlanBillVO[] bills = panPlanList.toArray(new PayPlanBillVO[panPlanList.size()]); return bills; } /** * 组装采购订单付款计划表头VO * @param pk_payment 采购订单付款协议主键 * @param orderHVO 采购订单表头数据 * @param payPlanItems 采购订单付款计划表体数据 * @param hvoCrowno 采购订单付款计划表头序号基数,乘以10作为采购订单付款计划表头的序号使用 * @return * */ public PayPlanVO getPayPlanHVO(String pk_payment, OrderHeaderVO orderHVO, PayPlanItemVO[] payPlanItems, int hvoCrowno) { BillBodySortUtils.sort(payPlanItems);// 排一下序 // 存放已经设置过数值的字段,例如表头的应付财务组织,设置过之后,如果发现表体的应付组织不完全相同,则需要清空,后续不再设置 Set<String> hadSetValue = new HashSet<String>(); PayPlanVO payPlanHVO = new PayPlanVO(); // 集团 payPlanHVO.setPk_group(orderHVO.getPk_group()); // 采购组织 payPlanHVO.setPk_org(orderHVO.getPk_org()); payPlanHVO.setPk_org_v(orderHVO.getPk_org_v()); // 采购订单主键 payPlanHVO.setPk_order(orderHVO.getPk_order()); // 采购订单编码(单据号) payPlanHVO.setVordercode(orderHVO.getVbillcode()); // 采购订单单据日期 payPlanHVO.setVorderbilldate(orderHVO.getDbilldate()); // 采购订单单据类型、交易类型、交易类型编码 payPlanHVO.setVordertype(POBillType.Order.getCode()); payPlanHVO.setVordertrantype(orderHVO.getCtrantypeid()); payPlanHVO.setVordertrantypecode(orderHVO.getVtrantypecode()); // 供应商 payPlanHVO.setCvendorid(orderHVO.getPk_supplier()); payPlanHVO.setCvendorvid(orderHVO.getPk_supplier_v()); // 开票供应商 payPlanHVO.setPk_invcsupllier(orderHVO.getPk_invcsupllier()); payPlanHVO.setPk_invcsupllier_v(orderHVO.getPk_invcsupllier_v()); // 散户 payPlanHVO.setPk_freecust(orderHVO.getPk_freecust()); // 质保金 payPlanHVO.setIsdeposit(payPlanItems[0].getIsdeposit()); // 账期号(付款计划子表的账期号都一样,都取自付款协议) payPlanHVO.setIaccounttermno(payPlanItems[0].getIaccounttermno()); // 起算依据(付款计划子表的起算依据都一样,都取自付款协议) payPlanHVO.setFeffdatetype(payPlanItems[0].getFeffdatetype()); // 账期天数(付款计划子表的账期天数都一样,都取自付款协议) payPlanHVO.setIitermdays(payPlanItems[0].getIitermdays()); // 起效日期延迟天数(付款计划子表起效日期延迟天数都一样,都取自付款协议) payPlanHVO.setEffectdateadddate(payPlanItems[0].getEffectdateadddate()); // 付款协议主键 payPlanHVO.setPk_paytermch(pk_payment); // 付款协议参照 String pk_payterm = orderHVO.getPk_payterm(); payPlanHVO.setPk_payterm(pk_payterm); // 预付款(付款计划子表的预付款都一样,都取自付款协议) payPlanHVO.setBpreflag(payPlanItems[0].getBpreflag()); // 比率(%)(付款计划子表的比率(%)都一样,都取自付款协议) payPlanHVO.setNrate(payPlanItems[0].getNrate()); // 币种 payPlanHVO.setCorigcurrencyid(orderHVO.getCorigcurrencyid()); // 开户银行 payPlanHVO.setPk_bankdoc(orderHVO.getPk_bankdoc()); // 退货 payPlanHVO.setBreturn(orderHVO.getBreturn()); // 冻结 payPlanHVO.setBfrozen(orderHVO.getBfrozen()); // 业务流程 payPlanHVO.setPk_busitype(orderHVO.getPk_busitype()); // 整单扣税类别 payPlanHVO.setFhtaxtypeflag(orderHVO.getFhtaxtypeflag()); // 整单税率 payPlanHVO.setNhtaxrate(orderHVO.getNhtaxrate()); // 贸易术语 payPlanHVO.setCtradewordid(orderHVO.getCtradewordid()); // 结算方式 与05金盘一致,取表头 if (payPlanItems[0].getPk_balatype() != null) { // 如果表体有,就取表体的,如果表体没有,就取表头的 payPlanHVO.setPk_balatype(payPlanItems[0].getPk_balatype()); } else { payPlanHVO.setPk_balatype(orderHVO.getPk_balatype()); } // 总重量 payPlanHVO.setNtotalweight(orderHVO.getNtotalweight()); // 总体积 payPlanHVO.setNtotalvolume(orderHVO.getNtotalvolume()); // 总件数 payPlanHVO.setNtotalpiece(orderHVO.getNtotalpiece()); // 项目 payPlanHVO.setPk_project(orderHVO.getPk_project()); // 制单人 payPlanHVO.setBillmaker(orderHVO.getBillmaker()); // 制单日期 payPlanHVO.setDmakedate(orderHVO.getDmakedate()); // 采购员 payPlanHVO.setCemployeeid(orderHVO.getCemployeeid()); // 采购部门 payPlanHVO.setPk_dept(orderHVO.getPk_dept()); // 采购部门vid payPlanHVO.setPk_dept_v(orderHVO.getPk_dept_v()); // 里程碑采购(付款计划子表的里程碑采购数都一样,都取自采购订单表头) payPlanHVO.setBismilepost(payPlanItems[0].getBismilepost()); for (PayPlanItemVO payPlanItemVO : payPlanItems) { // 应付财务组织(如果表体行的应付财务组织相同再给表头赋值,否则不赋值) String pk_financeorg = payPlanHVO.getPk_financeorg(); String pk_financeorgItem = payPlanItemVO.getPk_financeorg(); String pk_financeorg_vItem = payPlanItemVO.getPk_financeorg_v(); String ccurrencyid = payPlanItemVO.getCcurrencyid();// 本币币种 if (pk_financeorg == null && !hadSetValue.contains(AbstractPayPlanVO.PK_FINANCEORG)) { hadSetValue.add(AbstractPayPlanVO.PK_FINANCEORG); payPlanHVO.setPk_financeorg(pk_financeorgItem); payPlanHVO.setPk_financeorg_v(pk_financeorg_vItem); payPlanHVO.setCcurrencyid(ccurrencyid); } else if (pk_financeorg != null && !pk_financeorg.equals(pk_financeorgItem)) { payPlanHVO.setPk_financeorg(null); payPlanHVO.setPk_financeorg_v(null); payPlanHVO.setCcurrencyid(null); } // 序号 payPlanHVO.setCrowno(String.valueOf(10 * hvoCrowno)); // 起算日期(取表体最新的起算日期),账期到账日(取表体最新的账期到账日即可,表体在组装的时候已经计算过了) UFDate dbegindate = payPlanHVO.getDbegindate(); UFDate dbegindateItem = payPlanItemVO.getDbegindate(); UFDate denddateItem = payPlanItemVO.getDenddate(); if (dbegindate == null) { payPlanHVO.setDbegindate(dbegindateItem); payPlanHVO.setDenddate(denddateItem); } else { if (dbegindate.compareTo(dbegindateItem) < 0) { payPlanHVO.setDbegindate(dbegindateItem); payPlanHVO.setDenddate(denddateItem); } } // 金额 UFDouble norigmny = payPlanHVO.getNorigmny(); UFDouble norigmnyItem = payPlanItemVO.getNorigmny(); payPlanHVO.setNorigmny(MathTool.add(norigmny, norigmnyItem)); // 本币金额 UFDouble nmny = payPlanHVO.getNmny(); UFDouble nmnyItem = payPlanItemVO.getNmny(); payPlanHVO.setNmny(MathTool.add(nmny, nmnyItem)); // 折本汇率(付款计划子表的折本汇率如果一致,则给表头赋值,否则不赋值) this.setGatherPayPlanHVO(payPlanHVO, payPlanItemVO, AbstractPayPlanVO.NEXCHANGERATE, hadSetValue); // 组织汇率类型(付款计划子表的组织汇率类型如果一致,则给表头赋值,否则不赋值) this.setGatherPayPlanHVO(payPlanHVO, payPlanItemVO, AbstractPayPlanVO.CRATETYPE, hadSetValue); // 组织汇率类别(付款计划子表的组织汇率类别如果一致,则给表头赋值,否则不赋值) this.setGatherPayPlanHVO(payPlanHVO, payPlanItemVO, AbstractPayPlanVO.FRATECATEGORY, hadSetValue); // 组织汇率来源日期(付款计划子表的组织汇率来源日期如果一致,则给表头赋值,否则不赋值) this.setGatherPayPlanHVO(payPlanHVO, payPlanItemVO, AbstractPayPlanVO.DRATEDATE, hadSetValue); // 合同号(付款计划子表的合同号如果一致,则给表头赋值,否则不赋值) this.setGatherPayPlanHVO(payPlanHVO, payPlanItemVO, OrderItemVO.CCONTRACTID, hadSetValue); } // 总数量 payPlanHVO.setNtotalastnum(orderHVO.getNtotalastnum()); // 总价税合计 payPlanHVO.setNtotalorigmny(orderHVO.getNtotalorigmny()); // 审批时间 payPlanHVO.setTaudittime(orderHVO.getTaudittime()); // 审批人 payPlanHVO.setApprover(orderHVO.getApprover()); // 备注 payPlanHVO.setVmemo(orderHVO.getVmemo()); if (StringUtil.isSEmptyOrNull(payPlanHVO.getCcurrencyid())) { payPlanHVO.setNmny(null); } return payPlanHVO; } /** * 处理尾差 * @param bills 付款计划主子表主键 * @param orderBidToBvo Map<采购订单表体主键,采购订单表体> * */ public void processLastDiff(PayPlanBillVO[] bills, Map<String, OrderItemVO> orderBidToBvo) { // 将相同物料付款计划子表放在一起 Map<String, List<PayPlanItemVO>> mapItemVO = new HashMap<String, List<PayPlanItemVO>>(); // Map<订单付款计划表头主键,订单付款计划表头vo>,用于设置付款计划表头的本币金额 Map<String, PayPlanVO> pkToHvo = new HashMap<String, PayPlanVO>(); // 将相同物料子表行放在一起 for (int i = 0; i < bills.length; i++) { // 设置表头映射,用于设置表头的本币金额,本币金额单价金额算法只计算表体的,表头的金额是表体汇总的 PayPlanVO hvo = bills[i].getHVO(); String pk_order_payplan = hvo.getPk_order_payplan(); pkToHvo.put(pk_order_payplan, hvo); // 设置表体的映射,计算表体尾差使用 PayPlanItemVO[] itemVOs = bills[i].getBVO(); for (int j = 0; j < itemVOs.length; j++) { PayPlanItemVO item = itemVOs[j]; List<PayPlanItemVO> listItemVO = new ArrayList<PayPlanItemVO>(); if (mapItemVO.containsKey(itemVOs[j].getPk_order_b())) { mapItemVO.get(itemVOs[j].getPk_order_b()).add(item); } else { listItemVO.add(item); mapItemVO.put(itemVOs[j].getPk_order_b(), listItemVO); } } } String[] pk_order_bs = mapItemVO.keySet().toArray(new String[0]); // 创建精度处理工具 String pk_group = AppContext.getInstance().getPkGroup(); ScaleUtils scale = new ScaleUtils(pk_group); // 处理尾差 for (int i = 0; i < pk_order_bs.length; i++) { PayPlanItemVO[] itemvos = mapItemVO.get(pk_order_bs[i]).toArray(new PayPlanItemVO[0]); BillBodySortUtils.sort(itemvos);// 对付款计划进行排序 UFDouble[] accs = new UFDouble[12]; accs[0] = UFDouble.ZERO_DBL;// 0-税额 accs[1] = UFDouble.ZERO_DBL;// 1-本币金额 accs[2] = UFDouble.ZERO_DBL;// 2-无税金额 accs[3] = UFDouble.ZERO_DBL;// 3-本币无税金额 accs[4] = UFDouble.ZERO_DBL;// 4-价税合计 accs[5] = UFDouble.ZERO_DBL;// 5-计税金额 accs[6] = UFDouble.ZERO_DBL;// 6-计成本金额 accs[7] = UFDouble.ZERO_DBL;// 7-不可抵扣税额 accs[8] = UFDouble.ZERO_DBL;// 8-全局本币无税金额 accs[9] = UFDouble.ZERO_DBL;// 9-全局本币价税合计 accs[10] = UFDouble.ZERO_DBL;// 10-集团本币无税金额 accs[11] = UFDouble.ZERO_DBL;// 11-集团本币价税合计 for (int j = 0; j < itemvos.length; j++) { // 这里把订单的单价设置回付款计划自表上,因为生成付款计划的时候,单价不变才是对的 String pk_order_b = itemvos[j].getPk_order_b(); OrderItemVO orderItemVO = orderBidToBvo.get(pk_order_b); if (orderItemVO != null) { // 恢复单价 // this.setPrice(itemvos[j], orderItemVO); } // 以下是求金额尾差逻辑,前面的行先求和,最后一行再求尾差 if (j < itemvos.length - 1) { // 求和 accs[0] = MathTool.add(accs[0], itemvos[j].getNtax());// 0-税额 accs[1] = MathTool.add(accs[1], itemvos[j].getNmny());// 1-本币金额 accs[2] = MathTool.add(accs[2], itemvos[j].getNorderorigmny());// 2-无税金额 accs[3] = MathTool.add(accs[3], itemvos[j].getNordermny());// 3-无税本币金额 accs[4] = MathTool.add(accs[4], itemvos[j].getNorigtaxmny());// 4-价税合计 accs[5] = MathTool.add(accs[5], itemvos[j].getNcaltaxmny());// 5-计税金额 accs[6] = MathTool.add(accs[6], itemvos[j].getNcalcostmny());// 6-计成本金额 accs[7] = MathTool.add(accs[7], itemvos[j].getNnosubtax());// 7-不可抵扣税额 accs[8] = MathTool.add(accs[8], itemvos[j].getNglobalmny());// 8-全局本币无税金额 accs[9] = MathTool.add(accs[9], itemvos[j].getNglobaltaxmny());// 9-全局本币价税合计 accs[10] = MathTool.add(accs[10], itemvos[j].getNgroupmny());// 10-集团本币无税金额 accs[11] = MathTool.add(accs[11], itemvos[j].getNgrouptaxmny());// 11-集团本币价税合计 } else { // 倒挤 this.processLastDiffMnyAndScale(scale, orderBidToBvo, itemvos[j], accs); } } } } /** * 设置表头的本币金额,重构前是先计算了本币金额,然后汇总到订单表头,重构后,单价金额算法统一计算 * 付款计划表头的本币金额是表体汇总的,因此这里重新汇总一下 * 新增的数据没有主键,没有办法做集合处理,因此,这里统一处理 * @param bills 单价金额算法之后的付款计划 * */ private void sumHeadMny(PayPlanBillVO[] bills) { for (PayPlanBillVO bill : bills) { UFDouble accHvoMny = UFDouble.ZERO_DBL; // PayPlanVO hvo = bill.getHVO(); // UFDouble headMny = hvo.getNmny(); PayPlanItemVO[] bvos = bill.getBVO(); for (PayPlanItemVO bvo : bvos) { UFDouble bodyMny = bvo.getNmny(); accHvoMny = MathTool.add(accHvoMny, bodyMny); } bill.getHVO().setNmny(accHvoMny); } } /** * 设置汇总信息,表体上的数据如果相同,则给表头设置,如果不同则不设置 * @param payPlanHVO 付款计划表头信息 * @param payPlanItem 付款计划表体信息 * @param key 字段 * @param hadSetValue 已经设置过的字段,如果这个集合里面有着字段,则这个字段的值为null时,不需要再设置 * */ public void setGatherPayPlanHVO(PayPlanVO payPlanHVO, PayPlanItemVO payPlanItem, String key, Set<String> hadSetValue) { Object headValue = payPlanHVO.getAttributeValue(key); Object bodyValue = payPlanItem.getAttributeValue(key); if (headValue == null && !hadSetValue.contains(key)) { hadSetValue.add(key); payPlanHVO.setAttributeValue(key, bodyValue); } else if (headValue != null && !headValue.equals(bodyValue)) { payPlanHVO.setAttributeValue(key, null); } } /** * 获取非null的UFDouble类型 * @param number 数值 * @return * */ public UFDouble getUFDouleNotNull(UFDouble number) { return number == null ? UFDouble.ZERO_DBL : number; } /** * 设置金额的精度,总数-和值=尾差。 * @param scale 精度工具类(调用处已创建对象) * @param orderBidToBvo Map<采购订单表体主键,采购订单表体> * @param item 付款计划表体 * @param accs 和值数组(数值的下标对应的业务含义与mnyArrs一致) * */ public void processLastDiffMnyAndScale(ScaleUtils scale, Map<String, OrderItemVO> orderBidToBvo, PayPlanItemVO item, UFDouble[] accs) { String corigcurrencyid = item.getCorigcurrencyid();// 原币币种 String ccurrencyid = item.getCcurrencyid();// 本币币种 String pk_order_b = item.getPk_order_b(); // 总数数组,顺序和mnyArrs一致 OrderItemVO orderItemVO = orderBidToBvo.get(pk_order_b); if (orderItemVO == null) { // 修订时删除了物料行,这个表体就找不到了 return; } for (int i = 0; i < mnyArrs.length; i++) { String mnyArr = mnyArrs[i];// 对应的金额字段 // 判断全局NC002是否启用,不启用不处理尾差 if(PayPlanItemVO.NGLOBALMNY.equals(mnyArr) || PayPlanItemVO.NGLOBALTAXMNY.equals(mnyArr)){ String nc002 = PubSysParamUtil.getNC002(); if (NCPara.NC002_NOUSEGLOBALCURRTYPE.getName().equals(nc002)) { continue; } } // 判断集团NC001是否启用,不启用不处理尾差 if(PayPlanItemVO.NGROUPMNY.equals(mnyArr) || PayPlanItemVO.NGROUPTAXMNY.equals(mnyArr)){ String nc001 = PubSysParamUtil.getNC001(item.getPk_group()); if (NCPara.NC001_NOUSEGROUPCURRTYPE.getName().equals(nc001)) { continue; } } UFDouble acc = accs[i];// 和值,求尾差使用的 // 获取订单金额,mnyArr是付款计划子表的字段,需要找到对应订单的字段 Object mnyObj = orderItemVO.getAttributeValue(planToOrderMnyKeys.get(mnyArr)); UFDouble mny = mnyObj == null ? null : (UFDouble) mnyObj; // 尾差 UFDouble lastDiffNumber = MathTool.sub(mny, acc); if (oriMnyKeyList.contains(mnyArr)) { // 处理原币金额精度 item.setAttributeValue(mnyArr, scale.adjustMnyScale(lastDiffNumber, corigcurrencyid)); } else if (mnyKeyList.contains(mnyArr)) { if (glogalAndGroupMnyKeyList.contains(mnyArr) && mny == null) { // 如果是全局、集团本币金额,没有金额就不需要处理了 continue; } // 处理本币金额精度 item.setAttributeValue(mnyArr, scale.adjustMnyScale(lastDiffNumber, ccurrencyid)); } } } /** * 设置付款计划子表行上的单价,在付款计划子表行单价金额算法之后,需要把单价恢复成订单的 * * 设置过程: * 1、获取付款计划单价字段 * 2、通过 planToOrderPriceKeys 集合,获取到订单上对应的单价字段 * 3、获取订单单价,设置到付款计划子表上 * * @param item 单价金额算法之后的付款计划子表 * @param orderItemVO 订单表体行数据 * */ public void setPrice(PayPlanItemVO item, OrderItemVO orderItemVO) { for (String priceKey : priceArrs) { String orderPriceKey = planToOrderPriceKeys.get(priceKey); Object price = orderItemVO.getAttributeValue(orderPriceKey); item.setAttributeValue(priceKey, price); } } } ``` 3. 检查当前工程下有没有对应的源码类:`nc.pubitf.pu.m21p.util.PayPlanBillVODataUtil` 若存在源码,则在工程的源码中处理要求的业务 若不存在源码,则先按2生成源码,再按要求处理业务 4. 要求 * 不管工程中有没有源码,只需要在业务处理点处理业务,整体不做重构 * 源码的编码格式为GBK,不可修改源码的编码格式