localizer
ljw 2025-10-31 16:38:43 +08:00
parent ff2df428fd
commit 15607cc37f
12 changed files with 448 additions and 109 deletions

View File

@ -0,0 +1,20 @@
package com.njzscloud.supervisory.order.contant;
import com.njzscloud.common.core.ienum.DictStr;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* change_price_type
*
*/
@Getter
@RequiredArgsConstructor
public enum ChangePriceType implements DictStr {
GOODS("goods", "产品"),
SERVICE_FEE_PRICE("serviceFeePrice", "服务费价格"),
WEIGHT("weight", "磅重"),
;
private final String val;
private final String txt;
}

View File

@ -12,6 +12,7 @@ import com.njzscloud.supervisory.order.pojo.result.OrderCertificateResult;
import com.njzscloud.supervisory.order.pojo.result.OrderPagingResult;
import com.njzscloud.supervisory.order.pojo.result.TrainBillResult;
import com.njzscloud.supervisory.order.service.OrderInfoService;
import com.njzscloud.supervisory.sys.log.annotation.Log;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@ -257,4 +258,14 @@ public class OrderInfoController {
orderInfoService.export(response, param);
}
/**
*
*/
@Log("订单改价")
@PostMapping("/change_price")
public R<?> changePrice(@RequestBody ChangePriceParam param) {
orderInfoService.changePrice(param);
return R.success();
}
}

View File

@ -166,6 +166,12 @@ public class OrderExpenseItemsEntity {
@TableLogic
private Boolean deleted;
/**
* ;
*/
private BigDecimal changeMoney;
}

View File

@ -297,4 +297,9 @@ public class OrderInfoEntity {
private LocalDateTime refundTime;
/**
* ;
*/
private BigDecimal changeMoney;
}

View File

@ -0,0 +1,51 @@
package com.njzscloud.supervisory.order.pojo.param;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
import java.util.List;
/**
*
*/
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class ChangePriceParam {
/**
* Id
*/
private Long orderId;
/**
* goods serviceFeePrice weight
*/
private String changePriceType;
/**
*
*/
List<OrderItemsParams> serviceFeeList;
/**
* Id
*/
private Long goodsId;
/**
* ;
*/
private BigDecimal unitPrice;
/**
* ;
*/
private Integer roughWeight;
}

View File

@ -0,0 +1,26 @@
package com.njzscloud.supervisory.order.pojo.param;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Getter
@Setter
@ToString
@Accessors(chain = true)
public class OrderItemsParams {
/**
* id
*/
private Long id;
/**
* ;
*/
private BigDecimal unitPrice;
}

View File

