|
@@ -0,0 +1,275 @@
|
|
|
|
|
+package nckd.fi.er.webapi.cutomer;
|
|
|
|
|
+
|
|
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import kd.bos.coderule.api.CodeRuleInfo;
|
|
|
|
|
+import kd.bos.dataentity.entity.DynamicObject;
|
|
|
|
|
+import kd.bos.dataentity.entity.DynamicObjectCollection;
|
|
|
|
|
+import kd.bos.entity.EntityMetadataCache;
|
|
|
|
|
+import kd.bos.entity.MainEntityType;
|
|
|
|
|
+import kd.bos.logging.Log;
|
|
|
|
|
+import kd.bos.logging.LogFactory;
|
|
|
|
|
+import kd.bos.openapi.common.custom.annotation.ApiController;
|
|
|
|
|
+import kd.bos.openapi.common.custom.annotation.ApiMapping;
|
|
|
|
|
+import kd.bos.openapi.common.custom.annotation.ApiParam;
|
|
|
|
|
+import kd.bos.openapi.common.custom.annotation.ApiPostMapping;
|
|
|
|
|
+import kd.bos.openapi.common.result.CustomApiResult;
|
|
|
|
|
+import kd.bos.orm.query.QCP;
|
|
|
|
|
+import kd.bos.orm.query.QFilter;
|
|
|
|
|
+import kd.bos.servicehelper.BusinessDataServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.QueryServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.coderule.CodeRuleServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.operation.SaveServiceHelper;
|
|
|
|
|
+import kd.bos.servicehelper.user.UserServiceHelper;
|
|
|
|
|
+import kd.qmc.qcbd.common.constant.BosOrgConst;
|
|
|
|
|
+import nckd.base.common.constant.BaseFieldConst;
|
|
|
|
|
+import nckd.base.common.constant.BosUserConstant;
|
|
|
|
|
+import nckd.base.common.enums.BillStatusEnum;
|
|
|
|
|
+import nckd.base.common.utils.DateUtil;
|
|
|
|
|
+import nckd.base.common.utils.OperationUtils;
|
|
|
|
|
+import nckd.fi.er.common.constant.TripReqBillConstant;
|
|
|
|
|
+import nckd.fi.er.common.utils.TripReqBillUtils;
|
|
|
|
|
+import nckd.fi.er.webapi.model.TripEntryModel;
|
|
|
|
|
+import nckd.fi.er.webapi.model.TripReqBillModel;
|
|
|
|
|
+import nckd.fi.er.webapi.model.UserPageModel;
|
|
|
|
|
+import org.apache.commons.lang3.ObjectUtils;
|
|
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
+
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
|
+import java.util.*;
|
|
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
+import java.util.stream.Stream;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @description:出差申请单接口
|
|
|
|
|
+ * @author: dingsixi
|
|
|
|
|
+ * @create: 2025/12/11 14:51
|
|
|
|
|
+ */
|
|
|
|
|
+@ApiController(value = "TripReqBillWebApiPlugin", desc = "出差申请单")
|
|
|
|
|
+@ApiMapping(value = "/er_tripreqbill")
|
|
|
|
|
+public class TripReqBillWebApiPlugin {
|
|
|
|
|
+ private final static Log logger = LogFactory.getLog(TripReqBillWebApiPlugin.class);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 报销类型
|
|
|
|
|
+ */
|
|
|
|
|
+ private final static String NCKD_AGENTACCOUNTTYPE = "nckd_agentaccounttype";
|
|
|
|
|
+
|
|
|
|
|
+ @ApiPostMapping(desc = "新增出差申请单", value = "/addNew")
|
|
|
|
|
+ public CustomApiResult<Object> addNew(
|
|
|
|
|
+ @ApiParam("出差申请") List<TripReqBillModel> tripReqBillModelList) {
|
|
|
|
|
+ logger.info("新增出差申请单入参:" + JSONObject.toJSONString(tripReqBillModelList));
|
|
|
|
|
+
|
|
|
|
|
+ //校验出差申请单入参
|
|
|
|
|
+ List<String> errorMessages = TripReqBillUtils.validateTripReqBillModels(tripReqBillModelList);
|
|
|
|
|
+ if (!errorMessages.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", String.join(",", errorMessages));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //报销类型 (默认编码:03 常规报销)
|
|
|
|
|
+ DynamicObject type = TripReqBillUtils.getEntityIdByNumber(NCKD_AGENTACCOUNTTYPE, BaseFieldConst.NUMBER, QCP.equals, "03");
|
|
|
|
|
+ //币别 默认人民币
|
|
|
|
|
+ DynamicObject currency = TripReqBillUtils.getEntityIdByNumber("bd_currency", BaseFieldConst.NUMBER, QCP.equals, "CNY");
|
|
|
|
|
+ //费用项目 默认差旅费16.001
|
|
|
|
|
+ DynamicObject expenseItem = TripReqBillUtils.getEntityIdByNumber("er_expenseitemedit", BaseFieldConst.NUMBER, QCP.equals, "16.001");
|
|
|
|
|
+ //校验默认值
|
|
|
|
|
+ errorMessages = TripReqBillUtils.validateDefaultValue(type, currency, expenseItem);
|
|
|
|
|
+ if (!errorMessages.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", String.join(",", errorMessages));
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**提取所有需要查询的基础资料编码,统一查询,只查一次,避免循环*/
|
|
|
|
|
+ //所有行程信息
|
|
|
|
|
+ List<TripEntryModel> tripEntryModelList = tripReqBillModelList.stream().flatMap(it -> it.getTripEntryModelList().stream()).collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ //申请人
|
|
|
|
|
+ List<String> applierList = tripReqBillModelList.stream().map(TripReqBillModel::getApplier).collect(Collectors.toList());
|
|
|
|
|
+ //出差人(行程信息内的出差人,存在多个出差人的情况)
|
|
|
|
|
+ List<String> multiTravelersList = tripReqBillModelList.stream().flatMap(it -> it.getMultiTravelers().stream()).collect(Collectors.toList());
|
|
|
|
|
+ //人员、出差人
|
|
|
|
|
+ List<String> allUserNumberList = TripReqBillUtils.mergeLists(applierList, multiTravelersList);
|
|
|
|
|
+
|
|
|
|
|
+ //申请人费用承担公司
|
|
|
|
|
+ List<String> headCostCompanyList = tripReqBillModelList.stream().map(TripReqBillModel::getCostCompany).collect(Collectors.toList());
|
|
|
|
|
+ //申请人费用承担部门
|
|
|
|
|
+ List<String> headCostDeptList = tripReqBillModelList.stream().map(TripReqBillModel::getCostDept).collect(Collectors.toList());
|
|
|
|
|
+ //行程信息.费用承担部门
|
|
|
|
|
+ List<String> costDeptList = tripEntryModelList.stream().map(TripEntryModel::getCostDept).collect(Collectors.toList());
|
|
|
|
|
+ //行程信息.费用承担公司
|
|
|
|
|
+ List<String> costCompanyList = tripEntryModelList.stream().map(TripEntryModel::getCostCompany).collect(Collectors.toList());
|
|
|
|
|
+ //申请人公司、费用承担部门、费用承担公司 合并部门公司编码
|
|
|
|
|
+ List<String> allOrgNumberList = TripReqBillUtils.mergeLists(headCostDeptList, headCostCompanyList, costDeptList, costCompanyList);
|
|
|
|
|
+
|
|
|
|
|
+ //行程信息.成本中心
|
|
|
|
|
+ List<String> costCenterList = tripEntryModelList.stream().map(TripEntryModel::getCostCenter).collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ //行程信息.出发地-目的地
|
|
|
|
|
+ List<String> formList = tripEntryModelList.stream().map(TripEntryModel::getFrom).collect(Collectors.toList());
|
|
|
|
|
+ List<String> toList = tripEntryModelList.stream().map(TripEntryModel::getTo).collect(Collectors.toList());
|
|
|
|
|
+ //合并城市
|
|
|
|
|
+ List<String> cityList = TripReqBillUtils.mergeLists(formList, toList);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ //人员信息
|
|
|
|
|
+ Map<String, DynamicObject> userMap = TripReqBillUtils.getEntityIdsByNumbers(BosUserConstant.FORMBILLID, BaseFieldConst.NUMBER, QCP.in, allUserNumberList);
|
|
|
|
|
+ String userMsg = TripReqBillUtils.validateBaseDataIsExists(allUserNumberList, userMap, "人员");
|
|
|
|
|
+ if (!userMsg.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", userMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+ //查询所有部门公司编码id
|
|
|
|
|
+ Map<String, DynamicObject> orgMap = TripReqBillUtils.getEntityIdsByNumbers(BosOrgConst.BOS_ORG, BaseFieldConst.NUMBER, QCP.in, allOrgNumberList);
|
|
|
|
|
+ String orgMsg = TripReqBillUtils.validateBaseDataIsExists(allOrgNumberList, orgMap, "组织");
|
|
|
|
|
+ if (!orgMsg.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", orgMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+ //成本中心
|
|
|
|
|
+ Map<String, DynamicObject> costCenterMap = TripReqBillUtils.getEntityIdsByNumbers("bos_costcenter", BaseFieldConst.NUMBER, QCP.in, costCenterList);
|
|
|
|
|
+ String costCenterMsg = TripReqBillUtils.validateBaseDataIsExists(costCenterList, costCenterMap, "成本中心");
|
|
|
|
|
+ if (!costCenterMsg.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", costCenterMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+ //查询所有城市的id
|
|
|
|
|
+ Map<String, DynamicObject> cityMap = TripReqBillUtils.getEntityIdsByNumbers("bd_admindivision", BaseFieldConst.NUMBER, QCP.in, cityList);
|
|
|
|
|
+ String cityMsg = TripReqBillUtils.validateBaseDataIsExists(cityList, cityMap, "城市");
|
|
|
|
|
+ if (!cityMsg.isEmpty()) {
|
|
|
|
|
+ return CustomApiResult.fail("500", cityMsg);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ //创建出差申请单
|
|
|
|
|
+ List<DynamicObject> tripReqBillList = createTripReqBill(tripReqBillModelList, currency, type, expenseItem, orgMap, userMap, cityMap, costCenterMap);
|
|
|
|
|
+
|
|
|
|
|
+ return getResult(tripReqBillList);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param tripReqBillModelList 出差申请单入参
|
|
|
|
|
+ * @param currency 币别
|
|
|
|
|
+ * @param type 报销类型
|
|
|
|
|
+ * @param expenseItem 费用项目
|
|
|
|
|
+ * @param orgMap 组织信息
|
|
|
|
|
+ * @param userMap 人员信息
|
|
|
|
|
+ * @param cityMap 城市信息
|
|
|
|
|
+ * @param costCenterMap 成本中心信息
|
|
|
|
|
+ * @return 创建出差申请单
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<DynamicObject> createTripReqBill(List<TripReqBillModel> tripReqBillModelList, DynamicObject currency,
|
|
|
|
|
+ DynamicObject type, DynamicObject expenseItem, Map<String, DynamicObject> orgMap,
|
|
|
|
|
+ Map<String, DynamicObject> userMap, Map<String, DynamicObject> cityMap,
|
|
|
|
|
+ Map<String, DynamicObject> costCenterMap) {
|
|
|
|
|
+ List<DynamicObject> addList = new ArrayList<>();
|
|
|
|
|
+ for (TripReqBillModel tripReqBillModel : tripReqBillModelList) {
|
|
|
|
|
+
|
|
|
|
|
+ //创建出差申请单
|
|
|
|
|
+ DynamicObject tripReqBill = BusinessDataServiceHelper.newDynamicObject(TripReqBillConstant.FORMBILLID);
|
|
|
|
|
+
|
|
|
|
|
+ //单据编号
|
|
|
|
|
+ CodeRuleInfo codeRule = CodeRuleServiceHelper.getCodeRule(tripReqBill.getDataEntityType().getName(), tripReqBill, null);
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.BILLNO, CodeRuleServiceHelper.getNumber(codeRule, tripReqBill));
|
|
|
|
|
+
|
|
|
|
|
+ //单据状态
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.BILLSTATUS, BillStatusEnum.SAVE.getValue());
|
|
|
|
|
+ //默认非借款
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.ISLOAN, Boolean.FALSE);
|
|
|
|
|
+ //默认人民币
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.CURRENCY, currency);
|
|
|
|
|
+ //职位 主职或兼职 暂定对方传,传不了再通过人员部门查询对应的职位
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.APPLIERPOSITIONSTR, tripReqBillModel.getApplierPosition());
|
|
|
|
|
+ //部门 取费用承担部门
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.ORG, orgMap.get(tripReqBillModel.getCostDept()));
|
|
|
|
|
+
|
|
|
|
|
+ //报销类型
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.NCKD_BXLX, type);
|
|
|
|
|
+ //申请人
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.APPLIER, userMap.get(tripReqBillModel.getApplier()));
|
|
|
|
|
+ //出差人(行程信息内的出差人) 存在多个的情况
|
|
|
|
|
+ List<String> multiTravelers = tripReqBillModel.getMultiTravelers();
|
|
|
|
|
+ DynamicObjectCollection multiTravelersCol = tripReqBill.getDynamicObjectCollection(TripReqBillConstant.MULTITRAVELERS);
|
|
|
|
|
+ userMap.entrySet().stream().filter(it -> multiTravelers.contains(it.getKey())).forEach(it -> {
|
|
|
|
|
+ multiTravelersCol.addNew().set("fbasedataid", it);
|
|
|
|
|
+ });
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.MULTITRAVELERS, multiTravelersCol);
|
|
|
|
|
+ //申请日期
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.BIZDATE, DateUtil.string2date(tripReqBillModel.getApplyDate(), DateUtil.DATE_FORMAT_YYYY_MM_DD));
|
|
|
|
|
+ //是否多出差人
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.ISTRAVELERS, tripReqBillModel.getTravelers());
|
|
|
|
|
+ //事由
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.DESCRIPTION, tripReqBillModel.getDescription());
|
|
|
|
|
+ //申请人公司
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.COMPANY, orgMap.get(tripReqBillModel.getCostCompany()));
|
|
|
|
|
+ //费用承担公司
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.COSTCOMPANY, orgMap.get(tripReqBillModel.getCostCompany()));
|
|
|
|
|
+ //费用承担部门
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.COSTDEPT, orgMap.get(tripReqBillModel.getCostDept()));
|
|
|
|
|
+ //表单id
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.FORMID, TripReqBillConstant.FORMBILLID);
|
|
|
|
|
+ BigDecimal amountCount = BigDecimal.ZERO;
|
|
|
|
|
+ DynamicObjectCollection tripEntryCol = tripReqBill.getDynamicObjectCollection(TripReqBillConstant.TRIPENTRY);
|
|
|
|
|
+
|
|
|
|
|
+ //行程信息
|
|
|
|
|
+ List<TripEntryModel> tripEntryModelList1 = tripReqBillModel.getTripEntryModelList();
|
|
|
|
|
+ for (int i = 0; i < tripEntryModelList1.size(); i++) {
|
|
|
|
|
+ TripEntryModel tripEntryModel = tripEntryModelList1.get(i);
|
|
|
|
|
+ DynamicObject tripEntry = tripEntryCol.addNew();
|
|
|
|
|
+ //默认行号 必须要
|
|
|
|
|
+ tripEntry.set("seq", i + 1);
|
|
|
|
|
+ //出发地
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.FROM, cityMap.get(tripEntryModel.getFrom()));
|
|
|
|
|
+ //目的地
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TO, cityMap.get(tripEntryModel.getTo()));
|
|
|
|
|
+ //行程期间
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.STARTDATE, DateUtil.string2date(tripEntryModel.getStartDate(), DateUtil.DATE_FORMAT_YYYY_MM_DD));
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.ENDDATE, DateUtil.string2date(tripEntryModel.getEndDate(), DateUtil.DATE_FORMAT_YYYY_MM_DD));
|
|
|
|
|
+ //交通工具
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.VEHICLES, tripEntryModel.getVehicle());
|
|
|
|
|
+ //费用承担部门
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.ENTRYCOSTDEPT, orgMap.get(tripEntryModel.getCostDept()));
|
|
|
|
|
+ //费用承担公司
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.ENTRYCOSTCOMPANY, orgMap.get(tripEntryModel.getCostCompany()));
|
|
|
|
|
+ //成本中心
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.STD_ENTRYCOSTCENTER, costCenterMap.get(tripEntryModel.getCostCenter()));
|
|
|
|
|
+ //费用项目
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPEXPENSEITEM, expenseItem);
|
|
|
|
|
+ //申请金额 核定金额(本位币) 核定金额
|
|
|
|
|
+ BigDecimal applyAmount = tripEntryModel.getTripOriAmount();
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPORIAMOUNT, applyAmount);
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPACCAPPAMOUNT, applyAmount);
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPORIACCAPPAMOUNT, applyAmount);
|
|
|
|
|
+ amountCount = amountCount.add(applyAmount);
|
|
|
|
|
+ //行程币种
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPCURRENCY, currency);
|
|
|
|
|
+ //汇率
|
|
|
|
|
+ tripEntry.set(TripReqBillConstant.TRIPEXCHANGERATE, 1);
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+ //总金额
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.AMOUNT, amountCount);
|
|
|
|
|
+ //核定金额
|
|
|
|
|
+ tripReqBill.set(TripReqBillConstant.APPROVEAMOUNT, amountCount);
|
|
|
|
|
+
|
|
|
|
|
+ addList.add(tripReqBill);
|
|
|
|
|
+ }
|
|
|
|
|
+ return addList;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * @param addList 新增的出差申请单
|
|
|
|
|
+ * @return 获取新增的结果
|
|
|
|
|
+ */
|
|
|
|
|
+ private CustomApiResult<Object> getResult(List<DynamicObject> addList) {
|
|
|
|
|
+ DynamicObject[] objs = addList.toArray(new DynamicObject[0]);
|
|
|
|
|
+ try {
|
|
|
|
|
+ //保存至审核
|
|
|
|
|
+ OperationUtils.operationDoSave2Audit(objs, TripReqBillConstant.FORMBILLID);
|
|
|
|
|
+ return CustomApiResult.success(null);
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ //未审核成功,找出已存在数据库中的数据,将已存在数据库的数据反审核至删除
|
|
|
|
|
+ List<DynamicObject> objList = Arrays.stream(objs).filter(it -> it.getDataEntityState().getFromDatabase()).collect(Collectors.toList());
|
|
|
|
|
+ if (!objList.isEmpty()) {
|
|
|
|
|
+ OperationUtils.operationDoUnAudit2Delete(objList.toArray(new DynamicObject[0]), TripReqBillConstant.FORMBILLID);
|
|
|
|
|
+ }
|
|
|
|
|
+ return CustomApiResult.fail("500", e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+}
|