Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
许允枞 2024-10-30 18:07:13 +08:00
commit 68dd037dcc
13 changed files with 274 additions and 43 deletions

View File

@ -16,6 +16,18 @@
</description>
<dependencies>
<!-- 生成二维码 -->
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>${zxing.version}</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>${zxing.version}</version>
</dependency>
<!-- 百度富文本-->
<dependency>
<groupId>com.blingblingbang</groupId>

View File

@ -66,5 +66,8 @@ public class Company extends TenantBaseDO {
private String loginAccount ;
/** 关联的服务编号(多个以英文逗号隔开)(实际就是这个企业的用户登录后有哪些系统权限) */
private String serviceCodes ;
/** 开户行 */
private String bankAccount;
/** 收款账号 */
private String account;
}

View File

@ -19,6 +19,11 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 维修模块 订单")
@ -95,4 +100,17 @@ public class RepairOrderInfoController {
public CommonResult<?> census() {
return success(repairOrderInfoService.census());
}
/**
* PC支付按钮
*
* @author 小李
* @date 17:26 2024/10/30
* @param id id
**/
@GetMapping("/toPay")
@Operation(summary = "PC支付按钮")
public CommonResult<?> toPay(@RequestParam("id")String id) throws IOException, NoSuchAlgorithmException, SignatureException, InvalidKeyException {
return success(repairOrderInfoService.payTransactions(id));
}
}

View File

@ -0,0 +1,43 @@
package cn.iocoder.yudao.util;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import org.springframework.stereotype.Component;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
/**
* 用于生成二维码的工具类
*
* @author 小李
* @date 14:56 2024/10/30
**/
public class CreateQRCodeUtil {
/**
* 生成二维码的方法
*
* @author 小李
* @date 15:00 2024/10/30
* @param text 二维码的内容
* @param width 二维码的宽度
* @param height 二维码的高度
**/
public static byte[] GenerateQRCode(String text, int width, int height) {
try {
BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height);
try (ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream()) {
MatrixToImageWriter.writeToStream(bitMatrix, "PNG", pngOutputStream);
return pngOutputStream.toByteArray();
}
}catch (Exception e){
e.printStackTrace();
return null;
}
}
}

View File

@ -59,9 +59,11 @@
AND main.phone_number LIKE concat('%',#{entity.phoneNumber},'%')
</if>
<if test="entity.phoneOrCar != null and entity.phoneOrCar != ''">
AND main.phone_number = #{entity.phoneOrCar}
OR car.license_number = #{entity.phoneOrCar}
OR car.vin = #{entity.phoneOrCar}
AND (
main.phone_number LIKE CONCAT('%',#{entity.phoneOrCar},'%')
OR car.license_number LIKE CONCAT('%',#{entity.phoneOrCar},'%')
OR car.vin LIKE CONCAT('%',#{entity.phoneOrCar},'%')
)
</if>
</where>
GROUP BY main.id

View File

@ -334,5 +334,19 @@ public class DlRepairTicketsController {
dlRepairTicketsService.addItems(respVO);
return CommonResult.ok();
}
/**
* 修改工单主表只是主表
*
* @author 小李
* @date 10:25 2024/10/30
* @param respVO 请求对象
**/
@PostMapping("/updateTicket")
@Operation(summary = "修改工单主表,只是主表")
public CommonResult<?> updateTicket(@RequestBody DlRepairTicketsRespVO respVO) {
dlRepairTicketsService.updateTicket(respVO);
return CommonResult.ok();
}
}

View File

@ -217,4 +217,13 @@ public interface DlRepairTicketsService extends IService<DlRepairTickets> {
* @date 16:35 2024/10/26
**/
void autoInspection();
/**
* 修改工单主表只是主表
*
* @author 小李
* @date 10:25 2024/10/30
* @param respVO 请求对象
**/
void updateTicket(DlRepairTicketsRespVO respVO);
}

View File

@ -6,6 +6,8 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.common.*;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
import cn.iocoder.yudao.module.base.entity.RepairWorker;
import cn.iocoder.yudao.module.base.service.RepairRecordsService;
import cn.iocoder.yudao.module.base.service.RepairWorkerService;
@ -13,6 +15,8 @@ import cn.iocoder.yudao.module.base.vo.RepairRecordsPageReqVO;
import cn.iocoder.yudao.module.base.vo.RepairRecordsRespVO;
import cn.iocoder.yudao.module.booking.entity.DlRepairBooking;
import cn.iocoder.yudao.module.booking.service.DlRepairBookingService;
import cn.iocoder.yudao.module.company.entity.Company;
import cn.iocoder.yudao.module.company.service.CompanyService;
import cn.iocoder.yudao.module.conf.entity.BaseType;
import cn.iocoder.yudao.module.conf.service.BaseTypeService;
import cn.iocoder.yudao.module.custom.entity.*;
@ -49,6 +53,7 @@ import cn.iocoder.yudao.module.tickets.service.DlTicketWaresService;
import cn.iocoder.yudao.module.tickets.service.DlTwItemService;
import cn.iocoder.yudao.module.tickets.tools.WordUtil;
import cn.iocoder.yudao.module.tickets.vo.*;
import cn.iocoder.yudao.util.CreateQRCodeUtil;
import cn.iocoder.yudao.util.SendSmsUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -59,6 +64,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.PictureType;
import com.deepoove.poi.plugin.table.HackLoopTableRenderPolicy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
@ -170,6 +177,10 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
@Lazy
private BaseTypeService baseTypeService;
@Resource
@Lazy
private CompanyService companyService;
/**
* 维修工单表 新增
*
@ -513,9 +524,8 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
params.put("plate", tickets.getCarNo());
params.put("frameNumber", tickets.getCarVin());
params.put("billingTime", time.format(tickets.getCreateTime()));
// todo 已行里程
// 取不到先给未知
params.put("mileage", "未知");
// 已行里程
params.put("mileage", tickets.getMileageTraveled());
// 旧件处理
// 获取字典数据
List<DictDataRespDTO> dataList = dictDataApi.getDictDataList(DICT_REPAIR_PART_DISPOSAL);
@ -526,10 +536,9 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
// 车辆其他信息发动机号码三包单位保险名称车型
CarMain carMain = carMainService.getById(tickets.getCarId());
params.put("engineNumber", carMain.getEngineNumber());
// todo 三包单位保险名称
// 取不到先给未知
params.put("tripleUnit", "未知");
params.put("insuranceName", "未知");
// 三包单位保险名称
params.put("tripleUnit", tickets.getThreePackUnits());
params.put("insuranceName", tickets.getInsuranceName());
// 先查车辆对应的品牌
String brandAndModel = "";
if (ObjectUtil.isNotEmpty(carMain.getCarBrand())) {
@ -642,6 +651,16 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
params.put("matFavorable", matFavorable);
// 计算没打折的工单总价
BigDecimal matTotalCost = titems.stream().map(item -> item.getItemPrice().multiply(BigDecimal.valueOf(item.getItemCount()))).reduce(BigDecimal.ZERO, BigDecimal::add);
// 加上特殊费用
// 管理费
BigDecimal managerMoney = ObjectUtil.isNotEmpty(tickets.getManagerMoney()) ? tickets.getManagerMoney() : new BigDecimal("0");
// 救援费
BigDecimal rescueMoney = ObjectUtil.isNotEmpty(tickets.getRescueMoney()) ? tickets.getRescueMoney() : new BigDecimal("0");
// 三包费
BigDecimal threePackMoney = ObjectUtil.isNotEmpty(tickets.getThreePackMoney()) ? tickets.getThreePackMoney() : new BigDecimal("0");
// 定损费
BigDecimal confirmFaultMoney = ObjectUtil.isNotEmpty(tickets.getConfirmFaultMoney()) ? tickets.getConfirmFaultMoney() : new BigDecimal("0");
matTotalCost = matTotalCost.add(managerMoney).add(rescueMoney).add(threePackMoney).add(confirmFaultMoney);
params.put("matTotalCost", matTotalCost);
// 应收费目前是工单的打折后的总价
params.put("allCost", tickets.getTotalPrice());
@ -661,14 +680,12 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
// 材料工时优惠 材料优惠+工时优惠
params.put("matlabourFavorable", "0.00");
// todo 目前取不到管理费救援费三包费定损费结算备注这个是因为和工单备注用的同一个客户签字
// 取不到的先默认为0或未知
params.put("manageCost", 0.00);
params.put("rescueCost", 0.00);
params.put("tripleCost", 0.00);
params.put("lossCost", 0.00);
params.put("costCondition", "未知");
params.put("costRemark", "未知");
// 管理费救援费三包费定损费结算备注这个是因为和工单备注用的同一个todo 客户签字
params.put("manageCost", ObjectUtil.isNotEmpty(tickets.getManagerMoney()) ? tickets.getManagerMoney() : "0.00") ;
params.put("rescueCost", ObjectUtil.isNotEmpty(tickets.getRescueMoney()) ? tickets.getRescueMoney() : "0.00");
params.put("tripleCost", ObjectUtil.isNotEmpty(tickets.getThreePackMoney()) ? tickets.getThreePackMoney() : "0.00");
params.put("lossCost", ObjectUtil.isNotEmpty(tickets.getConfirmFaultMoney()) ? tickets.getConfirmFaultMoney() : "0.00");
params.put("costRemark", tickets.getBillingRemark());
/*
5最后结尾
*/
@ -678,11 +695,11 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
if (ObjectUtil.isNotEmpty(adviser) && ObjectUtil.isNotEmpty(adviser.getMobile())) {
params.put("serviceTelephone", adviser.getMobile());
}
// 结算日期
params.put("settleDate", date.format(LocalDateTime.now()));
// 取订单
RepairOrderInfo orderInfo = repairOrderInfoService.getOne(new LambdaQueryWrapper<RepairOrderInfo>().eq(RepairOrderInfo::getGoodsId, tickets.getId()));
if (ObjectUtil.isNotEmpty(orderInfo)) {
if (ObjectUtil.isNotEmpty(orderInfo.getPayTime())) {
params.put("settleDate", date.format(orderInfo.getPayTime()));
}
// 付款情况
// 先取支付字典
List<DictDataRespDTO> payTypes = dictDataApi.getDictDataList(DICT_REPAIR_PAY_TYPE);
@ -696,12 +713,51 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
params.put("costCondition", costCondition);
}
// todo 目前取不到单位开户行地址账号
// 单位开户行地址账号
// 取当前租户的公司们
Long tenantId = tickets.getTenantId();
List<Company> companies = companyService.list(new LambdaQueryWrapper<Company>().in(Company::getTenantId, tenantId));
// 得到属于当前业务的公司
Company company = companies.stream().filter(item -> {
String[] service = item.getServiceCodes().split(",");
for (String s : service) {
if (s.equals("weixiu")) {
return true;
}
}
return false;
}).findFirst().orElse(null);
String corporation = "";
String bank = "";
String bankAddress = "";
String account = "";
if (company != null){
corporation = company.getCorpName();
bankAddress = company.getAddress();
bank = company.getBankAccount();
account = company.getAccount();
}
// 取不到的先给未知
params.put("corporation", "未知");
params.put("bank", "未知");
params.put("bankAddress", "未知");
params.put("account", "未知");
params.put("corporation", corporation);
params.put("bank", bank);
params.put("bankAddress", bankAddress);
params.put("account", account);
// 调支付接口 todo 这个地方应该还要加东西
String payUrl = "";
try {
Map<String, Object> stringObjectMap = repairOrderInfoService.payTransactions(orderInfo.getId());
payUrl = (String) stringObjectMap.get("prepay_id");
}catch (Exception e){
e.printStackTrace();
throw exception0(500, "系统异常");
}
// 生成收款二维码
int width = 100, height = 100;
byte[] texts = CreateQRCodeUtil.GenerateQRCode(payUrl, width, height);
if (ObjectUtil.isNotEmpty(texts)){
params.put("qrCode", new PictureRenderData(width, height, PictureType.PNG, texts));
}
Configure config = configureBuilder.build();
try {
@ -742,14 +798,25 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
} else if (userRoleCode.equals(RepairRoleEnum.REPAIR_STAFF.getCode())) {
//维修工进一步判断是否是班组长
boolean ifLeader = repairWorkerService.getIfLeader();
repairTicketsReqVO.setRoleCode(RepairRoleEnum.REPAIR_STAFF.getCode());
if (ifLeader) {
//班组长看本班组所有数据
RepairWorker one = repairWorkerService.getOne(new LambdaQueryWrapper<RepairWorker>().eq(RepairWorker::getUserId, SecurityFrameworkUtils.getLoginUserId()));
// 查自己班组的员工信息
List<RepairWorker> list = repairWorkerService.list(new LambdaQueryWrapper<RepairWorker>().eq(RepairWorker::getWorkType, one.getWorkType()));
// 所有的员工信息
List<Long> userIds = list.stream().map(RepairWorker::getUserId).collect(Collectors.toList());
String userIdsStr = "";
List<Long> userIds = new ArrayList<>();
for (RepairWorker worker:list){
userIds.add(worker.getUserId());
if("".equals(userIdsStr)){
userIdsStr = String.valueOf(worker.getUserId());
}else{
userIdsStr = ","+worker.getUserId();
}
}
repairTicketsReqVO.setUserIds(userIds);
repairTicketsReqVO.setUserIdsStr(userIdsStr);
} else {
//普通维修工
repairTicketsReqVO.setUserIds(Collections.singletonList(SecurityFrameworkUtils.getLoginUserId()));
@ -1276,6 +1343,20 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
tickets.setOtherPrice(reduce);
}
});
// 工单总价还需要变把其他新加的费用也需要算上
// 查主表
DlRepairTickets oldTicket = baseMapper.selectById(ticketId);
// 管理费
BigDecimal managerMoney = ObjectUtil.isNotEmpty(oldTicket.getManagerMoney()) ? oldTicket.getManagerMoney() : new BigDecimal("0");
// 救援费
BigDecimal rescueMoney = ObjectUtil.isNotEmpty(oldTicket.getRescueMoney()) ? oldTicket.getRescueMoney() : new BigDecimal("0");
// 三包费
BigDecimal threePackMoney = ObjectUtil.isNotEmpty(oldTicket.getThreePackMoney()) ? oldTicket.getThreePackMoney() : new BigDecimal("0");
// 定损费
BigDecimal confirmFaultMoney = ObjectUtil.isNotEmpty(oldTicket.getConfirmFaultMoney()) ? oldTicket.getConfirmFaultMoney() : new BigDecimal("0");
tickets.setTotalPrice(tickets.getTotalPrice().add(managerMoney).add(rescueMoney).add(threePackMoney).add(confirmFaultMoney));
return baseMapper.updateById(tickets) > 0;
}
@ -1392,6 +1473,26 @@ public class DlRepairTicketsServiceImpl extends ServiceImpl<DlRepairTicketsMappe
repairRecordsService.saveRepairRecord(item.getId(), null, RecordTypeEnum.ZJ.getCode(), "该工单由系统自动总检完成", null);
});
}
/**
* 修改工单主表只是主表
*
* @author 小李
* @date 10:25 2024/10/30
* @param respVO 请求对象
**/
@Override
@DSTransactional
public void updateTicket(DlRepairTicketsRespVO respVO){
// 更新主表
baseMapper.updateById(respVO);
// 重新计算
boolean flag = computeTicket(respVO.getId());
if (!flag){
throw exception0(500, "系统异常");
}
}
}