@ -31,6 +31,16 @@ public class OrderPagingSearchParam {
private Long stationId;
private CheckStatus checkStatus;
/**
* ID
*/
private Long transCompanyId;
/**
* ID
*/
private Long goodsId;
/**
*
*/

View File

@ -19,6 +19,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
/**
@ -35,12 +36,15 @@ public class OrderGoodsService extends ServiceImpl<OrderGoodsMapper, OrderGoodsE
*
*/
@Transactional(rollbackFor = Exception.class)
public long add(Long goodsId) {
public long add(Long goodsId, BigDecimal unitPrice) {
GoodsInfoEntity goodsInfoEntity = goodsInfoService.getById(goodsId);
Assert.notNull(goodsInfoEntity, () -> Exceptions.clierr("产品不存在"));
goodsInfoEntity.setId(null);
OrderGoodsEntity orderGoodsEntity = BeanUtil.copyProperties(goodsInfoEntity, OrderGoodsEntity.class)
.setOriginGoodsId(goodsId);
if (null != unitPrice) {
orderGoodsEntity.setUnitPrice(unitPrice);
}
this.save(orderGoodsEntity);
return orderGoodsEntity.getId();
}

View File

@ -32,7 +32,6 @@ import com.njzscloud.supervisory.biz.service.BizWarnService;
import com.njzscloud.supervisory.biz.service.TruckLocationTrackService;
import com.njzscloud.supervisory.constant.Constant;
import com.njzscloud.supervisory.device.pojo.entity.DeviceLocalizerEntity;
import com.njzscloud.supervisory.device.service.DeviceInfoService;
import com.njzscloud.supervisory.expense.contant.BillingType;
import com.njzscloud.supervisory.expense.contant.ExpenseItemCategory;
import com.njzscloud.supervisory.expense.contant.GoodsScope;
@ -47,10 +46,7 @@ import com.njzscloud.supervisory.money.service.MoneyAccountService;
import com.njzscloud.supervisory.money.service.MoneyChangeDetailService;
import com.njzscloud.supervisory.order.contant.*;
import com.njzscloud.supervisory.order.mapper.OrderInfoMapper;
import com.njzscloud.supervisory.order.pojo.entity.OrderCargoPlaceEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderExpenseItemsEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderGoodsEntity;
import com.njzscloud.supervisory.order.pojo.entity.OrderInfoEntity;
import com.njzscloud.supervisory.order.pojo.entity.*;
import com.njzscloud.supervisory.order.pojo.param.*;
import com.njzscloud.supervisory.order.pojo.result.*;
import com.njzscloud.supervisory.order.utils.FileUtil;
@ -119,7 +115,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
Long goodsId = addOrderInfoParam.getGoodsId();
Long orderGoodsId = orderGoodsService.add(goodsId);
Long orderGoodsId = orderGoodsService.add(goodsId, null);
OrderInfoEntity orderInfoEntity = BeanUtil.copyProperties(addOrderInfoParam, OrderInfoEntity.class)
.setSn(orderSn == null ? SnUtil.next() : orderSn)
@ -191,6 +187,8 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
String phone = orderPagingSearchParam.getPhone();
LocalDateTime startTime = orderPagingSearchParam.getStartTime();
LocalDateTime endTime = orderPagingSearchParam.getEndTime();
Long transCompanyId = orderPagingSearchParam.getTransCompanyId();
Long goodsId = orderPagingSearchParam.getGoodsId();
Page<OrderPagingResult> page = pageParam.toPage();
QueryWrapper<OrderPagingResult> ew = Wrappers.<OrderPagingResult>query()
.like(StrUtil.isNotBlank(sn), "a.sn", sn)
@ -198,7 +196,9 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
.like(StrUtil.isNotBlank(nickname), "a.contacts", nickname)
.like(StrUtil.isNotBlank(phone), "a.phone", phone)
.ge(startTime != null, "a.create_time", startTime)
.le(endTime != null, "a.create_time", endTime);
.le(endTime != null, "a.create_time", endTime)
.eq(null != transCompanyId, "a.trans_company_id", transCompanyId)
.eq(null != goodsId, "c.origin_goods_id", goodsId);
OrderViewType type = orderPagingSearchParam.getType();
Assert.notNull(type, () -> Exceptions.clierr("订单类型不能为空"));
switch (type) {
@ -729,7 +729,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
if (MoneyWay.IN.getVal().equals(entity.getMoneyWay())) {
// 入场付费无称重,不需要更新付费项
// 处理公司支付
handleCompanyPay(orderInfo, Boolean.TRUE);
handleCompanyPay(orderInfo, Boolean.TRUE, new BigDecimal("0"), Boolean.FALSE);
}
this.updateById(new OrderInfoEntity()
@ -775,64 +775,70 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
});
}
public void handleCompanyPay(OrderInfoEntity orderInfo, Boolean isIn) {
public boolean handleCompanyPay(OrderInfoEntity orderInfo, Boolean isIn, BigDecimal changeMoney, Boolean isChange) {
PaymentContextResult ctx = paymentContext(orderInfo.getId());
if (!SettlementWay.CASH.getVal().equals(ctx.getSettlementWay())) {
/*// 验证资金账户信息
if (ctx.getCompanyAccountId() == null) {
throw Exceptions.clierr("公司资金账户不存在");
}
// 根据结算方式判断是否需要检查余额
if (SettlementWay.BALANCE.getVal().equals(ctx.getSettlementWay())) {
// 余额结算:允许本次支付后余额为负数,但仅限于余额首次变为负数
if (ctx.getCompanyBalance() == null) {
ctx.setCompanyBalance(BigDecimal.ZERO);
}
if (ctx.getCompanyBalance().compareTo(BigDecimal.ZERO) < 0) {
// 已经是负数,禁止再次支付
throw Exceptions.clierr("公司账户余额不足");
}
}*/
BigDecimal oldBalance = ctx.getCompanyBalance();
BigDecimal newBalance = oldBalance.subtract(ctx.getSettleMoney());
// 更新账户余额(支持负数余额)
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
.setId(ctx.getCompanyAccountId())
.setMoney(newBalance);
moneyAccountService.updateById(companyAccount);
// 记录资金变动明细
MoneyChangeDetailEntity changeDetail = new MoneyChangeDetailEntity()
.setCompanyId(ctx.getTransCompanyId())
.setOrderId(orderInfo.getId())
.setMoneyAccountId(companyAccount.getId())
.setOldMoney(oldBalance)
.setDelta(ctx.getSettleMoney().negate()) // 扣减为负数
.setNewMoney(newBalance)
.setMoneyChangeCategory(MoneyChangeCategory.DingDanKouKuan)
.setMemo("订单支付扣款,订单号:" + orderInfo.getSn() + ",结算方式:" + ctx.getSettlementWay());
moneyChangeDetailService.save(changeDetail);
log.info("公司账户扣减成功用户ID{},扣减金额:{},余额:{} -> {},结算方式:{}",
ctx.getCompanyUserId(), ctx.getSettleMoney(), oldBalance, newBalance, ctx.getSettlementWay());
// 更新订单支付状态为已支付
this.updateById(new OrderInfoEntity()
.setId(orderInfo.getId())
.setPaymentStatus(PaymentStatus.YiZhiFu)
.setOrderStatus(OrderStatus.YiWanCheng)
.setSettlementWay(ctx.getSettlementWay())
.setPayTime(LocalDateTime.now())
);
if (!isIn) {
DeviceInfoService.open(orderInfo.getSn());
}
BigDecimal payMoney = ctx.getSettleMoney();
if (isChange) {
payMoney = changeMoney;
}
if (payMoney != null && payMoney.compareTo(BigDecimal.ZERO) > 0) {
if (!SettlementWay.CASH.getVal().equals(ctx.getSettlementWay())) {
BigDecimal oldBalance = ctx.getCompanyBalance();
BigDecimal newBalance = oldBalance.subtract(payMoney);
// 更新账户余额(支持负数余额)
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
.setId(ctx.getCompanyAccountId())
.setMoney(newBalance);
moneyAccountService.updateById(companyAccount);
// 记录资金变动明细
MoneyChangeDetailEntity changeDetail = new MoneyChangeDetailEntity()
.setCompanyId(ctx.getTransCompanyId())
.setOrderId(orderInfo.getId())
.setMoneyAccountId(companyAccount.getId())
.setOldMoney(oldBalance)
.setDelta(payMoney.negate()) // 扣减为负数
.setNewMoney(newBalance)
.setMoneyChangeCategory(MoneyChangeCategory.DingDanKouKuan)
.setMemo("订单支付扣款,订单号:" + orderInfo.getSn() + ",结算方式:" + ctx.getSettlementWay());
moneyChangeDetailService.save(changeDetail);
log.info("公司账户扣减成功用户ID{},扣减金额:{},余额:{} -> {},结算方式:{}",
ctx.getCompanyUserId(), payMoney, oldBalance, newBalance, ctx.getSettlementWay());
// 更新订单支付状态为已支付
OrderInfoEntity entity = new OrderInfoEntity();
entity.setId(orderInfo.getId());
entity.setPaymentStatus(PaymentStatus.YiZhiFu);
entity.setSettlementWay(ctx.getSettlementWay());
entity.setPayTime(LocalDateTime.now());
if (!isIn) {
entity.setOrderStatus(OrderStatus.YiWanCheng);
this.updateById(entity);
return true;
} else {
this.updateById(entity);
}
}
} else {
// 如果支付金额为0则直接改状态
// 更新订单支付状态为已支付
OrderInfoEntity entity = new OrderInfoEntity();
entity.setId(orderInfo.getId());
entity.setSettlementWay(ctx.getSettlementWay());
entity.setPaymentStatus(PaymentStatus.YiZhiFu);
entity.setPayTime(LocalDateTime.now());
if (!isIn) {
entity.setOrderStatus(OrderStatus.YiWanCheng);
this.updateById(entity);
return true;
} else {
this.updateById(entity);
}
}
return false;
}
@Transactional(rollbackFor = Exception.class)
@ -899,7 +905,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
dto.setReason("订单取消");
// 获取支付上下文
PaymentContextResult ctx = this.paymentContext(orderId);
paymentService.refund(dto, ctx);
paymentService.refund(dto, ctx, Boolean.FALSE);
this.lambdaUpdate()
.eq(OrderInfoEntity::getId, orderId)
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.YiTuiKuan)
@ -1070,13 +1076,10 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
// 出厂付费
if (MoneyWay.OUT.getVal().equals(entity.getMoneyWay())) {
// 计算费用,出厂付费可能需要称重,需要更新付费项
updateOrderItems(orderInfoEntity.getId(), settleWeight);
updateOrderItems(orderInfoEntity.getId(), settleWeight, Boolean.FALSE);
// 扣费
handleCompanyPay(orderInfoEntity, Boolean.FALSE);
return false;
} else {
return true;
return handleCompanyPay(orderInfoEntity, Boolean.FALSE, new BigDecimal("0"), Boolean.FALSE);
}
} finally {
@ -1085,6 +1088,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
String gpsId = truckInfo.getGps();
stopTrack(gpsId);
}
return false;
}
/**
@ -1138,7 +1142,7 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
*
* @param item
*/
private void calculateAndSetItemMoney(OrderExpenseItemsEntity item) {
private void calculateAndSetItemMoney(OrderExpenseItemsEntity item, Boolean isChange) {
// 计算总金额
BigDecimal totalMoney = calculateItemTotalMoney(item);
@ -1146,8 +1150,11 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
BigDecimal discount = item.getDiscountMoney() == null ? BigDecimal.ZERO : item.getDiscountMoney();
BigDecimal revise = item.getReviseMoney() == null ? BigDecimal.ZERO : item.getReviseMoney();
BigDecimal settle = totalMoney.add(discount).add(revise);
item.setTotalMoney(totalMoney).setSettleMoney(settle);
if (isChange) {
item.setChangeMoney(settle);
} else {
item.setTotalMoney(totalMoney).setSettleMoney(settle);
}
}
/**
@ -1156,50 +1163,59 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
* @param orderId ID
* @param items
*/
private void updateOrderTotalMoney(Long orderId, List<OrderExpenseItemsEntity> items) {
private void updateOrderTotalMoney(Long orderId, List<OrderExpenseItemsEntity> items, Boolean isChange) {
BigDecimal totalDiscountMoney = BigDecimal.ZERO;
BigDecimal totalReviseMoney = BigDecimal.ZERO;
BigDecimal totalSettleMoney = BigDecimal.ZERO;
BigDecimal totalTotalMoney = BigDecimal.ZERO;
BigDecimal totalChangeMoney = BigDecimal.ZERO;
// 汇总各项金额
for (OrderExpenseItemsEntity item : items) {
BigDecimal discount = item.getDiscountMoney() == null ? BigDecimal.ZERO : item.getDiscountMoney();
BigDecimal revise = item.getReviseMoney() == null ? BigDecimal.ZERO : item.getReviseMoney();
BigDecimal change = item.getChangeMoney() == null ? BigDecimal.ZERO : item.getChangeMoney();
totalDiscountMoney = totalDiscountMoney.add(discount);
totalReviseMoney = totalReviseMoney.add(revise);
totalSettleMoney = totalSettleMoney.add(item.getSettleMoney());
totalTotalMoney = totalTotalMoney.add(item.getTotalMoney());
totalChangeMoney = totalChangeMoney.add(change);
}
// 更新订单表的优惠金额; 手动修正金额;结算金额;总金额;
this.lambdaUpdate()
.eq(OrderInfoEntity::getId, orderId)
.set(OrderInfoEntity::getDiscountMoney, totalDiscountMoney)
.set(OrderInfoEntity::getReviseMoney, totalReviseMoney)
.set(OrderInfoEntity::getSettleMoney, totalSettleMoney)
.set(OrderInfoEntity::getTotalMoney, totalTotalMoney)
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.WeiZhiFu)
.update();
if (isChange) {
this.lambdaUpdate()
.eq(OrderInfoEntity::getId, orderId)
.set(OrderInfoEntity::getChangeMoney, totalChangeMoney)
.update();
} else {
this.lambdaUpdate()
.eq(OrderInfoEntity::getId, orderId)
.set(OrderInfoEntity::getDiscountMoney, totalDiscountMoney)
.set(OrderInfoEntity::getReviseMoney, totalReviseMoney)
.set(OrderInfoEntity::getSettleMoney, totalSettleMoney)
.set(OrderInfoEntity::getTotalMoney, totalTotalMoney)
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.WeiZhiFu)
.update();
}
}
/**
*
*
* @param orderId ID
* @param orderId ID
* @param items
*/
private void calculateItemsAndUpdateOrder(Long orderId, List<OrderExpenseItemsEntity> items) {
// 计算各付费项金额
for (OrderExpenseItemsEntity item : items) {
calculateAndSetItemMoney(item);
calculateAndSetItemMoney(item, Boolean.FALSE);
}
// 更新订单汇总金额
updateOrderTotalMoney(orderId, items);
updateOrderTotalMoney(orderId, items, Boolean.FALSE);
}
public void updateOrderItems(Long orderId, Integer settleWeight) {
public void updateOrderItems(Long orderId, Integer settleWeight, Boolean isChange) {
List<OrderExpenseItemsEntity> extraItems = orderExpenseItemsService.list(Wrappers.lambdaQuery(OrderExpenseItemsEntity.class)
.eq(OrderExpenseItemsEntity::getOrderId, orderId)
.eq(OrderExpenseItemsEntity::getDeleted, Boolean.FALSE));
@ -1208,14 +1224,14 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
for (OrderExpenseItemsEntity item : extraItems) {
item.setQuantity(MoneyStrategy.Che.getVal().equals(item.getMoneyStrategy()) ? 1 : settleWeight);
// 重新计算金额totalMoney、settleMoney
calculateAndSetItemMoney(item);
calculateAndSetItemMoney(item, isChange);
}
// 批量更新付费项包含quantity和所有金额字段
orderExpenseItemsService.updateBatchById(extraItems);
// 汇总并更新订单总金额
updateOrderTotalMoney(orderId, extraItems);
updateOrderTotalMoney(orderId, extraItems, isChange);
}
/**
@ -1230,20 +1246,17 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
// 第一步:复制产品信息为付费项记录
BigDecimal unitPrice = orderGoods.getUnitPrice();
OrderExpenseItemsEntity productItem = null;
if (unitPrice != null && unitPrice.compareTo(BigDecimal.ZERO) > 0) {
productItem = new OrderExpenseItemsEntity()
.setExpenseItemCategory(ExpenseItemCategory.ChanPin.getVal())
.setOrderId(orderId)
.setOriginExpenseItemId(orderGoods.getId())
.setExpenseItemName(orderGoods.getGoodsName())
.setUnitPrice(unitPrice)
.setUnit(orderGoods.getUnit())
.setMoneyStrategy(orderGoods.getMoneyStrategy() == null ? null : orderGoods.getMoneyStrategy().getVal())
.setMoneyConfigId(orderGoods.getMoneyConfigId())
.setTaxRate(orderGoods.getTaxRate())
.setQuantity((orderGoods.getMoneyStrategy() == MoneyStrategy.Che) ? 1 : 0);
}
OrderExpenseItemsEntity productItem = new OrderExpenseItemsEntity()
.setExpenseItemCategory(ExpenseItemCategory.ChanPin.getVal())
.setOrderId(orderId)
.setOriginExpenseItemId(orderGoods.getId())
.setExpenseItemName(orderGoods.getGoodsName())
.setUnitPrice(unitPrice)
.setUnit(orderGoods.getUnit())
.setMoneyStrategy(orderGoods.getMoneyStrategy() == null ? null : orderGoods.getMoneyStrategy().getVal())
.setMoneyConfigId(orderGoods.getMoneyConfigId())
.setTaxRate(orderGoods.getTaxRate())
.setQuantity((orderGoods.getMoneyStrategy() == MoneyStrategy.Che) ? 1 : 0);
// 第二步:读取启用的付费项配置,并按 scope 过滤
@ -1556,4 +1569,193 @@ public class OrderInfoService extends ServiceImpl<OrderInfoMapper, OrderInfoEnti
test_thread.start();
}
/**
* 退
* 退
*/
@Transactional(rollbackFor = Exception.class)
public void changePrice(ChangePriceParam param) {
OrderInfoEntity order = this.getById(param.getOrderId());
Assert.notNull(order, () -> Exceptions.clierr("订单不存在"));
if (ChangePriceType.GOODS.getVal().equals(param.getChangePriceType())) {
// 变更产品与单价单价如果为空当0计算依然不加入订单付费项
Assert.isFalse(null == param.getGoodsId(), () -> Exceptions.clierr("产品ID不可为空"));
// 删除原来的订单产品数据
Assert.isFalse(null == order.getGoodsId(), () -> Exceptions.clierr("订单商品信息不存在"));
OrderGoodsEntity orderGoodsEntity = orderGoodsService.getById(order.getGoodsId());
String oldMoneyWay = orderGoodsEntity.getMoneyWay();
orderGoodsService.removeById(order.getGoodsId());
// 添加新的订单产品
Long orderGoodsId = orderGoodsService.add(param.getGoodsId(), param.getUnitPrice());
// 更新订单表goodsId
this.updateById(new OrderInfoEntity()
.setId(param.getOrderId())
.setGoodsId(orderGoodsId)
);
// 因更改产品可能影响到订单服务费的付费项,所以直接删除原有订单付费项,重新匹配
orderExpenseItemsService.remove(Wrappers.<OrderExpenseItemsEntity>lambdaQuery()
.in(OrderExpenseItemsEntity::getOrderId, param.getOrderId()));
// 新增订单付费项
OrderGoodsEntity entity = orderGoodsService.getById(orderGoodsId);
String newMoneyWay = entity.getMoneyWay();
OrderExpenseItemsEntity productItem = new OrderExpenseItemsEntity()
.setExpenseItemCategory(ExpenseItemCategory.ChanPin.getVal())
.setOrderId(param.getOrderId())
.setOriginExpenseItemId(orderGoodsId)
.setExpenseItemName(entity.getGoodsName())
.setUnitPrice(param.getUnitPrice())
.setUnit(entity.getUnit())
.setMoneyStrategy(entity.getMoneyStrategy() == null ? null : entity.getMoneyStrategy().getVal())
.setMoneyConfigId(entity.getMoneyConfigId())
.setTaxRate(entity.getTaxRate())
.setQuantity((entity.getMoneyStrategy() == MoneyStrategy.Che) ? 1 : 0);
orderExpenseItemsService.save(productItem);
// 第二步:读取启用的付费项配置,并按 scope 过滤
List<ExpenseItemsConfigEntity> configs = expenseItemsConfigService.list(Wrappers.<ExpenseItemsConfigEntity>lambdaQuery()
.eq(ExpenseItemsConfigEntity::getCanuse, Boolean.TRUE)
.eq(ExpenseItemsConfigEntity::getDeleted, Boolean.FALSE));
Long transCompanyId = order.getTransCompanyId();
Long goodsId = entity.getOriginGoodsId();
List<OrderExpenseItemsEntity> extraItems = configs.stream()
.filter(cfg -> {
Scope scope = cfg.getScope();
GoodsScope goodsScope = cfg.getGoodsScope();
List<String> companyIds = cfg.getCompanyIds();
List<String> goodsIds = cfg.getGoodsIds();
boolean isComTrue = companyIds != null && transCompanyId != null && companyIds.contains(String.valueOf(transCompanyId));
boolean isGoodsTrue = goodsIds != null && goodsId != null && goodsIds.contains(String.valueOf(goodsId));
if (scope == Scope.ALL && goodsScope == GoodsScope.ALL) return true;
if (scope == Scope.ALL && goodsScope == GoodsScope.GOODS) {
return isGoodsTrue;
}
if (scope == Scope.CUSTOMER && goodsScope == GoodsScope.ALL) {
return isComTrue;
}
if (scope == Scope.CUSTOMER && goodsScope == GoodsScope.GOODS) {
return isComTrue && isGoodsTrue;
}
return false;
})
// 复制配置为订单付费项(数量口径与产品一致:按车=1否则=settleWeight
.map(cfg -> new OrderExpenseItemsEntity()
.setExpenseItemCategory(cfg.getExpenseItemCategory())
.setOrderId(param.getOrderId())
.setOriginExpenseItemId(cfg.getId())
.setExpenseItemName(cfg.getExpenseItemName())
.setUnitPrice(cfg.getUnitPrice())
.setUnit(cfg.getUnit())
.setMoneyStrategy(cfg.getMoneyStrategy())
.setMoneyConfigId(cfg.getMoneyConfigId())
.setScope(cfg.getScope())
.setBizObj(cfg.getBizObj())
.setCompanyIds(cfg.getCompanyIds())
.setGoodsScope(cfg.getGoodsScope())
.setGoodsIds(cfg.getGoodsIds())
.setBillingType(cfg.getBillingType())
.setBasicWeight(cfg.getBasicWeight())
.setBasicPrice(cfg.getBasicPrice())
.setEveryWeight(cfg.getEveryWeight())
.setEveryPrice(cfg.getEveryPrice())
.setTaxRate(cfg.getTaxRate())
.setQuantity(MoneyStrategy.Che.getVal().equals(cfg.getMoneyStrategy()) ? 1 : 0))
.collect(Collectors.toList());
// 第三步:合并集合并计算金额,然后批量落库
if (productItem != null) extraItems.add(0, productItem);
if (extraItems.isEmpty()) {
return;
}
// 批量保存付费项
orderExpenseItemsService.saveBatch(extraItems);
// 退款
if (MoneyWay.IN.getVal().equals(oldMoneyWay) && MoneyWay.OUT.getVal().equals(newMoneyWay)) {
// 如果从进场付费改成了出厂付费,则全部退款,在出厂时会重新称重计算费用,否则重新计费,并多退少补
if (PaymentStatus.YiZhiFu.getVal().equals(order.getPaymentStatus().getVal())) {
RefundRequestDto dto = new RefundRequestDto();
dto.setOrderId(order.getId());
dto.setRefundAmount(order.getSettleMoney());
dto.setOutTradeNo(order.getOutTradeNo());
dto.setReason("订单改价,进场->出厂");
// 获取支付上下文
PaymentContextResult ctx = this.paymentContext(order.getId());
paymentService.refund(dto, ctx, Boolean.TRUE);
this.lambdaUpdate()
.eq(OrderInfoEntity::getId, order.getId())
.set(OrderInfoEntity::getSettleMoney, new BigDecimal("0"))
.set(OrderInfoEntity::getTotalMoney, new BigDecimal("0"))
.set(OrderInfoEntity::getPaymentStatus, PaymentStatus.WeiZhiFu)
.update();
}
} else if (MoneyWay.IN.getVal().equals(oldMoneyWay) && MoneyWay.IN.getVal().equals(newMoneyWay)) {
// 重新计算,多退少补
reSettlement(order);
}
// 更新产品不用考虑出厂问题,在称重时会重新计算费用并付费
} else if (ChangePriceType.SERVICE_FEE_PRICE.getVal().equals(param.getChangePriceType())) {
// 变更服务费单价
if (null != param.getServiceFeeList() && param.getServiceFeeList().size() > 0) {
List<OrderItemsParams> params = param.getServiceFeeList();
for (OrderItemsParams itemsParam : params) {
OrderExpenseItemsEntity itemsEntity = new OrderExpenseItemsEntity();
itemsEntity.setId(itemsParam.getId());
itemsEntity.setUnitPrice(itemsParam.getUnitPrice());
orderExpenseItemsService.updateById(itemsEntity);
}
// 重新计算,多退少补
reSettlement(order);
} else {
throw Exceptions.clierr("清运服务费不可为空");
}
} else if (ChangePriceType.WEIGHT.getVal().equals(param.getChangePriceType())) {
// 变更磅重,勘料在出厂之前,出厂会重新称重,所以只需要改毛重,不需要更新净重,
// 也不需要退款,按车不需要退款,按吨不可能在进场就付费
Assert.isFalse(null == param.getRoughWeight(), () -> Exceptions.clierr("毛重不可为空"));
OrderCarInOutEntity carInOutEntity = new OrderCarInOutEntity();
carInOutEntity.setId(order.getCarInOutId());
carInOutEntity.setRoughWeight(param.getRoughWeight());
orderCarInOutService.updateById(carInOutEntity);
}
}
/**
* 退
*/
public void reSettlement(OrderInfoEntity order) {
// 计算费用
updateOrderItems(order.getId(), 0, Boolean.TRUE);
// 多退少补 获取改价后的订单信息
OrderInfoEntity newOrder = this.getById(order.getId());
BigDecimal changeMoney = newOrder.getChangeMoney() == null ? BigDecimal.ZERO : newOrder.getChangeMoney();
BigDecimal settleMoney = newOrder.getSettleMoney() == null ? BigDecimal.ZERO : newOrder.getSettleMoney();
// 只有当订单已支付时,才需要多退少补
if (PaymentStatus.YiZhiFu.getVal().equals(order.getPaymentStatus().getVal())) {
// 比较改价后金额和结算金额
if (changeMoney.compareTo(settleMoney) > 0) {
// 改价后金额大于结算金额,需要付款(多付)
BigDecimal payAmount = changeMoney.subtract(settleMoney);
// 处理公司支付
handleCompanyPay(newOrder, Boolean.TRUE, payAmount, Boolean.TRUE);
// TODO: 微信支付暂不处理
// paymentService.pay(order, payAmount);
} else if (changeMoney.compareTo(settleMoney) < 0) {
// 改价后金额小于结算金额,需要退款(少补)
BigDecimal refundAmount = settleMoney.subtract(changeMoney);
// 调用退款接口
RefundRequestDto dto = new RefundRequestDto();
dto.setOrderId(order.getId());
dto.setRefundAmount(refundAmount);
dto.setOutTradeNo(order.getOutTradeNo());
dto.setReason("订单改价,进场->进场,退差额");
// 获取支付上下文
PaymentContextResult ctx = this.paymentContext(order.getId());
paymentService.refund(dto, ctx, Boolean.TRUE);
}
// 如果金额相等,则不需要处理
}
}
}

