| | |
| | | import com.mzl.flower.config.exception.ValidationException; |
| | | import com.mzl.flower.config.security.SecurityUtils; |
| | | import com.mzl.flower.constant.Constants; |
| | | import com.mzl.flower.constant.LockConstants; |
| | | import com.mzl.flower.dto.request.payment.*; |
| | | import com.mzl.flower.dto.response.payment.OrderSettlementDTO; |
| | | import com.mzl.flower.dto.response.payment.OrderSettlementDetailDTO; |
| | |
| | | import com.mzl.flower.entity.supplier.Station; |
| | | import com.mzl.flower.entity.supplier.Supplier; |
| | | import com.mzl.flower.entity.system.UserWechat; |
| | | import com.mzl.flower.entity.wallet.WalletBillRecordDO; |
| | | import com.mzl.flower.entity.wallet.WalletDO; |
| | | import com.mzl.flower.mapper.flower.FlowerSupplierSaleNumMapper; |
| | | import com.mzl.flower.mapper.payment.*; |
| | | import com.mzl.flower.mapper.supplier.StationMapper; |
| | | import com.mzl.flower.mapper.system.UserWechatMapper; |
| | | import com.mzl.flower.mapper.wallet.WalletBillRecordDetailMapper; |
| | | import com.mzl.flower.mapper.wallet.WalletBillRecordMapper; |
| | | import com.mzl.flower.mapper.wallet.WalletMapper; |
| | | import com.mzl.flower.service.BaseService; |
| | | import com.mzl.flower.service.wallet.WalletService; |
| | | import com.mzl.flower.utils.ExcelExportUtil; |
| | | import com.mzl.flower.utils.UUIDGenerator; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.redisson.api.RLock; |
| | | import org.redisson.api.RedissonClient; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.ObjectUtils; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.net.URLEncoder; |
| | | import java.time.LocalDateTime; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | @Slf4j |
| | | @Service |
| | |
| | | @Autowired |
| | | private TransferDetailMapper transferDetailMapper; |
| | | |
| | | @Autowired |
| | | private WalletBillRecordMapper walletBillRecordMapper; |
| | | |
| | | @Autowired |
| | | private WalletMapper walletMapper; |
| | | |
| | | @Autowired |
| | | private WalletBillRecordDetailMapper walletBillRecordDetailMapper; |
| | | |
| | | @Autowired |
| | | private WalletService walletService; |
| | | |
| | | @Autowired |
| | | RedissonClient redissonClient; |
| | | |
| | | public Page<OrderSettlementListDTO> selectSettlementList(Page page, OrderSettlementQueryDTO dto){ |
| | | dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true)); |
| | | dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false)); |
| | |
| | | if(settlement == null){ |
| | | throw new ValidationException("结算单不存在"); |
| | | } |
| | | String type = settlement.getType(); |
| | | |
| | | //2024-10-23 |
| | | //供应商新的结算逻辑不结算供应商的钱。 |
| | | if (Constants.SETTLEMENT_TYPE.supplier.name().equals(type)) { |
| | | throw new ValidationException("供应商不需要手动结算"); |
| | | } |
| | | String status = settlement.getStatus(); |
| | | if(Constants.SETTLEMENT_STATUS.PROCESSING.name().equals(status)){ |
| | | throw new ValidationException("结算中,不用重复结算"); |
| | |
| | | if(Constants.SETTLEMENT_STATUS.COMPLETED.name().equals(status)){ |
| | | throw new ValidationException("结算成功,不用重复结算"); |
| | | } |
| | | String type = settlement.getType(); |
| | | |
| | | String name = ""; |
| | | if(Constants.SETTLEMENT_TYPE.supplier.name().equals(type)){ |
| | |
| | | detail.create(); |
| | | settlementDetailMapper.insert(detail); |
| | | |
| | | //2024-10-23 |
| | | //copy信息到t_wallet_bill_record_detail |
| | | // WalletBillRecordDetail walletBillRecordDetail = new WalletBillRecordDetail(); |
| | | // BeanUtils.copyProperties(detail, walletBillRecordDetail, "id"); |
| | | // walletBillRecordDetail.setBillRecordId(walletBillRecord.getId()); |
| | | // walletBillRecordDetailMapper.insert(walletBillRecordDetail); |
| | | |
| | | flowerNum += oi.getNum(); |
| | | totalAmount = totalAmount.add(detail.getTotalAmount()); |
| | | checkFee = checkFee.add(detail.getCheckFee()); |
| | |
| | | serviceFee = serviceFee.add(ois.getServiceFee()); |
| | | serviceFeeRate = ois.getServiceFeeRate(); |
| | | settlementAmount = settlementAmount.add(ois.getIncomeSupplier()); |
| | | WalletDO walletDO = walletService.getOrCreateBySupplierId(supplierId); |
| | | RLock lock = redissonClient.getLock(String.format(LockConstants.WALLET_ID_KEY, walletDO.getId())); |
| | | try { |
| | | if (lock.tryLock(10, 30, TimeUnit.SECONDS)) { |
| | | try { |
| | | //2024-10-28 直接保存到walletBillRecord |
| | | //新增WalletBillRecordDO |
| | | if(ois.getIncomeSupplier().compareTo(BigDecimal.ZERO) > 0) { |
| | | WalletBillRecordDO walletBillRecord = new WalletBillRecordDO(); |
| | | walletBillRecord.setId(UUIDGenerator.getUUID()); |
| | | WalletDO walletDOInfo = walletService.getBySupplierId(supplierId); |
| | | //增加供应商结算金额保存到钱包 |
| | | walletBillRecord.setSupplierId(supplierId); |
| | | walletBillRecord.setWalletId(walletDOInfo.getId()); |
| | | walletBillRecord.setSettlementId(settlement.getId()); |
| | | walletBillRecord.setOrderItemId(detail.getOrderItemId()); |
| | | //变动金额等于供应商收入 |
| | | walletBillRecord.setTotalAmount(ois.getIncomeSupplier()); |
| | | walletBillRecord.setType(Constants.BILL_CHANGE_TYPE.settlement.name()); |
| | | walletBillRecord.setMethod(Constants.BILL_CHANGE_METHOD.add.name()); |
| | | walletBillRecord.setOriginalAmount(walletDOInfo.getTotalAmount()); |
| | | walletBillRecord.setChangeAmount(ois.getIncomeSupplier()); |
| | | walletBillRecord.setBalance(walletDOInfo.getWithdrawableAmount().add(ois.getIncomeSupplier())); |
| | | Order order = orderMapper.selectById(detail.getOrderId()); |
| | | if (!ObjectUtils.isEmpty(order)) { |
| | | walletBillRecord.setRemark("订单完成(订单号" + order.getOrderNo() + ")" + ",获得收入"); |
| | | walletBillRecord.setOrderNo(order.getOrderNo()); |
| | | } |
| | | //更新钱包 |
| | | //可提现金额=钱包余额=结算金额 |
| | | walletDOInfo.setWithdrawableAmount(walletDOInfo.getWithdrawableAmount().add(ois.getIncomeSupplier())); |
| | | walletDOInfo.setTotalAmount(walletDOInfo.getWithdrawableAmount()); |
| | | //已结算金额 |
| | | walletDOInfo.setSettledAmount(walletDOInfo.getSettledAmount().add(ois.getIncomeSupplier())); |
| | | walletMapper.updateById(walletDOInfo); |
| | | walletBillRecord.create(); |
| | | walletBillRecordMapper.insert(walletBillRecord); |
| | | } |
| | | } finally { |
| | | lock.unlock(); |
| | | } |
| | | } |
| | | } catch (InterruptedException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | } |
| | | |
| | | settlement.setFlowerNum(flowerNum); |
| | |
| | | settlement.setSettlementAmount(settlementAmount); |
| | | settlement.create(); |
| | | |
| | | //2024-10-23 |
| | | //计算到钱包后订单状态变成已结算 |
| | | //旧逻辑转账的时候才会标记状态为结算中 |
| | | //新逻辑不是立即转账。不走结算后转账逻辑。此时没有转账时间、openID、转账ID、转账明细ID,直接标记结算状态完成,存金额到钱包中 |
| | | settlement.setStatus(Constants.SETTLEMENT_STATUS.COMPLETED.name()); |
| | | settlementMapper.insert(settlement); |
| | | |
| | | } |
| | | |
| | | /* ******************************************************************** */ |
| | |
| | | orderMapper.updateById(o); |
| | | } |
| | | } |
| | | |
| | | public void exportSettlementList(HttpServletResponse response, OrderSettlementQueryDTO dto) { |
| | | dto.setStartDate(parseLocalDateTime(dto.getStartDateStr(), true)); |
| | | dto.setEndDate(parseLocalDateTime(dto.getEndDateStr(), false)); |
| | | List<OrderSettlementListDTO> ls = settlementMapper.selectSettlementListInfo(null, dto); |
| | | |
| | | String[] rowsName = new String[]{"序号","结算人", "结算金额(元)", "订单数量", "买家数量", "商品数量", "结算合计(元)", "结算均价(元)", "降级扣款(元)", |
| | | "缺货扣款(元)", "补货扣款(元)", "售后理赔(元)", "服务费(元)", "集货站运费(元)", "结算类型", "结算状态", "结算时间"}; |
| | | List<Object[]> dataList = new ArrayList<>(); |
| | | int sn = 1; |
| | | for (OrderSettlementListDTO o : ls) { |
| | | Object[] objs = new Object[rowsName.length]; |
| | | int a = 0; |
| | | objs[a++] = sn; |
| | | objs[a++] = o.getUserName(); |
| | | objs[a++] = o.getSettlementAmount(); |
| | | objs[a++] = o.getOrderNum(); |
| | | objs[a++] = o.getCustomerNum(); |
| | | objs[a++] = o.getFlowerNum(); |
| | | objs[a++] = o.getTotalAmount(); |
| | | objs[a++] = o.getPrice(); |
| | | objs[a++] = o.getCheckFee(); |
| | | objs[a++] = o.getLackFee(); |
| | | objs[a++] = o.getReplaceFee(); |
| | | objs[a++] = o.getSalesFee(); |
| | | objs[a++] = o.getServiceFee(); |
| | | objs[a++] = o.getStationFee(); |
| | | objs[a++] = o.getTypeStr(); |
| | | objs[a++] = o.getStatusStr(); |
| | | objs[a++] = o.getTransferTime(); |
| | | dataList.add(objs); |
| | | |
| | | sn++; |
| | | } |
| | | ExcelExportUtil excelExportUtil = new ExcelExportUtil("结算列表", rowsName, dataList, response); |
| | | try { |
| | | response.addHeader("filename", URLEncoder.encode("结算列表.xls", "UTF-8")); |
| | | response.addHeader("Access-Control-Expose-Headers", "filename"); |
| | | excelExportUtil.export(); |
| | | } catch (Exception e) { |
| | | log.error(e.getMessage(), e); |
| | | } |
| | | |
| | | } |
| | | } |