diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerController.java new file mode 100644 index 0000000..3b313d8 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerController.java @@ -0,0 +1,99 @@ +package com.chaozhanggui.system.cashierservice.controller; + +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyer; +import com.chaozhanggui.system.cashierservice.service.TbCreditBuyerService; +import com.chaozhanggui.system.cashierservice.sign.CodeEnum; +import com.chaozhanggui.system.cashierservice.sign.Result; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + + +/** + * 挂账人 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@CrossOrigin(origins = "*") +@RestController +@RequestMapping("/credit/buyer") +public class TbCreditBuyerController { + + @Autowired + private TbCreditBuyerService tbCreditBuyerService; + + /** + * 分页 + * + * @param params + * @return + */ + @GetMapping("page") + public Result page(@RequestParam Map params) { + PageInfo page = tbCreditBuyerService.page(params); + return Result.success(CodeEnum.SUCCESS, page); + } + + /** + * 信息 + * + * @param id + * @return + */ + @GetMapping("{id}") + public Result get(@PathVariable("id") String id) { + TbCreditBuyer data = tbCreditBuyerService.getById(id); + return Result.success(CodeEnum.SUCCESS, data); + } + + /** + * 保存 + * + * @param entity + * @return + */ + @PostMapping + public Result save(@RequestBody TbCreditBuyer entity) { + boolean ret = tbCreditBuyerService.save(entity); + return Result.success(CodeEnum.SUCCESS, ret); + } + + /** + * 修改 + * + * @param dto + * @return + */ + @PutMapping + public Result update(@RequestBody TbCreditBuyer dto) { + boolean ret = tbCreditBuyerService.update(dto); + return Result.success(CodeEnum.SUCCESS, ret); + } + + /** + * 删除 + * + * @param id + * @return + */ + @DeleteMapping("{id}") + public Result delete(@PathVariable("id") String id) { + tbCreditBuyerService.delete(id); + return Result.success(CodeEnum.SUCCESS); + } + + /** + * 还款 + * + * @param params + * @return + */ + @PostMapping("repayment") + public Result repayment(@RequestBody Map params) { + Map data = tbCreditBuyerService.repayment(params); + return Result.success(CodeEnum.SUCCESS, data); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerOrderController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerOrderController.java new file mode 100644 index 0000000..b7530fd --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditBuyerOrderController.java @@ -0,0 +1,64 @@ +package com.chaozhanggui.system.cashierservice.controller; + +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.entity.dto.CreditBuyerOrderDTO; +import com.chaozhanggui.system.cashierservice.service.TbCreditBuyerOrderService; +import com.chaozhanggui.system.cashierservice.sign.CodeEnum; +import com.chaozhanggui.system.cashierservice.sign.Result; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@CrossOrigin(origins = "*") +@RestController +@RequestMapping("/credit/buyer-order") +public class TbCreditBuyerOrderController { + + @Autowired + private TbCreditBuyerOrderService tbCreditBuyerOrderService; + + /** + * 分页 + * + * @param params + * @return + */ + @GetMapping("page") + public Result page(@RequestParam Map params) { + PageInfo page = tbCreditBuyerOrderService.page(params); + return Result.success(CodeEnum.SUCCESS, page); + } + + /** + * 付款 + * + * @param record + * @return + */ + @PostMapping("pay") + public Result pay(@RequestBody TbCreditPaymentRecord record) { + tbCreditBuyerOrderService.pay(record); + return Result.success(CodeEnum.SUCCESS); + } + + /** + * 统计 + * + * @param params + * @return + */ + @GetMapping("summary") + public Result summary(@RequestParam Map params) { + Map data = tbCreditBuyerOrderService.summary(params); + return Result.success(CodeEnum.SUCCESS, data); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditPaymentRecordController.java b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditPaymentRecordController.java new file mode 100644 index 0000000..bbfa73a --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/controller/TbCreditPaymentRecordController.java @@ -0,0 +1,40 @@ +package com.chaozhanggui.system.cashierservice.controller; + +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.service.TbCreditPaymentRecordService; +import com.chaozhanggui.system.cashierservice.sign.CodeEnum; +import com.chaozhanggui.system.cashierservice.sign.Result; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + + +/** + * 挂账账单付款记录 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@CrossOrigin(origins = "*") +@RestController +@RequestMapping("/credit/payment-record") +public class TbCreditPaymentRecordController { + + @Autowired + private TbCreditPaymentRecordService tbCreditPaymentRecordService; + + /** + * 分页 + * + * @param params + * @return + */ + @GetMapping("page") + public Result page(@RequestParam Map params) { + PageInfo page = tbCreditPaymentRecordService.page(params); + return Result.success(CodeEnum.SUCCESS, page); + } + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyer.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyer.java new file mode 100644 index 0000000..23ad411 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyer.java @@ -0,0 +1,107 @@ +package com.chaozhanggui.system.cashierservice.entity; + +import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; + +/** + * 挂账人 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("tb_credit_buyer") +public class TbCreditBuyer { + private static final long serialVersionUID = 1L; + + /** + * 挂账编码 + */ + @TableId(type = IdType.ASSIGN_ID) + private String id; + /** + * 店铺id + */ + private Integer shopId; + /** + * 状态 1-启用 0-停用 + */ + private Integer status; + /** + * 挂账人 + */ + private String debtor; + /** + * 手机号 + */ + private String mobile; + /** + * 职务 + */ + private String position; + /** + * 挂账额度 + */ + private BigDecimal creditAmount; + /** + * 账户余额 + */ + private BigDecimal accountBalance; + /** + * 还款方式 total-按总金额还款 order-按订单还款 + */ + private String repaymentMethod; + /** + * 支付方式 + */ + private String paymentMethod; + /** + * 责任人 + */ + private String responsiblePerson; + /** + * 备注 + */ + private String remark; + /** + * 删除标志 0-正常 1-删除 + */ + private Integer delFlag; + + + /** + * 已挂账金额 + */ + @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; + + /** + * 剩余挂账额度 + */ + @TableField(exist = false) + private BigDecimal remainingAmount; + + /** + * 累计挂账金额 + */ + @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 = tb_credit_buyer.shop_id)", select = false, insertStrategy = FieldStrategy.NEVER, updateStrategy = FieldStrategy.NEVER) + private String shopName; + + /** + * 剩余挂账额度 + */ + public BigDecimal getRemainingAmount() { + return NumberUtil.sub(creditAmount, NumberUtil.null2Zero(owedAmount)); + } +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyerOrder.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyerOrder.java new file mode 100644 index 0000000..fbb1a56 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditBuyerOrder.java @@ -0,0 +1,60 @@ +package com.chaozhanggui.system.cashierservice.entity; + +import com.alibaba.fastjson.annotation.JSONField; +import com.baomidou.mybatisplus.annotation.*; +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Data +@EqualsAndHashCode(callSuper = false) +@TableName("tb_credit_buyer_order") +public class TbCreditBuyerOrder { + private static final long serialVersionUID = 1L; + + /** + * 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.NEVER) + private String remark; +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditPaymentRecord.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditPaymentRecord.java new file mode 100644 index 0000000..c1c5ef7 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/TbCreditPaymentRecord.java @@ -0,0 +1,63 @@ +package com.chaozhanggui.system.cashierservice.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; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 挂账账单付款记录 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Data +@EqualsAndHashCode(callSuper=false) +@TableName("tb_credit_payment_record") +public class TbCreditPaymentRecord { + private static final long serialVersionUID = 1L; + + /** + * id + */ + @TableId(type = IdType.AUTO) + private Long id; + /** + * 订单id + */ + private Long orderId; + /** + * 挂账人编码 + */ + private String creditBuyerId; + /** + * 还款金额 + */ + private BigDecimal repaymentAmount; + /** + * 支付方式 + */ + private String paymentMethod; + /** + * 备注 + */ + private String remark; + /** + * 还款时间 + */ + @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/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/CreditBuyerOrderDTO.java b/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/CreditBuyerOrderDTO.java new file mode 100644 index 0000000..16aa691 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/entity/dto/CreditBuyerOrderDTO.java @@ -0,0 +1,69 @@ +package com.chaozhanggui.system.cashierservice.entity.dto; + +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/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerMapper.java new file mode 100644 index 0000000..fc73774 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerMapper.java @@ -0,0 +1,16 @@ +package com.chaozhanggui.system.cashierservice.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyer; +import org.apache.ibatis.annotations.Mapper; + +/** + * 挂账人 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Mapper +public interface TbCreditBuyerMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerOrderMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerOrderMapper.java new file mode 100644 index 0000000..1e0b8ea --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditBuyerOrderMapper.java @@ -0,0 +1,33 @@ +package com.chaozhanggui.system.cashierservice.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyerOrder; +import com.chaozhanggui.system.cashierservice.entity.dto.CreditBuyerOrderDTO; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Mapper +public interface TbCreditBuyerOrderMapper extends BaseMapper { + + List getList(Map params); + + long getCount(Map params); + + BigDecimal getSumPayAmount(Map params); + + BigDecimal getSumPaidAmount(Map params); + + BigDecimal getSumUnpaidAmount(Map params); + + CreditBuyerOrderDTO getOne(Map params); + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditPaymentRecordMapper.java b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditPaymentRecordMapper.java new file mode 100644 index 0000000..9aed291 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/mapper/TbCreditPaymentRecordMapper.java @@ -0,0 +1,16 @@ +package com.chaozhanggui.system.cashierservice.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import org.apache.ibatis.annotations.Mapper; + +/** +* 挂账账单付款记录 +* +* @author Tankaikai tankaikai@aliyun.com +* @since 2.0 2024-11-20 +*/ +@Mapper +public interface TbCreditPaymentRecordMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerOrderService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerOrderService.java new file mode 100644 index 0000000..bbed870 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerOrderService.java @@ -0,0 +1,51 @@ +package com.chaozhanggui.system.cashierservice.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyerOrder; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.entity.dto.CreditBuyerOrderDTO; +import com.github.pagehelper.PageInfo; + +import java.math.BigDecimal; +import java.util.Map; + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +public interface TbCreditBuyerOrderService extends IService { + + PageInfo page(Map params); + Map summary(Map params); + + void pay(TbCreditPaymentRecord record); + + /** + * 保存挂账账单 + * @param creditBuyerId 挂账人id + * @param orderId 订单id + */ + boolean save(String creditBuyerId, Long orderId); + + /** + * 挂账人退款(整单退款) + * @param creditBuyerId 挂账人id + * @param orderId 订单id + * @return + */ + @Deprecated + boolean refund(String creditBuyerId, Long orderId); + + + /** + * 挂账人退款(部分退款) + * @param creditBuyerId 挂账人id + * @param orderId 订单id + * @param refundAmount 退款金额 + * @return + */ + boolean partRefund(String creditBuyerId, Long orderId, BigDecimal refundAmount); + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerService.java new file mode 100644 index 0000000..f547f66 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditBuyerService.java @@ -0,0 +1,32 @@ +package com.chaozhanggui.system.cashierservice.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyer; +import com.github.pagehelper.PageInfo; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Map; + +/** + * 挂账人 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Mapper +public interface TbCreditBuyerService extends IService { + + PageInfo page(Map params); + + boolean save(TbCreditBuyer entity); + + boolean update(TbCreditBuyer dto); + + void delete(String id); + + TbCreditBuyer getById(String id); + + Map repayment(Map params); + + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditPaymentRecordService.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditPaymentRecordService.java new file mode 100644 index 0000000..41c5e9c --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/TbCreditPaymentRecordService.java @@ -0,0 +1,19 @@ +package com.chaozhanggui.system.cashierservice.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.github.pagehelper.PageInfo; + +import java.util.Map; + +/** + * 挂账账单付款记录 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +public interface TbCreditPaymentRecordService extends IService { + + PageInfo page(Map params); + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerOrderServiceImpl.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerOrderServiceImpl.java new file mode 100644 index 0000000..917fb6f --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerOrderServiceImpl.java @@ -0,0 +1,347 @@ +package com.chaozhanggui.system.cashierservice.service.impl; + +import cn.hutool.core.bean.BeanUtil; +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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyer; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyerOrder; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.entity.TbOrderInfo; +import com.chaozhanggui.system.cashierservice.entity.dto.CreditBuyerOrderDTO; +import com.chaozhanggui.system.cashierservice.exception.MsgException; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditBuyerMapper; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditBuyerOrderMapper; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditPaymentRecordMapper; +import com.chaozhanggui.system.cashierservice.service.MpOrderInfoService; +import com.chaozhanggui.system.cashierservice.service.TbCreditBuyerOrderService; +import com.chaozhanggui.system.cashierservice.service.TbCreditBuyerService; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * 挂账账单 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Service +public class TbCreditBuyerOrderServiceImpl extends ServiceImpl implements TbCreditBuyerOrderService { + + @Autowired + private TbCreditBuyerService tbCreditBuyerService; + @Autowired + private TbCreditBuyerMapper tbCreditBuyerMapper; + @Autowired + private TbCreditBuyerOrderMapper tbCreditBuyerOrderMapper; + @Autowired + private TbCreditPaymentRecordMapper tbCreditPaymentRecordMapper; + @Autowired + private MpOrderInfoService mpOrderInfoService; + + 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 PageInfo page(Map params) { + MapProxy mapProxy = MapProxy.create(params); + int pageNum = mapProxy.getInt("page", 1); + int pageSize = mapProxy.getInt("size", 10); + PageInfo pageInfo = PageHelper.startPage(pageNum, pageSize).setOrderBy("order_id desc").doSelectPageInfo(() -> baseMapper.getList(params)); + return pageInfo; + } + + @Override + public Map summary(Map params) { + long count = baseMapper.getCount(params); + Map data = new HashMap<>(5); + // 总交易笔数 + data.put("count", count); + // 总交易金额 + BigDecimal payAmount = baseMapper.getSumPayAmount(params); + data.put("payAmountTotal", payAmount); + + // 待支付笔数 + params.put("statusList", Arrays.asList("unpaid", "partial")); + long unpaidCount = baseMapper.getCount(params); + data.put("unpaidCount", unpaidCount); + params.put("statusList", Arrays.asList("paid", "partial")); + BigDecimal paidAmount = baseMapper.getSumPaidAmount(params); + params.put("statusList", Arrays.asList("unpaid", "partial")); + 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 MsgException(e.getMessage()); + } + TbCreditBuyer creditBuyer = tbCreditBuyerMapper.selectById(record.getCreditBuyerId()); + if (creditBuyer == null) { + throw new MsgException("挂账人不存在"); + } + String repaymentMethod = creditBuyer.getRepaymentMethod(); + if (!"order".equals(repaymentMethod)) { + throw new MsgException("该挂账人不支持按订单付款"); + } + 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 MsgException("挂账订单不存在"); + } + if ("paid".equals(dto.getStatus())) { + throw new MsgException("挂账订单已还清,无需还款"); + } + if (NumberUtil.isLess(record.getRepaymentAmount(), BigDecimal.ZERO)) { + throw new MsgException("还款金额不能小于0"); + } + if (NumberUtil.isGreater(record.getRepaymentAmount(), dto.getUnpaidAmount())) { + throw new MsgException("还款金额不能大于未支付金额"); + } + TbCreditBuyerOrder entity = new TbCreditBuyerOrder(); + BeanUtil.copyProperties(dto, entity); + 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()); + entity.setRemark(record.getRemark()); + super.updateById(entity); + record.setCreateTime(new Date()); + record.setPaymentTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean save(String creditBuyerId, Long orderId) { + if (StrUtil.isBlank(creditBuyerId)) { + throw new MsgException("挂账人id不能为空"); + } + TbCreditBuyer creditBuyer = tbCreditBuyerService.getById(creditBuyerId); + if (creditBuyer == null) { + throw new MsgException("挂账人不存在"); + } + Integer delFlag = creditBuyer.getDelFlag(); + if (delFlag != null && delFlag == 1) { + throw new MsgException("挂账人已删除"); + } + Integer status = creditBuyer.getStatus(); + if (status != null && status == 0) { + throw new MsgException("挂账人已被停用"); + } + TbOrderInfo orderInfo = mpOrderInfoService.getById(orderId); + if (orderInfo == null) { + throw new MsgException("订单不存在"); + } + // 账户余额 + BigDecimal accountBalance = creditBuyer.getAccountBalance(); + // 如果有余额的话,从余额里面扣除,没有余额的话,从信用额度里面扣除,余额和信用额度都为0,则不允许挂账,余额+信用额度刚好够支付这笔订单的话需要同时减余额减信用额度 + if (NumberUtil.isGreaterOrEqual(accountBalance, orderInfo.getOrderAmount())) { + // 减余额 + creditBuyer.setAccountBalance(NumberUtil.sub(accountBalance, orderInfo.getOrderAmount())); + tbCreditBuyerMapper.updateById(creditBuyer); + // 记录还款记录 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(creditBuyerId); + record.setOrderId(orderId); + record.setRepaymentAmount(orderInfo.getOrderAmount()); + 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.getOrderAmount()); + 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.getOrderAmount(), accountBalance)); + } + // 剩余挂账额度 + BigDecimal remainingAmount = creditBuyer.getRemainingAmount(); + // 验证挂账金额是否大于剩余额度 + boolean greater = NumberUtil.isGreater(orderInfo.getOrderAmount(), remainingAmount); + if (greater) { + throw new MsgException(StrUtil.format("{}:¥{}不能大于剩余挂账额度({})", "挂账金额", orderInfo.getOrderAmount(), remainingAmount)); + } + if (entity == null) { + entity = new TbCreditBuyerOrder(); + entity.setStatus("unpaid"); + entity.setPaidAmount(BigDecimal.ZERO); + entity.setCreditBuyerId(creditBuyerId); + entity.setOrderId(orderId); + } + return super.saveOrUpdate(entity); + } + + @Override + @Deprecated + @Transactional(rollbackFor = Exception.class) + public boolean refund(String creditBuyerId, Long orderId) { + if (StrUtil.isBlank(creditBuyerId)) { + throw new MsgException("挂账人id不能为空"); + } + TbCreditBuyer creditBuyer = tbCreditBuyerService.getById(creditBuyerId); + if (creditBuyer == null) { + throw new MsgException("挂账人不存在"); + } + TbOrderInfo orderInfo = mpOrderInfoService.getById(orderId); + if (orderInfo == null) { + throw new MsgException("订单不存在"); + } + + Map params = new HashMap<>(2); + params.put("creditBuyerId", creditBuyerId); + params.put("orderId", orderId); + CreditBuyerOrderDTO dto = baseMapper.getOne(params); + if (dto == null) { + throw new MsgException("挂账订单不存在"); + } + // 1.只挂账未还款的情况,直接删除挂账订单 + if ("unpaid".equals(dto.getStatus())) { + baseMapper.deleteById(dto.getId()); + return true; + } + // 2.部分还款/已还款,删除挂账订单+红冲还款记录,并把已还款金额退回余额或挂账额度 + if ("partial".equals(dto.getStatus()) || "paid".equals(dto.getStatus())) { + // 已还款金额 + BigDecimal paidAmount = dto.getPaidAmount(); + // 已还款金额进行红冲 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(creditBuyerId); + record.setOrderId(orderId); + record.setRepaymentAmount(NumberUtil.sub(BigDecimal.ZERO, paidAmount)); + record.setPaymentMethod("挂账退款"); + record.setPaymentTime(new Date()); + record.setRemark(StrUtil.format("挂账订单:{}申请退款,已归还挂账额度或账户余额", orderInfo.getOrderNo())); + record.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + // 删除挂账订单,恢复挂账额度 + baseMapper.deleteById(dto.getId()); + // 退回余额 + creditBuyer.setAccountBalance(NumberUtil.add(creditBuyer.getAccountBalance(), paidAmount)); + tbCreditBuyerService.updateById(creditBuyer); + return true; + } + return false; + } + + @Override + public boolean partRefund(String creditBuyerId, Long orderId, BigDecimal refundAmount) { + if (StrUtil.isBlank(creditBuyerId)) { + throw new MsgException("挂账人id不能为空"); + } + TbCreditBuyer creditBuyer = tbCreditBuyerService.getById(creditBuyerId); + if (creditBuyer == null) { + throw new MsgException("挂账人不存在"); + } + TbOrderInfo orderInfo = mpOrderInfoService.getById(orderId); + if (orderInfo == null) { + throw new MsgException("订单不存在"); + } + + Map params = new HashMap<>(2); + params.put("creditBuyerId", creditBuyerId); + params.put("orderId", orderId); + CreditBuyerOrderDTO dto = baseMapper.getOne(params); + if (dto == null) { + throw new MsgException("挂账订单不存在"); + } + // 已还款金额进行红冲 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(creditBuyerId); + record.setOrderId(orderId); + record.setRepaymentAmount(NumberUtil.sub(BigDecimal.ZERO, refundAmount)); + record.setPaymentMethod("挂账退款"); + record.setPaymentTime(new Date()); + record.setRemark(StrUtil.format("挂账订单:{},申请退款¥{}元,已恢复挂账额度。", orderInfo.getOrderNo(), refundAmount)); + record.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(record); + dto = baseMapper.getOne(params); + BigDecimal sub = NumberUtil.sub(refundAmount, dto.getUnpaidAmount()); + if (NumberUtil.isGreater(sub, BigDecimal.ZERO)) { + TbCreditPaymentRecord flow = new TbCreditPaymentRecord(); + flow.setCreditBuyerId(creditBuyerId); + flow.setOrderId(orderId); + flow.setRepaymentAmount(sub); + flow.setPaymentMethod("转储余额"); + flow.setPaymentTime(new Date()); + flow.setRemark(StrUtil.format("挂账订单:{},申请退款¥{}元,由于此挂账订单已提前还款,溢出部分¥{}元将转储至账户余额。", orderInfo.getOrderNo(), refundAmount, sub)); + flow.setCreateTime(new Date()); + tbCreditPaymentRecordMapper.insert(flow); + tbCreditBuyerOrderMapper.update(null, Wrappers.lambdaUpdate() + .eq(TbCreditBuyerOrder::getId, dto.getId()) + .set(TbCreditBuyerOrder::getPaidAmount, NumberUtil.sub(dto.getPaidAmount(), sub)) + ); + // 退回余额 + creditBuyer.setAccountBalance(NumberUtil.add(creditBuyer.getAccountBalance(), sub)); + tbCreditBuyerService.updateById(creditBuyer); + } + return true; + } +} diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerServiceImpl.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerServiceImpl.java new file mode 100644 index 0000000..855aefd --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditBuyerServiceImpl.java @@ -0,0 +1,303 @@ +package com.chaozhanggui.system.cashierservice.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.lang.Assert; +import cn.hutool.core.lang.Validator; +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 com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyer; +import com.chaozhanggui.system.cashierservice.entity.TbCreditBuyerOrder; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.entity.dto.CreditBuyerOrderDTO; +import com.chaozhanggui.system.cashierservice.exception.MsgException; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditBuyerMapper; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditBuyerOrderMapper; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditPaymentRecordMapper; +import com.chaozhanggui.system.cashierservice.service.TbCreditBuyerService; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.math.BigDecimal; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 挂账人 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Service +public class TbCreditBuyerServiceImpl extends ServiceImpl implements TbCreditBuyerService { + + @Autowired + private TbCreditBuyerOrderMapper tbCreditBuyerOrderMapper; + + @Autowired + private TbCreditPaymentRecordMapper tbCreditPaymentRecordMapper; + + private LambdaQueryWrapper getWrapper(Map params) { + MapProxy mapProxy = MapProxy.create(params); + String keywords = mapProxy.getStr("keywords"); + String repaymentStatus = mapProxy.getStr("repaymentStatus"); + TbCreditBuyer param = BeanUtil.toBean(params, TbCreditBuyer.class); + + LambdaQueryWrapper 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)); + } + if (StrUtil.isNotEmpty(repaymentStatus)) { + if ("unpaid".equals(repaymentStatus)) { + wrapper.apply("0 < ifnull((select x.count from view_credit_buyer_order_count x where x.credit_buyer_id = tb_credit_buyer.id and x.status = 'unpaid'),0)"); + wrapper.apply("0 = ifnull((select x.count from view_credit_buyer_order_count x where x.credit_buyer_id = tb_credit_buyer.id and x.status = 'partial'),0)"); + } else if ("partial".equals(repaymentStatus)) { + wrapper.apply("0 < ifnull((select x.count from view_credit_buyer_order_count x where x.credit_buyer_id = tb_credit_buyer.id and x.status = 'partial'),0)"); + } else if ("paid".equals(repaymentStatus)) { + wrapper.apply("0 = ifnull((select sum(x.count) from view_credit_buyer_order_count x where x.credit_buyer_id = tb_credit_buyer.id and x.status in ('unpaid','partial')),0)"); + } + } + 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, TbCreditBuyer::getResponsiblePerson, TbCreditBuyer::getAccountBalance); + wrapper.orderByDesc(TbCreditBuyer::getStatus); + wrapper.orderByDesc(TbCreditBuyer::getId); + return wrapper; + } + + @Override + public PageInfo page(Map params) { + MapProxy mapProxy = MapProxy.create(params); + int pageNum = mapProxy.getInt("page", 1); + int pageSize = mapProxy.getInt("size", 10); + LambdaQueryWrapper wrapper = getWrapper(params); + PageInfo pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> baseMapper.selectList(wrapper)); + return pageInfo; + } + + private void commonVerify(TbCreditBuyer entity) { + try { + Assert.notNull(entity.getShopId(), "{}({})不能为空", "店铺id", "shopId"); + Assert.notNull(entity.getStatus(), "{}({})不能为空", "状态", "status"); + Assert.notEmpty(entity.getDebtor(), "{}({})不能为空", "挂账人", "debtor"); + Assert.notEmpty(entity.getMobile(), "{}({})不能为空", "手机号", "mobile"); + Assert.notNull(entity.getCreditAmount(), "{}({})不能为空", "挂账额度", "creditAmount"); + } catch (IllegalArgumentException e) { + throw new MsgException(e.getMessage()); + } + if (!Validator.isMobile(entity.getMobile())) { + throw new MsgException(StrUtil.format("{}({})不合法", "手机号", "mobile")); + } + if (NumberUtil.isLessOrEqual(entity.getCreditAmount(), BigDecimal.ZERO)) { + throw new MsgException(StrUtil.format("{}({})必须大于0", "挂账额度", "creditAmount")); + } + } + + @Override + public boolean save(TbCreditBuyer entity) { + commonVerify(entity); + try { + Assert.notEmpty(entity.getRepaymentMethod(), "{}({})不能为空", "还款方式", "repaymentMethod"); + } catch (IllegalArgumentException e) { + throw new MsgException(e.getMessage()); + } + if (!ArrayUtil.contains(new String[]{"total", "order"}, entity.getRepaymentMethod())) { + throw new MsgException(StrUtil.format("{}({})不合法", "还款方式", "repaymentMethod")); + } + entity.setAccountBalance(BigDecimal.ZERO); + return super.save(entity); + } + + @Override + public boolean update(TbCreditBuyer dto) { + try { + Assert.notEmpty(dto.getId(), "{}不能为空", "id"); + } catch (IllegalArgumentException e) { + throw new MsgException(e.getMessage()); + } + commonVerify(dto); + TbCreditBuyer entity = super.getById(dto.getId()); + if (entity == null) { + throw new MsgException("挂账人不存在"); + } + Map params = new HashMap<>(); + params.put("id", dto.getId()); + params.put("shopId", dto.getShopId()); + LambdaQueryWrapper wrapper = getWrapper(params); + entity = baseMapper.selectOne(wrapper); + + // 验证挂账额度是否小于已挂账金额 + boolean less = NumberUtil.isLess(dto.getCreditAmount(), NumberUtil.null2Zero(entity.getOwedAmount())); + if (less) { + throw new MsgException(StrUtil.format("{}({})不能小于已挂账金额({})", "挂账额度", "creditAmount", entity.getOwedAmount())); + } + BeanUtil.copyProperties(dto, entity, CopyOptions.create().setIgnoreNullValue(false).setIgnoreProperties("repaymentMethod", "accountBalance")); + return super.updateById(entity); + } + + @Override + public void delete(String id) { + try { + Assert.notEmpty(id, "{}不能为空", "id"); + } catch (IllegalArgumentException e) { + throw new MsgException(e.getMessage()); + } + super.update(Wrappers.lambdaUpdate().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 MsgException(e.getMessage()); + } + TbCreditBuyer entity = getById(param.getId()); + if (entity == null) { + throw new MsgException("挂账人不存在"); + } + Integer delFlag = entity.getDelFlag(); + if (delFlag == 1) { + throw new MsgException("挂账人已删除"); + } + if (!"total".equals(entity.getRepaymentMethod())) { + throw new MsgException("此挂账人不能以【按总账户还款】进行还款"); + } + if (NumberUtil.isLess(repaymentAmount, BigDecimal.ZERO)) { + throw new MsgException("还款金额不能小于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); + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(param.getId()); + record.setRepaymentAmount(repaymentAmount); + record.setPaymentMethod(param.getPaymentMethod()); + record.setCreateTime(new Date()); + record.setPaymentTime(new Date()); + record.setRemark(param.getRemark()); + tbCreditPaymentRecordMapper.insert(record); + 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); + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + record.setCreditBuyerId(param.getId()); + record.setRepaymentAmount(rechargeAmount); + record.setPaymentMethod(param.getPaymentMethod()); + record.setCreateTime(new Date()); + record.setPaymentTime(new Date()); + record.setRemark(param.getRemark()); + tbCreditPaymentRecordMapper.insert(record); + } + + // 校验完毕,可以批量还款 + 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 MsgException("没有需要还款的订单"); + } + int repaymentCount = 0; + List orderList = list.stream().sorted(Comparator.comparing(CreditBuyerOrderDTO::getOrderId)).collect(Collectors.toList()); + for (CreditBuyerOrderDTO dto : orderList) { + // 未付款金额 + BigDecimal unpaidAmount = dto.getUnpaidAmount(); + // 记录还款记录 + TbCreditPaymentRecord record = new TbCreditPaymentRecord(); + if (NumberUtil.isGreaterOrEqual(repaymentAmount, unpaidAmount)) { + // 还全额 + tbCreditBuyerOrderMapper.update(null, 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()) + ); + record.setRepaymentAmount(unpaidAmount); + repaymentAmount = NumberUtil.sub(repaymentAmount, unpaidAmount); + } else if (NumberUtil.isLess(repaymentAmount, unpaidAmount)) { + // 还部分 + tbCreditBuyerOrderMapper.update(null, 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()) + ); + record.setRepaymentAmount(repaymentAmount); + repaymentAmount = BigDecimal.ZERO; + } + record.setCreditBuyerId(dto.getCreditBuyerId()); + record.setOrderId(dto.getOrderId()); + record.setPaymentMethod(param.getPaymentMethod()); + record.setCreateTime(new Date()); + record.setPaymentTime(new Date()); + record.setRemark(param.getRemark()); + tbCreditPaymentRecordMapper.insert(record); + repaymentCount++; + if (NumberUtil.equals(repaymentAmount, BigDecimal.ZERO)) { + break; + } + } + Map result = new HashMap<>(5); + 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, rechargeAmount, entity.getAccountBalance())); + return result; + } + + +} \ No newline at end of file diff --git a/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditPaymentRecordServiceImpl.java b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditPaymentRecordServiceImpl.java new file mode 100644 index 0000000..70fb607 --- /dev/null +++ b/src/main/java/com/chaozhanggui/system/cashierservice/service/impl/TbCreditPaymentRecordServiceImpl.java @@ -0,0 +1,47 @@ +package com.chaozhanggui.system.cashierservice.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.map.MapProxy; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.chaozhanggui.system.cashierservice.entity.TbCreditPaymentRecord; +import com.chaozhanggui.system.cashierservice.mapper.TbCreditPaymentRecordMapper; +import com.chaozhanggui.system.cashierservice.service.TbCreditPaymentRecordService; +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import org.springframework.stereotype.Service; + +import java.util.Map; + +/** + * 挂账账单付款记录 + * + * @author Tankaikai tankaikai@aliyun.com + * @since 2.0 2024-11-20 + */ +@Service +public class TbCreditPaymentRecordServiceImpl extends ServiceImpl implements TbCreditPaymentRecordService { + + 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 PageInfo page(Map params) { + 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); + PageInfo pageInfo = PageHelper.startPage(pageNum, pageSize).doSelectPageInfo(() -> baseMapper.selectList(wrapper)); + return pageInfo; + } +} \ No newline at end of file diff --git a/src/main/resources/mapper/TbCreditBuyerOrderMapper.xml b/src/main/resources/mapper/TbCreditBuyerOrderMapper.xml new file mode 100644 index 0000000..60e7417 --- /dev/null +++ b/src/main/resources/mapper/TbCreditBuyerOrderMapper.xml @@ -0,0 +1,72 @@ + + + + + + + + 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