View File

@ -269,7 +269,7 @@ public class PaymentController {
throw Exceptions.clierr("退款金额总和不能超过订单已结算金额");
}
refundRequest.setOutTradeNo(orderInfo.getOutTradeNo());
paymentService.refund(refundRequest, ctx);
paymentService.refund(refundRequest, ctx, Boolean.FALSE);
if (SettlementWay.MONTH.getVal().equals(ctx.getOiPayWay()) || SettlementWay.BALANCE.getVal().equals(ctx.getOiPayWay())) {
// 更新订单状态为已退款
orderInfoService.lambdaUpdate()

View File

@ -11,6 +11,6 @@ public interface PaymentService {
/**
* 退
*/
void refund(RefundRequestDto refundRequest, PaymentContextResult ctx);
void refund(RefundRequestDto refundRequest, PaymentContextResult ctx, Boolean isChange);
}

View File

@ -35,14 +35,18 @@ public class PaymentServiceImpl implements PaymentService {
/**
* 退
*/
public void refund(RefundRequestDto refundRequest, PaymentContextResult ctx) {
public void refund(RefundRequestDto refundRequest, PaymentContextResult ctx, Boolean isChange) {
try {
// 根据支付方式处理退款
if (SettlementWay.CASH.getVal().equals(ctx.getOiPayWay())) {
//微信退款 生成退款单号
String orderSn = IdUtil.getSnowflake(0, 0).nextIdStr();
int money = ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue();
// 微信退全款
int money = ctx.getSettleMoney().multiply(new BigDecimal("100")).intValue();
// 如果是改价,不一定退全额
if (isChange) {
money = refundRequest.getRefundAmount().multiply(new BigDecimal("100")).intValue();
}
String notifyUrl = properties.getRefundNotifyUrl();
wechatPayService.refund(refundRequest.getOutTradeNo(), orderSn, money, money, notifyUrl);
} else if (SettlementWay.MONTH.getVal().equals(ctx.getOiPayWay()) || SettlementWay.BALANCE.getVal().equals(ctx.getOiPayWay())) {