提单费用均摊处理
This commit is contained in:
+11
@@ -0,0 +1,11 @@
|
||||
package com.bms.price.airbill.domain;
|
||||
|
||||
import java.util.List;
|
||||
import lombok.Data;
|
||||
|
||||
/** 提单费用分摊请求。一次最多 5 个提单号。 */
|
||||
@Data
|
||||
public class SrvBillAirAllocCommand
|
||||
{
|
||||
private List<String> billCodes;
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
package com.bms.price.airbill.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import lombok.Data;
|
||||
|
||||
/** 待分摊的一条提单费用,供费用处理弹框展示。 */
|
||||
@Data
|
||||
public class SrvBillAirAllocFee
|
||||
{
|
||||
private Long id;
|
||||
|
||||
private String billCode;
|
||||
|
||||
/** 提单主键 srv_bill_air.guid,写入订单费用的 source_id */
|
||||
private String ladingId;
|
||||
|
||||
/** 费用阶段,字典 bms_fee_level */
|
||||
private String feeLevel;
|
||||
|
||||
/** 费用状态,字典 bill_fee_status */
|
||||
private String billFeeStatus;
|
||||
|
||||
private String feeName;
|
||||
|
||||
private BigDecimal price;
|
||||
|
||||
private String currency;
|
||||
|
||||
/** 分摊维度:1订单 2重量 */
|
||||
private String allocDim;
|
||||
|
||||
/** 提单实际重量。只在按重量分摊时按提单号填入,不返回页面 */
|
||||
@JsonIgnore
|
||||
private BigDecimal actualWeight;
|
||||
|
||||
/** 干线打板重量。只在按重量分摊时按提单号填入,不返回页面 */
|
||||
@JsonIgnore
|
||||
private BigDecimal bandBoxWeight;
|
||||
|
||||
private Integer orderCount;
|
||||
|
||||
/** 不能分摊时的原因。空表示可以分摊 */
|
||||
private String blockReason;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
package com.bms.price.airbill.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import lombok.Data;
|
||||
|
||||
/** 提单下参与分摊的一票订单。 */
|
||||
@Data
|
||||
public class SrvBillAirAllocOrder
|
||||
{
|
||||
private String billCode;
|
||||
|
||||
private String orderNo;
|
||||
|
||||
/** 计费订单 ID,对应 prc_order_bill.bill_id */
|
||||
private String billId;
|
||||
|
||||
/** 计费重,没有计费重时依次取实际重量、收货重量 */
|
||||
private BigDecimal chargeWeight;
|
||||
}
|
||||
@@ -17,6 +17,12 @@ public class SrvBillAirFeeLog
|
||||
|
||||
public static final String DELETE = "3";
|
||||
|
||||
/** 已分摊费用确定。日志不记录字段变化。 */
|
||||
public static final String CONFIRM = "4";
|
||||
|
||||
/** 已分摊或已确定费用作废。 */
|
||||
public static final String VOID = "5";
|
||||
|
||||
private Long logId;
|
||||
|
||||
private String billCode;
|
||||
|
||||
@@ -19,6 +19,9 @@ public class PrcPayBillFee implements Serializable
|
||||
private String feeType;
|
||||
private String feeName;
|
||||
private Long scId;
|
||||
|
||||
/** 费用所属阶段:1 a段,2 b段,3 c段,4 d段 */
|
||||
private String feeLevel;
|
||||
private BigDecimal amount;
|
||||
private String currency;
|
||||
private String roundMode;
|
||||
|
||||
@@ -38,4 +38,21 @@ public interface PrcPayBillFeeMapper
|
||||
* @return 影响行数
|
||||
*/
|
||||
public int deleteByBillId(String billId);
|
||||
|
||||
/**
|
||||
* 逻辑删除某一条提单费用分摊到订单上的明细。
|
||||
*
|
||||
* @param feeId 提单费用 ID,保存在 sc_id
|
||||
* @return 影响行数
|
||||
*/
|
||||
public int markLadingFeeDeleted(@Param("feeId") Long feeId);
|
||||
|
||||
/**
|
||||
* 这条提单费用分摊到的订单里,取一个已经生成应付账单的订单号。
|
||||
* 是否出账看 prc_order_bill_ext.is_meet:1 已生成。
|
||||
*
|
||||
* @param feeId 提单费用 ID,保存在 sc_id
|
||||
* @return 订单号,没有已出账订单时为空
|
||||
*/
|
||||
public String selectBilledOrderNo(@Param("feeId") Long feeId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.bms.price.mapper;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import com.bms.price.airbill.domain.SrvBillAirAllocFee;
|
||||
import com.bms.price.airbill.domain.SrvBillAirAllocOrder;
|
||||
import com.bms.price.domain.PrcPayBill;
|
||||
|
||||
/**
|
||||
* 提单费用分摊到订单。
|
||||
*/
|
||||
public interface SrvBillAirAllocMapper
|
||||
{
|
||||
/**
|
||||
* 查询这些提单上尚未分摊、且标记为需要分摊的费用。
|
||||
*
|
||||
* @param billCodes 提单号
|
||||
* @return 待分摊费用
|
||||
*/
|
||||
List<SrvBillAirAllocFee> selectPendingFees(@Param("billCodes") List<String> billCodes);
|
||||
|
||||
/**
|
||||
* 按提单号取出实际重量和打板重量,只供按重量分摊计算。
|
||||
*
|
||||
* @param billCodes 提单号
|
||||
* @return 提单号、实际重量、打板重量
|
||||
*/
|
||||
List<SrvBillAirAllocFee> selectLadingWeight(@Param("billCodes") List<String> billCodes);
|
||||
|
||||
/**
|
||||
* 按提单号查出关联订单。订单号在扩展表,计费单号和重量在订单表。
|
||||
*
|
||||
* @param billCodes 提单号,对应 prc_order_bill_ext.air_no_old
|
||||
* @return 订单
|
||||
*/
|
||||
List<SrvBillAirAllocOrder> selectOrders(@Param("billCodes") List<String> billCodes);
|
||||
|
||||
/**
|
||||
* 按计费订单号取出已有的应付主表。
|
||||
*
|
||||
* @param billIds 计费订单 ID
|
||||
* @return 应付主表编号
|
||||
*/
|
||||
List<PrcPayBill> selectPayBills(@Param("billIds") List<String> billIds);
|
||||
|
||||
/**
|
||||
* 把仍是未分摊的费用改为已分摊。已经不是未分摊的行不会被改到。
|
||||
*
|
||||
* @param ids 提单费用 ID
|
||||
* @param updateBy 操作人
|
||||
* @param updateTime 操作时间
|
||||
* @return 实际改到的行数
|
||||
*/
|
||||
int markAllocated(@Param("ids") List<Long> ids, @Param("updateBy") String updateBy, @Param("updateTime") Date updateTime);
|
||||
}
|
||||
@@ -22,6 +22,14 @@ public interface SrvBillAirFeeMapper
|
||||
int deleteFee(@Param("id") Long id, @Param("billCode") String billCode, @Param("updateBy") String updateBy,
|
||||
@Param("updateTime") java.util.Date updateTime);
|
||||
|
||||
/** 已分摊改为已确定。 */
|
||||
int confirmFee(@Param("id") Long id, @Param("billCode") String billCode, @Param("updateBy") String updateBy,
|
||||
@Param("updateTime") java.util.Date updateTime);
|
||||
|
||||
/** 已分摊或已确定的费用作废:状态改为已作废,并逻辑删除。 */
|
||||
int voidFee(@Param("id") Long id, @Param("billCode") String billCode, @Param("updateBy") String updateBy,
|
||||
@Param("updateTime") java.util.Date updateTime);
|
||||
|
||||
int insertLog(SrvBillAirFeeLog log);
|
||||
|
||||
List<SrvBillAirFeeLog> selectLogs(String billCode);
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.bms.price.service;
|
||||
|
||||
import java.util.List;
|
||||
import com.bms.price.airbill.domain.SrvBillAirAllocFee;
|
||||
|
||||
/**
|
||||
* 把提单上待分摊的费用均摊到关联订单。
|
||||
*/
|
||||
public interface ISrvBillAirAllocService
|
||||
{
|
||||
/**
|
||||
* 查出勾选提单上需要分摊、且尚未分摊的费用。
|
||||
*
|
||||
* @param billCodes 提单号,最多 5 个
|
||||
* @return 费用和不能分摊的原因
|
||||
*/
|
||||
List<SrvBillAirAllocFee> preview(List<String> billCodes);
|
||||
|
||||
/**
|
||||
* 按费用上的分摊维度把金额摊到每个订单,并改费用状态为已分摊。整次处理在一个事务里,写入按 1000 条一批。
|
||||
*
|
||||
* @param billCodes 提单号,最多 5 个
|
||||
* @return 给页面的处理结果
|
||||
*/
|
||||
String allocate(List<String> billCodes);
|
||||
}
|
||||
@@ -16,4 +16,22 @@ public interface ISrvBillAirFeeService
|
||||
|
||||
/** 只写入有变动的行,并按行记录修改前后。返回给页面的提示。 */
|
||||
String save(SrvBillAirFeeSave command);
|
||||
|
||||
/**
|
||||
* 已分摊的费用确认为已确定。
|
||||
*
|
||||
* @param billCode 提单号
|
||||
* @param feeId 费用 ID
|
||||
* @return 给页面的提示
|
||||
*/
|
||||
String confirm(String billCode, Long feeId);
|
||||
|
||||
/**
|
||||
* 作废已分摊或已确定的费用。订单上的分摊明细逻辑删除,这条提单费用也逻辑删除。
|
||||
*
|
||||
* @param billCode 提单号
|
||||
* @param feeId 费用 ID
|
||||
* @return 给页面的提示
|
||||
*/
|
||||
String voidFee(String billCode, Long feeId);
|
||||
}
|
||||
|
||||
+472
@@ -0,0 +1,472 @@
|
||||
package com.bms.price.service.impl;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.bms.common.core.domain.entity.SysUser;
|
||||
import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.DateUtils;
|
||||
import com.bms.common.utils.SecurityUtils;
|
||||
import com.bms.price.airbill.domain.SrvBillAirAllocFee;
|
||||
import com.bms.price.airbill.domain.SrvBillAirAllocOrder;
|
||||
import com.bms.price.airbill.domain.SrvBillAirFeeLog;
|
||||
import com.bms.price.domain.PrcPayBill;
|
||||
import com.bms.price.domain.PrcPayBillFee;
|
||||
import com.bms.price.mapper.SrvBillAirAllocMapper;
|
||||
import com.bms.price.mapper.SrvBillAirFeeMapper;
|
||||
import com.bms.price.mapper.SrvBillAirMapper;
|
||||
import com.bms.price.mapper.PrcPayBillFeeMapper;
|
||||
import com.bms.price.service.ISrvBillAirAllocService;
|
||||
|
||||
/**
|
||||
* 提单费用分摊。只处理标记为分摊、状态仍是未分摊的费用。
|
||||
*/
|
||||
@Service
|
||||
public class SrvBillAirAllocServiceImpl implements ISrvBillAirAllocService
|
||||
{
|
||||
private static final int MAX_BILLS = 5;
|
||||
|
||||
private static final int BATCH_SIZE = 1000;
|
||||
|
||||
private static final String DIM_ORDER = "1";
|
||||
|
||||
private static final String DIM_WEIGHT = "2";
|
||||
|
||||
private static final String FEE_TYPE = "LADING";
|
||||
|
||||
private static final String FEE_SOURCE = "LADING";
|
||||
|
||||
private static final BigDecimal ZERO = BigDecimal.ZERO;
|
||||
|
||||
@Autowired
|
||||
private SrvBillAirAllocMapper allocMapper;
|
||||
|
||||
@Autowired
|
||||
private SrvBillAirMapper billMapper;
|
||||
|
||||
@Autowired
|
||||
private SrvBillAirFeeMapper feeMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcPayBillFeeMapper payBillFeeMapper;
|
||||
|
||||
@Override
|
||||
public List<SrvBillAirAllocFee> preview(List<String> billCodes)
|
||||
{
|
||||
List<String> codes = normalize(billCodes);
|
||||
List<SrvBillAirAllocFee> fees = dedupe(allocMapper.selectPendingFees(codes));
|
||||
fillWeight(fees);
|
||||
Map<String, List<SrvBillAirAllocOrder>> orders = ordersOf(codes);
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
List<SrvBillAirAllocOrder> rows = orders.getOrDefault(fee.getBillCode(), List.of());
|
||||
fee.setOrderCount(rows.size());
|
||||
fee.setBlockReason(blockReason(fee, rows));
|
||||
}
|
||||
return fees;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String allocate(List<String> billCodes)
|
||||
{
|
||||
List<String> codes = normalize(billCodes);
|
||||
List<SrvBillAirAllocFee> fees = dedupe(allocMapper.selectPendingFees(codes));
|
||||
fillWeight(fees);
|
||||
if (fees.isEmpty())
|
||||
{
|
||||
throw new ServiceException("所选提单没有需要分摊的费用");
|
||||
}
|
||||
Map<String, List<SrvBillAirAllocOrder>> orders = ordersOf(codes);
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
List<SrvBillAirAllocOrder> rows = orders.getOrDefault(fee.getBillCode(), List.of());
|
||||
fee.setOrderCount(rows.size());
|
||||
String reason = blockReason(fee, rows);
|
||||
if (!reason.isEmpty())
|
||||
{
|
||||
throw new ServiceException(fee.getBillCode() + " " + blankName(fee) + ":" + reason);
|
||||
}
|
||||
}
|
||||
Map<String, String> payBillIds = payBillIds(orders);
|
||||
List<PrcPayBillFee> batch = new ArrayList<>(BATCH_SIZE);
|
||||
int lineCount = 0;
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
List<SrvBillAirAllocOrder> rows = orders.get(fee.getBillCode());
|
||||
fee.setOrderCount(rows.size());
|
||||
boolean byWeight = DIM_WEIGHT.equals(fee.getAllocDim());
|
||||
List<BigDecimal> shares = split(byWeight ? weightAmount(fee) : fee.getPrice(), rows, byWeight);
|
||||
for (int i = 0; i < rows.size(); i++)
|
||||
{
|
||||
batch.add(toOrderFee(fee, rows.get(i), shares.get(i), payBillIds));
|
||||
if (batch.size() == BATCH_SIZE)
|
||||
{
|
||||
lineCount += flush(batch);
|
||||
}
|
||||
}
|
||||
}
|
||||
lineCount += flush(batch);
|
||||
Date now = DateUtils.getNowDate();
|
||||
String operator = SecurityUtils.getUsername();
|
||||
int updated = allocMapper.markAllocated(feeIds(fees), operator, now);
|
||||
if (updated != fees.size())
|
||||
{
|
||||
throw new ServiceException("费用状态已变化,请重新打开后再分摊");
|
||||
}
|
||||
writeLogs(fees, operator, now);
|
||||
return "已将 " + fees.size() + " 条费用分摊为 " + lineCount + " 笔订单费用";
|
||||
}
|
||||
|
||||
/**
|
||||
* 按重量分摊的费用,按提单号补上实际重量和打板重量。按订单数量分摊的不查、不填。
|
||||
* 这两个值只参与计算,不返回给页面。
|
||||
*/
|
||||
private void fillWeight(List<SrvBillAirAllocFee> fees)
|
||||
{
|
||||
List<String> codes = new ArrayList<>();
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
if (fee != null && DIM_WEIGHT.equals(fee.getAllocDim()) && fee.getBillCode() != null && !codes.contains(fee.getBillCode()))
|
||||
{
|
||||
codes.add(fee.getBillCode());
|
||||
}
|
||||
}
|
||||
if (codes.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
Map<String, SrvBillAirAllocFee> weights = new LinkedHashMap<>();
|
||||
for (SrvBillAirAllocFee row : allocMapper.selectLadingWeight(codes))
|
||||
{
|
||||
if (row != null && row.getBillCode() != null)
|
||||
{
|
||||
weights.put(row.getBillCode(), row);
|
||||
}
|
||||
}
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
if (fee == null || !DIM_WEIGHT.equals(fee.getAllocDim()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
SrvBillAirAllocFee weight = weights.get(fee.getBillCode());
|
||||
if (weight == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fee.setActualWeight(weight.getActualWeight());
|
||||
fee.setBandBoxWeight(weight.getBandBoxWeight());
|
||||
}
|
||||
}
|
||||
|
||||
/** 提单号去重、去空白,并限制单次 5 条。 */
|
||||
private List<String> normalize(List<String> billCodes)
|
||||
{
|
||||
LinkedHashSet<String> codes = new LinkedHashSet<>();
|
||||
if (billCodes != null)
|
||||
{
|
||||
for (String raw : billCodes)
|
||||
{
|
||||
if (raw == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
for (String part : raw.split("[,,\\s]+"))
|
||||
{
|
||||
if (!part.isBlank())
|
||||
{
|
||||
codes.add(part.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (codes.isEmpty())
|
||||
{
|
||||
throw new ServiceException("请勾选提单");
|
||||
}
|
||||
if (codes.size() > MAX_BILLS)
|
||||
{
|
||||
throw new ServiceException("单次最多处理5条提单");
|
||||
}
|
||||
for (String code : codes)
|
||||
{
|
||||
if (billMapper.selectSrvBillAirByBillCode(code) == null)
|
||||
{
|
||||
throw new ServiceException("提单不存在:" + code);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(codes);
|
||||
}
|
||||
|
||||
private Map<String, List<SrvBillAirAllocOrder>> ordersOf(List<String> codes)
|
||||
{
|
||||
Map<String, List<SrvBillAirAllocOrder>> grouped = new LinkedHashMap<>();
|
||||
for (SrvBillAirAllocOrder order : allocMapper.selectOrders(codes))
|
||||
{
|
||||
if (order.getBillId() == null || order.getBillId().isBlank())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
grouped.computeIfAbsent(order.getBillCode(), key -> new ArrayList<>()).add(order);
|
||||
}
|
||||
return grouped;
|
||||
}
|
||||
|
||||
private Map<String, String> payBillIds(Map<String, List<SrvBillAirAllocOrder>> orders)
|
||||
{
|
||||
List<String> billIds = new ArrayList<>();
|
||||
for (List<SrvBillAirAllocOrder> rows : orders.values())
|
||||
{
|
||||
for (SrvBillAirAllocOrder order : rows)
|
||||
{
|
||||
billIds.add(order.getBillId());
|
||||
}
|
||||
}
|
||||
Map<String, String> payIds = new LinkedHashMap<>();
|
||||
for (int from = 0; from < billIds.size(); from += BATCH_SIZE)
|
||||
{
|
||||
List<String> chunk = billIds.subList(from, Math.min(from + BATCH_SIZE, billIds.size()));
|
||||
for (PrcPayBill payBill : allocMapper.selectPayBills(chunk))
|
||||
{
|
||||
if (payBill.getBillId() != null && payBill.getPayBillId() != null)
|
||||
{
|
||||
payIds.put(payBill.getBillId(), payBill.getPayBillId());
|
||||
}
|
||||
}
|
||||
}
|
||||
return payIds;
|
||||
}
|
||||
|
||||
private String blockReason(SrvBillAirAllocFee fee, List<SrvBillAirAllocOrder> orders)
|
||||
{
|
||||
if (fee.getPrice() == null)
|
||||
{
|
||||
return "费用没有价格";
|
||||
}
|
||||
if (fee.getPrice().signum() < 0)
|
||||
{
|
||||
return "费用价格不能小于0";
|
||||
}
|
||||
if (fee.getCurrency() == null || fee.getCurrency().isBlank())
|
||||
{
|
||||
return "费用没有币种";
|
||||
}
|
||||
if (fee.getLadingId() == null || fee.getLadingId().isBlank())
|
||||
{
|
||||
return "提单缺少主键";
|
||||
}
|
||||
if (!DIM_ORDER.equals(fee.getAllocDim()) && !DIM_WEIGHT.equals(fee.getAllocDim()))
|
||||
{
|
||||
return "未选择分摊维度";
|
||||
}
|
||||
if (orders == null || orders.isEmpty())
|
||||
{
|
||||
return "提单下没有关联订单";
|
||||
}
|
||||
if (DIM_WEIGHT.equals(fee.getAllocDim()))
|
||||
{
|
||||
if (fee.getActualWeight() == null || fee.getActualWeight().signum() <= 0)
|
||||
{
|
||||
return "提单没有实际重量,无法按重量分摊";
|
||||
}
|
||||
if (fee.getBandBoxWeight() == null || fee.getBandBoxWeight().signum() <= 0)
|
||||
{
|
||||
return "干线没有打板重量,无法按重量分摊";
|
||||
}
|
||||
if (totalWeight(orders).signum() <= 0)
|
||||
{
|
||||
return "订单没有可用重量,无法按重量分摊";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private PrcPayBillFee toOrderFee(SrvBillAirAllocFee fee, SrvBillAirAllocOrder order, BigDecimal amount, Map<String, String> payBillIds)
|
||||
{
|
||||
PrcPayBillFee row = new PrcPayBillFee();
|
||||
row.setFeeId(UUID.randomUUID().toString());
|
||||
row.setBillId(order.getBillId());
|
||||
row.setPayBillId(payBillIds.get(order.getBillId()));
|
||||
row.setFeeType(FEE_TYPE);
|
||||
row.setFeeName(blankName(fee));
|
||||
row.setScId(fee.getId() == null ? 0L : fee.getId());
|
||||
row.setFeeLevel(fee.getFeeLevel());
|
||||
row.setAmount(amount);
|
||||
row.setCurrency(fee.getCurrency().trim());
|
||||
row.setRoundMode("HALF_UP");
|
||||
row.setRemark(remark(fee));
|
||||
row.setFeeSource(FEE_SOURCE);
|
||||
row.setSourceId(fee.getLadingId().trim());
|
||||
row.setIsDeleted("0");
|
||||
return row;
|
||||
}
|
||||
|
||||
private int flush(List<PrcPayBillFee> batch)
|
||||
{
|
||||
if (batch.isEmpty())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
int rows = batch.size();
|
||||
payBillFeeMapper.insertBatch(batch);
|
||||
batch.clear();
|
||||
return rows;
|
||||
}
|
||||
|
||||
private void writeLogs(List<SrvBillAirAllocFee> fees, String operator, Date now)
|
||||
{
|
||||
SysUser user = SecurityUtils.getLoginUser().getUser();
|
||||
String name = user.getNickName() == null || user.getNickName().isBlank() ? operator : user.getNickName();
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
SrvBillAirFeeLog log = new SrvBillAirFeeLog();
|
||||
log.setBillCode(fee.getBillCode());
|
||||
log.setFeeId(fee.getId());
|
||||
log.setOperationType(SrvBillAirFeeLog.UPDATE);
|
||||
log.setSummary("分摊到 " + fee.getOrderCount() + " 票订单");
|
||||
log.setChangeContent(JSON.toJSONString(List.of(
|
||||
new SrvBillAirFeeLog.FieldChange("billFeeStatus", "费用状态", "未分摊", "已分摊"))));
|
||||
log.setCreateBy(operator);
|
||||
log.setCreateByName(name);
|
||||
log.setCreateTime(now);
|
||||
feeMapper.insertLog(log);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 按重量分摊时,先算出这一票提单实际可分摊的金额。
|
||||
* 百分比 = 提单实际重量 srv_bill_air.actual_weight / 干线打板重量 srv_bill_air_flight.band_box_weight。
|
||||
* 可分摊金额 = 费用价格 × 百分比,保留两位,四舍五入。
|
||||
* 调用前须已确认实际重量和打板重量都大于 0。
|
||||
*
|
||||
* @param fee 待分摊的提单费用,带有实际重量和打板重量
|
||||
* @return 按百分比算出的可分摊金额
|
||||
*/
|
||||
private static BigDecimal weightAmount(SrvBillAirAllocFee fee)
|
||||
{
|
||||
BigDecimal price = fee.getPrice().setScale(2, RoundingMode.HALF_UP);
|
||||
return price.multiply(fee.getActualWeight()).divide(fee.getBandBoxWeight(), 2, RoundingMode.HALF_UP);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把金额拆到每一票订单,结果保留两位。
|
||||
* 按订单数量:每一票先向下取整,差额补在最后一票,合计等于费用价格。
|
||||
* 按重量:传入的金额已是「费用价格 × 提单实际重量 / 干线打板重量」。
|
||||
* 再按订单重量占这些订单总重量的比例分摊;前面的订单向下取整,差额补在最后一票有重量的订单上,合计等于这笔金额。
|
||||
* 订单重量优先取计费重,没有计费重时取实际重量,再没有取收货重量。
|
||||
*
|
||||
* @param price 本次要拆开的金额。按重量时是百分比计算后的可分摊金额
|
||||
* @param orders 该提单下的订单
|
||||
* @param byWeight true 按订单重量占比,false 按订单数量均分
|
||||
* @return 与订单顺序一致的分摊金额
|
||||
*/
|
||||
private static List<BigDecimal> split(BigDecimal price, List<SrvBillAirAllocOrder> orders, boolean byWeight)
|
||||
{
|
||||
BigDecimal total = price.setScale(2, RoundingMode.HALF_UP);
|
||||
int count = orders.size();
|
||||
List<BigDecimal> shares = new ArrayList<>(count);
|
||||
if (!byWeight)
|
||||
{
|
||||
BigDecimal each = total.divide(BigDecimal.valueOf(count), 2, RoundingMode.DOWN);
|
||||
BigDecimal used = ZERO;
|
||||
for (int i = 0; i < count - 1; i++)
|
||||
{
|
||||
shares.add(each);
|
||||
used = used.add(each);
|
||||
}
|
||||
shares.add(total.subtract(used));
|
||||
return shares;
|
||||
}
|
||||
BigDecimal sum = totalWeight(orders);
|
||||
int last = count - 1;
|
||||
for (int i = count - 1; i >= 0; i--)
|
||||
{
|
||||
if (weight(orders.get(i)).signum() > 0)
|
||||
{
|
||||
last = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BigDecimal used = ZERO;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
if (i == last)
|
||||
{
|
||||
shares.add(null);
|
||||
continue;
|
||||
}
|
||||
BigDecimal share = total.multiply(weight(orders.get(i))).divide(sum, 2, RoundingMode.DOWN);
|
||||
shares.add(share);
|
||||
used = used.add(share);
|
||||
}
|
||||
shares.set(last, total.subtract(used));
|
||||
return shares;
|
||||
}
|
||||
|
||||
private static BigDecimal totalWeight(List<SrvBillAirAllocOrder> orders)
|
||||
{
|
||||
BigDecimal sum = ZERO;
|
||||
for (SrvBillAirAllocOrder order : orders)
|
||||
{
|
||||
sum = sum.add(weight(order));
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
private static BigDecimal weight(SrvBillAirAllocOrder order)
|
||||
{
|
||||
return order.getChargeWeight() == null ? ZERO : order.getChargeWeight();
|
||||
}
|
||||
|
||||
private static List<SrvBillAirAllocFee> dedupe(List<SrvBillAirAllocFee> fees)
|
||||
{
|
||||
Map<Long, SrvBillAirAllocFee> unique = new LinkedHashMap<>();
|
||||
if (fees != null)
|
||||
{
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
if (fee != null && fee.getId() != null)
|
||||
{
|
||||
unique.putIfAbsent(fee.getId(), fee);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<>(unique.values());
|
||||
}
|
||||
|
||||
private static List<Long> feeIds(List<SrvBillAirAllocFee> fees)
|
||||
{
|
||||
List<Long> ids = new ArrayList<>();
|
||||
for (SrvBillAirAllocFee fee : fees)
|
||||
{
|
||||
ids.add(fee.getId());
|
||||
}
|
||||
return ids;
|
||||
}
|
||||
|
||||
private static String blankName(SrvBillAirAllocFee fee)
|
||||
{
|
||||
if (fee.getFeeName() != null && !fee.getFeeName().isBlank())
|
||||
{
|
||||
return fee.getFeeName().trim();
|
||||
}
|
||||
return "提单费用";
|
||||
}
|
||||
|
||||
private static String remark(SrvBillAirAllocFee fee)
|
||||
{
|
||||
String dim = DIM_WEIGHT.equals(fee.getAllocDim()) ? "重量" : "订单";
|
||||
return "提单" + fee.getBillCode() + "按" + dim + "分摊";
|
||||
}
|
||||
}
|
||||
+129
-1
@@ -22,6 +22,7 @@ import com.bms.price.airbill.domain.SrvBillAirFee;
|
||||
import com.bms.price.airbill.domain.SrvBillAirFeeLog;
|
||||
import com.bms.price.airbill.domain.SrvBillAirFeeSave;
|
||||
import com.bms.price.domain.PrcSurcharge;
|
||||
import com.bms.price.mapper.PrcPayBillFeeMapper;
|
||||
import com.bms.price.mapper.SrvBillAirFeeMapper;
|
||||
import com.bms.price.mapper.SrvBillAirMapper;
|
||||
import com.bms.price.service.IPrcSurchargeService;
|
||||
@@ -42,11 +43,18 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
|
||||
private static final String STATUS_DICT = "bill_fee_status";
|
||||
|
||||
private static final String STATUS_ALLOCATED = "1";
|
||||
|
||||
private static final String STATUS_CONFIRMED = "3";
|
||||
|
||||
private static final String CURRENCY_DICT = "bms_currency";
|
||||
|
||||
@Autowired
|
||||
private SrvBillAirFeeMapper feeMapper;
|
||||
|
||||
@Autowired
|
||||
private PrcPayBillFeeMapper payBillFeeMapper;
|
||||
|
||||
@Autowired
|
||||
private IPrcSurchargeService surchargeService;
|
||||
|
||||
@@ -121,6 +129,10 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
{
|
||||
throw new ServiceException("费用已删除或不属于该提单");
|
||||
}
|
||||
if (locked(current))
|
||||
{
|
||||
throw new ServiceException("已分摊或已确定的费用不能删除,请使用作废");
|
||||
}
|
||||
int rows = feeMapper.deleteFee(current.getId(), billCode, operator.account, now);
|
||||
if (rows > 0)
|
||||
{
|
||||
@@ -143,6 +155,10 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
{
|
||||
throw new ServiceException("费用已删除或不属于该提单");
|
||||
}
|
||||
if (locked(current))
|
||||
{
|
||||
throw new ServiceException("已分摊或已确定的费用不能修改");
|
||||
}
|
||||
SrvBillAirFee next = normalize(incoming, levelLabels, allocLabels, dimLabels, currencyLabels);
|
||||
next.setBillFeeStatus(current.getBillFeeStatus() == null || current.getBillFeeStatus().isBlank() ? "0" : current.getBillFeeStatus());
|
||||
Map<String, String> feeNames = feeNames(current, next);
|
||||
@@ -187,11 +203,90 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
return "已保存:新增 " + inserted + " 条,修改 " + updated + " 条,删除 " + removed + " 条";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String confirm(String billCode, Long feeId)
|
||||
{
|
||||
String code = requireBill(billCode);
|
||||
if (feeId == null)
|
||||
{
|
||||
throw new ServiceException("请选择要确定的费用");
|
||||
}
|
||||
SrvBillAirFee current = liveFee(feeId, code);
|
||||
if (current == null)
|
||||
{
|
||||
throw new ServiceException("费用已删除或不属于该提单");
|
||||
}
|
||||
if (!STATUS_ALLOCATED.equals(current.getBillFeeStatus()))
|
||||
{
|
||||
throw new ServiceException("只有已分摊的费用可以确定");
|
||||
}
|
||||
Operator operator = operator();
|
||||
Date now = DateUtils.getNowDate();
|
||||
if (feeMapper.confirmFee(feeId, code, operator.account, now) != 1)
|
||||
{
|
||||
throw new ServiceException("费用状态已变化,请刷新后再确定");
|
||||
}
|
||||
writePlainLog(code, feeId, SrvBillAirFeeLog.CONFIRM, "确定费用", operator, now);
|
||||
return "费用已确定";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String voidFee(String billCode, Long feeId)
|
||||
{
|
||||
String code = requireBill(billCode);
|
||||
if (feeId == null)
|
||||
{
|
||||
throw new ServiceException("请选择要作废的费用");
|
||||
}
|
||||
SrvBillAirFee current = liveFee(feeId, code);
|
||||
if (current == null)
|
||||
{
|
||||
throw new ServiceException("费用已删除或不属于该提单");
|
||||
}
|
||||
if (!locked(current))
|
||||
{
|
||||
throw new ServiceException("只有已分摊或已确定的费用可以作废");
|
||||
}
|
||||
String billedOrderNo = payBillFeeMapper.selectBilledOrderNo(feeId);
|
||||
if (billedOrderNo != null)
|
||||
{
|
||||
String orderNo = billedOrderNo.trim();
|
||||
if (orderNo.isEmpty())
|
||||
{
|
||||
orderNo = "未知订单";
|
||||
}
|
||||
throw new ServiceException("该费用存在单笔或多笔订单已出账单-如:" + orderNo + ",不可作废");
|
||||
}
|
||||
Operator operator = operator();
|
||||
Date now = DateUtils.getNowDate();
|
||||
payBillFeeMapper.markLadingFeeDeleted(feeId);
|
||||
if (feeMapper.voidFee(feeId, code, operator.account, now) != 1)
|
||||
{
|
||||
throw new ServiceException("费用状态已变化,请刷新后再作废");
|
||||
}
|
||||
Map<String, String> levelLabels = dictLabels(LEVEL_DICT, "费用阶段");
|
||||
Map<String, String> allocLabels = dictLabels(ALLOC_DICT, "是否分摊");
|
||||
Map<String, String> dimLabels = dictLabels(ALLOC_DIM_DICT, "分摊维度");
|
||||
Map<String, String> statusLabels = dictLabels(STATUS_DICT, "费用状态");
|
||||
Map<String, String> currencyLabels = dictLabels(CURRENCY_DICT, "币种");
|
||||
writeLog(code, feeId, SrvBillAirFeeLog.VOID, current, null, feeNames(current, null),
|
||||
levelLabels, allocLabels, dimLabels, statusLabels, currencyLabels, operator, now);
|
||||
return "费用已作废";
|
||||
}
|
||||
|
||||
private SrvBillAirFee liveFee(Long id, String billCode)
|
||||
{
|
||||
return feeMapper.selectLive(id, billCode);
|
||||
}
|
||||
|
||||
private static boolean locked(SrvBillAirFee fee)
|
||||
{
|
||||
String status = fee == null ? "" : text(fee.getBillFeeStatus());
|
||||
return STATUS_ALLOCATED.equals(status) || STATUS_CONFIRMED.equals(status);
|
||||
}
|
||||
|
||||
private SrvBillAirFee normalize(SrvBillAirFee raw, Map<String, String> levelLabels,
|
||||
Map<String, String> allocLabels, Map<String, String> dimLabels, Map<String, String> currencyLabels)
|
||||
{
|
||||
@@ -270,6 +365,22 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
return fee;
|
||||
}
|
||||
|
||||
/**
|
||||
* 费用日志组装
|
||||
* @param billCode
|
||||
* @param feeId
|
||||
* @param operation
|
||||
* @param before
|
||||
* @param after
|
||||
* @param feeLabels
|
||||
* @param levelLabels
|
||||
* @param allocLabels
|
||||
* @param dimLabels
|
||||
* @param statusLabels
|
||||
* @param currencyLabels
|
||||
* @param operator
|
||||
* @param now
|
||||
*/
|
||||
private void writeLog(String billCode, Long feeId, String operation, SrvBillAirFee before, SrvBillAirFee after,
|
||||
Map<String, String> feeLabels, Map<String, String> levelLabels, Map<String, String> allocLabels,
|
||||
Map<String, String> dimLabels, Map<String, String> statusLabels, Map<String, String> currencyLabels, Operator operator, Date now)
|
||||
@@ -287,6 +398,21 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
feeMapper.insertLog(log);
|
||||
}
|
||||
|
||||
/** 确定费用不比较字段,更改前和更改后都留空。 */
|
||||
private void writePlainLog(String billCode, Long feeId, String operation, String summary, Operator operator, Date now)
|
||||
{
|
||||
SrvBillAirFeeLog log = new SrvBillAirFeeLog();
|
||||
log.setBillCode(billCode);
|
||||
log.setFeeId(feeId);
|
||||
log.setOperationType(operation);
|
||||
log.setSummary(summary);
|
||||
log.setChangeContent("[]");
|
||||
log.setCreateBy(operator.account);
|
||||
log.setCreateByName(operator.name);
|
||||
log.setCreateTime(now);
|
||||
feeMapper.insertLog(log);
|
||||
}
|
||||
|
||||
private static List<SrvBillAirFeeLog.FieldChange> diff(SrvBillAirFee before, SrvBillAirFee after,
|
||||
Map<String, String> feeLabels, Map<String, String> levelLabels, Map<String, String> allocLabels,
|
||||
Map<String, String> dimLabels, Map<String, String> statusLabels, Map<String, String> currencyLabels)
|
||||
@@ -323,7 +449,9 @@ public class SrvBillAirFeeServiceImpl implements ISrvBillAirFeeService
|
||||
private static String summary(String operation, List<SrvBillAirFeeLog.FieldChange> changes)
|
||||
{
|
||||
String action = SrvBillAirFeeLog.INSERT.equals(operation) ? "新增费用"
|
||||
: SrvBillAirFeeLog.DELETE.equals(operation) ? "删除费用" : "修改费用";
|
||||
: SrvBillAirFeeLog.DELETE.equals(operation) ? "删除费用"
|
||||
: SrvBillAirFeeLog.CONFIRM.equals(operation) ? "确定费用"
|
||||
: SrvBillAirFeeLog.VOID.equals(operation) ? "作废费用" : "修改费用";
|
||||
StringBuilder text = new StringBuilder(action);
|
||||
for (SrvBillAirFeeLog.FieldChange change : changes)
|
||||
{
|
||||
|
||||
@@ -11,7 +11,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="feeType" column="fee_type" />
|
||||
<result property="feeName" column="fee_name" />
|
||||
<result property="scId" column="sc_id" />
|
||||
<result property="feeLevel" column="fee_level" />
|
||||
<result property="amount" column="amount" />
|
||||
<result property="feeSource" column="fee_source" />
|
||||
<result property="currency" column="currency" />
|
||||
<result property="roundMode" column="round_mode" />
|
||||
<result property="remark" column="remark" />
|
||||
@@ -21,8 +23,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
</resultMap>
|
||||
|
||||
<select id="selectByBillId" parameterType="String" resultMap="PrcPayBillFeeResult">
|
||||
select fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark,
|
||||
source_id, is_deleted, create_time
|
||||
select fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, fee_level, amount, currency, round_mode, remark,
|
||||
fee_source, source_id, is_deleted, create_time
|
||||
from prc_pay_bill_fee
|
||||
where bill_id = #{billId}
|
||||
and is_deleted = '0'
|
||||
@@ -31,25 +33,46 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
|
||||
<insert id="insertPrcPayBillFee" parameterType="PrcPayBillFee">
|
||||
insert into prc_pay_bill_fee (
|
||||
fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark,
|
||||
source_id, is_deleted, create_time
|
||||
fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, fee_level, amount, currency, round_mode, remark,
|
||||
fee_source, source_id, is_deleted, create_time
|
||||
) values (
|
||||
#{feeId}, #{billId}, #{payBillId}, #{feeType}, #{feeName}, #{scId}, #{amount}, #{currency}, #{roundMode}, #{remark},
|
||||
#{sourceId}, ifnull(#{isDeleted}, '0'), sysdate()
|
||||
#{feeId}, #{billId}, #{payBillId}, #{feeType}, #{feeName}, #{scId}, #{feeLevel}, #{amount}, #{currency}, #{roundMode}, #{remark},
|
||||
ifnull(#{feeSource}, 'CALC'), #{sourceId}, ifnull(#{isDeleted}, '0'), sysdate()
|
||||
)
|
||||
</insert>
|
||||
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
insert into prc_pay_bill_fee (
|
||||
fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, amount, currency, round_mode, remark,
|
||||
source_id, is_deleted, create_time
|
||||
fee_id, bill_id, pay_bill_id, fee_type, fee_name, sc_id, fee_level, amount, currency, round_mode, remark,
|
||||
fee_source, source_id, is_deleted, create_time
|
||||
) values
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(#{item.feeId}, #{item.billId}, #{item.payBillId}, #{item.feeType}, #{item.feeName}, #{item.scId}, #{item.amount},
|
||||
#{item.currency}, #{item.roundMode}, #{item.remark}, #{item.sourceId}, ifnull(#{item.isDeleted}, '0'), sysdate())
|
||||
(#{item.feeId}, #{item.billId}, #{item.payBillId}, #{item.feeType}, #{item.feeName}, #{item.scId}, #{item.feeLevel},
|
||||
#{item.amount}, #{item.currency}, #{item.roundMode}, #{item.remark}, ifnull(#{item.feeSource}, 'CALC'),
|
||||
#{item.sourceId}, ifnull(#{item.isDeleted}, '0'), sysdate())
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="selectBilledOrderNo" resultType="String">
|
||||
select e.order_no
|
||||
from prc_pay_bill_fee f
|
||||
inner join prc_order_bill_ext e on e.bill_id = f.bill_id
|
||||
where f.fee_source = 'LADING'
|
||||
and f.sc_id = #{feeId}
|
||||
and ifnull(f.is_deleted, '0') = '0'
|
||||
and e.is_meet = 1
|
||||
order by e.order_no
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<update id="markLadingFeeDeleted">
|
||||
update prc_pay_bill_fee
|
||||
set is_deleted = '1'
|
||||
where fee_source = 'LADING'
|
||||
and sc_id = #{feeId}
|
||||
and ifnull(is_deleted, '0') = '0'
|
||||
</update>
|
||||
|
||||
<delete id="deleteByBillId" parameterType="String">
|
||||
delete from prc_pay_bill_fee
|
||||
where bill_id = #{billId}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bms.price.mapper.SrvBillAirAllocMapper">
|
||||
|
||||
<select id="selectPendingFees" resultType="com.bms.price.airbill.domain.SrvBillAirAllocFee">
|
||||
select f.id, f.bill_code as billCode, a.guid as ladingId, f.fee_level as feeLevel,
|
||||
f.bill_fee_status as billFeeStatus, sc.sc_name as feeName, f.price, f.currency,
|
||||
f.alloc_dim as allocDim
|
||||
from srv_bill_air_fee f
|
||||
left join srv_bill_air a on a.bill_code = f.bill_code
|
||||
left join prc_surcharge sc on sc.sc_id = f.fee_type and ifnull(sc.is_del, '0') = '0'
|
||||
where f.del_flag = '0'
|
||||
and f.alloc_flag = '1'
|
||||
and f.bill_fee_status = '0'
|
||||
and f.bill_code in
|
||||
<foreach collection="billCodes" item="code" open="(" separator="," close=")">#{code}</foreach>
|
||||
order by f.bill_code, f.id
|
||||
</select>
|
||||
|
||||
<select id="selectLadingWeight" resultType="com.bms.price.airbill.domain.SrvBillAirAllocFee">
|
||||
select a.bill_code as billCode, a.actual_weight as actualWeight, fl.band_box_weight as bandBoxWeight
|
||||
from srv_bill_air a
|
||||
left join srv_bill_air_flight fl on fl.bill_code = a.bill_code
|
||||
where a.bill_code in
|
||||
<foreach collection="billCodes" item="code" open="(" separator="," close=")">#{code}</foreach>
|
||||
</select>
|
||||
|
||||
<select id="selectOrders" resultType="com.bms.price.airbill.domain.SrvBillAirAllocOrder">
|
||||
select trim(e.air_no_old) as billCode, e.order_no as orderNo, e.bill_id as billId,
|
||||
case
|
||||
when ifnull(b.charge_weight, 0) > 0 then b.charge_weight
|
||||
when ifnull(b.actual_weight, 0) > 0 then b.actual_weight
|
||||
when ifnull(b.receive_weight, 0) > 0 then b.receive_weight
|
||||
else 0
|
||||
end as chargeWeight
|
||||
from prc_order_bill_ext e
|
||||
inner join prc_order_bill b on b.bill_id = e.bill_id
|
||||
where trim(e.air_no_old) in
|
||||
<foreach collection="billCodes" item="code" open="(" separator="," close=")">#{code}</foreach>
|
||||
order by e.air_no_old, e.order_no, e.bill_id
|
||||
</select>
|
||||
|
||||
<select id="selectPayBills" resultType="com.bms.price.domain.PrcPayBill">
|
||||
select bill_id as billId, pay_bill_id as payBillId
|
||||
from prc_pay_bill
|
||||
where bill_id in
|
||||
<foreach collection="billIds" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</select>
|
||||
|
||||
<update id="markAllocated">
|
||||
update srv_bill_air_fee
|
||||
set bill_fee_status = '1',
|
||||
update_by = #{updateBy},
|
||||
update_time = #{updateTime}
|
||||
where del_flag = '0'
|
||||
and alloc_flag = '1'
|
||||
and bill_fee_status = '0'
|
||||
and id in
|
||||
<foreach collection="ids" item="id" open="(" separator="," close=")">#{id}</foreach>
|
||||
</update>
|
||||
</mapper>
|
||||
@@ -12,6 +12,7 @@
|
||||
left join prc_surcharge sc on sc.sc_id = f.fee_type and ifnull(sc.is_del, '0') = '0'
|
||||
where f.bill_code = #{billCode}
|
||||
and f.del_flag = '0'
|
||||
and ifnull(f.bill_fee_status, '0') <> '2'
|
||||
order by f.id
|
||||
</select>
|
||||
|
||||
@@ -26,6 +27,7 @@
|
||||
where f.id = #{id}
|
||||
and f.bill_code = #{billCode}
|
||||
and f.del_flag = '0'
|
||||
and ifnull(f.bill_fee_status, '0') <> '2'
|
||||
</select>
|
||||
|
||||
<insert id="insertFee" useGeneratedKeys="true" keyProperty="id">
|
||||
@@ -52,6 +54,30 @@
|
||||
where id = #{id}
|
||||
and bill_code = #{billCode}
|
||||
and del_flag = '0'
|
||||
and ifnull(bill_fee_status, '0') not in ('1', '3')
|
||||
</update>
|
||||
|
||||
<update id="confirmFee">
|
||||
update srv_bill_air_fee
|
||||
set bill_fee_status = '3',
|
||||
update_by = #{updateBy},
|
||||
update_time = #{updateTime}
|
||||
where id = #{id}
|
||||
and bill_code = #{billCode}
|
||||
and del_flag = '0'
|
||||
and bill_fee_status = '1'
|
||||
</update>
|
||||
|
||||
<update id="voidFee">
|
||||
update srv_bill_air_fee
|
||||
set del_flag = '1',
|
||||
bill_fee_status = '2',
|
||||
update_by = #{updateBy},
|
||||
update_time = #{updateTime}
|
||||
where id = #{id}
|
||||
and bill_code = #{billCode}
|
||||
and del_flag = '0'
|
||||
and bill_fee_status in ('1', '3')
|
||||
</update>
|
||||
|
||||
<update id="deleteFee">
|
||||
@@ -62,6 +88,7 @@
|
||||
where id = #{id}
|
||||
and bill_code = #{billCode}
|
||||
and del_flag = '0'
|
||||
and ifnull(bill_fee_status, '0') not in ('1', '3')
|
||||
</update>
|
||||
|
||||
<insert id="insertLog" useGeneratedKeys="true" keyProperty="logId">
|
||||
|
||||
Reference in New Issue
Block a user