localizer
parent
dbc31ab6e6
commit
a2bea2e4ca
|
|
@ -2,7 +2,9 @@ package com.njzscloud.supervisory;
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
|
||||||
|
@EnableScheduling
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
public class Main {
|
public class Main {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import java.util.List;
|
||||||
@Setter
|
@Setter
|
||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@TableName("expense_items_config")
|
@TableName(value = "expense_items_config", autoResultMap = true)
|
||||||
public class ExpenseItemsConfigEntity {
|
public class ExpenseItemsConfigEntity {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,12 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import com.njzscloud.supervisory.money.pojo.entity.MoneyBillEntity;
|
import com.njzscloud.supervisory.money.pojo.entity.MoneyBillEntity;
|
||||||
|
import com.njzscloud.supervisory.money.pojo.result.MoneyBillResult;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.apache.ibatis.annotations.Param;
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对账单
|
* 对账单
|
||||||
*/
|
*/
|
||||||
|
|
@ -18,4 +21,9 @@ public interface MoneyBillMapper extends BaseMapper<MoneyBillEntity> {
|
||||||
*/
|
*/
|
||||||
IPage<MoneyBillEntity> selectMoneyBillWithNames(Page<MoneyBillEntity> page, @Param("entity") MoneyBillEntity entity);
|
IPage<MoneyBillEntity> selectMoneyBillWithNames(Page<MoneyBillEntity> page, @Param("entity") MoneyBillEntity entity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询对账单列表(关联用户、公司、订单信息)
|
||||||
|
*/
|
||||||
|
List<MoneyBillResult> selectMoneyBillList(@Param("entity") MoneyBillResult entity);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ public class MoneyBillEntity {
|
||||||
*/
|
*/
|
||||||
private Integer totalWeight;
|
private Integer totalWeight;
|
||||||
|
|
||||||
|
private Integer carCount;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠金额
|
* 优惠金额
|
||||||
*/
|
*/
|
||||||
|
|
@ -131,9 +133,8 @@ public class MoneyBillEntity {
|
||||||
private String companyName;
|
private String companyName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产品名称(扩展字段,不存储到数据库)
|
* 产品名称
|
||||||
*/
|
*/
|
||||||
@TableField(exist = false)
|
|
||||||
private String goodsName;
|
private String goodsName;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.njzscloud.supervisory.money.pojo.result;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class MoneyBillResult {
|
||||||
|
private Long userId;
|
||||||
|
private Long transCompanyId;
|
||||||
|
private String companyName;
|
||||||
|
private String nickname;
|
||||||
|
private String expenseItemName;
|
||||||
|
private String moneyStrategy;
|
||||||
|
private Long originExpenseItemId;
|
||||||
|
private Long orderId;
|
||||||
|
private BigDecimal discountMoney;
|
||||||
|
private BigDecimal settleMoney;
|
||||||
|
private Integer quantity;
|
||||||
|
/**
|
||||||
|
* 开始时间(用于时间范围查询)
|
||||||
|
*/
|
||||||
|
private LocalDateTime startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 结束时间(用于时间范围查询)
|
||||||
|
*/
|
||||||
|
private LocalDateTime endTime;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
package com.njzscloud.supervisory.money.quartz;
|
||||||
|
|
||||||
|
import com.njzscloud.supervisory.goods.contant.MoneyStrategy;
|
||||||
|
import com.njzscloud.supervisory.money.mapper.MoneyBillMapper;
|
||||||
|
import com.njzscloud.supervisory.money.pojo.entity.MoneyBillEntity;
|
||||||
|
import com.njzscloud.supervisory.money.pojo.result.MoneyBillResult;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.compress.utils.Lists;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class MoneyBillQuartz {
|
||||||
|
|
||||||
|
private final MoneyBillMapper moneyBillMapper;
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0/1 * * * ?")//每3分钟一次
|
||||||
|
public void syncAssetsDiscover() {
|
||||||
|
generateMoneyBill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateMoneyBill() {
|
||||||
|
// 计算上个月的时间范围
|
||||||
|
LocalDateTime now = LocalDateTime.now();
|
||||||
|
LocalDateTime lastMonthStart = now.minusMonths(1).withDayOfMonth(1).with(LocalTime.MIN); // 上个月1号0点0分0秒
|
||||||
|
LocalDateTime lastMonthEnd = now.minusMonths(1).withDayOfMonth(now.minusMonths(1).toLocalDate().lengthOfMonth())
|
||||||
|
.with(LocalTime.MAX); // 上个月月末23点59分59秒
|
||||||
|
|
||||||
|
// 创建查询条件
|
||||||
|
MoneyBillResult queryCondition = new MoneyBillResult();
|
||||||
|
queryCondition.setStartTime(lastMonthStart);
|
||||||
|
queryCondition.setEndTime(lastMonthEnd);
|
||||||
|
|
||||||
|
// 执行查询
|
||||||
|
List<MoneyBillResult> billResults = moneyBillMapper.selectMoneyBillList(queryCondition);
|
||||||
|
|
||||||
|
log.info("查询到上个月账单数据 {} 条", billResults.size());
|
||||||
|
|
||||||
|
if (billResults.size() > 0) {
|
||||||
|
// 先按transCompanyId分组,再按originExpenseItemId分组
|
||||||
|
Map<Long, Map<Long, List<MoneyBillResult>>> groupedResults = billResults.stream()
|
||||||
|
.collect(Collectors.groupingBy(
|
||||||
|
MoneyBillResult::getTransCompanyId,
|
||||||
|
Collectors.groupingBy(MoneyBillResult::getOriginExpenseItemId)
|
||||||
|
));
|
||||||
|
|
||||||
|
log.info("按transCompanyId和originExpenseItemId二级分组后共 {} 个公司分组", groupedResults.size());
|
||||||
|
|
||||||
|
// 处理每个公司分组的数据
|
||||||
|
List<MoneyBillEntity> entityList = Lists.newArrayList();
|
||||||
|
for (Map.Entry<Long, Map<Long, List<MoneyBillResult>>> companyEntry : groupedResults.entrySet()) {
|
||||||
|
Long transCompanyId = companyEntry.getKey();
|
||||||
|
Map<Long, List<MoneyBillResult>> companyGroupResults = companyEntry.getValue();
|
||||||
|
|
||||||
|
log.info("transCompanyId: {}, 该公司包含 {} 个originExpenseItemId分组",
|
||||||
|
transCompanyId, companyGroupResults.size());
|
||||||
|
|
||||||
|
// 处理该公司下的每个originExpenseItemId分组
|
||||||
|
for (Map.Entry<Long, List<MoneyBillResult>> itemEntry : companyGroupResults.entrySet()) {
|
||||||
|
Long originExpenseItemId = itemEntry.getKey();
|
||||||
|
List<MoneyBillResult> itemGroupResults = itemEntry.getValue();
|
||||||
|
|
||||||
|
log.info("transCompanyId: {}, originExpenseItemId: {}, 该分组包含 {} 条数据",
|
||||||
|
transCompanyId, originExpenseItemId, itemGroupResults.size());
|
||||||
|
|
||||||
|
// 这里可以根据业务需求处理每个分组的数据
|
||||||
|
// 例如:计算总金额、创建MoneyBillEntity等
|
||||||
|
MoneyBillEntity entity = new MoneyBillEntity();
|
||||||
|
entity.setStationId(transCompanyId);
|
||||||
|
entity.setStartTime(lastMonthStart.toLocalDate());
|
||||||
|
entity.setEndTime(lastMonthEnd.toLocalDate());
|
||||||
|
entity.setGoodsId(originExpenseItemId);
|
||||||
|
|
||||||
|
// 1. 订单数量:通过orderId分组,条数就是订单数
|
||||||
|
long orderCount = itemGroupResults.stream()
|
||||||
|
.map(MoneyBillResult::getOrderId)
|
||||||
|
.distinct()
|
||||||
|
.count();
|
||||||
|
entity.setOrderCount((int) orderCount);
|
||||||
|
|
||||||
|
// 2. 总质量:quantity求和,条件是计费策略不等于"车"
|
||||||
|
int totalWeight = itemGroupResults.stream()
|
||||||
|
.filter(result -> !MoneyStrategy.Che.getVal().equals(result.getMoneyStrategy()))
|
||||||
|
.mapToInt(MoneyBillResult::getQuantity)
|
||||||
|
.sum();
|
||||||
|
entity.setTotalWeight(totalWeight);
|
||||||
|
|
||||||
|
// 3. 车数:quantity求和,条件是计费策略等于"车"
|
||||||
|
int totalCars = itemGroupResults.stream()
|
||||||
|
.filter(result -> MoneyStrategy.Che.getVal().equals(result.getMoneyStrategy()))
|
||||||
|
.mapToInt(MoneyBillResult::getQuantity)
|
||||||
|
.sum();
|
||||||
|
entity.setCarCount(totalCars);
|
||||||
|
|
||||||
|
// 4. 优惠金额:discountMoney求和,可能是负数
|
||||||
|
BigDecimal totalDiscountMoney = itemGroupResults.stream()
|
||||||
|
.map(MoneyBillResult::getDiscountMoney)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
entity.setDiscountMoney(totalDiscountMoney);
|
||||||
|
|
||||||
|
// 5. 账单金额:settleMoney求和,可能是负数
|
||||||
|
BigDecimal totalSettleMoney = itemGroupResults.stream()
|
||||||
|
.map(MoneyBillResult::getSettleMoney)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
entity.setTotalMoney(totalSettleMoney);
|
||||||
|
|
||||||
|
// 设置其他基本信息(取第一条记录的信息)
|
||||||
|
MoneyBillResult firstResult = itemGroupResults.get(0);
|
||||||
|
entity.setUserId(firstResult.getUserId());
|
||||||
|
entity.setGoodsName(firstResult.getExpenseItemName());
|
||||||
|
entityList.add(entity);
|
||||||
|
log.info("生成账单实体: transCompanyId={}, originExpenseItemId={}, 订单数={}, 总质量={}, 车数={}, 优惠金额={}, 账单金额={}",
|
||||||
|
transCompanyId, originExpenseItemId, orderCount, totalWeight, totalCars, totalDiscountMoney, totalSettleMoney);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 账单入库
|
||||||
|
moneyBillMapper.insert(entityList);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.njzscloud.supervisory.order.contant;
|
||||||
|
|
||||||
|
import com.njzscloud.common.core.ienum.DictStr;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字典代码:payment_status
|
||||||
|
* 字典名称:支付状态
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public enum SettlementWay implements DictStr {
|
||||||
|
MONTH("month", "月结"),
|
||||||
|
BALANCE("balance", "余额")
|
||||||
|
;
|
||||||
|
private final String val;
|
||||||
|
private final String txt;
|
||||||
|
}
|
||||||
|
|
@ -16,6 +16,7 @@ import com.njzscloud.supervisory.money.service.MoneyChangeDetailService;
|
||||||
import com.njzscloud.supervisory.order.contant.OrderStatus;
|
import com.njzscloud.supervisory.order.contant.OrderStatus;
|
||||||
import com.njzscloud.supervisory.order.contant.PaymentStatus;
|
import com.njzscloud.supervisory.order.contant.PaymentStatus;
|
||||||
import com.njzscloud.supervisory.order.contant.PaymentWay;
|
import com.njzscloud.supervisory.order.contant.PaymentWay;
|
||||||
|
import com.njzscloud.supervisory.order.contant.SettlementWay;
|
||||||
import com.njzscloud.supervisory.order.pojo.dto.*;
|
import com.njzscloud.supervisory.order.pojo.dto.*;
|
||||||
import com.njzscloud.supervisory.order.pojo.entity.OrderExpenseItemsEntity;
|
import com.njzscloud.supervisory.order.pojo.entity.OrderExpenseItemsEntity;
|
||||||
import com.njzscloud.supervisory.order.pojo.entity.OrderInfoEntity;
|
import com.njzscloud.supervisory.order.pojo.entity.OrderInfoEntity;
|
||||||
|
|
@ -129,9 +130,15 @@ public class PaymentController {
|
||||||
if (ctx.getTransCompanyId() == null || ctx.getCompanyUserId() == null) {
|
if (ctx.getTransCompanyId() == null || ctx.getCompanyUserId() == null) {
|
||||||
throw Exceptions.clierr("订单未关联清运公司,无法公司支付");
|
throw Exceptions.clierr("订单未关联清运公司,无法公司支付");
|
||||||
}
|
}
|
||||||
if (ctx.getCompanyBalance() == null || ctx.getCompanyBalance().compareTo(dbTotalAmount) < 0) {
|
|
||||||
throw Exceptions.clierr("公司账户余额不足");
|
// 根据结算方式判断是否需要检查余额
|
||||||
|
if (SettlementWay.BALANCE.getVal().equals(ctx.getSettlementWay())) {
|
||||||
|
// 余额结算:需要检查余额是否充足
|
||||||
|
if (ctx.getCompanyBalance() == null || ctx.getCompanyBalance().compareTo(dbTotalAmount) < 0) {
|
||||||
|
throw Exceptions.clierr("公司账户余额不足");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// 月结方式:不需要检查余额,允许余额为负数
|
||||||
|
|
||||||
// 直接扣减公司账户余额
|
// 直接扣减公司账户余额
|
||||||
deductCompanyBalance(ctx, dbTotalAmount, paymentParam.getOrderId());
|
deductCompanyBalance(ctx, dbTotalAmount, paymentParam.getOrderId());
|
||||||
|
|
@ -189,7 +196,7 @@ public class PaymentController {
|
||||||
BigDecimal oldBalance = ctx.getCompanyBalance();
|
BigDecimal oldBalance = ctx.getCompanyBalance();
|
||||||
BigDecimal newBalance = oldBalance.subtract(amount);
|
BigDecimal newBalance = oldBalance.subtract(amount);
|
||||||
|
|
||||||
// 更新账户余额
|
// 更新账户余额(支持负数余额)
|
||||||
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
|
MoneyAccountEntity companyAccount = new MoneyAccountEntity()
|
||||||
.setId(ctx.getCompanyAccountId())
|
.setId(ctx.getCompanyAccountId())
|
||||||
.setMoney(newBalance);
|
.setMoney(newBalance);
|
||||||
|
|
@ -205,12 +212,12 @@ public class PaymentController {
|
||||||
.setDelta(amount.negate()) // 扣减为负数
|
.setDelta(amount.negate()) // 扣减为负数
|
||||||
.setNewMoney(newBalance)
|
.setNewMoney(newBalance)
|
||||||
.setMoneyChangeCategory(MoneyChangeCategory.DingDanKouKuan)
|
.setMoneyChangeCategory(MoneyChangeCategory.DingDanKouKuan)
|
||||||
.setMemo("订单支付扣款,订单ID:" + orderId);
|
.setMemo("订单支付扣款,订单ID:" + orderId + ",结算方式:" + ctx.getSettlementWay());
|
||||||
|
|
||||||
moneyChangeDetailService.save(changeDetail);
|
moneyChangeDetailService.save(changeDetail);
|
||||||
|
|
||||||
log.info("公司账户扣减成功,用户ID:{},扣减金额:{},余额:{} -> {}",
|
log.info("公司账户扣减成功,用户ID:{},扣减金额:{},余额:{} -> {},结算方式:{}",
|
||||||
ctx.getCompanyUserId(), amount, oldBalance, newBalance);
|
ctx.getCompanyUserId(), amount, oldBalance, newBalance, ctx.getSettlementWay());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ public class PaymentContextResult {
|
||||||
private Long companyAccountId;
|
private Long companyAccountId;
|
||||||
private BigDecimal companyBalance;
|
private BigDecimal companyBalance;
|
||||||
|
|
||||||
|
private String settlementWay;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,11 @@
|
||||||
mb.deleted,
|
mb.deleted,
|
||||||
u.nickname,
|
u.nickname,
|
||||||
bc.company_name as companyName,
|
bc.company_name as companyName,
|
||||||
og.goods_name as goodsName
|
mb.goods_name as goodsName,
|
||||||
|
mb.car_count
|
||||||
FROM money_bill mb
|
FROM money_bill mb
|
||||||
LEFT JOIN sys_user u ON mb.user_id = u.id
|
LEFT JOIN sys_user u ON mb.user_id = u.id
|
||||||
LEFT JOIN biz_company bc ON mb.station_id = bc.id AND bc.station = 1
|
LEFT JOIN biz_company bc ON mb.station_id = bc.id AND bc.station = 1
|
||||||
LEFT JOIN order_goods og ON mb.goods_id = og.id
|
|
||||||
<where>
|
<where>
|
||||||
<if test="entity.userId != null">
|
<if test="entity.userId != null">
|
||||||
AND mb.user_id = #{entity.userId}
|
AND mb.user_id = #{entity.userId}
|
||||||
|
|
@ -63,4 +63,32 @@
|
||||||
ORDER BY mb.modify_time DESC
|
ORDER BY mb.modify_time DESC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectMoneyBillList" resultType="com.njzscloud.supervisory.money.pojo.result.MoneyBillResult">
|
||||||
|
SELECT
|
||||||
|
oi.trans_company_id,
|
||||||
|
bc.user_id,
|
||||||
|
bc.company_name,
|
||||||
|
su.nickname,
|
||||||
|
oei.expense_item_name,
|
||||||
|
oei.money_strategy,
|
||||||
|
oei.origin_expense_item_id,
|
||||||
|
oei.order_id,
|
||||||
|
oei.discount_money,
|
||||||
|
oei.settle_money,
|
||||||
|
oei.quantity
|
||||||
|
FROM
|
||||||
|
order_expense_items oei
|
||||||
|
LEFT JOIN order_info oi ON oi.id = oei.order_id
|
||||||
|
LEFT JOIN biz_company bc ON oi.trans_company_id = bc.id
|
||||||
|
LEFT JOIN sys_user su ON bc.user_id = su.id
|
||||||
|
WHERE
|
||||||
|
oi.order_status = 'YiWanCheng'
|
||||||
|
<if test="entity.startTime != null">
|
||||||
|
AND oi.create_time >= #{entity.startTime}
|
||||||
|
</if>
|
||||||
|
<if test="entity.endTime != null">
|
||||||
|
AND oi.create_time <= #{entity.endTime}
|
||||||
|
</if>
|
||||||
|
order by oei.create_time desc
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
@ -197,7 +197,8 @@
|
||||||
a.trans_company_id AS transCompanyId,
|
a.trans_company_id AS transCompanyId,
|
||||||
bc.user_id AS companyUserId,
|
bc.user_id AS companyUserId,
|
||||||
ma1.id AS companyAccountId,
|
ma1.id AS companyAccountId,
|
||||||
ma1.money AS companyBalance
|
ma1.money AS companyBalance,
|
||||||
|
bc.settlement_way
|
||||||
FROM order_info a
|
FROM order_info a
|
||||||
LEFT JOIN biz_company bc ON bc.id = a.trans_company_id
|
LEFT JOIN biz_company bc ON bc.id = a.trans_company_id
|
||||||
LEFT JOIN money_account ma1 ON ma1.user_id = bc.user_id
|
LEFT JOIN money_account ma1 ON ma1.user_id = bc.user_id
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue