Merge remote-tracking branch 'origin/master'

This commit is contained in:
zjf committed 2025-08-28 18:00:52 +08:00
commit bf69954e9d
27 files changed
+1280 -128

No files matched your search

+27
View File
@@ -220,6 +220,33 @@ CREATE TABLE hard_car
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='购物车表';
-- ----------------------------
-- Table structure for hard_after_sale_car
-- ----------------------------
DROP TABLE IF EXISTS `hard_after_sale_car`;
CREATE TABLE hard_after_sale_car
(
id bigint NOT NULL COMMENT '编号',
refund_id bigint NOT NULL COMMENT '退款id',
parent_car_id bigint NOT NULL COMMENT '父购物车id',
product_id bigint NOT NULL COMMENT '商品id',
product_name varchar(128) NOT NULL COMMENT '商品名',
product_pic varchar(256) NOT NULL COMMENT '商品图片',
product_price bigint NOT NULL COMMENT '商品价格',
product_count int NOT NULL COMMENT '数量',
product_weight decimal(10, 2) COMMENT '重量',
total_price bigint COMMENT '总价(分)',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='购物车退款表';
-- ----------------------------
-- Table structure for hard_parent_car
-- ----------------------------
+28
View File
@@ -58,6 +58,34 @@ CREATE TABLE `sys_user_face`
COLLATE = utf8mb4_general_ci COMMENT ='人脸样本表';
CREATE INDEX idx_dept_id ON sys_user_face (user_id);
-- ----------------------------
-- Table structure for sys_user_car
-- ----------------------------
DROP TABLE IF EXISTS sys_user_car;
CREATE TABLE `sys_user_car`
(
id bigint NOT NULL COMMENT '编号',
user_id bigint NOT NULL COMMENT '用户ID',
car_number char(64) COMMENT '车牌号',
car_type char(32) COMMENT '车辆类型(字典)',
enable_status char(32) COMMENT '启用状态(字典)',
process_id varchar(256) COMMENT '流程id',
process_status varchar(10) NOT NULL COMMENT '审核状体',
process_time datetime COMMENT '审核时间',
create_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '创建人',
create_time datetime DEFAULT NULL COMMENT '创建时间',
update_by varchar(64) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '修改人',
update_time datetime DEFAULT NULL COMMENT '修改时间',
del_flag char(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记',
tenant_id bigint DEFAULT NULL COMMENT '租户ID',
PRIMARY KEY (id)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4
COLLATE = utf8mb4_general_ci COMMENT ='人员车辆表';
-- ----------------------------
-- Table structure for mch_manage
-- ----------------------------
@@ -0,0 +1,16 @@
package com.bsd.pjcloud.hard.api.dto.order;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity;
import lombok.Data;
import java.util.List;
@Data
public class HardAdminRefundReinforceDto extends HardAdminRefundDto {
/**
* 退款商品列表
*/
private List<HardAfterSaleCarEntity> carList;
}
@@ -0,0 +1,131 @@
package com.bsd.pjcloud.hard.api.entity.order;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* 购物车退款表
*/
@Data
@TenantTable
@TableName("hard_after_sale_car")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "购物车退款表")
public class HardAfterSaleCarEntity extends Model<HardAfterSaleCarEntity> {
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "编号")
private Long id;
/**
* 退款id
*/
@Schema(description = "退款id")
private Long refundId;
/**
* 父购物车id
*/
@Schema(description = "父购物车id")
private Long parentCarId;
/**
* 商品id
*/
@Schema(description = "商品id")
private Long productId;
/**
* 商品名
*/
@Schema(description = "商品名")
private String productName;
/**
* 商品图片
*/
@Schema(description = "商品图片")
private String productPic;
/**
* 商品价格
*/
@Schema(description = "商品价格")
private Long productPrice;
/**
* 商品性质(字典)
*/
@Schema(description = "商品性质(字典)")
private String productNature;
/**
* 数量
*/
@Schema(description = "数量")
private Integer productCount;
/**
* 重量
*/
@Schema(description = "重量")
private BigDecimal productWeight;
/**
* 总价(分)
*/
@Schema(description = "总价(分)")
private Long totalPrice;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
@@ -23,154 +24,154 @@ import java.time.LocalDateTime;
@Schema(description = "售后订单")
public class HardAfterSaleEntity extends Model<HardAfterSaleEntity> {
/**
* 售后编号
*/
/**
* 售后编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description="售后编号")
@Schema(description = "售后编号")
private Long id;
/**
* 售后单号
*/
@Schema(description="售后单号")
/**
* 售后单号
*/
@Schema(description = "售后单号")
private String no;
/**
* 售后类型
*/
@Schema(description="售后类型")
/**
* 售后类型
*/
@Schema(description = "售后类型")
private String type;
/**
* 售后状态
*/
@Schema(description="售后状态")
/**
* 售后状态
*/
@Schema(description = "售后状态")
private String status;
/**
* 售后方式
*/
@Schema(description="售后方式")
/**
* 售后方式
*/
@Schema(description = "售后方式")
private String way;
/**
* 用户id
*/
@Schema(description="用户id")
/**
* 用户id
*/
@Schema(description = "用户id")
private Long userId;
/**
* 申请原因
*/
@Schema(description="申请原因")
/**
* 申请原因
*/
@Schema(description = "申请原因")
private String applyReason;
/**
* 补充描述
*/
@Schema(description="补充描述")
/**
* 补充描述
*/
@Schema(description = "补充描述")
private String applyDescription;
/**
* 补充凭证图片
*/
@Schema(description="补充凭证图片")
/**
* 补充凭证图片
*/
@Schema(description = "补充凭证图片")
private String applyPicUrls;
/**
* 订单编号
*/
@Schema(description="订单编号")
/**
* 订单编号
*/
@Schema(description = "订单编号")
private Long orderId;
/**
* 订单流水号
*/
@Schema(description="订单流水号")
/**
* 订单流水号
*/
@Schema(description = "订单流水号")
private String orderNo;
/**
* 审批时间
*/
@Schema(description="审批时间")
/**
* 审批时间
*/
@Schema(description = "审批时间")
private LocalDateTime auditTime;
/**
* 审批人
*/
@Schema(description="审批人")
/**
* 审批人
*/
@Schema(description = "审批人")
private Long auditUserId;
/**
* 审批备注
*/
@Schema(description="审批备注")
/**
* 审批备注
*/
@Schema(description = "审批备注")
private String auditReason;
/**
* 退款金额,单位:分
*/
@Schema(description="退款金额,单位:分")
/**
* 退款金额,单位:分
*/
@Schema(description = "退款金额,单位:分")
private Integer refundPrice;
/**
* 支付退款编号
*/
@Schema(description="支付退款编号")
/**
* 支付退款编号
*/
@Schema(description = "支付退款编号")
private Long payRefundId;
/**
* 退款时间
*/
@Schema(description="退款时间")
/**
* 退款时间
*/
@Schema(description = "退款时间")
private LocalDateTime refundTime;
/**
* 退货时间
*/
@Schema(description="退货时间")
/**
* 退货时间
*/
@Schema(description = "退货时间")
private LocalDateTime deliveryTime;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建人")
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description="创建时间")
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改人")
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description="修改时间")
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description="删除标记")
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description="租户ID")
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -3,12 +3,14 @@ package com.bsd.pjcloud.hard.controller.hard;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.hard.api.constant.HardProductNatureEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.dto.async.SyncOfflineReqVo;
import com.bsd.pjcloud.hard.api.dto.hard.HandCancelCodeDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardBindDto;
import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardChartLatitudeVo;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.vo.HardInvoiceVo;
import com.bsd.pjcloud.hard.api.vo.manager.HardManagerVo;
import com.bsd.pjcloud.hard.api.vo.android.HardAdUserVo;
@@ -23,6 +25,7 @@ import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
@RestController
@@ -68,6 +71,17 @@ public class HardApiController {
@Operation(summary = "创建订单")
@Idempotent(expireTime = 10, info = "正在创建订单中,请勿重复操作")
public R<Long> createOrder(@Valid @RequestBody HardCreateOrderDto dto) {
// 处理商品类型
if (ObjectUtil.isNotEmpty(dto.getList())) {
for (HardCreateCarDto item : dto.getList()) {
if (ObjectUtil.isEmpty(item.getProductNature())) continue;
if (ObjectUtil.isNotEmpty(item.getProductWeight()) && item.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
item.setProductNature(HardProductNatureEnum.WEIGHT);
} else if (ObjectUtil.isNotEmpty(item.getProductCount())) {
item.setProductNature(HardProductNatureEnum.DEFAULT);
}
}
}
return R.ok(hardwareOrderService.createOrder(dto));
}
@@ -10,10 +10,7 @@ import com.bsd.pjcloud.common.idempotent.annotation.Idempotent;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.hard.api.dto.order.HardAdminRefundDto;
import com.bsd.pjcloud.hard.api.dto.order.HardAfterSaleDto;
import com.bsd.pjcloud.hard.api.dto.order.HardDisagreeDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.*;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleLogEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardAfterSaleVo;
@@ -26,6 +23,7 @@ import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@@ -115,6 +113,15 @@ public class HardAfterSaleController {
return R.ok(hardAfterSaleService.adminRefund(dto, user));
}
@PostMapping(value = "/admin-reinforce-refund")
@Operation(summary = "后台强化退款")
@Idempotent(expireTime = 10, info = "正在退款中,请勿重复操作")
@PreAuthorize("@pms.hasPermission('hard_hardAfterSale_adminRefund')")
public R<Boolean> adminReinforceRefund(@RequestBody HardAdminRefundReinforceDto dto) {
PjcloudUser user = SecurityUtils.getUser();
return R.ok(hardAfterSaleService.adminReinforceRefund(dto, user));
}
@GetMapping(value = "/history")
@Operation(summary = "查询售后进度")
public R<List<HardAfterSaleLogEntity>> history(@RequestParam Long id) {
@@ -14,9 +14,11 @@ import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.dto.app.HardCarSaveOrUpdateDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCarDto;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.service.HardAfterSaleCarService;
import com.bsd.pjcloud.hard.service.HardCarService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import org.springframework.security.access.prepost.PreAuthorize;
@@ -46,6 +48,7 @@ public class HardCarController {
private final HardCarService hardCarService;
private final HardOrderService hardOrderService;
private final HardAfterSaleCarService hardAfterSaleCarService;
/* ************************************* start app start ************************************* */
@GetMapping("/app/mch-detail")
@@ -88,9 +91,16 @@ public class HardCarController {
return R.ok(hardCarService.pageJoin(page, dto));
}
@GetMapping("/refund-car")
@Operation(summary = "查询退款购物车根据订单id")
public R<List<HardAfterSaleCarEntity>> refundCar(@RequestParam Long orderId) {
return R.ok(hardAfterSaleCarService.getByOrderId(orderId));
}
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('hard_hardCar_view')")
public R getHardCarPage(@ParameterObject Page page, @ParameterObject HardCarEntity hardCar) {
LambdaQueryWrapper<HardCarEntity> wrapper = Wrappers.lambdaQuery();
return R.ok(hardCarService.page(page, wrapper));
@@ -0,0 +1,15 @@
package com.bsd.pjcloud.hard.mapper.order;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface HardAfterSaleCarMapper extends PjcloudBaseMapper<HardAfterSaleCarEntity> {
List<HardAfterSaleCarEntity> getByCarPrentId(@Param("carParentId") Long carParentId);
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.hard.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import java.util.List;
public interface HardAfterSaleCarService extends IService<HardAfterSaleCarEntity> {
List<HardAfterSaleCarEntity> getByOrderId(Long orderId);
List<HardAfterSaleCarEntity> getByCarPrentId(Long carParentId);
void create(List<HardAfterSaleCarEntity> carList, HardOrderEntity order, HardAfterSaleEntity afterSale);
}
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.dto.order.HardAdminRefundDto;
import com.bsd.pjcloud.hard.api.dto.order.HardAdminRefundReinforceDto;
import com.bsd.pjcloud.hard.api.dto.order.HardAfterSaleDto;
import com.bsd.pjcloud.hard.api.dto.order.HardDisagreeDto;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
@@ -69,6 +70,11 @@ public interface HardAfterSaleService extends IService<HardAfterSaleEntity> {
*/
Boolean adminRefund(HardAdminRefundDto dto, PjcloudUser user);
/**
* 后台强化退款
*/
Boolean adminReinforceRefund(HardAdminRefundReinforceDto dto, PjcloudUser user);
/**
* 消费机限时退款
*/
@@ -14,6 +14,7 @@ import com.bsd.pjcloud.hard.api.dto.hard.HardCreateOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.HardCreateCarDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.app.HardAppCreateOrderDto;
import com.bsd.pjcloud.hard.api.entity.order.HardCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.thirdparty.dto.ks.KsRecognitionCallbackDto;
@@ -104,6 +105,8 @@ public interface HardOrderService extends IService<HardOrderEntity> {
*/
void fastenerInventory(HardOrderEntity order, YesNoEnum isReduce);
void fastenerInventory(HardOrderEntity order, List<HardCarEntity> refundCarList, YesNoEnum isReduce);
/**
* 核销硬件二维码
*/
@@ -0,0 +1,58 @@
package com.bsd.pjcloud.hard.service.impl.order;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.mapper.order.HardAfterSaleCarMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.HardAfterSaleCarService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.util.ArrayList;
import java.util.List;
/**
* 购物车退款表
*/
@Validated
@Slf4j
@RequiredArgsConstructor
@Service
public class HardAfterSaleCarServiceImpl extends ServiceImpl<HardAfterSaleCarMapper, HardAfterSaleCarEntity> implements HardAfterSaleCarService {
private final HardOrderMapper hardOrderMapper;
@Override
public List<HardAfterSaleCarEntity> getByOrderId(Long orderId) {
HardOrderEntity order = hardOrderMapper.selectById(orderId);
if (ObjectUtil.isEmpty(order)) return null;
return getByCarPrentId(order.getParentCarId());
}
@Override
public List<HardAfterSaleCarEntity> getByCarPrentId(Long carParentId) {
return baseMapper.getByCarPrentId(carParentId);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void create(List<HardAfterSaleCarEntity> carList, HardOrderEntity order, HardAfterSaleEntity afterSale) {
if (ObjectUtil.isEmpty(carList)) return;
carList = carList.stream().map(item -> {
item.setParentCarId(order.getParentCarId());
item.setRefundId(afterSale.getId());
return item;
}).toList();
List<HardAfterSaleCarEntity> saveList = new ArrayList<>(carList).stream().map(item -> {
item.setId(null);
return item;
}).toList();
saveBatch(saveList);
}
}
@@ -20,6 +20,8 @@ import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.hard.api.constant.HardProductNatureEnum;
import com.bsd.pjcloud.hard.api.constant.HardTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderStatusEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardOrderTypeEnum;
import com.bsd.pjcloud.hard.api.constant.order.HardPayTypeEnum;
@@ -28,31 +30,26 @@ import com.bsd.pjcloud.hard.api.constant.refund.HardRefundStatusEnum;
import com.bsd.pjcloud.hard.api.constant.refund.HardSaleStatusEnum;
import com.bsd.pjcloud.hard.api.constant.refund.HardSaleTypeEnum;
import com.bsd.pjcloud.hard.api.dto.ali.AliRefundDto;
import com.bsd.pjcloud.hard.api.dto.order.HardAdminRefundDto;
import com.bsd.pjcloud.hard.api.dto.order.HardAfterSaleDto;
import com.bsd.pjcloud.hard.api.dto.order.HardDisagreeDto;
import com.bsd.pjcloud.hard.api.dto.order.HardOrderDto;
import com.bsd.pjcloud.hard.api.dto.order.*;
import com.bsd.pjcloud.hard.api.dto.wechat.WechatRefundDto;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleLogEntity;
import com.bsd.pjcloud.hard.api.entity.order.HardOrderEntity;
import com.bsd.pjcloud.hard.api.entity.order.*;
import com.bsd.pjcloud.hard.api.utils.HardUtil;
import com.bsd.pjcloud.hard.api.vo.order.HardAfterSaleVo;
import com.bsd.pjcloud.hard.api.vo.order.HardCarVo;
import com.bsd.pjcloud.hard.api.vo.order.HardOrderVo;
import com.bsd.pjcloud.hard.api.vo.wechat.WechantRefunCallbackVo;
import com.bsd.pjcloud.hard.api.vo.wechat.WechatRefundVo;
import com.bsd.pjcloud.hard.mapper.order.HardAfterSaleLogMapper;
import com.bsd.pjcloud.hard.mapper.order.HardAfterSaleMapper;
import com.bsd.pjcloud.hard.mapper.order.HardCarMapper;
import com.bsd.pjcloud.hard.mapper.order.HardOrderMapper;
import com.bsd.pjcloud.hard.service.AlipayService;
import com.bsd.pjcloud.hard.service.HardAfterSaleService;
import com.bsd.pjcloud.hard.service.HardOrderService;
import com.bsd.pjcloud.hard.service.WechatPayService;
import com.bsd.pjcloud.hard.service.*;
import com.bsd.pjcloud.wallet.api.dto.recharge.WalletRechargeRefundDto;
import com.bsd.pjcloud.wallet.api.feign.RemoteWalletRechargeService;
import com.bsd.pjcloud.wallet.api.vo.recharge.WalletRechargeVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
@@ -83,6 +80,8 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
private final RemoteUserService userService;
private final RemoteDeptService deptService;
private final RemoteWalletRechargeService walletRechargeService;
private final HardCarService hardCarService;
private final HardAfterSaleCarService hardAfterSaleCarService;
@Override
@@ -230,7 +229,7 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
// 生成退款单号
if (ObjectUtil.isEmpty(prefixStr)) prefixStr = "hard";
String refundCode = prefixStr + "_" + order.getId();
// 创建退款单
// 查询总的退款金额
Integer refundPrice = afterSale.getRefundPrice();
if (ObjectUtil.isEmpty(refundPrice)) {
refundPrice = order.getPayPrice();
@@ -401,10 +400,6 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
if (!HardOrderTypeEnum.isRefund(orderTypeEnum)) {
throw new RuntimeException("该订单类型不支持退款");
}
// 校验订单是否已退款
// if (ObjectUtil.isNotEmpty(order.getPayRefundId())) {
// throw new RuntimeException("发起退款失败,订单已退款");
// }
// 查询所有成功的退款
List<HardAfterSaleEntity> afterList = baseMapper.selectList(new LambdaQueryWrapper<HardAfterSaleEntity>()
.eq(HardAfterSaleEntity::getOrderId, order.getId())
@@ -419,6 +414,33 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
return orderVo;
}
public void validateOrderCarCanRefund(HardOrderEntity order, List<HardAfterSaleCarEntity> refundCarList) {
if (ObjectUtil.isEmpty(refundCarList)) throw new RuntimeException("售后商品列表不能为空");
// 查询订单购物车
List<HardCarVo> orderCarList = hardCarService.getByOrderId(order.getId());
if (ObjectUtil.isEmpty(orderCarList)) throw new RuntimeException("订单购物车不存在");
// 查询已退款商品
List<HardAfterSaleCarEntity> refundSuccessCarList = hardAfterSaleCarService.getByCarPrentId(order.getParentCarId());
for (HardAfterSaleCarEntity refundCar : refundCarList) {
HardCarVo orderCar = orderCarList.stream().filter(v -> ObjectUtil.equal(v.getId(), refundCar.getId())).findFirst().orElse(null);
if (orderCar == null) throw new RuntimeException("退款商品<" + refundCar.getProductName() + ">不存在");
int refundCount = 0;
if (ObjectUtil.isNotEmpty(refundCar.getProductCount())) {
refundCount = refundCar.getProductCount();
}
// 已经退货成功的商品列表
if (ObjectUtil.isNotEmpty(refundSuccessCarList)) {
HardAfterSaleCarEntity refundSuccessCar = refundSuccessCarList.stream().filter(v -> ObjectUtil.equal(v.getId(), refundCar.getId())).findFirst().orElse(null);
if (ObjectUtil.isNotEmpty(refundSuccessCar)) {
refundCount += refundSuccessCar.getProductCount();
}
}
if (orderCar.getProductCount() < refundCount) {
throw new RuntimeException("退款商品<" + refundCar.getProductName() + ">数量超出");
}
}
}
private HardAfterSaleEntity validateAfterSaleAuditable(Long id) {
HardAfterSaleEntity afterSale = baseMapper.selectById(id);
if (afterSale == null) throw new RuntimeException("售后单不存在");
@@ -500,6 +522,70 @@ public class HardAfterSaleServiceImpl extends ServiceImpl<HardAfterSaleMapper, H
return true;
}
/**
* 后台强化退款
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean adminReinforceRefund(HardAdminRefundReinforceDto dto, PjcloudUser user) {
if (ObjectUtil.isEmpty(dto.getCarList())) throw new RuntimeException("退款商品列表不能为空");
// 校验订单是否可以退款
HardOrderVo order = validateOrderCanRefund(dto.getOrderId());
// 校验订单购物车是否支持退款
validateOrderCarCanRefund(order, dto.getCarList());
// 添加售后订单
HardAfterSaleEntity saveObj = BeanUtils.toBean(dto, HardAfterSaleEntity.class);
String refundCode = "hard_" + order.getId();
// 计算退款金额
List<HardCreateCarDto> computerCarList = dto.getCarList().stream().map((item) -> {
HardCreateCarDto entity = new HardCreateCarDto();
entity.setParentCarId(item.getParentCarId());
entity.setProductId(item.getProductId());
entity.setProductNature(HardProductNatureEnum.valueOfByType(item.getProductNature()));
entity.setProductCount(item.getProductCount());
entity.setProductWeight(item.getProductWeight());
return entity;
}).toList();
int refundPrice = hardCarService.computerCarTotalPrice(HardTypeEnum.valueOfByType(order.getSysType()), HardOrderTypeEnum.valueOfByType(order.getOrderType()), computerCarList);
saveObj.setType(HardSaleTypeEnum.AFTER_SALE.getType());
saveObj.setStatus(HardSaleStatusEnum.COMPLETE.getStatus());
saveObj.setNo(refundCode);
saveObj.setOrderId(order.getId());
saveObj.setRefundPrice(refundPrice);
saveObj.setUserId(order.getUserId());
saveObj.setAuditUserId(user.getId());
saveObj.setAuditTime(LocalDateTime.now());
saveObj.setAuditReason("后台退款");
baseMapper.insert(saveObj);
// 添加退款购物车
hardAfterSaleCarService.create(dto.getCarList(), order, saveObj);
// 添加售后进度
HardAfterSaleLogEntity saveLogObj = HardAfterSaleLogEntity.builder()
.afterSaleId(saveObj.getId())
.userId(order.getUserId())
.operateType(HardAfterSaleOperateTypeEnum.ADMIN_REFUND.getType())
.beforeStatus(order.getOrderStatus())
.afterStatus(HardSaleStatusEnum.COMPLETE.getStatus())
.content(HardSaleStatusEnum.COMPLETE.getContent())
.build();
hardAfterSaleLogMapper.insert(saveLogObj);
// 执行退款
getSelf().refund(saveObj.getId());
// 退库存
List<HardCarEntity> carList = dto.getCarList().stream().map((item) ->
HardCarEntity.builder()
.productId(item.getProductId())
.productCount(item.getProductCount())
.productWeight(item.getProductWeight())
.productNature(item.getProductName())
.build()
).toList();
hardOrderService.fastenerInventory(order, carList, YesNoEnum.NO);
return true;
}
/**
* 消费机限时退款
*/
@@ -259,7 +259,9 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductPrice(spu.getPrice());
item.setProductPic(spu.getPicUrl());
item.setTotalPrice((long) totalPrice);
// item.setProductNature(v.getProductNature().getType());
if (ObjectUtil.isNotEmpty(v.getProductNature())) {
item.setProductNature(v.getProductNature().getType());
}
item.setProductCount(v.getProductCount());
item.setProductWeight(new BigDecimal(0));
carObjectList.add(item);
@@ -278,7 +280,9 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductPrice(spu.getPrice());
item.setProductPic(spu.getPicUrl());
item.setTotalPrice((long) totalPrice);
// item.setProductNature(v.getProductNature().getType());
if (ObjectUtil.isNotEmpty(v.getProductNature())) {
item.setProductNature(v.getProductNature().getType());
}
item.setProductCount(v.getProductCount());
item.setProductWeight(new BigDecimal(0));
carObjectList.add(item);
@@ -310,7 +314,9 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductPrice(price);
item.setProductPic(spu.getPicUrl());
item.setTotalPrice((long) totalPrice);
// item.setProductNature(v.getProductNature().getType());
if (ObjectUtil.isNotEmpty(v.getProductNature())) {
item.setProductNature(v.getProductNature().getType());
}
item.setProductCount(v.getProductCount());
item.setProductWeight(v.getProductWeight());
carObjectList.add(item);
@@ -341,7 +347,9 @@ public class HardCarServiceImpl extends ServiceImpl<HardCarMapper, HardCarEntity
item.setProductPrice(price);
item.setProductPic(spu.getCover());
item.setTotalPrice((long) totalPrice);
// item.setProductNature(v.getProductNature().getType());
if (ObjectUtil.isNotEmpty(v.getProductNature())) {
item.setProductNature(v.getProductNature().getType());
}
item.setProductCount(v.getProductCount());
item.setProductWeight(v.getProductWeight());
carObjectList.add(item);
@@ -246,6 +246,12 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
}
if (ObjectUtil.isEmpty(wallet)) {
throw new RuntimeException("用户钱包不存在");
} else {
if (ObjectUtil.isNotEmpty(wallet.getUserId()) && ObjectUtil.isNotEmpty(dto.getUserId())) {
if (ObjectUtil.notEqual(wallet.getUserId(), dto.getUserId())) {
throw new RuntimeException("该用户没有这个钱包");
}
}
}
} else if (isVerify) {
// 判断该二维码有没有被核销
@@ -852,6 +858,12 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
@Override
@Transactional(rollbackFor = Exception.class)
public void fastenerInventory(HardOrderEntity order, YesNoEnum isReduce) {
getSelf().fastenerInventory(order, null, isReduce);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void fastenerInventory(HardOrderEntity order, List<HardCarEntity> refundCarList, YesNoEnum isReduce) {
HardTypeEnum hardTypeEnum = HardTypeEnum.valueOfByType(order.getSysType());
HardOrderTypeEnum orderTypeEnum = HardOrderTypeEnum.valueOfByType(order.getOrderType());
if (!ObjectUtil.isAllNotEmpty(hardTypeEnum, orderTypeEnum)) return;
@@ -867,6 +879,13 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
CanteenSpuUpdateStockReqDTO.Item item = new CanteenSpuUpdateStockReqDTO.Item();
item.setId(v.getProductId());
item.setIncrCount(v.getProductCount() * base);
// 如果退款购物车数组里有,就用退款购物车的数量
if (ObjectUtil.isNotEmpty(refundCarList)) {
HardCarEntity refundCarTarget = refundCarList.stream().filter(i -> ObjectUtil.equals(i.getProductId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isNotEmpty(refundCarTarget) && ObjectUtil.isNotEmpty(refundCarTarget.getProductCount())) {
item.setIncrCount(refundCarTarget.getProductCount() * base);
}
}
return item;
}).toList();
dto.setItems(list);
@@ -889,15 +908,31 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
item.setId(v.getProductId());
if (ObjectUtil.isNotEmpty(v.getProductCount()) && !ObjectUtil.equals(v.getProductCount(), 0)) {
// 按数量
double count = BigDecimal.valueOf(v.getProductCount()).multiply(BigDecimal.valueOf(base)).setScale(2, RoundingMode.HALF_UP).doubleValue();
int prouctCount = v.getProductCount();
// 如果退款购物车数组里有,就用退款购物车的数量
if (ObjectUtil.isNotEmpty(refundCarList)) {
HardCarEntity refundCarTarget = refundCarList.stream().filter(i -> ObjectUtil.equals(i.getProductId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isNotEmpty(refundCarTarget) && ObjectUtil.isNotEmpty(refundCarTarget.getProductCount())) {
prouctCount = refundCarTarget.getProductCount();
}
}
double count = BigDecimal.valueOf(prouctCount).multiply(BigDecimal.valueOf(base)).setScale(2, RoundingMode.HALF_UP).doubleValue();
item.setIncrCount(count);
} else if (ObjectUtil.isNotEmpty(v.getProductWeight()) && v.getProductWeight().compareTo(BigDecimal.valueOf(0)) != 0) {
// 按重量
double weight = v.getProductWeight().multiply(BigDecimal.valueOf(base)).setScale(2, RoundingMode.HALF_UP).doubleValue();
BigDecimal productWeight = v.getProductWeight();
// 如果退款购物车数组里有,就用退款购物车的数量
if (ObjectUtil.isNotEmpty(refundCarList)) {
HardCarEntity refundCarTarget = refundCarList.stream().filter(i -> ObjectUtil.equals(i.getProductId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isNotEmpty(refundCarTarget) && ObjectUtil.isNotEmpty(refundCarTarget.getProductCount())) {
productWeight = refundCarTarget.getProductWeight();
}
}
double weight = productWeight.multiply(BigDecimal.valueOf(base)).setScale(2, RoundingMode.HALF_UP).doubleValue();
item.setIncrCount(weight);
}
return item;
}).toList();
}).filter(v -> ObjectUtil.isNotEmpty(v.getIncrCount()) && v.getIncrCount() > 0).toList();
dto.setItems(list);
R updateSkuStockRes = supermarketSpuService.updateSpuStock(dto);
if (updateSkuStockRes.getCode() != 0) {
@@ -916,6 +951,13 @@ public class HardOrderServiceImpl extends ServiceImpl<HardOrderMapper, HardOrder
DeductionSpuStockDto entity = new DeductionSpuStockDto();
entity.setHardSpuId(v.getProductId());
entity.setIncrCount(v.getProductCount());
// 如果退款购物车数组里有,就用退款购物车的数量
if (ObjectUtil.isNotEmpty(refundCarList)) {
HardCarEntity refundCarTarget = refundCarList.stream().filter(i -> ObjectUtil.equals(i.getProductId(), v.getProductId())).findFirst().orElse(null);
if (ObjectUtil.isNotEmpty(refundCarTarget) && ObjectUtil.isNotEmpty(refundCarTarget.getProductCount())) {
entity.setIncrCount(refundCarTarget.getProductCount());
}
}
return entity;
}).toList();
// 查询订单流程
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.hard.mapper.order.HardAfterSaleCarMapper">
<sql id="selectA">
select a.id,
a.refund_id,
a.parent_car_id,
a.product_id,
a.product_name,
a.product_pic,
a.product_nature,
a.product_price,
a.product_count,
a.product_weight,
a.total_price,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
</sql>
<sql id="whereA">
a.del_flag = '0'
<if test="id != null">
and a.id = #{id}
</if>
<if test="refundId != null">
and a.refund_id = #{refundId}
</if>
<if test="parentCarId != null">
and a.parent_car_id = #{parentCarId}
</if>
</sql>
<select id="getByCarPrentId" resultType="com.bsd.pjcloud.hard.api.entity.order.HardAfterSaleCarEntity">
select a.id,
a.refund_id,
a.parent_car_id,
a.product_id,
a.product_name,
a.product_pic,
a.product_nature,
a.product_price,
sum(a.product_count) as productCount,
sum(a.product_weight) as productWeight,
sum(a.total_price) as totalPrice,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
from hard_after_sale_car a
<where>
a.del_flag = '0'
and a.parent_car_id = #{carParentId}
</where>
group by a.product_id
</select>
</mapper>
@@ -0,0 +1,33 @@
package com.bsd.pjcloud.admin.api.constant.car;
import cn.hutool.core.util.ObjectUtil;
import com.bsd.pjcloud.admin.api.constant.UserTransactionEnum;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
/**
* 车辆类型
*/
@AllArgsConstructor
@Getter
public enum CarTypeEnum {
SELF("1", "私家车"),
PUBLIC("2", "公车"),
ARMY("3", "军车"),
POLICE("4", "警车"),
;
private final String type;
private final String description;
public static CarTypeEnum valueOfByType(String type) {
if (ObjectUtil.isEmpty(type)) return null;
return Arrays.stream(values()).filter(v -> ObjectUtil.equals(type, v.getType())).findFirst().get();
}
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.admin.api.dto.car;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserDeptInterface;
import lombok.Data;
@Data
public class SysUserCarDto extends SysUserCarEntity implements BaseUserDeptInterface {
/**
* 用户相关
*/
private String username;
private String userMobile;
private String userAvatar;
private Long userDeptId;
private String userDeptName;
}
@@ -0,0 +1,120 @@
package com.bsd.pjcloud.admin.api.entity.car;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.*;
import com.bsd.pjcloud.common.core.util.TenantTable;
import java.time.LocalDateTime;
/**
* 车辆管理
*/
@Data
@TenantTable
@TableName("sys_user_car")
@EqualsAndHashCode(callSuper = true)
@Schema(description = "车辆管理")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class SysUserCarEntity extends Model<SysUserCarEntity> {
/**
* 编号
*/
@TableId(type = IdType.ASSIGN_ID)
@Schema(description = "编号")
private Long id;
/**
* 用户ID
*/
@Schema(description = "用户ID")
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 车牌号
*/
@Schema(description = "车牌号")
@NotEmpty(message = "车牌号不能为空")
private String carNumber;
/**
* 车辆类型(字典)
*/
@Schema(description = "车辆类型(字典)")
@NotEmpty(message = "车辆类型不能为空")
private String carType;
/**
* 启用状态(字典)
*/
@Schema(description = "启用状态(字典)")
private String enableStatus;
/**
* 流程id
*/
@Schema(description = "流程id")
private String processId;
/**
* 审核状体
*/
@Schema(description = "审核状体")
private String processStatus;
/**
* 审核时间
*/
@Schema(description = "审核时间")
private LocalDateTime processTime;
/**
* 创建人
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建人")
private String createBy;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
@Schema(description = "创建时间")
private LocalDateTime createTime;
/**
* 修改人
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改人")
private String updateBy;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
@Schema(description = "修改时间")
private LocalDateTime updateTime;
/**
* 删除标记
*/
@TableLogic
@TableField(fill = FieldFill.INSERT)
@Schema(description = "删除标记")
private String delFlag;
/**
* 租户ID
*/
@Schema(description = "租户ID")
private Long tenantId;
}
@@ -0,0 +1,23 @@
package com.bsd.pjcloud.admin.api.vo.car;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.admin.api.vo.base.BaseUserDeptInterface;
import lombok.Data;
@Data
public class SysUserCarVo extends SysUserCarEntity implements BaseUserDeptInterface {
/**
* 用户相关
*/
private String username;
private String userMobile;
private String userAvatar;
private Long userDeptId;
private String userDeptName;
}
@@ -0,0 +1,129 @@
package com.bsd.pjcloud.admin.controller.car;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.admin.api.dto.car.SysUserCarDto;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.admin.api.vo.car.SysUserCarVo;
import com.bsd.pjcloud.common.core.util.R;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.log.annotation.SysLog;
import com.bsd.pjcloud.admin.service.SysUserCarService;
import com.bsd.pjcloud.common.security.annotation.Inner;
import com.bsd.pjcloud.common.security.service.PjcloudUser;
import com.bsd.pjcloud.common.security.util.SecurityUtils;
import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import org.springframework.security.access.prepost.PreAuthorize;
import com.bsd.pjcloud.common.excel.annotation.ResponseExcel;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.http.HttpHeaders;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Objects;
/**
* 车辆管理
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("/sysUserCar")
@Tag(description = "sysUserCar", name = "车辆管理管理")
@SecurityRequirement(name = HttpHeaders.AUTHORIZATION)
public class SysUserCarController {
private final SysUserCarService sysUserCarService;
/* ************************************* start callback start ************************************* */
@Inner(value = false)
@PostMapping("/apply-callback")
public void applyCallback(@RequestBody ProcessNodeRecordAssignUserParamDto dto, @RequestParam(required = false) Long tenantId) {
sysUserCarService.applyCallback(dto, tenantId);
}
/* ************************************* end callback end ************************************* */
/* ************************************* start app start ************************************* */
@PostMapping("/app/create")
public void appCreateCar(@Validated @RequestBody SysUserCarDto dto) {
PjcloudUser user = SecurityUtils.getUser();
dto.setUserId(user.getId());
sysUserCarService.appCreateCar(dto);
}
/* ************************************* end app end ************************************* */
/**
* 分页查询
*/
@Operation(summary = "分页查询", description = "分页查询")
@GetMapping("/page")
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_view')")
public R<Page<SysUserCarVo>> getSysUserCarPage(@ParameterObject Page page, @ParameterObject SysUserCarDto dto) {
return R.ok(sysUserCarService.scopePageJoin(page, dto, DataScope.of()));
}
/**
* 通过id查询车辆管理
*/
@Operation(summary = "通过id查询", description = "通过id查询")
@GetMapping("/{id}")
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_view')")
public R getById(@PathVariable("id") Long id) {
return R.ok(sysUserCarService.getById(id));
}
/**
* 新增车辆管理
*/
@Operation(summary = "新增车辆管理", description = "新增车辆管理")
@SysLog("新增车辆管理")
@PostMapping
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_add')")
public R save(@RequestBody SysUserCarDto sysUserCar) {
return R.ok(sysUserCarService.create(sysUserCar));
}
/**
* 修改车辆管理
*/
@Operation(summary = "修改车辆管理", description = "修改车辆管理")
@SysLog("修改车辆管理")
@PutMapping
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_edit')")
public R updateById(@RequestBody SysUserCarDto sysUserCar) {
sysUserCarService.edit(sysUserCar);
return R.ok();
}
/**
* 通过id删除车辆管理
*/
@Operation(summary = "通过id删除车辆管理", description = "通过id删除车辆管理")
@SysLog("通过id删除车辆管理")
@DeleteMapping
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_del')")
public R removeById(@RequestBody Long[] ids) {
return R.ok(sysUserCarService.removeBatchByIds(CollUtil.toList(ids)));
}
/**
* 导出excel 表格
*/
@ResponseExcel
@GetMapping("/export")
@PreAuthorize("@pms.hasPermission('admin_sysUserCar_export')")
public List<SysUserCarEntity> export(SysUserCarEntity sysUserCar, Long[] ids) {
return sysUserCarService.list(Wrappers.lambdaQuery(sysUserCar).in(ArrayUtil.isNotEmpty(ids), SysUserCarEntity::getId, ids));
}
}
@@ -0,0 +1,17 @@
package com.bsd.pjcloud.admin.mapper.car;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bsd.pjcloud.admin.api.dto.car.SysUserCarDto;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.admin.api.vo.car.SysUserCarVo;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.data.datascope.PjcloudBaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface SysUserCarMapper extends PjcloudBaseMapper<SysUserCarEntity> {
Page<SysUserCarVo> scopePageJoin(Page page, @Param("dto") SysUserCarDto dto, DataScope dataScope);
}
@@ -0,0 +1,28 @@
package com.bsd.pjcloud.admin.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.bsd.pjcloud.admin.api.dto.car.SysUserCarDto;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
public interface SysUserCarService extends IService<SysUserCarEntity> {
Page scopePageJoin(Page page, SysUserCarDto dto, DataScope dataScope);
Long create(SysUserCarDto sysUserCar);
void edit(SysUserCarDto sysUserCar);
/**
* app创建车辆
*/
void appCreateCar(SysUserCarDto dto);
/**
* 审批回调
*/
void applyCallback(ProcessNodeRecordAssignUserParamDto dto, Long tenantId);
}
@@ -0,0 +1,189 @@
package com.bsd.pjcloud.admin.service.impl.car;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bsd.pjcloud.admin.api.constant.car.CarTypeEnum;
import com.bsd.pjcloud.admin.api.dto.car.SysUserCarDto;
import com.bsd.pjcloud.admin.api.entity.SysDept;
import com.bsd.pjcloud.admin.api.entity.SysUser;
import com.bsd.pjcloud.admin.api.entity.car.SysUserCarEntity;
import com.bsd.pjcloud.admin.api.utils.DataUtil;
import com.bsd.pjcloud.admin.api.vo.UserVO;
import com.bsd.pjcloud.admin.api.vo.car.SysUserCarVo;
import com.bsd.pjcloud.admin.mapper.car.SysUserCarMapper;
import com.bsd.pjcloud.admin.service.SysDeptService;
import com.bsd.pjcloud.admin.service.SysUserCarService;
import com.bsd.pjcloud.admin.service.SysUserService;
import com.bsd.pjcloud.admin.utils.flow.FlowUtil;
import com.bsd.pjcloud.admin.utils.flow.dto.UserCarFlowDto;
import com.bsd.pjcloud.common.core.constant.enums.YesNoEnum;
import com.bsd.pjcloud.common.core.util.CollectionUtils;
import com.bsd.pjcloud.common.data.datascope.DataScope;
import com.bsd.pjcloud.common.data.tenant.TenantContextHolder;
import com.bsd.pjcloud.flow.task.constant.TaskCheckStatusEnum;
import com.bsd.pjcloud.flow.task.dto.ProcessNodeRecordAssignUserParamDto;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* 车辆管理
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserCarServiceImpl extends ServiceImpl<SysUserCarMapper, SysUserCarEntity> implements SysUserCarService {
static private final String TAG = "车辆管理";
private final SysUserService userService;
private final SysDeptService deptService;
private final FlowUtil flowUtil;
@Override
public Page<SysUserCarVo> scopePageJoin(Page page, SysUserCarDto dto, DataScope dataScope) {
Page<SysUserCarVo> pageList = baseMapper.scopePageJoin(page, dto, dataScope);
disposeList(pageList.getRecords());
return pageList;
}
@Override
public Long create(SysUserCarDto sysUserCar) {
if (existName(sysUserCar)) {
throw new RuntimeException("车牌号不能重复");
}
if (ObjectUtil.isEmpty(sysUserCar.getEnableStatus())) {
sysUserCar.setEnableStatus(YesNoEnum.YES.getCode());
}
// 后台新增,默认审核通过
sysUserCar.setProcessStatus(TaskCheckStatusEnum.RESULT.getCode());
baseMapper.insert(sysUserCar);
return sysUserCar.getId();
}
@Override
public void edit(SysUserCarDto sysUserCar) {
if (existName(sysUserCar)) {
throw new RuntimeException("车牌号不能重复");
}
baseMapper.updateById(sysUserCar);
}
/**
* app创建车辆
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void appCreateCar(SysUserCarDto dto) {
if (existName(dto)) {
throw new RuntimeException("车牌号不能重复");
}
if (ObjectUtil.isEmpty(dto.getEnableStatus())) {
dto.setEnableStatus(YesNoEnum.YES.getCode());
}
// 查询申请用户
SysUser user = userService.getById(dto.getUserId());
// 查询申请部门
SysDept dept = deptService.getById(user.getDeptId());
baseMapper.insert(dto);
// 创建审批
UserCarFlowDto flowDto = new UserCarFlowDto();
flowDto.setApplyUsername(user.getUsername());
flowDto.setApplyUserId(user.getUserId());
flowDto.setApplyDeptName(dept.getName());
flowDto.setApplyDeptId(dept.getDeptId());
flowDto.setApplyCreateTime(LocalDateTimeUtil.format(dto.getCreateTime(), DatePattern.NORM_DATETIME_PATTERN));
flowDto.setCarNumber(dto.getCarNumber());
flowDto.setCarType(CarTypeEnum.valueOfByType(dto.getCarType()).getDescription());
String processId = flowUtil.startFlow("TASK_APPLY_USER_CAR", user, dto.getId(), flowDto);
// 更新
SysUserCarEntity updateObj = new SysUserCarEntity();
updateObj.setId(dto.getId());
updateObj.setProcessId(processId);
updateObj.setProcessStatus(TaskCheckStatusEnum.PADDING.getCode());
updateObj.setProcessTime(LocalDateTime.now());
baseMapper.updateById(updateObj);
}
/**
* 审批回调
*/
@Override
public void applyCallback(ProcessNodeRecordAssignUserParamDto dto, Long tenantId) {
if (!flowUtil.checkCallback(dto)) {
return;
}
if (ObjectUtil.isNotEmpty(tenantId) && ObjectUtil.notEqual(tenantId, 1L)) {
TenantContextHolder.setTenantId(tenantId);
}
String processId = dto.getProcessInstanceId();
SysUserCarEntity detail = baseMapper.selectOne(new LambdaQueryWrapper<SysUserCarEntity>().eq(SysUserCarEntity::getProcessId, processId));
if (ObjectUtil.isEmpty(detail)) {
return;
}
if (!ObjectUtil.equals(detail.getProcessStatus(), TaskCheckStatusEnum.PADDING.getCode())) {
log.error("|{}|重复的回调,dto:|{}|", TAG, JSON.toJSONString(dto));
return;
}
try {
Boolean isConsent = flowUtil.isConsent(dto);
String processStatus = isConsent ? TaskCheckStatusEnum.RESULT.getCode() : TaskCheckStatusEnum.REJECT.getCode();
baseMapper.updateById(SysUserCarEntity.builder().id(detail.getId()).processTime(LocalDateTime.now()).processStatus(processStatus).build());
} catch (Exception e) {
e.printStackTrace();
log.error("|{}|审批回调意外的错误,dto:|{}|error:|{}|", TAG, JSON.toJSONString(dto), e.getMessage());
throw new RuntimeException(e);
}
}
// 判断车牌号是否重复
private boolean existName(SysUserCarEntity dto) {
Long count = baseMapper.selectCount(new LambdaQueryWrapper<SysUserCarEntity>()
.eq(ObjectUtil.isNotEmpty(dto.getCarNumber()), SysUserCarEntity::getCarNumber, dto.getCarNumber())
.ne(ObjectUtil.isNotEmpty(dto.getId()), SysUserCarEntity::getId, dto.getId())
);
if (ObjectUtil.isNotEmpty(dto.getId())) {
return count >= 1;
}
return count > 0;
}
private void disposeList(List<SysUserCarVo> list) {
if (ObjectUtil.isEmpty(list)) return;
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
// 用户部门
CompletableFuture<Void> deptUserFuture = CompletableFuture.runAsync(() -> {
RequestContextHolder.setRequestAttributes(requestAttributes);
List<Long> userIds = list.stream().map(SysUserCarVo::getUserId).filter(ObjectUtil::isNotEmpty).distinct().toList();
if (ObjectUtil.isNotEmpty(userIds)) {
List<UserVO> userList = userService.getUserDeptByIds(new ArrayList<>(userIds));
if (ObjectUtil.isNotEmpty(userList)) {
DataUtil.convertUserDeptList(list, CollectionUtils.convertMap(userList, UserVO::getUserId));
}
}
});
CompletableFuture.allOf(deptUserFuture).join();
}
}
@@ -0,0 +1,13 @@
package com.bsd.pjcloud.admin.utils.flow.dto;
import com.bsd.pjcloud.flow.task.dto.base.FlowBaseDto;
import lombok.Data;
@Data
public class UserCarFlowDto extends FlowBaseDto {
private String carNumber;
private String carType;
}
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.bsd.pjcloud.admin.mapper.car.SysUserCarMapper">
<sql id="selectA">
select a.id,
a.user_id,
a.car_number,
a.car_type,
a.enable_status,
a.create_by,
a.create_time,
a.update_by,
a.update_time,
a.del_flag,
a.tenant_id
</sql>
<sql id="whereA">
a.del_flag = '0'
<if test="dto.userId != null">
and a.user_id = #{dto.userId}
</if>
<if test="dto.carNumber != null">
and a.car_number LIKE CONCAT('%',#{dto.carNumber},'%')
</if>
<if test="dto.carType != null and dto.carType != '' ">
and a.car_type = #{dto.carType}
</if>
<if test="dto.enableStatus != null and dto.enableStatus != '' ">
and a.enable_status = #{dto.enableStatus}
</if>
</sql>
<select id="scopePageJoin" resultType="com.bsd.pjcloud.admin.api.vo.car.SysUserCarVo">
<include refid="selectA"/>
from sys_user_car a
<where>
<include refid="whereA"/>
</where>
order by a.create_time desc , a.id desc
</select>
</mapper>