diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerController.java b/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerController.java index 3f432be9..3a8439c9 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerController.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerController.java @@ -60,4 +60,11 @@ public class TbCreditBuyerController { tbCreditBuyerService.delete(id); return ResponseEntity.ok().build(); } + + @PostMapping("repayment") + @ApiOperation("还款") + public ResponseEntity repayment(@RequestBody Map params) { + Map data = tbCreditBuyerService.repayment(params); + return ResponseEntity.ok().body(data); + } } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerOrderController.java b/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerOrderController.java index a96e23b5..9ca18496 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerOrderController.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/controller/credit/TbCreditBuyerOrderController.java @@ -1,6 +1,6 @@ package cn.ysk.cashier.controller.credit; -import cn.ysk.cashier.mybatis.entity.TbCreditBuyerOrder; +import cn.ysk.cashier.mybatis.entity.TbCreditPaymentRecord; import cn.ysk.cashier.mybatis.service.TbCreditBuyerOrderService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -12,11 +12,11 @@ import java.util.Map; /** -* 挂账账单 -* -* @author Tankaikai tankaikai@aliyun.com -* @since 2.0 2024-11-20 -*/ + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ @RestController @RequestMapping("/api/credit/buyer-order") @Api(tags = "挂账账单") @@ -27,21 +27,21 @@ public class TbCreditBuyerOrderController { @GetMapping("page") @ApiOperation("分页") - public ResponseEntity page(@RequestParam Map params){ + public ResponseEntity page(@RequestParam Map params) { Map page = tbCreditBuyerOrderService.page(params); return ResponseEntity.ok().body(page); } @PostMapping("pay") @ApiOperation("付款") - public ResponseEntity pay(@RequestBody TbCreditBuyerOrder dto){ - boolean ret = tbCreditBuyerOrderService.save(dto); - return ResponseEntity.ok().body(ret); + public ResponseEntity pay(@RequestBody TbCreditPaymentRecord record) { + tbCreditBuyerOrderService.pay(record); + return ResponseEntity.ok().build(); } @GetMapping("summary") @ApiOperation("统计") - public ResponseEntity summary(@RequestParam Map params){ + public ResponseEntity summary(@RequestParam Map params) { Map data = tbCreditBuyerOrderService.summary(params); return ResponseEntity.ok().body(data); } diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/dto/credit/CreditBuyerOrderDTO.java b/eladmin-system/src/main/java/cn/ysk/cashier/dto/credit/CreditBuyerOrderDTO.java new file mode 100644 index 00000000..0ed9cf5b --- /dev/null +++ b/eladmin-system/src/main/java/cn/ysk/cashier/dto/credit/CreditBuyerOrderDTO.java @@ -0,0 +1,69 @@ +package cn.ysk.cashier.dto.credit; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; + +import java.io.Serializable; +import java.math.BigDecimal; +import java.util.Date; + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Data +public class CreditBuyerOrderDTO implements Serializable { + private static final long serialVersionUID = 1L; + + /** + * id + */ + private Long id; + /** + * 订单id + */ + private Long orderId; + /** + * 挂账人编码 + */ + private String creditBuyerId; + /** + * 应付金额 + */ + private BigDecimal payAmount; + /** + * 已付金额 + */ + private BigDecimal paidAmount; + /** + * 未付金额 + */ + private BigDecimal unpaidAmount; + /** + * 状态 unpaid-未付款 partial-部分支付 paid-已付款 + */ + private String status; + /** + * 最近一次付款时间 + */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date lastPaymentTime; + /** + * 最近一次付款方式 + */ + private String lastPaymentMethod; + /** + * 备注 + */ + private String remark; + /** + * 创建时间 + */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date createTime; +} \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyer.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyer.java index 7ca67722..c4f151db 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyer.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyer.java @@ -48,6 +48,10 @@ public class TbCreditBuyer { * 挂账额度 */ private BigDecimal creditAmount; + /** + * 账户余额 + */ + private BigDecimal accountBalance; /** * 还款方式 total-按总金额还款 order-按订单还款 */ @@ -56,6 +60,10 @@ public class TbCreditBuyer { * 支付方式 */ private String paymentMethod; + /** + * 责任人 + */ + private String responsiblePerson; /** * 备注 */ @@ -69,7 +77,7 @@ public class TbCreditBuyer { /** * 已挂账金额 */ - @TableField(value = "(select sum(unpaid_amount) from view_credit_buyer_order where credit_buyer_id = id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) + @TableField(value = "(select ifnull(sum(unpaid_amount),0) from view_credit_buyer_order where credit_buyer_id = tb_credit_buyer.id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) private BigDecimal owedAmount; /** @@ -81,13 +89,13 @@ public class TbCreditBuyer { /** * 累计挂账金额 */ - @TableField(value = "(select sum(pay_amount) from view_credit_buyer_order where credit_buyer_id = id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) + @TableField(value = "(select ifnull(sum(pay_amount),0) from view_credit_buyer_order where credit_buyer_id = tb_credit_buyer.id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) private BigDecimal accumulateAmount; /** * 适用门店 */ - @TableField(value = "(select shop_name from tb_shop_info where id = shop_id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) + @TableField(value = "(select shop_name from tb_shop_info where id = tb_credit_buyer.shop_id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) private String shopName; public BigDecimal getRemainingAmount() { diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyerOrder.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyerOrder.java index 675c316e..93e6f038 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyerOrder.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditBuyerOrder.java @@ -1,8 +1,8 @@ package cn.ysk.cashier.mybatis.entity; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import lombok.EqualsAndHashCode; @@ -16,46 +16,45 @@ import java.util.Date; * @since 2.0 2024-11-20 */ @Data -@EqualsAndHashCode(callSuper=false) +@EqualsAndHashCode(callSuper = false) @TableName("tb_credit_buyer_order") public class TbCreditBuyerOrder { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** - * id - */ - @TableId(type = IdType.AUTO) - private Long id; - /** - * 订单id - */ - private Long orderId; - /** - * 挂账人编码 - */ - private String creditBuyerId; - /** - * 已付金额 - */ - private BigDecimal paidAmount; - /** - * 未付金额 - */ - private BigDecimal unpaidAmount; - /** - * 状态 unpaid-未付款 paid-已付款 - */ - private String status; - /** - * 最近一次付款时间 - */ - private Date lastPaymentTime; - /** - * 最近一次付款方式 - */ - private String lastPaymentMethod; - /** - * 备注 - */ - private String remark; + /** + * id + */ + @TableId(type = IdType.AUTO) + private Long id; + /** + * 订单id + */ + private Long orderId; + /** + * 挂账人编码 + */ + private String creditBuyerId; + /** + * 已付金额 + */ + private BigDecimal paidAmount; + /** + * 状态 unpaid-未付款 partial-部分支付 paid-已付款 + */ + private String status; + /** + * 最近一次付款时间 + */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private Date lastPaymentTime; + /** + * 最近一次付款方式 + */ + private String lastPaymentMethod; + /** + * 备注 + */ + @TableField(value = "remark", updateStrategy = FieldStrategy.ALWAYS) + private String remark; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditPaymentRecord.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditPaymentRecord.java index 0d161a39..e6c6c097 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditPaymentRecord.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/entity/TbCreditPaymentRecord.java @@ -1,8 +1,10 @@ package cn.ysk.cashier.mybatis.entity; +import com.alibaba.fastjson.annotation.JSONField; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Data; import lombok.EqualsAndHashCode; @@ -49,9 +51,13 @@ public class TbCreditPaymentRecord { /** * 还款时间 */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date paymentTime; /** * 操作时间 */ + @JSONField(format = "yyyy-MM-dd HH:mm:ss") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date createTime; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbCreditBuyerOrderMapper.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbCreditBuyerOrderMapper.java index ff9f0290..1010a72c 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbCreditBuyerOrderMapper.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/mapper/TbCreditBuyerOrderMapper.java @@ -1,9 +1,14 @@ package cn.ysk.cashier.mybatis.mapper; +import cn.ysk.cashier.dto.credit.CreditBuyerOrderDTO; import cn.ysk.cashier.mybatis.entity.TbCreditBuyerOrder; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + /** * 挂账账单 * @@ -12,5 +17,13 @@ import org.apache.ibatis.annotations.Mapper; */ @Mapper public interface TbCreditBuyerOrderMapper extends BaseMapper { - + + List getList(Map params); + long getCount(Map params); + + BigDecimal getSumPaidAmount(Map params); + BigDecimal getSumUnpaidAmount(Map params); + + CreditBuyerOrderDTO getOne(Map params); + } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerOrderService.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerOrderService.java index 1ebcb706..5a96a86f 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerOrderService.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerOrderService.java @@ -1,6 +1,7 @@ package cn.ysk.cashier.mybatis.service; import cn.ysk.cashier.mybatis.entity.TbCreditBuyerOrder; +import cn.ysk.cashier.mybatis.entity.TbCreditPaymentRecord; import com.baomidou.mybatisplus.extension.service.IService; import java.util.Map; @@ -16,4 +17,13 @@ public interface TbCreditBuyerOrderService extends IService Map page(Map params); Map summary(Map params); + void pay(TbCreditPaymentRecord record); + + /** + * 保存挂账账单 + * @param creditBuyerId 挂账人id + * @param orderId 订单id + */ + boolean save(String creditBuyerId, Long orderId); + } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerService.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerService.java index d8842225..32240ac1 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerService.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/TbCreditBuyerService.java @@ -21,4 +21,9 @@ public interface TbCreditBuyerService extends IService { void delete(String id); + TbCreditBuyer getById(String id); + + Map repayment(Map params); + + } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerOrderServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerOrderServiceImpl.java index 7f63f00c..1f0136a9 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerOrderServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerOrderServiceImpl.java @@ -1,12 +1,38 @@ package cn.ysk.cashier.mybatis.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.map.MapProxy; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.StrUtil; +import cn.ysk.cashier.dto.credit.CreditBuyerOrderDTO; +import cn.ysk.cashier.dto.product.PadProductCategoryDTO; +import cn.ysk.cashier.exception.BadRequestException; +import cn.ysk.cashier.mybatis.entity.TbCreditBuyer; import cn.ysk.cashier.mybatis.entity.TbCreditBuyerOrder; +import cn.ysk.cashier.mybatis.entity.TbCreditPaymentRecord; +import cn.ysk.cashier.mybatis.mapper.TbCreditBuyerMapper; import cn.ysk.cashier.mybatis.mapper.TbCreditBuyerOrderMapper; +import cn.ysk.cashier.mybatis.mapper.TbCreditPaymentRecordMapper; +import cn.ysk.cashier.mybatis.service.MpOrderInfoService; import cn.ysk.cashier.mybatis.service.TbCreditBuyerOrderService; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import cn.ysk.cashier.mybatis.service.TbCreditBuyerService; +import cn.ysk.cashier.pojo.order.TbOrderInfo; +import cn.ysk.cashier.utils.PageUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; +import java.math.BigDecimal; +import java.util.Date; +import java.util.HashMap; +import java.util.List; import java.util.Map; /** @@ -18,20 +44,197 @@ import java.util.Map; @Service public class TbCreditBuyerOrderServiceImpl extends ServiceImpl implements TbCreditBuyerOrderService { - public QueryWrapper getWrapper(Map params){ - QueryWrapper wrapper = new QueryWrapper<>(); + @Resource + private TbCreditBuyerService tbCreditBuyerService; + @Resource + private TbCreditBuyerMapper tbCreditBuyerMapper; + @Resource + private TbCreditPaymentRecordMapper tbCreditPaymentRecordMapper; + @Resource + private MpOrderInfoService mpOrderInfoService; - wrapper.orderByDesc("id"); + private LambdaQueryWrapper getWrapper(Map params) { + MapProxy mapProxy = MapProxy.create(params); + String beginDate = mapProxy.getStr("beginDate"); + String endDate = mapProxy.getStr("endDate"); + TbCreditBuyerOrder param = BeanUtil.toBean(params, TbCreditBuyerOrder.class); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.orderByDesc(TbCreditBuyerOrder::getOrderId); return wrapper; } @Override public Map page(Map params) { - return null; + MapProxy mapProxy = MapProxy.create(params); + int pageNum = mapProxy.getInt("page", 1); + int pageSize = mapProxy.getInt("size", 10); + Page page = new Page<>(pageNum, pageSize); + page.addOrder(OrderItem.desc("order_id")); + params.put("page", page); + List list = baseMapper.getList(params); + return PageUtil.toPlusPage(list, Convert.toInt(page.getTotal())); } @Override public Map summary(Map params) { - return null; + long count = baseMapper.getCount(params); + Map data = new HashMap<>(4); + // 总交易笔数 + data.put("count", count); + // 未支付 + params.put("status", "unpaid"); + long unpaidCount = baseMapper.getCount(params); + // 部分支付 + params.put("status", "partial"); + long partialCount = baseMapper.getCount(params); + // 待支付笔数 = 未支付笔数 + 部分支付笔数 + data.put("unpaidCount", unpaidCount + partialCount); + + BigDecimal paidAmount = baseMapper.getSumPaidAmount(params); + BigDecimal unpaidAmount = baseMapper.getSumUnpaidAmount(params); + data.put("paidAmountTotal", paidAmount); + data.put("unpaidAmountTotal", unpaidAmount); + return data; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void pay(TbCreditPaymentRecord record) { + try { + Assert.notNull(record.getCreditBuyerId(), "{}({})不能为空", "挂账人id", "creditBuyerId"); + Assert.notNull(record.getOrderId(), "{}({})不能为空", "订单id", "orderId"); + Assert.notNull(record.getRepaymentAmount(), "{}({})不能为空", "还款金额", "repaymentAmount"); + Assert.notEmpty(record.getPaymentMethod(), "{}({})不能为空", "支付方式", "paymentMethod"); + Assert.notNull(record.getPaymentTime(), "{}({})不能为空", "还款时间", "paymentTime"); + } catch (IllegalArgumentException e) { + throw new BadRequestException(e.getMessage()); + } + TbCreditBuyer creditBuyer = tbCreditBuyerMapper.selectById(record.getCreditBuyerId()); + if (creditBuyer == null) { + throw new BadRequestException("挂账人不存在"); + } + String repaymentMethod = creditBuyer.getRepaymentMethod(); + if (!"order".equals(repaymentMethod)) { + throw new BadRequestException("该挂账人不支持按订单付款"); + } + Map params = new HashMap<>(2); + params.put("creditBuyerId", record.getCreditBuyerId()); + params.put("orderId", record.getOrderId()); + CreditBuyerOrderDTO dto = baseMapper.getOne(params); + if (dto == null) { + throw new BadRequestException("挂账订单不存在"); + } + if ("paid".equals(dto.getStatus())) { + throw new BadRequestException("挂账订单已还清,无需还款"); + } + if (NumberUtil.isLess(record.getRepaymentAmount(), BigDecimal.ZERO)) { + throw new BadRequestException("还款金额不能小于0"); + } + if (NumberUtil.isGreater(record.getRepaymentAmount(), dto.getUnpaidAmount())) { + throw new BadRequestException("还款金额不能大于未支付金额"); + } + TbCreditBuyerOrder entity = BeanUtil.copyProperties(dto, TbCreditBuyerOrder.class); + if (NumberUtil.equals(record.getRepaymentAmount(), dto.getUnpaidAmount())) { + entity.setStatus("paid"); + } else { + entity.setStatus("partial"); + } + entity.setPaidAmount(NumberUtil.add(entity.getPaidAmount(), record.getRepaymentAmount())); + entity.setLastPaymentTime(new Date()); + entity.setLastPaymentMethod(record.getPaymentMethod()); + super.updateById(entity); + record.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + } + + @Override + public boolean save(String creditBuyerId, Long orderId) { + if (StrUtil.isBlank(creditBuyerId)) { + throw new BadRequestException("挂账人id不能为空"); + } + TbCreditBuyer creditBuyer = tbCreditBuyerService.getById(creditBuyerId); + if (creditBuyer == null) { + throw new BadRequestException("挂账人不存在"); + } + Integer delFlag = creditBuyer.getDelFlag(); + if (delFlag != null && delFlag == 1) { + throw new BadRequestException("挂账人已删除"); + } + Integer status = creditBuyer.getStatus(); + if (status != null && status == 0) { + throw new BadRequestException("挂账人已被停用"); + } + TbOrderInfo orderInfo = mpOrderInfoService.getById(orderId); + if (orderInfo == null) { + throw new BadRequestException("订单不存在"); + } + // 账户余额 + BigDecimal accountBalance = creditBuyer.getAccountBalance(); + // 如果有余额的话,从余额里面扣除,没有余额的话,从信用额度里面扣除,余额和信用额度都为0,则不允许挂账,余额+信用额度刚好够支付这笔订单的话需要同时减余额减信用额度 + if (NumberUtil.isGreaterOrEqual(accountBalance, orderInfo.getPayAmount())) { + // 减余额 + creditBuyer.setAccountBalance(NumberUtil.sub(accountBalance, orderInfo.getPayAmount())); + tbCreditBuyerMapper.updateById(creditBuyer); + // 记录还款记录 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(creditBuyerId); + record.setOrderId(orderId); + record.setRepaymentAmount(orderInfo.getPayAmount()); + record.setPaymentMethod("余额支付"); + record.setPaymentTime(new Date()); + record.setRemark("挂账时余额充足,直接从余额扣除"); + record.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + TbCreditBuyerOrder entity = new TbCreditBuyerOrder(); + entity.setCreditBuyerId(creditBuyerId); + entity.setOrderId(orderId); + entity.setPaidAmount(orderInfo.getPayAmount()); + entity.setStatus("paid"); + entity.setLastPaymentTime(new Date()); + entity.setLastPaymentMethod(record.getPaymentMethod()); + entity.setRemark(record.getRemark()); + return super.save(entity); + } + TbCreditBuyerOrder entity = null; + if (NumberUtil.isGreater(accountBalance, BigDecimal.ZERO)) { + // 减余额 + creditBuyer.setAccountBalance(BigDecimal.ZERO); + tbCreditBuyerMapper.updateById(creditBuyer); + // 记录还款记录 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(creditBuyerId); + record.setOrderId(orderId); + record.setRepaymentAmount(accountBalance); + record.setPaymentMethod("余额支付"); + record.setPaymentTime(new Date()); + record.setRemark("挂账时余额不足,先扣除现有余额,其他的从挂账额度中扣除"); + record.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + entity = new TbCreditBuyerOrder(); + entity.setCreditBuyerId(creditBuyerId); + entity.setOrderId(orderId); + entity.setPaidAmount(accountBalance); + entity.setStatus("partial"); + entity.setLastPaymentTime(new Date()); + entity.setLastPaymentMethod(record.getPaymentMethod()); + entity.setRemark(record.getRemark()); + //super.save(entity); + orderInfo.setPayAmount(NumberUtil.sub(orderInfo.getPayAmount(), accountBalance)); + } + // 剩余挂账额度 + BigDecimal remainingAmount = creditBuyer.getRemainingAmount(); + // 验证挂账金额是否大于剩余额度 + boolean greater = NumberUtil.isGreater(orderInfo.getPayAmount(), remainingAmount); + if (greater) { + throw new BadRequestException(StrUtil.format("{}:¥{}不能大于剩余挂账额度({})", "挂账金额", orderInfo.getPayAmount(), remainingAmount)); + } + if (entity == null) { + entity = new TbCreditBuyerOrder(); + entity.setStatus("unpaid"); + entity.setPaidAmount(BigDecimal.ZERO); + entity.setCreditBuyerId(creditBuyerId); + entity.setOrderId(orderId); + } + return super.saveOrUpdate(entity); } } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerServiceImpl.java index c2245f70..10c96535 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditBuyerServiceImpl.java @@ -2,6 +2,7 @@ package cn.ysk.cashier.mybatis.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Validator; @@ -9,9 +10,12 @@ import cn.hutool.core.map.MapProxy; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; +import cn.ysk.cashier.dto.credit.CreditBuyerOrderDTO; import cn.ysk.cashier.exception.BadRequestException; import cn.ysk.cashier.mybatis.entity.TbCreditBuyer; +import cn.ysk.cashier.mybatis.entity.TbCreditBuyerOrder; import cn.ysk.cashier.mybatis.mapper.TbCreditBuyerMapper; +import cn.ysk.cashier.mybatis.mapper.TbCreditBuyerOrderMapper; import cn.ysk.cashier.mybatis.service.TbCreditBuyerService; import cn.ysk.cashier.utils.PageUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -19,10 +23,12 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import javax.annotation.Resource; import java.math.BigDecimal; -import java.util.HashMap; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * 挂账人 @@ -33,6 +39,9 @@ import java.util.Map; @Service public class TbCreditBuyerServiceImpl extends ServiceImpl implements TbCreditBuyerService { + @Resource + private TbCreditBuyerOrderMapper tbCreditBuyerOrderMapper; + private LambdaQueryWrapper getWrapper(Map params) { MapProxy mapProxy = MapProxy.create(params); String keywords = mapProxy.getStr("keywords"); @@ -41,12 +50,13 @@ public class TbCreditBuyerServiceImpl extends ServiceImpl wrapper = Wrappers.lambdaQuery(); wrapper.eq(TbCreditBuyer::getShopId, param.getShopId()); wrapper.eq(StrUtil.isNotEmpty(param.getId()), TbCreditBuyer::getId, param.getId()); + wrapper.like(StrUtil.isNotEmpty(param.getResponsiblePerson()), TbCreditBuyer::getResponsiblePerson, param.getResponsiblePerson()); wrapper.eq(param.getStatus() != null, TbCreditBuyer::getStatus, param.getStatus()); if (StrUtil.isNotEmpty(keywords)) { wrapper.nested(i -> i.like(TbCreditBuyer::getDebtor, keywords).or().like(TbCreditBuyer::getMobile, keywords)); } wrapper.eq(TbCreditBuyer::getDelFlag, 0); - wrapper.select(TbCreditBuyer::getId, TbCreditBuyer::getShopId, TbCreditBuyer::getStatus, TbCreditBuyer::getDebtor, TbCreditBuyer::getMobile, TbCreditBuyer::getPosition, TbCreditBuyer::getCreditAmount, TbCreditBuyer::getRepaymentMethod, TbCreditBuyer::getPaymentMethod, TbCreditBuyer::getRemark, TbCreditBuyer::getDelFlag, TbCreditBuyer::getOwedAmount, TbCreditBuyer::getAccumulateAmount, TbCreditBuyer::getShopName); + wrapper.select(TbCreditBuyer::getId, TbCreditBuyer::getShopId, TbCreditBuyer::getStatus, TbCreditBuyer::getDebtor, TbCreditBuyer::getMobile, TbCreditBuyer::getPosition, TbCreditBuyer::getCreditAmount, TbCreditBuyer::getRepaymentMethod, TbCreditBuyer::getPaymentMethod, TbCreditBuyer::getRemark, TbCreditBuyer::getDelFlag, TbCreditBuyer::getOwedAmount, TbCreditBuyer::getAccumulateAmount, TbCreditBuyer::getShopName, TbCreditBuyer::getResponsiblePerson, TbCreditBuyer::getAccountBalance); wrapper.orderByDesc(TbCreditBuyer::getStatus); wrapper.orderByDesc(TbCreditBuyer::getId); return wrapper; @@ -58,7 +68,6 @@ public class TbCreditBuyerServiceImpl extends ServiceImpl wrapper = getWrapper(params); - Page page = super.page(new Page<>(pageNum, pageSize), wrapper); return PageUtil.toPlusPage(page.getRecords(), Convert.toInt(page.getTotal())); } @@ -92,6 +101,7 @@ public class TbCreditBuyerServiceImpl extends ServiceImpllambdaUpdate().set(TbCreditBuyer::getDelFlag, 1).eq(TbCreditBuyer::getId, id)); } + + @Override + public TbCreditBuyer getById(String id) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(TbCreditBuyer::getId, id); + wrapper.select(TbCreditBuyer::getId, TbCreditBuyer::getShopId, TbCreditBuyer::getStatus, TbCreditBuyer::getDebtor, TbCreditBuyer::getMobile, TbCreditBuyer::getPosition, TbCreditBuyer::getCreditAmount, TbCreditBuyer::getRepaymentMethod, TbCreditBuyer::getPaymentMethod, TbCreditBuyer::getRemark, TbCreditBuyer::getDelFlag, TbCreditBuyer::getOwedAmount, TbCreditBuyer::getAccumulateAmount, TbCreditBuyer::getShopName, TbCreditBuyer::getResponsiblePerson, TbCreditBuyer::getAccountBalance); + return baseMapper.selectOne(wrapper); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Map repayment(Map params) { + MapProxy mapProxy = MapProxy.create(params); + // 还款金额 + BigDecimal repaymentAmount = mapProxy.getBigDecimal("repaymentAmount"); + TbCreditBuyer param = BeanUtil.toBean(params, TbCreditBuyer.class); + try { + Assert.notEmpty(param.getId(), "{}不能为空", "id"); + Assert.notNull(repaymentAmount, "{}({})不能为空", "还款金额", "repaymentAmount"); + Assert.notNull(param.getPaymentMethod(), "{}({})不能为空", "支付方式", "paymentMethod"); + } catch (IllegalArgumentException e) { + throw new BadRequestException(e.getMessage()); + } + TbCreditBuyer entity = getById(param.getId()); + if (entity == null) { + throw new BadRequestException("挂账人不存在"); + } + Integer delFlag = entity.getDelFlag(); + if (delFlag == 1) { + throw new BadRequestException("挂账人已删除"); + } + if (!"total".equals(entity.getRepaymentMethod())) { + throw new BadRequestException("此挂账人不能以【按总账户还款】进行还款"); + } + if (NumberUtil.isLess(repaymentAmount, BigDecimal.ZERO)) { + throw new BadRequestException("还款金额不能小于0"); + } + BigDecimal initRepaymentAmount = NumberUtil.add(repaymentAmount, BigDecimal.ZERO); + // 已挂账金额 + BigDecimal owedAmount = entity.getOwedAmount(); + if (NumberUtil.equals(owedAmount, BigDecimal.ZERO)) { + entity.setAccountBalance(NumberUtil.add(entity.getAccountBalance(), repaymentAmount)); + super.updateById(entity); + Map result = new HashMap<>(3); + result.put("repaymentCount", 0); + result.put("repaymentAmount", repaymentAmount); + result.put("repaymentMsg", StrUtil.format("账单无需还款,{}元已转储至余额。", repaymentAmount)); + return result; + } + BigDecimal rechargeAmount = BigDecimal.ZERO; + if (NumberUtil.isGreater(repaymentAmount, owedAmount)) { + rechargeAmount = NumberUtil.sub(repaymentAmount, owedAmount); + entity.setAccountBalance(NumberUtil.add(entity.getAccountBalance(), rechargeAmount)); + super.updateById(entity); + } + + // 校验完毕,可以批量还款 + Map where = new HashMap<>(); + where.put("creditBuyerId", param.getId()); + where.put("statusList", Arrays.asList("unpaid", "partial")); + List list = tbCreditBuyerOrderMapper.getList(where); + if (CollUtil.isEmpty(list)) { + throw new BadRequestException("没有需要还款的订单"); + } + int repaymentCount = 0; + List orderList = list.stream().sorted(Comparator.comparing(CreditBuyerOrderDTO::getOrderId)).collect(Collectors.toList()); + for (CreditBuyerOrderDTO dto : orderList) { + // 未付款金额 + BigDecimal unpaidAmount = dto.getUnpaidAmount(); + if (NumberUtil.isGreaterOrEqual(repaymentAmount, unpaidAmount)) { + // 还全额 + tbCreditBuyerOrderMapper.update(Wrappers.lambdaUpdate() + .eq(TbCreditBuyerOrder::getStatus, dto.getStatus()) + .eq(TbCreditBuyerOrder::getId, dto.getId()) + .eq(TbCreditBuyerOrder::getOrderId, dto.getOrderId()) + .eq(TbCreditBuyerOrder::getCreditBuyerId, dto.getCreditBuyerId()) + .eq(TbCreditBuyerOrder::getPaidAmount, dto.getPaidAmount()) + .set(TbCreditBuyerOrder::getStatus, "paid") + .set(TbCreditBuyerOrder::getPaidAmount, NumberUtil.add(dto.getPaidAmount(), unpaidAmount)) + .set(TbCreditBuyerOrder::getRemark, param.getRemark()) + .set(TbCreditBuyerOrder::getLastPaymentMethod, param.getPaymentMethod()) + .set(TbCreditBuyerOrder::getLastPaymentTime, new Date()) + ); + repaymentAmount = NumberUtil.sub(repaymentAmount, unpaidAmount); + } else if (NumberUtil.isLess(repaymentAmount, unpaidAmount)) { + // 还部分 + tbCreditBuyerOrderMapper.update(Wrappers.lambdaUpdate() + .eq(TbCreditBuyerOrder::getStatus, dto.getStatus()) + .eq(TbCreditBuyerOrder::getId, dto.getId()) + .eq(TbCreditBuyerOrder::getOrderId, dto.getOrderId()) + .eq(TbCreditBuyerOrder::getCreditBuyerId, dto.getCreditBuyerId()) + .eq(TbCreditBuyerOrder::getPaidAmount, dto.getPaidAmount()) + .set(TbCreditBuyerOrder::getStatus, "partial") + .set(TbCreditBuyerOrder::getPaidAmount, NumberUtil.add(dto.getPaidAmount(), repaymentAmount)) + .set(TbCreditBuyerOrder::getRemark, param.getRemark()) + .set(TbCreditBuyerOrder::getLastPaymentMethod, param.getPaymentMethod()) + .set(TbCreditBuyerOrder::getLastPaymentTime, new Date()) + ); + repaymentAmount = BigDecimal.ZERO; + } + repaymentCount++; + if (NumberUtil.equals(repaymentAmount, BigDecimal.ZERO)) { + break; + } + } + Map result = new HashMap<>(3); + BigDecimal payAmount = NumberUtil.sub(initRepaymentAmount, repaymentAmount); + result.put("repaymentCount", repaymentCount); + result.put("repaymentAmount", initRepaymentAmount); + result.put("payAmount", payAmount); + result.put("rechargeAmount", rechargeAmount); + result.put("repaymentMsg", StrUtil.format("共计还款{}笔,还款金额:{}元,支付欠款:{}元,转存余额:{}元,当前余额:{}元。", repaymentCount, initRepaymentAmount, payAmount, entity.getAccountBalance())); + return result; + } + + } \ No newline at end of file diff --git a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditPaymentRecordServiceImpl.java b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditPaymentRecordServiceImpl.java index d42fac80..c30d30a0 100644 --- a/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditPaymentRecordServiceImpl.java +++ b/eladmin-system/src/main/java/cn/ysk/cashier/mybatis/service/impl/TbCreditPaymentRecordServiceImpl.java @@ -1,9 +1,16 @@ package cn.ysk.cashier.mybatis.service.impl; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.map.MapProxy; +import cn.hutool.core.util.StrUtil; import cn.ysk.cashier.mybatis.entity.TbCreditPaymentRecord; import cn.ysk.cashier.mybatis.mapper.TbCreditPaymentRecordMapper; import cn.ysk.cashier.mybatis.service.TbCreditPaymentRecordService; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import cn.ysk.cashier.utils.PageUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import org.springframework.stereotype.Service; @@ -18,15 +25,24 @@ import java.util.Map; @Service public class TbCreditPaymentRecordServiceImpl extends ServiceImpl implements TbCreditPaymentRecordService { - public QueryWrapper getWrapper(Map params){ - QueryWrapper wrapper = new QueryWrapper<>(); - - wrapper.orderByDesc("id"); + private LambdaQueryWrapper getWrapper(Map params) { + TbCreditPaymentRecord param = BeanUtil.toBean(params, TbCreditPaymentRecord.class); + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.eq(TbCreditPaymentRecord::getCreditBuyerId, param.getCreditBuyerId()); + wrapper.eq(param.getOrderId() != null, TbCreditPaymentRecord::getOrderId, param.getOrderId()); + wrapper.like(StrUtil.isNotEmpty(param.getPaymentMethod()), TbCreditPaymentRecord::getPaymentMethod, param.getPaymentMethod()); + wrapper.orderByDesc(TbCreditPaymentRecord::getId); return wrapper; } @Override public Map page(Map params) { - return null; + MapProxy mapProxy = MapProxy.create(params); + int pageNum = mapProxy.getInt("page", 1); + int pageSize = mapProxy.getInt("size", 10); + LambdaQueryWrapper wrapper = getWrapper(params); + wrapper.orderByDesc(TbCreditPaymentRecord::getId); + Page page = super.page(new Page<>(pageNum, pageSize), wrapper); + return PageUtil.toPlusPage(page.getRecords(), Convert.toInt(page.getTotal())); } } \ No newline at end of file diff --git a/eladmin-system/src/main/resources/mapper/plus/TbCreditBuyerOrderMapper.xml b/eladmin-system/src/main/resources/mapper/plus/TbCreditBuyerOrderMapper.xml new file mode 100644 index 00000000..d2dc56e4 --- /dev/null +++ b/eladmin-system/src/main/resources/mapper/plus/TbCreditBuyerOrderMapper.xml @@ -0,0 +1,66 @@ + + + + + + + + and t1.credit_buyer_id = #{creditBuyerId} + + and t1.order_id = #{orderId} + + + and t1.create_time >= str_to_date(concat(#{beginDate},' 00:00:00'), '%Y-%m-%d %H:%i:%s') + + + + + + and t1.status = #{status} + + + and t1.status in + + #{status} + + + + and t1.id = #{id} + + + + + + + + + + + + + + + \ No newline at end of file