fix: 增加校验

This commit is contained in:
2024-11-16 16:15:48 +08:00
parent 274304ec5b
commit 94d4dfebcb
15 changed files with 298 additions and 68 deletions

View File

@@ -211,6 +211,29 @@ public class JpaUtils {
return (entityManager.createQuery(query));
}
public static boolean hasDuplicateInCurrentOrg(
EntityManager entityManager,
Class clazz,
String fieldName,
Object value) {
return hasDuplicate(
entityManager,
clazz,
fieldName,
value,
Ctx.currentUser().getOrganizationId(),
null);
}
public static boolean hasDuplicateInCurrentOrg(
EntityManager entityManager,
Class clazz,
String fieldName,
Object value,
String selfId) {
return hasDuplicate(entityManager, clazz, fieldName, value, Ctx.currentUser().getOrganizationId(), selfId);
}
public static boolean hasDuplicate(
EntityManager entityManager,
Class clazz,

View File

@@ -8,6 +8,7 @@ import cn.lihongjie.coal.base.dto.R;
import cn.lihongjie.coal.orderNoRule.dto.CreateOrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.OrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.UpdateOrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.UpdateOrderSeqRequest;
import cn.lihongjie.coal.orderNoRule.service.OrderNoRuleService;
import lombok.extern.slf4j.Slf4j;
@@ -63,6 +64,11 @@ public class OrderNoRuleController {
return R.success(this.service.genOrderNo(request.getId()));
}
@PostMapping("/updateOrderSeq")
public R<String> updateOrderSeq(@RequestBody UpdateOrderSeqRequest request) {
return R.success(this.service.updateOrderSeq(request));
}
@PostMapping("/previewOrderNo")
public R<String> previewOrderNo(@RequestBody OrderNoRuleDto request) {

View File

@@ -4,8 +4,14 @@ import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class CreateOrderNoRuleDto extends OrgCommonDto {
private String ruleTemplate;
@Comment("初始序列号")
private Integer initValue;
}

View File

@@ -4,8 +4,14 @@ import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class OrderNoRuleDto extends OrgCommonDto {
private String ruleTemplate;
@Comment("初始序列号")
private Integer initValue;
}

View File

@@ -4,8 +4,15 @@ import cn.lihongjie.coal.base.dto.OrgCommonDto;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
public class UpdateOrderNoRuleDto extends OrgCommonDto {
private String ruleTemplate;
@Comment("初始序列号")
private Integer initValue;
}

View File

@@ -0,0 +1,11 @@
package cn.lihongjie.coal.orderNoRule.dto;
import lombok.Data;
import java.util.*;
@Data
public class UpdateOrderSeqRequest {
private String id;
private Long newSeq;
}

View File

@@ -7,6 +7,8 @@ import jakarta.persistence.Table;
import lombok.Data;
import org.hibernate.annotations.Comment;
@Data
@Entity
@Table(
@@ -20,6 +22,9 @@ public class OrderNoRuleEntity extends OrgCommonEntity {
@Comment("初始序列号")
private Integer initValue;

View File

@@ -74,6 +74,40 @@ public class OrderNoGenService {
context);
}
public @NotNull void updateSeq(String ruleCode, String orgId, String ruleTemplate, Long newSeq) {
RuleTemplateUtils.ResolveContext context = new RuleTemplateUtils.ResolveContext();
context.setDateTime(LocalDateTime.now());
RuleTemplateUtils.genNo(
ruleTemplate,
RuleTemplateUtils.CompositePlaceholderResolver.of(
new RuleTemplateUtils.PlaceholderResolver() {
@Override
public Boolean support(String placeholder) {
return placeholder.startsWith("seq:");
}
@Override
public String resolve(
String placeholder, RuleTemplateUtils.ResolveContext context) {
String current = context.get("current").toString();
String key = orgId + ":" + ruleCode + ":" + current;
redissonClient.getAtomicLong(key).set(newSeq);
return String.format("%0" + placeholder.substring(4) + "d", newSeq);
}
},
RuleTemplateUtils.DatePlaceholderResolver.INSTANCE,
RuleTemplateUtils.RandomPlaceholderResolver.INSTANCE),
context);
}
private @Nullable OrderNoRuleEntity getOrderNoRuleEntity(String ruleCode, String orgId) {
List<OrderNoRuleEntity> all = orderNoRuleService.findAll(new Specification<OrderNoRuleEntity>() {
@Override

View File

@@ -9,6 +9,7 @@ import cn.lihongjie.coal.exception.BizException;
import cn.lihongjie.coal.orderNoRule.dto.CreateOrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.OrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.UpdateOrderNoRuleDto;
import cn.lihongjie.coal.orderNoRule.dto.UpdateOrderSeqRequest;
import cn.lihongjie.coal.orderNoRule.entity.OrderNoRuleEntity;
import cn.lihongjie.coal.orderNoRule.mapper.OrderNoRuleMapper;
import cn.lihongjie.coal.orderNoRule.repository.OrderNoRuleRepository;
@@ -121,11 +122,10 @@ public class OrderNoRuleService extends BaseService<OrderNoRuleEntity, OrderNoRu
/**
* 库房相关
*/
insertOne(orgId, RuleCodeConstant.KF_QTRKD, "库房其他入库单", "QTRKD{yyyyMMdd}{seq:4}");
insertOne(orgId, RuleCodeConstant.KF_QTCKD, "库房其他出库单", "QTCKD{yyyyMMdd}{seq:4}");
insertOne(orgId, RuleCodeConstant.KF_RKD, "库房入库单", "RKD{yyyyMMdd}{seq:4}");
insertOne(orgId, RuleCodeConstant.KF_CKD, "库房出库单", "CKD{yyyyMMdd}{seq:4}");
insertOne(orgId, RuleCodeConstant.KF_PDD, "库房盘点单", "PDD{yyyyMMdd}{seq:4}");
insertOne(orgId, RuleCodeConstant.KF_PKD, "库房盘点单", "PKD{yyyyMMdd}{seq:4}");
}
@@ -138,4 +138,17 @@ public class OrderNoRuleService extends BaseService<OrderNoRuleEntity, OrderNoRu
rule.setStatus(1);
this.save(rule);
}
public String updateOrderSeq(UpdateOrderSeqRequest id) {
OrderNoRuleEntity rule = this.repository.get(id.getId());
orderNoGenService.updateSeq(
rule.getCode(),
Ctx.currentUser().getOrganizationId(),
rule.getRuleTemplate(),
id.getNewSeq());
return "success";
}
}

View File

@@ -1,13 +1,11 @@
package cn.lihongjie.coal.orderNoRule.service;
import java.util.*;
public class RuleCodeConstant {
public static final String MTCG = "MTCG";
public static final String MTXS = "MTXS";
public static final String KF_QTRKD = "KF_QTRKD";
public static final String KF_RKD = "KF_RKD";
public static final String KF_CKD = "KF_CKD";
public static final String KF_PDD = "KF_PDD";
public static final String KF_PKD = "KF_PKD";
public static final String KF_QTCKD = "KF_QTCKD";
}

View File

@@ -8,13 +8,20 @@ import jakarta.validation.ConstraintViolation;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.SessionFactory;
import org.jetbrains.annotations.Nullable;
import org.postgresql.util.PSQLException;
import org.postgresql.util.ServerErrorMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.HandlerMethod;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@@ -26,50 +33,29 @@ import java.util.stream.Collectors;
@Order(1)
public class GlobalExceptionHandler {
@Autowired SessionFactory sessionFactory;
@ExceptionHandler(InvalidDataAccessApiUsageException.class)
public R handleException(
InvalidDataAccessApiUsageException ex, HttpServletRequest request, HandlerMethod handlerMethod) {
logEx(ex, request, handlerMethod);
private static @Nullable String getDuplicateMsg(ServerErrorMessage serverErrorMessage) {
Pattern pattern = Pattern.compile("\\[(.+?)\\]");
String detail = serverErrorMessage.getDetail();
Matcher matcher = pattern.matcher(ex.getMessage());
Pattern pattern = Pattern.compile("Key \\((.+)\\)=\\((.+)\\) already exists.");
Matcher matcher = pattern.matcher(detail);
if (matcher.find()) {
return R.fail("fieldNotExist", "字段不存在: " + matcher.group(1));
String[] values = matcher.group(2).split(",");
String msg =
Arrays.stream(values)
.map(String::trim)
.filter(x -> !isUUID(x.trim()))
.collect(Collectors.joining(","));
return msg;
}
return R.fail("sysError", "系统异常: " + ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleException(
MethodArgumentNotValidException ex, HttpServletRequest request, HandlerMethod handlerMethod) {
logEx(ex, request, handlerMethod);
List<ConstraintViolation> allError =
ex.getBindingResult().getAllErrors().stream()
.map(oe -> oe.unwrap(ConstraintViolation.class))
.collect(Collectors.toList());
List<Map<String, ? extends Object>> errorData =
allError.stream()
.map(
x ->
Map.of(
"field",
x.getPropertyPath() == null? "null" : x.getPropertyPath().toString(),
"msg",
x.getMessage(),
"annotation",
x.getConstraintDescriptor()
.getAnnotation() == null ? "null":x.getConstraintDescriptor()
.getAnnotation()
.annotationType()
.getName()))
.collect(Collectors.toList());
return R.fail("validError", errorData.stream().map(x -> x.get("msg") + "").collect(Collectors.joining(", ")), errorData);
return serverErrorMessage.getDetail();
}
@ExceptionHandler(BizException.class)
@@ -105,4 +91,117 @@ public class GlobalExceptionHandler {
logEx(ex, request, handlerMethod);
return R.fail("sysError", "系统异常: " + ex.getMessage());
}
private static boolean isUUID(String x) {
return x.matches(
"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
}
@ExceptionHandler(InvalidDataAccessApiUsageException.class)
public R handleException(
InvalidDataAccessApiUsageException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
logEx(ex, request, handlerMethod);
Pattern pattern = Pattern.compile("\\[(.+?)\\]");
Matcher matcher = pattern.matcher(ex.getMessage());
if (matcher.find()) {
return R.fail("fieldNotExist", "字段不存在: " + matcher.group(1));
}
return R.fail("sysError", "系统异常: " + ex.getMessage());
}
@ExceptionHandler(MethodArgumentNotValidException.class)
public R handleException(
MethodArgumentNotValidException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
logEx(ex, request, handlerMethod);
List<ConstraintViolation> allError =
ex.getBindingResult().getAllErrors().stream()
.map(oe -> oe.unwrap(ConstraintViolation.class))
.collect(Collectors.toList());
List<Map<String, ? extends Object>> errorData =
allError.stream()
.map(
x ->
Map.of(
"field",
x.getPropertyPath() == null
? "null"
: x.getPropertyPath().toString(),
"msg",
x.getMessage(),
"annotation",
x.getConstraintDescriptor().getAnnotation() == null
? "null"
: x.getConstraintDescriptor()
.getAnnotation()
.annotationType()
.getName()))
.collect(Collectors.toList());
return R.fail(
"validError",
errorData.stream().map(x -> x.get("msg") + "").collect(Collectors.joining(", ")),
errorData);
}
@ExceptionHandler(DataIntegrityViolationException.class)
public R handleException(
DataIntegrityViolationException ex,
HttpServletRequest request,
HandlerMethod handlerMethod) {
logEx(ex, request, handlerMethod);
Throwable root = ex.getRootCause();
if (root instanceof PSQLException psqlException) {
ServerErrorMessage serverErrorMessage = psqlException.getServerErrorMessage();
String routine = serverErrorMessage.getRoutine();
switch (routine) {
case "_bt_check_unique" -> {
return R.fail(
"uniqueViolation", "数据重复: " + getDuplicateMsg(serverErrorMessage));
}
case "ExecConstraints" -> {
if (serverErrorMessage.getMessage().contains("not-null constraint")) {
// get table name and column name from message null value in column "code"
// of relation "t_warehouse_goods" violates not-null constraint'
String message = serverErrorMessage.getMessage();
Pattern pattern =
Pattern.compile(
"null value in column \"(.+?)\" of relation \"(.+?)\" violates not-null constraint");
Matcher matcher = pattern.matcher(message);
if (matcher.find()) {
String col = matcher.group(1);
String table = matcher.group(2);
return R.fail("notNullViolation", "数据项不能为空: " + col);
}
return R.fail("notNullViolation", "数据项不能为空");
}
}
}
return R.fail("dataIntegrityViolation", "数据完整性异常: " + serverErrorMessage);
}
return R.fail("sysError", "系统异常: " + ex.getMessage());
}
}

View File

@@ -8,6 +8,7 @@ import cn.lihongjie.coal.warehouseGoodsUnit.entity.WarehouseGoodsUnitEntity;
import cn.lihongjie.coal.warehouseShelve.entity.WarehouseShelveEntity;
import cn.lihongjie.coal.warehouseSupplier.entity.WarehouseSupplierEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
@@ -17,11 +18,21 @@ import org.hibernate.annotations.Comment;
@Data
@Entity
@jakarta.persistence.Table(
indexes = {
@jakarta.persistence.Index(
name = "idx_warehouse_goods_org_id",
columnList = "organization_id"),
@jakarta.persistence.Table(indexes = @jakarta.persistence.Index(name ="idx_warehouse_goods_org_id", columnList = "organization_id"))
@jakarta.persistence.Index(
name = "idx_warehouse_goods_code",
columnList = "code, organization_id",
unique = true)
})
public class WarehouseGoodsEntity extends OrgCommonEntity {
@Column(nullable = false)
private String code;
@ManyToOne
private WarehouseGoodsCategoryEntity category;

View File

@@ -8,7 +8,14 @@ import lombok.Data;
@Data
@Entity
@jakarta.persistence.Table(indexes = @jakarta.persistence.Index(name ="idx_warehouse_goods_brand_org_id", columnList = "organization_id"))
public class WarehouseGoodsBrandEntity extends OrgCommonEntity {}
@jakarta.persistence.Table(
indexes = {
@jakarta.persistence.Index(
name = "idx_warehouse_goods_brand_org_id",
columnList = "organization_id"),
@jakarta.persistence.Index(
name = "idx_warehouse_goods_brand_name",
columnList = "name, organization_id",
unique = true)
})
public class WarehouseGoodsBrandEntity extends OrgCommonEntity {}

View File

@@ -8,7 +8,14 @@ import lombok.Data;
@Data
@Entity
@jakarta.persistence.Table(indexes = @jakarta.persistence.Index(name ="idx_warehouse_goods_unit_org_id", columnList = "organization_id"))
public class WarehouseGoodsUnitEntity extends OrgCommonEntity {}
@jakarta.persistence.Table(
indexes = {
@jakarta.persistence.Index(
name = "idx_warehouse_goods_unit_org_id",
columnList = "organization_id")
,
@jakarta.persistence.Index(
name = "idx_warehouse_goods_unit_name",
columnList = "name, organization_id", unique = true)
})
public class WarehouseGoodsUnitEntity extends OrgCommonEntity {}

View File

@@ -17,11 +17,15 @@ import java.util.List;
@Data()
@Entity
@jakarta.persistence.Table(
indexes =
@jakarta.persistence.Index(
name = "idx_warehouse_receipt_org_id",
columnList = "organization_id"))
indexes = {
@jakarta.persistence.Index(
name = "idx_warehouse_receipt_org_id",
columnList = "organization_id"),
@jakarta.persistence.Index(
name = "idx_warehouse_receipt_receipt_no",
columnList = "receipt_no, organization_id",
unique = true)
})
@EqualsAndHashCode(exclude = {"detail", "parent"})
public class WarehouseReceiptEntity extends OrgCommonEntity {
@@ -38,6 +42,7 @@ public class WarehouseReceiptEntity extends OrgCommonEntity {
// private String receiptTypeName;
@Comment("单据编号")
@Column(nullable = false)
private String receiptNo;
@Comment("事由")
@@ -58,7 +63,6 @@ public class WarehouseReceiptEntity extends OrgCommonEntity {
@OneToMany(mappedBy = "receipt", cascade = CascadeType.REMOVE)
private List<WarehouseReceiptDetailEntity> detail;
private Double amount;
private Double number;
@@ -71,21 +75,14 @@ public class WarehouseReceiptEntity extends OrgCommonEntity {
@ManyToOne(cascade = CascadeType.REMOVE)
private WarehouseReceiptEntity receipt1;
@ManyToOne
private WarehouseReceiptEntity parent;
@ManyToOne private WarehouseReceiptEntity parent;
@Comment("制单人")
private String creator;
private String location;
@Comment("归档状态")
@ColumnDefault("'0'")
private String archiveStatus = "0";
}