View File

@ -25,6 +25,12 @@ public class DlRepairTicketsReqVO extends DlRepairTickets {
/** 工单中项目指定的施工人员的ids */
private List<Long> userIds;
/** 工单中项目指定的施工人员的ids字符串拼接 */
private String userIdsStr;
/** 查询类型(waiting 待处理的 | all 所有数据) */
private String selectType;
/** 人员角色code */
private String roleCode;
}

View File

@ -58,5 +58,7 @@ public class DlRepairTicketsRespVO extends DlRepairTickets {
/** 如果是完成并移交下一班组,就有移交给了那一个班组 */
private String nextName;
/** 维修班组长是否可以重新派工--当前施工人是自己或者本班组内的人员 */
private Boolean canOperate;
}

View File

@ -106,6 +106,7 @@
<result property="threePackMoney" column="three_pack_money" />
<result property="confirmFaultMoney" column="confirm_fault_money" />
<result property="billingRemark" column="billing_remark" />
<result property="canOperate" column="can_operate" />
<association property="booking" javaType="cn.iocoder.yudao.module.booking.entity.DlRepairBooking" select="selectBookingById" column="id"/>
<collection property="itemList" column="id" ofType="cn.iocoder.yudao.module.tickets.entity.DlRepairTitem" select="selectItemList" />
</resultMap>
@ -208,7 +209,13 @@
<select id="getPageType" resultMap="APPBaseResultMap">
-- 查待处理数据 --
select drt.*
<if test="map.roleCode=='repair_staff'">
-- 维修工,需要判断出当前用户是否可以重新派工 --
, IF(FIND_IN_SET(drt.now_repair_id, #{map.userIdsStr}) > 0,true,false) AS can_operate
</if>
from dl_repair_tickets drt
left join dl_repair_titem drti
on drt.id = drti.ticket_id AND drti.deleted = '0'
where (drt.deleted = '0') AND drt.tickets_status IN ('04','05','01','07')
<if test="map.ticketNo != null and map.ticketNo != ''">
and (
@ -238,22 +245,35 @@
</when>
<otherwise>
-- 正常查询用的逻辑 --
<if test="map.adviserId != null and map.adviserId != ''">
-- 查服务顾问 待处理的 工单未完成并且服务顾问是自己的 工单已完成且当前处理人是自己的--
AND ( drt.is_finish = '0' AND drt.adviser_id = #{map.adviserId} )
OR (drt.is_finish = '1' AND drt.now_repair_id = #{map.adviserId})
</if>
<if test="map.userIds != null and map.userIds.size > 0">
-- 查维修工、总检待处理的 --
AND (drt.is_finish = '0')
AND (drt.now_repair_id in
<foreach collection="map.userIds" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
)
</if>
<choose>
<when test="map.roleCode=='repair_staff'">
-- 维修工的查询逻辑,涉及维修项目的维修工是自己或者本班组内的--
AND (
<foreach item="item" collection="map.userIds" index="index" open="" separator="or" close="">
find_in_set(#{item}, drti.repair_ids) > 0
</foreach>
)
</when>
<otherwise>
<if test="map.adviserId != null and map.adviserId != ''">
-- 查服务顾问 待处理的 工单未完成并且服务顾问是自己的 工单已完成且当前处理人是自己的--
AND ( drt.is_finish = '0' AND drt.adviser_id = #{map.adviserId} )
OR (drt.is_finish = '1' AND drt.now_repair_id = #{map.adviserId})
</if>
<if test="map.userIds != null and map.userIds.size > 0">
-- 查总检待处理的 --
AND (drt.is_finish = '0')
AND (drt.now_repair_id in
<foreach collection="map.userIds" item="item" index="index" open="(" separator="," close=")">
#{item}
</foreach>
)
</if>
</otherwise>
</choose>
</otherwise>
</choose>
GROUP BY drt.id
order by drt.create_time desc
</select>
@ -311,7 +331,7 @@
-- 维修工或维修厂长查所有的就是维修人是自己的或者是自己班组内的 --
and (
<foreach item="item" collection="map.userIds" index="index" open="" separator="or" close="">
find_in_set(#{item}, drt.now_repair_id) > 0
find_in_set(#{item}, drti.repair_ids) > 0
</foreach>
)
</if>

View File

@ -52,6 +52,7 @@
<mapstruct.version>1.5.5.Final</mapstruct.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<ueditor.version>1.1.2</ueditor.version>
<zxing.version>3.4.1</zxing.version>
</properties>
<dependencyManagement>