更新财务结算收款相关功能

This commit is contained in:
xyc 2025-08-20 16:14:44 +08:00
parent 6788c0c1fd
commit 06560969c0
11 changed files with 331 additions and 24 deletions

View File

@ -91,7 +91,9 @@ public enum RecordTypeEnum {
NFPG("nfpg", "内返派工"),
/** 收款*/
SK("sk", "收款"),
PICKCAR("pickcar", "接车");
PICKCAR("pickcar", "接车"),
JSSQ("jssq", "结算申请"),
JSSP("jssp", "结算审批");
/**
* code

View File

@ -34,4 +34,7 @@ public interface RepairDictConstants {
/** 调拨状态 */
String REPAIR_ST_STATUS = "repair_st_status";
/** 基础业务配置 */
String BASE_BUSINESS_CONFIG = "base_business_config";
}

View File

@ -50,4 +50,9 @@ public class RepairRecords extends TenantBaseDO {
*/
private Long dealUserId;
/**
* 冗余字段
*/
private String otherData;
}

View File

@ -28,6 +28,16 @@ public interface RepairRecordsService extends IService<RepairRecords> {
**/
void saveRepairRecord(String ticketId, String repairItemId, String type, String remark, String images);
/**
* @Author
* @Description 保存维修记录
* @Date 13:38 2025/8/20
* @Param [ticketId, repairItemId, type, remark, images, otherData]
* @return void
**/
void saveRepairRecord(String ticketId, String repairItemId, String type, String remark, String images, String otherData);
/**
* 根据条件查询维修记录
* @author PQZ

View File

@ -76,6 +76,33 @@ public class RepairRecordsServiceImpl extends ServiceImpl<RepairRecordsMapper, R
//保存附件信息
itemService.saveItem(repairRecords.getId(), ticketId, repairItemId, images);
}
/**
* @Author
* @Description 保存维修记录
* @Date 13:38 2025/8/20
* @Param [ticketId, repairItemId, type, remark, images]
* @return void
**/
@Override
public void saveRepairRecord(String ticketId, String repairItemId, String type, String remark, String images, String otherData) {
//获取当前登录用户
Long userId = SecurityFrameworkUtils.getLoginUserId();
AdminUserRespDTO loginUser = userApi.getUser(userId);
//初始化维修记录
RepairRecords repairRecords = new RepairRecords();
repairRecords.setTicketId(ticketId);
repairRecords.setRepairItemId(repairItemId);
repairRecords.setType(type);
repairRecords.setRemark(remark);
repairRecords.setDealUserId(loginUser.getId());
repairRecords.setDealUserName(loginUser.getNickname());
repairRecords.setOtherData(otherData);
//保存维修记录
save(repairRecords);
//保存附件信息
itemService.saveItem(repairRecords.getId(), ticketId, repairItemId, images);
}
/**
* 根据条件查询维修记录

View File

@ -9,6 +9,7 @@ import cn.iocoder.yudao.common.RepairDictConstants;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.base.service.RepairRecordsService;
import cn.iocoder.yudao.module.custom.entity.CarMain;
import cn.iocoder.yudao.module.custom.entity.CustomerMain;
@ -16,6 +17,7 @@ import cn.iocoder.yudao.module.custom.service.CarMainService;
import cn.iocoder.yudao.module.custom.service.CustomerMainService;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.tickets.entity.DlRepairTickets;
import cn.iocoder.yudao.module.tickets.service.DlRepairTicketsService;
import cn.iocoder.yudao.module.tickets.vo.*;
@ -68,6 +70,9 @@ public class DlRepairTicketsController {
@Resource
private DictDataApi dictDataApi;
@Resource
private PermissionApi permissionApi;
/**
* 维修工单表 新增
@ -203,19 +208,60 @@ public class DlRepairTicketsController {
}
/**
* 维修工单表 结算
* 维修工单表 收款
*
* @param repairTicketsRespVO 工单
* @author 小李
* @date 8:50 2024/9/23
**/
@PostMapping("/paid")
@Operation(summary = "维修工单表 结算")
@Operation(summary = "维修工单表 收款")
public CommonResult<?> setTicketsPaid(@RequestBody DlRepairTicketsRespVO repairTicketsRespVO) {
dlRepairTicketsService.setTicketsPaid(repairTicketsRespVO);
return CommonResult.ok();
}
/**
* 维修工单表 结算
*
* @param vo 工单
* @author 小李
* @date 8:50 2024/9/23
**/
@PostMapping("/settlement")
@Operation(summary = "维修工单表 结算")
public CommonResult<?> setTicketsSettlement(@RequestBody TicketsSettlementVO vo) {
dlRepairTicketsService.setTicketsSettlement(vo);
return CommonResult.ok();
}
/**
* @Author
* @Description 结算审批
* @Date 13:43 2025/8/20
* @Param [vo]
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<?>
**/
@PostMapping("/settlementReview")
@Operation(summary = "维修工单表 结算")
public CommonResult<?> settlementReview(@RequestBody TicketsSettlementVO vo) {
dlRepairTicketsService.settlementReview(vo);
return CommonResult.ok();
}
/**
* @Author
* @Description 查询审批金额
* @Date 14:20 2025/8/20
* @Param [repairTicketsReqVO]
* @return cn.iocoder.yudao.framework.common.pojo.CommonResult<?>
**/
@GetMapping("/getSettlement")
public CommonResult<?> getSettlement(DlRepairTicketsReqVO repairTicketsReqVO) {
return CommonResult.success(dlRepairTicketsService.getSettlement(repairTicketsReqVO));
}
// /**
// * 维修工单表 导出
// *
@ -601,11 +647,15 @@ public class DlRepairTicketsController {
String profitRateWithLabor = statistics.get("profitRateWithLabor") != null ? formatPercentage(statistics.get("profitRateWithLabor").toString()) : "0%";
String profitRateWithoutLabor = statistics.get("profitRateWithoutLabor") != null ? formatPercentage(statistics.get("profitRateWithoutLabor").toString()) : "0%";
rows.add(CollUtil.newArrayList(
"产值:", totalLaborPartsMoney,
"毛利:", totalProfit,
"含工时毛利率:", profitRateWithLabor,
"不含工时毛利率:", profitRateWithoutLabor));
boolean hasAnyPermissions = permissionApi.hasAnyPermissions(SecurityFrameworkUtils.getLoginUserId(), "repair:tick:profit");
if (hasAnyPermissions) {
rows.add(CollUtil.newArrayList(
"产值:", totalLaborPartsMoney,
"毛利:", totalProfit,
"含工时毛利率:", profitRateWithLabor,
"不含工时毛利率:", profitRateWithoutLabor));
}
// 第二行写表头
rows.add(CollUtil.newArrayList("订单编号","维修类别", "客户名称", "车牌号", "车系", "手机号", "经办人姓名", "经办人电话"));

View File

@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.tickets.entity;
import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import cn.iocoder.yudao.module.tickets.vo.TicketsSettlementVO;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@ -249,6 +250,9 @@ public class DlRepairTickets extends TenantBaseDO {
/** 商业险保费 */
private BigDecimal shangye;
/** 支付状态 字典repair_pat_status */
private String payStatus;
/** 更新时上传的图片 */
@TableField(exist = false)
private String image;
@ -258,4 +262,8 @@ public class DlRepairTickets extends TenantBaseDO {
/** 支付方式文本 */
@TableField(exist = false)
private String payTypeText;
@TableField(exist = false)
private String settlementStr;
@TableField(exist = false)
private TicketsSettlementVO settlement;
}

View File

@ -1,10 +1,7 @@
package cn.iocoder.yudao.module.tickets.service;
import cn.iocoder.yudao.module.tickets.entity.DlRepairTickets;
import cn.iocoder.yudao.module.tickets.vo.CustomerAndCarVO;
import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsReqVO;
import cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsRespVO;
import cn.iocoder.yudao.module.tickets.vo.NoticeCusVO;
import cn.iocoder.yudao.module.tickets.vo.*;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
@ -291,4 +288,34 @@ public interface DlRepairTicketsService extends IService<DlRepairTickets> {
**/
Map<String, Object> getStatistics(DlRepairTicketsReqVO repairTicketsReqVO);
/**
* @Author
* @Description 结算申请
* @Date 10:12 2025/8/20
* @Param [repairTicketsRespVO]
* @return void
**/
void setTicketsSettlement(TicketsSettlementVO repairTicketsRespVO);
/**
* @Author
* @Description 结算审批
* @Date 13:41 2025/8/20
* @Param [vo]
* @return void
**/
void settlementReview(TicketsSettlementVO vo);
/**
* @Author
* @Description 查询审批金额
* @Date 14:20 2025/8/20
* @Param [repairTicketsReqVO]
* @return cn.iocoder.yudao.module.tickets.vo.TicketsSettlementVO
**/
TicketsSettlementVO getSettlement(DlRepairTicketsReqVO repairTicketsReqVO);
}

View File

@ -65,6 +65,7 @@ import cn.iocoder.yudao.module.tickets.utils.TicketsOperateUtil;
import cn.iocoder.yudao.module.tickets.vo.*;
import cn.iocoder.yudao.util.CreateQRCodeUtil;
import cn.iocoder.yudao.util.SendSmsUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
@ -97,6 +98,7 @@ import java.util.stream.Collectors;
import static cn.iocoder.yudao.common.BaseConstants.ORDER_TENANT_NAME;
import static cn.iocoder.yudao.common.RepairCons.*;
import static cn.iocoder.yudao.common.RepairDictConstants.BASE_BUSINESS_CONFIG;
import static cn.iocoder.yudao.common.RepairDictConstants.REPAIR_WORK_TYPE;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
@ -389,7 +391,14 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
**/
@Override
public IPage<DlRepairTickets> getTicketsPage(DlRepairTicketsReqVO repairTicketsReqVO, Page<DlRepairTickets> page) {
return baseMapper.getTicketsPage(repairTicketsReqVO, page);
IPage<DlRepairTickets> ticketsPage = baseMapper.getTicketsPage(repairTicketsReqVO, page);
ticketsPage.getRecords().forEach(item -> {
if (ObjectUtil.isNotEmpty(item.getSettlementStr())) {
// 将json字符串转换成对象
item.setSettlement(JSON.parseObject(item.getSettlementStr(), TicketsSettlementVO.class));
}
});
return ticketsPage;
}
/**
@ -685,7 +694,6 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
}
return result;
}
@ -733,33 +741,145 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
// 更新工单
// 在这里把工单的状态更新为已完成---需要判断如果是线上支付需要在支付回调更新----有点问题
if (repairTicketsRespVO.getPayType().equals("01")) {
// 线上支付需要在回调中去更新状态工单状态和订单状态
} else {
// if (repairTicketsRespVO.getPayType().equals("01")) {
// // 线上支付需要在回调中去更新状态工单状态和订单状态
//
// } else {
// 线下支付和签单挂账等其他支付方式才是直接结束工单和订单
DlRepairTickets repairTickets = this.getById(repairTicketsRespVO.getId());
//设置工单支付状态
repairTicketsRespVO.setPayStatus("03");
if ("1".equals(repairTickets.getIsHandover())) {
//已交车已结算那么工单状态改为 已完成
repairTicketsRespVO.setTicketsStatus(TicketsStatusEnum.OVER.getCode());
//工单结束
repairTicketsRespVO.setIsFinish("1");
}
// 根据工单id 查询工单记录中的审批记录
RepairRecords record = repairRecordsService.getOne(Wrappers.<RepairRecords>lambdaQuery()
.eq(RepairRecords::getTicketId, repairTicketsRespVO.getId())
.eq(RepairRecords::getType, RecordTypeEnum.JSSP)
.orderByDesc(RepairRecords::getCreateTime)
.last("limit 1"));
// 提取冗余字段
String otherData = record.getOtherData();
// 将json 转为对象
TicketsSettlementVO approvalVO = JSON.parseObject(otherData, TicketsSettlementVO.class);
// 设置订单金额信息
repairOrderInfo.setPayMoney(approvalVO.getActualMoney());
repairOrderInfo.setGoodsPrice(approvalVO.getMoney());
//判断优惠类型
if (approvalVO.getDiscountType().equals("1")) {
repairOrderInfo.setReduceMoney(BigDecimal.valueOf(approvalVO.getDiscount()));
} else if (approvalVO.getDiscountType().equals("2")) {
// 折扣计算
repairOrderInfo.setReduceMoney(repairOrderInfo.getGoodsPrice().multiply(BigDecimal.valueOf(approvalVO.getDiscount() / 10)));
}
// 设置订单支付时间和支付结果
repairOrderInfo.setPayTime(LocalDateTime.now());
repairOrderInfo.setOrderStatus("1");
}
// }
// 更新工单
baseMapper.updateById(repairTicketsRespVO);
//更新订单
repairOrderInfoService.updateById(repairOrderInfo);
// 记录日志
repairRecordsService.saveRepairRecord(one.getGoodsId(), null, RecordTypeEnum.JS.getCode(), "线下支付结算", null);
repairRecordsService.saveRepairRecord(one.getGoodsId(), null, RecordTypeEnum.SK.getCode(), "线下支付结算", null);
// 更新工单主表时间
refreshUpdateTime(repairTicketsRespVO.getId());
}
/**
* @return void
* @Author
* @Description 结算申请
* @Date 10:13 2025/8/20
* @Param [repairTicketsRespVO]
**/
public void setTicketsSettlement(TicketsSettlementVO vo) {
/*添加结算数据*/
// 将vo转为json
String json = JSON.toJSONString(vo);
//添加维修记录
repairRecordsService.saveRepairRecord(vo.getTicketId(), null, RecordTypeEnum.JSSQ.getCode(), "结算申请", null, json);
/*获取字典 判断是否自动审核通过该结算申请*/
DictDataRespDTO repairSettlementReview = dictDataApi.getDictData(BASE_BUSINESS_CONFIG, "repair_settlement_review");
boolean ifReview = false;
if (ObjectUtil.isNotEmpty(repairSettlementReview)) {
ifReview = repairSettlementReview.getRemark().equals("1");
}
// 如果是自动审核直接修改支付状态
if (ifReview) {
//添加维修记录
repairRecordsService.saveRepairRecord(vo.getTicketId(), null, RecordTypeEnum.JSSP.getCode(), "自动结算审批", null, json);
// 修改工单支付状态为待收款
update(Wrappers.<DlRepairTickets>lambdaUpdate()
.eq(DlRepairTickets::getId, vo.getTicketId())
.set(DlRepairTickets::getPayStatus, "02"));
// 修改工单支付状态为待收款
update(Wrappers.<DlRepairTickets>lambdaUpdate()
.eq(DlRepairTickets::getId, vo.getTicketId())
.set(DlRepairTickets::getPayStatus, "02"));
}
}
/**
* @return void
* @Author
* @Description 结算审批
* @Date 13:41 2025/8/20
* @Param [vo]
*/
@Override
public void settlementReview(TicketsSettlementVO vo) {
/*添加结算审核记录*/
// 将vo转为json
String json = JSON.toJSONString(vo);
//添加维修记录
repairRecordsService.saveRepairRecord(vo.getTicketId(), null, RecordTypeEnum.JSSP.getCode(), "结算审批", null, json);
// 修改工单支付状态为待收款
update(Wrappers.<DlRepairTickets>lambdaUpdate()
.eq(DlRepairTickets::getId, vo.getTicketId())
.set(DlRepairTickets::getPayStatus, "02"));
}
/**
* @return cn.iocoder.yudao.module.tickets.vo.TicketsSettlementVO
* @Author
* @Description 查询审批金额
* @Date 14:20 2025/8/20
* @Param [repairTicketsReqVO]
*/
@Override
public TicketsSettlementVO getSettlement(DlRepairTicketsReqVO repairTicketsReqVO) {
// 根据工单id 查询工单记录中的审批记录
RepairRecords record = repairRecordsService.getOne(Wrappers.<RepairRecords>lambdaQuery()
.eq(RepairRecords::getTicketId, repairTicketsReqVO.getId())
.eq(RepairRecords::getType, RecordTypeEnum.JSSP)
.orderByDesc(RepairRecords::getCreateTime)
.last("limit 1"));
// 提取冗余字段
if (record == null)
return null;
String otherData = record.getOtherData();
// 将json 转为对象
TicketsSettlementVO approvalVO = JSON.parseObject(otherData, TicketsSettlementVO.class);
return approvalVO;
}
/**
* 客户信息和车辆信息 新增修改
* @param customerAndCarVO 用户信息和车辆信息

View File

@ -0,0 +1,40 @@
package cn.iocoder.yudao.module.tickets.vo;
import lombok.Data;
import java.math.BigDecimal;
/**
* @BelongsProject: lanan-system
* @BelongsPackage: cn.iocoder.yudao.module.tickets.vo
* @Author:
* @CreateTime: 2025-08-20 12:47
* @Description: TODO
* @Version: 1.0
*/
@Data
public class TicketsSettlementVO {
/**
* 工单ID
*/
private String ticketId;
/**
* 实际金额
*/
private BigDecimal actualMoney;
/**
* 金额
*/
private BigDecimal money;
/**
* 优惠类型
*/
private String discountType;
/**
* 优惠金额|折扣
*/
private Integer discount;
}

View File

@ -60,6 +60,8 @@
<result property="insuranceType" column="insurance_type" />
<result property="jiaoqiang" column="jiaoqiang" />
<result property="shangye" column="shangye" />
<result property="payStatus" column="pay_status" />
<result property="settlementStr" column="settlementStr"/>
</resultMap>
<resultMap id="APPBaseResultMap" type="cn.iocoder.yudao.module.tickets.vo.DlRepairTicketsRespVO">
@ -191,19 +193,31 @@
SELECT * FROM dl_repair_booking WHERE tickets_id = #{id}
</select>
<select id="getTicketsPage" resultMap="BaseResultMap">
<include refid="Base_SQL"/>
-- 已结算的
SELECT drt.*
<if test="map.payStatus != null and map.payStatus != '' and map.payStatus == '01'">
,drr.other_data AS settlementStr
</if>
FROM dl_repair_tickets drt
<if test="map.payStatus != null and map.payStatus != '' and map.payStatus == '01'">
LEFT JOIN dl_repair_records drr ON drt.id = drr.ticket_id AND drr.type = 'jssq'
</if>
<where>
<!-- 已结算的 -->
<if test="map.ticketsStatus != null and map.ticketsStatus != '' and map.ticketsStatus == '02'">
and drt.tickets_status in ('08', #{map.ticketsStatus})
</if>
-- 已作废的
<!-- 已作废的 -->
<if test="map.ticketsStatus != null and map.ticketsStatus != '' and map.ticketsStatus == '03'">
and drt.tickets_status = #{map.ticketsStatus}
</if>
-- 待结算的
<!-- 待结算的 -->
<if test="map.ticketsStatus != null and map.ticketsStatus != '' and map.ticketsStatus == '01'">
and (drt.tickets_status = #{map.ticketsStatus})
</if>
<if test="map.payStatus != null and map.payStatus != ''">
and drt.pay_status = #{map.payStatus}
</if>
<if test="map.ticketNo != null and map.ticketNo != ''">
and (
drt.ticket_no like concat('%', #{map.ticketNo}, '%')
@ -232,6 +246,7 @@
<if test="map.ticketsWorkStatus != null and map.ticketsWorkStatus != ''">
and drt.tickets_work_status = #{map.ticketsWorkStatus}
</if>
</where>
order by drt.create_time desc
</select>