|
@@ -0,0 +1,499 @@
|
|
|
+package nckd.jimin.jyyy.fi.task;
|
|
|
+
|
|
|
+import kd.bos.algo.DataSet;
|
|
|
+import kd.bos.context.RequestContext;
|
|
|
+import kd.bos.dataentity.entity.DynamicObject;
|
|
|
+import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
|
+import kd.bos.db.tx.TX;
|
|
|
+import kd.bos.db.tx.TXHandle;
|
|
|
+import kd.bos.entity.EntityMetadataCache;
|
|
|
+import kd.bos.exception.KDBizException;
|
|
|
+import kd.bos.exception.KDException;
|
|
|
+import kd.bos.id.ID;
|
|
|
+import kd.bos.logging.Log;
|
|
|
+import kd.bos.logging.LogFactory;
|
|
|
+import kd.bos.orm.ORM;
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
+import kd.bos.orm.query.QFilter;
|
|
|
+import kd.bos.schedule.executor.AbstractTask;
|
|
|
+import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
+import kd.bos.servicehelper.QueryServiceHelper;
|
|
|
+import kd.bos.servicehelper.operation.SaveServiceHelper;
|
|
|
+import kd.bos.servicehelper.org.OrgUnitServiceHelper;
|
|
|
+import kd.bos.servicehelper.org.OrgViewType;
|
|
|
+import kd.bos.util.CollectionUtils;
|
|
|
+import nckd.jimin.jyyy.fi.common.constant.BillTypeConstants;
|
|
|
+import nckd.jimin.jyyy.fi.common.constant.travelcheck.*;
|
|
|
+import nckd.jimin.jyyy.fi.common.util.CommonUtils;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDate;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 创建商旅对账确认单
|
|
|
+ */
|
|
|
+public class TravelFinanConfirmCreateTask extends AbstractTask {
|
|
|
+
|
|
|
+ private static final Log logger = LogFactory.getLog(TravelFinanConfirmCreateTask.class);
|
|
|
+ @Override
|
|
|
+ public void execute(RequestContext requestContext, Map<String, Object> map) throws KDException {
|
|
|
+ logger.info("TravelFinanConfirmCreateTask begin");
|
|
|
+ // 创建当月的财务底稿确认单
|
|
|
+ String period = CommonUtils.parsePeriod(new Date());
|
|
|
+ if(ORM.create().exists(FinanceBillConfirmConstant.ENTITYID,
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_CHECKMONTH, QCP.equals, period).toArray())){
|
|
|
+ logger.info(String.format("期间[%s]已经存在商旅对账确认单,请勿重复创建!", period));
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ try(TXHandle tx = TX.requiresNew(this.getClass().getName())){
|
|
|
+ try {
|
|
|
+
|
|
|
+ DynamicObject financeConfirmInfo = BusinessDataServiceHelper.newDynamicObject(FinanceBillConfirmConstant.ENTITYID);
|
|
|
+ // 创建ID,用ID来清除已创建的数据
|
|
|
+ long financeConfirmId = ID.genLongId();
|
|
|
+ financeConfirmInfo.set(FinanceBillConfirmConstant.ID, financeConfirmId);
|
|
|
+ financeConfirmInfo.set(FinanceBillConfirmConstant.NCKD_CHECKMONTH, period);
|
|
|
+ financeConfirmInfo.set(FinanceBillConfirmConstant.KEY_BILLSTATUS, "A");
|
|
|
+ // 创建差旅补助
|
|
|
+ createBzEntry(financeConfirmInfo);
|
|
|
+ // 创建商旅费用
|
|
|
+ createSlEntry(financeConfirmInfo);
|
|
|
+ // 创建用车汇总
|
|
|
+ createYcEntry(financeConfirmInfo);
|
|
|
+ // 创建超标明细
|
|
|
+
|
|
|
+ // 创建退改明细
|
|
|
+
|
|
|
+ // 创建同性别未同住
|
|
|
+ SaveServiceHelper.save(new DynamicObject[]{financeConfirmInfo});
|
|
|
+
|
|
|
+ }catch (Exception e){
|
|
|
+ tx.markRollback();
|
|
|
+ logger.error(String.format("创建期间[%s]下的商旅对账确认单失败。", period),e);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ logger.info("TravelFinanConfirmCreateTask end");
|
|
|
+ }
|
|
|
+ protected void createYcEntry(DynamicObject financeConfirmInfo) {
|
|
|
+
|
|
|
+ DynamicObjectCollection ycEntryCol = financeConfirmInfo.getDynamicObjectCollection(FinanceBillConfirmConstant.NCKD_YC_ENTRY.ENTITYID);
|
|
|
+ ycEntryCol.clear();
|
|
|
+ long confirmBillId = financeConfirmInfo.getLong("id");
|
|
|
+
|
|
|
+ // 查询用车结算单
|
|
|
+ DynamicObjectCollection vehicleCheckCol = QueryServiceHelper.query("er_vehiclecheckingbill", "id,oabillnum,server,sourcebookedid.id applierId,totalamount", new QFilter[]{
|
|
|
+ new QFilter("happenddate", QCP.less_equals, new Date()),
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_YC_CONFRMID, QFilter.equals, 0)
|
|
|
+ .or(QFilter.isNull(FinanceBillConfirmConstant.NCKD_YC_CONFRMID)),
|
|
|
+ });
|
|
|
+ if(CollectionUtils.isEmpty(vehicleCheckCol)){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, List<DynamicObject>> applierGroupList = vehicleCheckCol.stream().collect(Collectors.groupingBy(r -> r.getLong("applierId")));
|
|
|
+ for (Map.Entry<Long, List<DynamicObject>> applierRow : applierGroupList.entrySet()) {
|
|
|
+ Long applierId = applierRow.getKey();
|
|
|
+ List<DynamicObject> dataList = applierRow.getValue();
|
|
|
+ DynamicObject ycEntry = ycEntryCol.addNew();
|
|
|
+ DynamicObject applierInfo = BusinessDataServiceHelper.loadSingleFromCache(applierId, "bos_user");
|
|
|
+ ycEntry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_TRAVELER, applierInfo);
|
|
|
+ createApplierInfo(ycEntry,applierInfo);
|
|
|
+ BigDecimal totalAmount = dataList.stream()
|
|
|
+ .map(r -> r.getBigDecimal("totalamount")).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ ycEntry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_AMOUNT, totalAmount);
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> vehicleBillIdList = vehicleCheckCol.stream().map(r -> r.getLong("id")).collect(Collectors.toList());
|
|
|
+ DynamicObject[] vehicleCheckBillArray = BusinessDataServiceHelper.load("er_vehiclecheckingbill", FinanceBillConfirmConstant.NCKD_SL_CONFRMID, new QFilter("id", QCP.in, vehicleBillIdList).toArray());
|
|
|
+ for(DynamicObject vehicleCheckBill : vehicleCheckBillArray){
|
|
|
+ vehicleCheckBill.set(FinanceBillConfirmConstant.NCKD_YC_CONFRMID, confirmBillId);
|
|
|
+ }
|
|
|
+ SaveServiceHelper.save(vehicleCheckBillArray);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void createSlEntry(DynamicObject financeConfirmInfo) {
|
|
|
+ // 该方法从各个明细中查询,注释掉,改成从全部订单上查询
|
|
|
+ //DynamicObjectCollection slOrderDataCol = getSlOrderDataCol();
|
|
|
+ DynamicObjectCollection slOrderDataCol = QueryServiceHelper.query("er_allcheckingbill", "id,oabillnum,server,sourcebookedid.id applierId,totalamount,operationtype", new QFilter[]{
|
|
|
+ new QFilter("happenddate", QCP.less_equals, new Date()),
|
|
|
+// new QFilter(FinanceBillConfirmConstant.NCKD_SL_CONFRMID, QFilter.equals, 0)
|
|
|
+// .or(QFilter.isNull(FinanceBillConfirmConstant.NCKD_SL_CONFRMID)),
|
|
|
+ new QFilter("operationtype", QFilter.in, Arrays.asList("1","2","4","5","6")),
|
|
|
+ });
|
|
|
+ long confirmBillId = financeConfirmInfo.getLong("id");
|
|
|
+ DynamicObjectCollection slEntryCol = financeConfirmInfo.getDynamicObjectCollection(FinanceBillConfirmConstant.NCKD_SL_ENTRY.ENTITYID);
|
|
|
+ slEntryCol.clear();
|
|
|
+ // 按照出差人分组汇总
|
|
|
+ Map<Long, List<DynamicObject>> applierGroupMap = slOrderDataCol.stream().collect(Collectors.groupingBy(r -> r.getLong("applierId")));
|
|
|
+ for (Map.Entry<Long, List<DynamicObject>> applierRow : applierGroupMap.entrySet()) {
|
|
|
+ Long applierId = applierRow.getKey();
|
|
|
+ List<DynamicObject> dataList = applierRow.getValue();
|
|
|
+ DynamicObject slEntry = slEntryCol.addNew();
|
|
|
+ DynamicObject applierInfo = BusinessDataServiceHelper.loadSingleFromCache(applierId, "bos_user");
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_TRAVELER, applierInfo);
|
|
|
+ createApplierInfo(slEntry,applierInfo);
|
|
|
+ // 服务商已经和实施沟通,取第一个就行,按理只会出现同城
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_SERVER,dataList.get(0).getString("server"));
|
|
|
+ // 对火车订单金额合计
|
|
|
+ BigDecimal trainTotalAmount = dataList.stream()
|
|
|
+ .filter(r -> "6".equals(r.getString("operationtype")))
|
|
|
+ .map(r -> r.getBigDecimal("totalamount")).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_TRAINPAYAMT, trainTotalAmount);
|
|
|
+ // 对机票订单金额合计
|
|
|
+ BigDecimal planeTotalAmount = dataList.stream()
|
|
|
+ .filter(r -> "2".equals(r.getString("operationtype")) || "4".equals(r.getString("operationtype")))
|
|
|
+ .map(r -> r.getBigDecimal("totalamount")).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_PLANPAYAMT, planeTotalAmount);
|
|
|
+ // 对酒店订单金额合计
|
|
|
+ BigDecimal hotelTotalAmount = dataList.stream()
|
|
|
+ .filter(r ->"1".equals(r.getString("operationtype")) || "5".equals(r.getString("operationtype")))
|
|
|
+ .map(r -> r.getBigDecimal("totalamount")).reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_HOTELPAYAMT, hotelTotalAmount);
|
|
|
+ slEntry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_ORDERAMT, trainTotalAmount.add(planeTotalAmount).add(hotelTotalAmount));
|
|
|
+
|
|
|
+ }
|
|
|
+ List<Long> allBillIdList = slOrderDataCol.stream().map(r -> r.getLong("id")).collect(Collectors.toList());
|
|
|
+ DynamicObject[] allCheckBillArray = BusinessDataServiceHelper.load("er_allcheckingbill", FinanceBillConfirmConstant.NCKD_SL_CONFRMID, new QFilter("id", QCP.in, allBillIdList).toArray());
|
|
|
+ for(DynamicObject allCheckBill : allCheckBillArray){
|
|
|
+ allCheckBill.set(FinanceBillConfirmConstant.NCKD_SL_CONFRMID, confirmBillId);
|
|
|
+ }
|
|
|
+ SaveServiceHelper.save(allCheckBillArray);
|
|
|
+ }
|
|
|
+ protected DynamicObjectCollection getSlOrderDataCol(){
|
|
|
+
|
|
|
+ // 查询火车订单
|
|
|
+ DataSet trainCheckDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "er_traincheckingbill", "'er_traincheckingbill' type,id,oabillnum,server,sourcebookedid.id applierId,totalamount", new QFilter[]{
|
|
|
+ new QFilter("happenddate", QCP.less_equals, new Date()),
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_SL_CONFRMID, QFilter.equals, 0),
|
|
|
+ }, "");
|
|
|
+
|
|
|
+ // 查询机票订单
|
|
|
+ DataSet planeCheckDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "er_planecheckingbill", "'er_planecheckingbill' type,id,oabillnum,server,sourcebookedid.id applierId,totalamount", new QFilter[]{
|
|
|
+ new QFilter("happenddate", QCP.less_equals, new Date()),
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_SL_CONFRMID, QFilter.equals, 0),
|
|
|
+ }, "");
|
|
|
+
|
|
|
+ // 查询酒店订单
|
|
|
+ DataSet hotelCheckDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), "er_hotelcheckingbill", "'er_hotelcheckingbill' type,id,oabillnum,server,sourcebookedid.id applierId,totalamount", new QFilter[]{
|
|
|
+ new QFilter("happenddate", QCP.less_equals, new Date()),
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_SL_CONFRMID, QFilter.equals, 0),
|
|
|
+ }, "");
|
|
|
+ DataSet sumDataSet = CommonUtils.joinDataSetList(Arrays.asList(trainCheckDataSet, planeCheckDataSet, hotelCheckDataSet));
|
|
|
+ return ORM.create().toPlainDynamicObjectCollection(sumDataSet);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ protected void createBzEntry(DynamicObject financeConfirmInfo){
|
|
|
+ long confirmBillId = financeConfirmInfo.getLong(FinanceBillConfirmConstant.ID);
|
|
|
+ BigDecimal bzAmount = getBzAmount();
|
|
|
+ // 获取本月月初
|
|
|
+ LocalDateTime firstDayStart = LocalDate.now().withDayOfMonth(1).atStartOfDay();
|
|
|
+ // 转换为Date对象
|
|
|
+ Date firstDay = Date.from(firstDayStart.atZone(ZoneId.systemDefault()).toInstant());
|
|
|
+
|
|
|
+ // 查询出差申请单
|
|
|
+ DynamicObjectCollection tripReqBillCol = QueryServiceHelper.query(TripReqBillConstant.ENTITYID, String.join(",",TripReqBillConstant.ID,TripReqBillConstant.BILLNO), new QFilter[]{
|
|
|
+ // 状态为审核通过、已付款、关闭
|
|
|
+ new QFilter(TripReqBillConstant.KEY_BILLSTATUS, QFilter.in, Arrays.asList("E", "G", "I")),
|
|
|
+// new QFilter(FinanceBillConfirmConstant.NCKD_BZ_CONFRMID, QFilter.equals, 0)
|
|
|
+// .or(QFilter.isNull(FinanceBillConfirmConstant.NCKD_BZ_CONFRMID)),
|
|
|
+ new QFilter(TripReqBillConstant.RENDDATE, QFilter.less_than, firstDay),
|
|
|
+ },"createtime desc" );
|
|
|
+ if(tripReqBillCol == null || tripReqBillCol.size() == 0){
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ List<Object> tripReqBillIdList = tripReqBillCol.stream().map(r -> r.get(TripReqBillConstant.ID)).collect(Collectors.toList());
|
|
|
+ // 创建财务对账底稿
|
|
|
+ //createTravelFinanDraft(financeConfirmInfo,tripReqBillIdList,bzAmount);
|
|
|
+ DynamicObjectCollection bzEntryCol = financeConfirmInfo.getDynamicObjectCollection(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.ENTITYID);
|
|
|
+ // 查询关联的商旅补助底稿数据
|
|
|
+ List<Long> draftBillIdList = QueryServiceHelper.query(TravelFinanDraftConstant.ENTITYID, TravelFinanDraftConstant.ID,
|
|
|
+ new QFilter(FinanceBillConfirmConstant.NCKD_BZ_CONFRMID, QCP.equals, confirmBillId)
|
|
|
+ .and(new QFilter(TravelFinanDraftConstant.NCKD_SUMDAYS,QCP.large_than,0)).toArray())
|
|
|
+ .stream().map(r -> r.getLong(TravelFinanDraftConstant.ID)).collect(Collectors.toList());
|
|
|
+ // 创建商旅对账确认补助
|
|
|
+ createCheckBzEntry(bzEntryCol,draftBillIdList);
|
|
|
+ }
|
|
|
+
|
|
|
+ protected BigDecimal getBzAmount(){
|
|
|
+ DynamicObject tripExpenseItem = QueryServiceHelper.queryOne("er_tripexpenseitem", "nckd_travelbzstd", new QFilter("longnumber", QCP.equals, "004").toArray());
|
|
|
+ if(tripExpenseItem == null){
|
|
|
+ throw new KDBizException("没有配置补助的差旅标准。");
|
|
|
+ }
|
|
|
+ BigDecimal bzAmount = tripExpenseItem.getBigDecimal("nckd_travelbzstd");
|
|
|
+ if(bzAmount == null || bzAmount.compareTo(BigDecimal.ZERO) <= 0){
|
|
|
+ throw new KDBizException("差旅补助金额不能为0。");
|
|
|
+ }
|
|
|
+ return bzAmount;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected void createCheckBzEntry(DynamicObjectCollection bzEntryCol,List<Long> draftBillIdList){
|
|
|
+ DynamicObject[] draftBillArray = BusinessDataServiceHelper.load(draftBillIdList.toArray(), EntityMetadataCache.getDataEntityType(TravelFinanDraftConstant.ENTITYID_F7));
|
|
|
+
|
|
|
+ // 按照出差人分组
|
|
|
+ Map<Long, List<DynamicObject>> applyGroupMap = Arrays.stream(draftBillArray)
|
|
|
+ .collect(Collectors.groupingBy(r -> r.getDynamicObject(TravelFinanDraftConstant.NCKD_TRIPREQBILL).getDynamicObject(TripReqBillConstant.APPLIER).getLong(TripReqBillConstant.ID)));
|
|
|
+
|
|
|
+ for(Map.Entry<Long, List<DynamicObject>> applierRow : applyGroupMap.entrySet()){
|
|
|
+ DynamicObject bzEntry = bzEntryCol.addNew();
|
|
|
+ Long applierId = applierRow.getKey();
|
|
|
+ List<DynamicObject> applierDraftList = applierRow.getValue();
|
|
|
+ int sumDays = 0 ;
|
|
|
+ BigDecimal sumAmount = BigDecimal.ZERO;
|
|
|
+ for(DynamicObject draftEntry : applierDraftList){
|
|
|
+ sumDays += draftEntry.getInt(TravelFinanDraftConstant.NCKD_SUMDAYS);
|
|
|
+ sumAmount = sumAmount.add(draftEntry.getBigDecimal(TravelFinanDraftConstant.NCKD_AMOUNT));
|
|
|
+ }
|
|
|
+ DynamicObject applierInfo = BusinessDataServiceHelper.loadSingleFromCache(applierId, "bos_user");
|
|
|
+ bzEntry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_TRAVELER, applierInfo);
|
|
|
+ bzEntry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_TRAVELDAYS, sumDays);
|
|
|
+ bzEntry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_AMOUNT, sumAmount);
|
|
|
+ bzEntry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_CHECKAMT, sumAmount);
|
|
|
+ // 设置出差人信息,工号、部门、岗位。 银行账户、开户行
|
|
|
+ createApplierInfo(bzEntry,applierInfo);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void createApplierInfo(DynamicObject entry , DynamicObject traveler){
|
|
|
+ if(traveler != null) {
|
|
|
+ String entryEntityName = entry.getDynamicObjectType().getName();
|
|
|
+ // 获取员工信息
|
|
|
+ DynamicObject userInfo = QueryServiceHelper.queryOne("bos_user", "number,entryentity.dpt,entryentity.orgstructure.fullname,entryentity.post.name",
|
|
|
+ new QFilter(FinanceBillConfirmConstant.ID, QCP.equals, traveler.getLong(FinanceBillConfirmConstant.ID)).toArray());
|
|
|
+ long deptId = userInfo.getLong("entryentity.dpt");
|
|
|
+ Map<String, Object> companyInfoMap = OrgUnitServiceHelper.getCompanyfromOrg(deptId);
|
|
|
+ Object companyId = companyInfoMap.get("id");
|
|
|
+ DynamicObject company = BusinessDataServiceHelper.loadSingleFromCache(companyId, "bos_org");
|
|
|
+ DynamicObject travelDeptSecretary = getTravelDeptSecretary(traveler.getLong(FinanceBillConfirmConstant.ID), deptId);
|
|
|
+ if (FinanceBillConfirmConstant.NCKD_BZ_ENTRY.ENTITYID.equals(entryEntityName)) {
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_DEPFULLNAME, userInfo.getString("entryentity.orgstructure.fullname"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_POST, userInfo.getString("entryentity.post.name"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_COMPANY, company);
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_DEPSECRETARY, travelDeptSecretary);
|
|
|
+ // 收款信息通过薪酬发放设置hsas_paysetting中获取
|
|
|
+ DynamicObject hrPaySetting = QueryServiceHelper.queryOne("hsas_paysetting", "entryentity.perbankcard.bankcardnum,entryentity.perbankcard.bankdeposit", new QFilter[]{
|
|
|
+ new QFilter("salaryfile.person.number", QCP.equals, traveler.getString("number")),
|
|
|
+ new QFilter("iscurrentversion", QCP.equals, "1"),
|
|
|
+ new QFilter("datastatus", QCP.equals, "1"),
|
|
|
+ new QFilter("entryentity.perbankcard.accountrelation.number", QCP.equals, "1010_S")
|
|
|
+ });
|
|
|
+ if (hrPaySetting != null) {
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_ACCOUNT, hrPaySetting.getString("entryentity.perbankcard.bankcardnum"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_BZ_ENTRY.NCKD_BZ_PAYERBANK, hrPaySetting.get("entryentity.perbankcard.bankdeposit"));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (FinanceBillConfirmConstant.NCKD_SL_ENTRY.ENTITYID.equals(entryEntityName)) {
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_DEPFULLNAME, userInfo.getString("entryentity.orgstructure.fullname"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_POST, userInfo.getString("entryentity.post.name"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_COMPANY, company);
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_SL_ENTRY.NCKD_SL_DEPSECRETARY, travelDeptSecretary);
|
|
|
+ }
|
|
|
+
|
|
|
+ if(FinanceBillConfirmConstant.NCKD_YC_ENTRY.ENTITYID.equals(entryEntityName)){
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_DEPFULLNAME, userInfo.getString("entryentity.orgstructure.fullname"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_POST, userInfo.getString("entryentity.post.name"));
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_COMPANY, company);
|
|
|
+ entry.set(FinanceBillConfirmConstant.NCKD_YC_ENTRY.NCKD_YC_DEPSECRETARY, travelDeptSecretary);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建财务对账底稿单据
|
|
|
+ * @param financeConfirmInfo 来源商旅对账确认单ID
|
|
|
+ * @param tripReqBillIdList 出差申请单ID
|
|
|
+ * @param bzAmount 补助金额
|
|
|
+ */
|
|
|
+ protected void createTravelFinanDraft(DynamicObject financeConfirmInfo, List<Object> tripReqBillIdList ,BigDecimal bzAmount) {
|
|
|
+ long confirmBillId = financeConfirmInfo.getLong(FinanceBillConfirmConstant.ID);
|
|
|
+ // 创建商旅财务对账底稿
|
|
|
+ DynamicObject[] tripReqBillArray = BusinessDataServiceHelper.load(tripReqBillIdList.toArray(), EntityMetadataCache.getDataEntityType(TripReqBillConstant.ENTITYID_F7));
|
|
|
+ List<String> tripReqBillNumberList = Arrays.stream(tripReqBillArray).map(r -> r.getString(TripReqBillConstant.BILLNO)).collect(Collectors.toList());
|
|
|
+ // 获取关联的火车订单
|
|
|
+ Map<String, List<DynamicObject>> trainBillMap = QueryServiceHelper.query("er_trainbill", "oabillnum,ordernum,departtime,arrivetime,departcity,arrivecity,totalamount",
|
|
|
+ new QFilter("oabillnum", QCP.in, tripReqBillNumberList).toArray())
|
|
|
+ .stream()
|
|
|
+ .collect(Collectors.groupingBy(r -> r.getString("oabillnum")));
|
|
|
+
|
|
|
+ // 获取机票订单
|
|
|
+ Map<String, List<DynamicObject>> planBillMap = QueryServiceHelper.query("er_planebill", "oabillnum,ordernum,takeofftime,landingtime,fromcityname,tocityname,totalamount",
|
|
|
+ new QFilter("oabillnum", QCP.in, tripReqBillNumberList).toArray())
|
|
|
+ .stream()
|
|
|
+ .collect(Collectors.groupingBy(r -> r.getString("oabillnum")));
|
|
|
+
|
|
|
+ // 获取关联的差旅报销发票分录 -》 发票与费用明细分录 联查 行程信息分录 通过源单行程分录ID 联查出差申请
|
|
|
+ Map<String, List<DynamicObject>> tripReimInvoiceData = getTripReimInvoiceData(tripReqBillNumberList);
|
|
|
+
|
|
|
+ for(DynamicObject tripReqBill : tripReqBillArray){
|
|
|
+ String billno = tripReqBill.getString(TripReqBillConstant.BILLNO);
|
|
|
+ DynamicObject travelFinanDraftInfo = BusinessDataServiceHelper.newDynamicObject(TravelFinanDraftConstant.ENTITYID);
|
|
|
+ travelFinanDraftInfo.set(FinanceBillConfirmConstant.NCKD_BZ_CONFRMID, confirmBillId);
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.NCKD_TRIPREQBILL, tripReqBill);
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.ORG, tripReqBill.get(TripReqBillConstant.COMPANY));
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.NCKD_DEPT, tripReqBill.get(TripReqBillConstant.ORG));
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.NCKD_CONFIRMSTATUS, "10");
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.KEY_BILLNO,tripReqBill.getString(TripReqBillConstant.BILLNO));
|
|
|
+
|
|
|
+ DynamicObjectCollection draftEntryCol = travelFinanDraftInfo.getDynamicObjectCollection(TravelFinanDraftConstant.NCKD_DETAILENTITY.ENTITYID);
|
|
|
+ if(trainBillMap.containsKey(billno) && trainBillMap.get(billno) != null){
|
|
|
+ List<DynamicObject> trainBillList = trainBillMap.get(billno);
|
|
|
+ trainBillList.stream().forEach(trainBill -> getDraftData(draftEntryCol.addNew(),"6",trainBill.getString("ordernum"),
|
|
|
+ trainBill.getDate("departtime"),trainBill.getDate("arrivetime"),
|
|
|
+ trainBill.getString("departcity"),trainBill.getString("arrivecity"), trainBill.getBigDecimal("totalamount")));
|
|
|
+ }
|
|
|
+ if(planBillMap.containsKey(billno) && planBillMap.get(billno) != null){
|
|
|
+ List<DynamicObject> planBillList = planBillMap.get(billno);
|
|
|
+ planBillList.stream().forEach(planBill -> getDraftData(draftEntryCol.addNew(),"2",planBill.getString("ordernum"),
|
|
|
+ planBill.getDate("takeofftime"),planBill.getDate("landingtime"),
|
|
|
+ planBill.getString("fromcityname"),planBill.getString("tocityname"),planBill.getBigDecimal("totalamount")));
|
|
|
+ }
|
|
|
+ if(tripReimInvoiceData.containsKey(billno) && tripReimInvoiceData.get(billno) != null){
|
|
|
+ List<DynamicObject> tripReimInvoiceList = tripReimInvoiceData.get(billno);
|
|
|
+ tripReimInvoiceList.stream().forEach(tripReimInvoice -> getDraftData(draftEntryCol.addNew(),"7",
|
|
|
+ String.join("-",tripReimInvoice.getString("tripBillno"),tripReimInvoice.getString("invoiceentry.invoiceno")),
|
|
|
+ tripReimInvoice.getDate("invoiceentry.carrierdate"),null,
|
|
|
+ tripReimInvoice.getString("invoiceentry.istartcity"),tripReimInvoice.getString("invoiceentry.idestcity"),tripReimInvoice.getBigDecimal("invoiceentry.totalamount")));
|
|
|
+ };
|
|
|
+
|
|
|
+ // 获取draftEntryCol中开始时间的额最早时间 和结束时间的最晚时间
|
|
|
+ Date earliestTime = draftEntryCol.stream()
|
|
|
+ .filter(d -> d.getDate(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_STARTDATE) != null)
|
|
|
+ .map(d -> d.getDate(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_STARTDATE))
|
|
|
+ .min(Comparator.comparing(Date::getTime)).orElse(null);
|
|
|
+
|
|
|
+ Date latestTime = draftEntryCol.stream()
|
|
|
+ .filter(d -> d.getDate(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_FINISHDATE) != null)
|
|
|
+ .map(d -> d.getDate(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_FINISHDATE))
|
|
|
+ .max(Comparator.comparing(Date::getTime)).orElse(null);
|
|
|
+ //获取latestTime与earliestTime 的日期相差天数,加上1
|
|
|
+ if(earliestTime != null && latestTime != null){
|
|
|
+ int days = getDays(earliestTime, latestTime, tripReqBill.getDynamicObject(TripReqBillConstant.COMPANY));
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.NCKD_SUMDAYS, days);
|
|
|
+ // 查询补助金额
|
|
|
+ travelFinanDraftInfo.set(TravelFinanDraftConstant.NCKD_AMOUNT, bzAmount.multiply(BigDecimal.valueOf(days)));
|
|
|
+ }
|
|
|
+ tripReqBill.set(FinanceBillConfirmConstant.NCKD_BZ_CONFRMID, confirmBillId);
|
|
|
+ // 分录为空的时候不创建底稿,但是更新
|
|
|
+ SaveServiceHelper.save(new DynamicObject[]{ travelFinanDraftInfo });
|
|
|
+ SaveServiceHelper.save(new DynamicObject[]{ tripReqBill });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected int getDays(Date startTime, Date endTime,DynamicObject org){
|
|
|
+ // 获取组织下的工作日历
|
|
|
+ DynamicObject workCalendar = getWorkCalandar(org.getLong("id"));
|
|
|
+ List<Date> notWorkDayList = new ArrayList<>();
|
|
|
+ if(workCalendar != null){
|
|
|
+ notWorkDayList = QueryServiceHelper.query("bd_workcalendar", "dateentry.workdate", new QFilter[]{
|
|
|
+ new QFilter("dateentry.datetype", QCP.equals, "3"),
|
|
|
+ new QFilter("dateentry.workdate", QCP.large_equals, startTime),
|
|
|
+ new QFilter("dateentry.workdate", QCP.less_equals, endTime),
|
|
|
+ new QFilter("id", QCP.equals, workCalendar.getPkValue())
|
|
|
+ }).stream().map(r -> r.getDate("dateentry.workdate")).collect(Collectors.toList());
|
|
|
+ }
|
|
|
+ startTime = CommonUtils.getStartOfDay(startTime);
|
|
|
+ endTime = CommonUtils.getStartOfDay(endTime);
|
|
|
+ // 计算开始日期和结束日期之间总天数,时间转成日期,然后相减
|
|
|
+ long diffInMillis = endTime.getTime() - startTime.getTime();
|
|
|
+ int totalDays = (int) (diffInMillis / (24 * 60 * 60 * 1000)) + 1;
|
|
|
+
|
|
|
+ // 计算工作日天数(总天数减去非工作日天数)
|
|
|
+ int workDays = totalDays - notWorkDayList.size();
|
|
|
+
|
|
|
+ return workDays;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected DynamicObject getWorkCalandar(Long orgId){
|
|
|
+ DynamicObject workCalendar = QueryServiceHelper.queryOne("bd_workcalendar", "id", new QFilter("org", QCP.equals, orgId).toArray());
|
|
|
+ if(workCalendar == null){
|
|
|
+ Map<Long, Long> parentOrgMap = OrgUnitServiceHelper.getDirectSuperiorOrg(OrgViewType.Admin, Collections.singletonList(orgId));
|
|
|
+ if(!parentOrgMap.containsKey(orgId)){
|
|
|
+ return null;
|
|
|
+ }else{
|
|
|
+ return getWorkCalandar(parentOrgMap.get(orgId));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return workCalendar;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ protected DynamicObject getDraftData( DynamicObject draftEntry , String source, String orderNum, Date startTime,
|
|
|
+ Date endTime , String from , String to , BigDecimal amount){
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_SOURCE, source);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_ORDER_NUMBER, orderNum);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_STARTDATE, startTime);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_FINISHDATE, endTime);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_FROM, from);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_TO, to);
|
|
|
+ draftEntry.set(TravelFinanDraftConstant.NCKD_DETAILENTITY.NCKD_ORDER_AMOUNT, amount);
|
|
|
+ return draftEntry;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ protected Map<String, List<DynamicObject>> getTripReimInvoiceData(List<String> tripReqBillNumberList){
|
|
|
+
|
|
|
+ // 查询关联的行程分录ID
|
|
|
+ DataSet queryTripReqEntryDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), TripReqBillConstant.ENTITYID,
|
|
|
+ "billno,tripentry.id", new QFilter("billno", QCP.in, tripReqBillNumberList).toArray(), "");
|
|
|
+ Set tripEntryIdSet = CommonUtils.getFiledFromDataSet(queryTripReqEntryDataSet, "tripentry.id");
|
|
|
+ // 通过行程分录ID 联查差旅报销行程
|
|
|
+ // 差旅报销单行程分录ID -> 出差申请分录ID映射
|
|
|
+ DataSet tripReimEntryDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), BillTypeConstants.ER_TRIPREIMBURSEBILL, "tripentry.tripentrysourceid,tripentry.entryentity.id",
|
|
|
+ new QFilter("tripentry.tripentrysourceid", QCP.in, tripEntryIdSet).toArray(), "");
|
|
|
+ Set tripReimEntryIdSet = CommonUtils.getFiledFromDataSet(tripReimEntryDataSet, "tripentry.entryentity.id");
|
|
|
+
|
|
|
+ // 获取行程信息分录下的发票信息
|
|
|
+ DataSet queryReimInvoiceEntryDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), BillTypeConstants.ER_TRIPREIMBURSEBILL, "invoiceitementry.itementryid,invoiceitementry.invoiceheadentryid",
|
|
|
+ new QFilter("invoiceitementry.itementryid", QCP.in, tripReimEntryIdSet).toArray(), "");
|
|
|
+ Set invoiceEntryIdSet = CommonUtils.getFiledFromDataSet(queryReimInvoiceEntryDataSet, "invoiceitementry.invoiceheadentryid");
|
|
|
+
|
|
|
+
|
|
|
+ // 查询发票相关信息
|
|
|
+ DataSet queryInvoiceEntryDataSet = QueryServiceHelper.queryDataSet(this.getClass().getName(), BillTypeConstants.ER_TRIPREIMBURSEBILL, "billno,invoiceentry.id,invoiceentry.invoiceno,invoiceentry.carrierdate,invoiceentry.istartcity,invoiceentry.idestcity,invoiceentry.totalamount",
|
|
|
+ new QFilter("invoiceentry.id", QCP.in, invoiceEntryIdSet).toArray(), "");
|
|
|
+
|
|
|
+ // 建议出差申请和发票明细的关联关系
|
|
|
+ DataSet queryReimInvoiceDataSet = queryTripReqEntryDataSet.leftJoin(tripReimEntryDataSet)
|
|
|
+ .on("tripentry.id", "tripentry.tripentrysourceid").select("billno", "tripentry.entryentity.id").finish()
|
|
|
+ .leftJoin(queryReimInvoiceEntryDataSet)
|
|
|
+ .on("tripentry.entryentity.id", "invoiceitementry.itementryid").select("billno", "invoiceitementry.invoiceheadentryid").finish()
|
|
|
+ .leftJoin(queryInvoiceEntryDataSet)
|
|
|
+ .on("invoiceitementry.invoiceheadentryid", "invoiceentry.id").select(new String[]{ "billno" }, new String[]{ "billno tripBillno","invoiceentry.invoiceno", "invoiceentry.carrierdate", "invoiceentry.istartcity","invoiceentry.idestcity", "invoiceentry.totalamount" }).finish();
|
|
|
+ DynamicObjectCollection reimInvoiceCol = ORM.create().toPlainDynamicObjectCollection(queryReimInvoiceDataSet);
|
|
|
+ return reimInvoiceCol.stream().filter(r -> !Objects.isNull(r.getString("invoiceentry.invoiceno"))).collect(Collectors.groupingBy(r -> r.getString("billno")));
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取出差人部门秘书
|
|
|
+ * @param applierId
|
|
|
+ * @param deptId
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ protected DynamicObject getTravelDeptSecretary(Long applierId , Long deptId){
|
|
|
+ // 优先从秘书特殊人员配置中取,如果没有特殊配置,则从部门秘书中取
|
|
|
+ DynamicObject speSettingInfo = QueryServiceHelper.queryOne(SecretarySpeSettingConstant.ENTITYID,
|
|
|
+ SecretarySpeSettingConstant.NCKD_ORG_CHECK, new QFilter(SecretarySpeSettingConstant.NCKD_USER, QCP.equals, applierId).toArray());
|
|
|
+ Long checkOrg = 0L;
|
|
|
+ if(speSettingInfo != null){
|
|
|
+ checkOrg = speSettingInfo.getLong(SecretarySpeSettingConstant.NCKD_ORG_CHECK);
|
|
|
+ }else{
|
|
|
+ checkOrg = deptId;
|
|
|
+ }
|
|
|
+ // 查询部门秘书配置
|
|
|
+ DynamicObject depSecretaryInfo = QueryServiceHelper.queryOne(DepSecretaryConstant.ENTITYID, DepSecretaryConstant.NCKD_SECRETARY,
|
|
|
+ new QFilter(CommonUtils.join(DepSecretaryConstant.ENTITYID_ENTRY, DepSecretaryConstant.NCKD_ORG), QCP.equals, checkOrg).toArray());
|
|
|
+ if(depSecretaryInfo != null){
|
|
|
+ return BusinessDataServiceHelper.loadSingleFromCache(depSecretaryInfo.getLong(DepSecretaryConstant.NCKD_SECRETARY),"bos_user");
|
|
|
+ }
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|