🐛 修复车务非必填-1占位落库,并完善总单分段调度与运单导入
上一段运单完成到达后才可调度且不超过到达量;车务多模块保存/列表/导出将-1归一为null;同步网关大报文限制与导入校验能力。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -2,6 +2,9 @@ server:
|
||||
port: 80
|
||||
|
||||
spring:
|
||||
codec:
|
||||
# 运单批量导入等大 JSON / 失败明细导出场景,默认 256KB 会触发网关 500
|
||||
max-in-memory-size: 20MB
|
||||
cloud:
|
||||
gateway:
|
||||
server:
|
||||
|
||||
+2
@@ -33,4 +33,6 @@ public class WaybillImportBatchRequest {
|
||||
private String planName;
|
||||
private String remark;
|
||||
private List<Map<String, Object>> rows;
|
||||
/** 分批确认导入时,是否追加到已有批次(首批为 false,后续批为 true)。 */
|
||||
private Boolean append;
|
||||
}
|
||||
|
||||
+5
@@ -41,6 +41,11 @@ public class MasterOrderVO extends MasterOrder {
|
||||
private List<Waybill> boundWaybills;
|
||||
@TableField(exist = false)
|
||||
private BigDecimal totalQuantity;
|
||||
/**
|
||||
* 各品类已调度量(按货物名称+类型聚合,取各分段已调度量的最大值)
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private Map<String, BigDecimal> dispatchedGoods;
|
||||
@TableField(exist = false)
|
||||
private String createUserName;
|
||||
@TableField(exist = false)
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
*/
|
||||
package org.springblade.transport.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/** 运单批量导入单行校验错误。 */
|
||||
@Data
|
||||
@Schema(description = "运单批量导入单行校验错误")
|
||||
public class WaybillImportRowErrorVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "行号(从0开始,相对当前批次)")
|
||||
private Integer rowIndex;
|
||||
|
||||
@Schema(description = "错误信息")
|
||||
private String errorMessage;
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* BladeX Commercial License Agreement
|
||||
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
|
||||
*/
|
||||
package org.springblade.transport.pojo.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** 运单批量导入校验结果。 */
|
||||
@Data
|
||||
@Schema(description = "运单批量导入校验结果")
|
||||
public class WaybillImportValidateResultVO implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Schema(description = "是否全部通过")
|
||||
private Boolean success;
|
||||
|
||||
@Schema(description = "校验错误列表")
|
||||
private List<WaybillImportRowErrorVO> errors = new ArrayList<>();
|
||||
}
|
||||
+12
-4
@@ -54,6 +54,7 @@ import org.springblade.transport.pojo.dto.WaybillImportBatchRequest;
|
||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
||||
import org.springblade.transport.pojo.vo.LoadingManageVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportBatchVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportValidateResultVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillLocateVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillTrackVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillPunchRecordsVO;
|
||||
@@ -192,15 +193,22 @@ public class WaybillController extends BladeController {
|
||||
@PostMapping("/import-batch/validate")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "校验运单批量导入数据")
|
||||
public void validateImportBatch(@RequestBody WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
waybillImportBatchService.validate(request, response);
|
||||
public R<WaybillImportValidateResultVO> validateImportBatch(@RequestBody WaybillImportBatchRequest request) {
|
||||
return R.data(waybillImportBatchService.validate(request));
|
||||
}
|
||||
|
||||
@PostMapping("/import-batch/export-failures")
|
||||
@ApiOperationSupport(order = 6)
|
||||
@Operation(summary = "导出运单批量导入失败明细")
|
||||
public void exportImportFailures(@RequestBody WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
waybillImportBatchService.exportFailures(request, response);
|
||||
}
|
||||
|
||||
@PostMapping("/import-batch/confirm")
|
||||
@ApiOperationSupport(order = 7)
|
||||
@Operation(summary = "确认运单批量导入")
|
||||
public void confirmImportBatch(@RequestBody WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
waybillImportBatchService.confirm(request, response);
|
||||
public R<WaybillImportBatchVO> confirmImportBatch(@RequestBody WaybillImportBatchRequest request) {
|
||||
return R.data(waybillImportBatchService.confirm(request));
|
||||
}
|
||||
|
||||
@PostMapping("/import-batch/remove")
|
||||
|
||||
+2
@@ -69,6 +69,8 @@ public class MasterOrderWaybillExcel {
|
||||
private String businessStatus;
|
||||
@ExcelProperty("备注")
|
||||
private String remark;
|
||||
@ExcelProperty("更新时间")
|
||||
private Date updateTime;
|
||||
@ExcelProperty("创建时间")
|
||||
private Date createTime;
|
||||
}
|
||||
|
||||
+2
-2
@@ -42,8 +42,8 @@
|
||||
accident_location,
|
||||
accident_nature,
|
||||
accident_responsibility,
|
||||
CASE WHEN direct_economic_loss < 0 THEN 0 ELSE direct_economic_loss END AS direct_economic_loss,
|
||||
CASE WHEN insurance_claim_amount < 0 THEN 0 ELSE insurance_claim_amount END AS insurance_claim_amount,
|
||||
CASE WHEN direct_economic_loss = -1 THEN NULL WHEN direct_economic_loss < 0 THEN 0 ELSE direct_economic_loss END AS direct_economic_loss,
|
||||
CASE WHEN insurance_claim_amount = -1 THEN NULL WHEN insurance_claim_amount < 0 THEN 0 ELSE insurance_claim_amount END AS insurance_claim_amount,
|
||||
accident_reason_damage,
|
||||
attachments,
|
||||
remark
|
||||
|
||||
+1
-1
@@ -88,7 +88,7 @@
|
||||
valid_until_date,
|
||||
passenger_type_level,
|
||||
inspection_unit,
|
||||
CASE WHEN fee < 0 THEN 0 ELSE fee END AS fee,
|
||||
CASE WHEN fee = -1 THEN NULL WHEN fee < 0 THEN 0 ELSE fee END AS fee,
|
||||
assessment_unit,
|
||||
attachments,
|
||||
remark
|
||||
|
||||
+2
-2
@@ -44,8 +44,8 @@
|
||||
policy_no,
|
||||
start_date,
|
||||
end_date,
|
||||
CASE WHEN insured_amount < 0 THEN 0 ELSE insured_amount END AS insured_amount,
|
||||
CASE WHEN premium < 0 THEN 0 ELSE premium END AS premium,
|
||||
CASE WHEN insured_amount = -1 THEN NULL ELSE insured_amount END AS insured_amount,
|
||||
CASE WHEN premium = -1 THEN NULL ELSE premium END AS premium,
|
||||
invoice_no,
|
||||
invoice_date,
|
||||
ocr_template,
|
||||
|
||||
+2
-2
@@ -44,7 +44,7 @@
|
||||
vehicle_no,
|
||||
maintainer,
|
||||
maintenance_time,
|
||||
CASE WHEN mileage < 0 THEN 0 ELSE mileage END AS mileage,
|
||||
CASE WHEN mileage = -1 THEN NULL WHEN mileage < 0 THEN 0 ELSE mileage END AS mileage,
|
||||
mileage_unit,
|
||||
maintenance_item,
|
||||
cost,
|
||||
@@ -52,7 +52,7 @@
|
||||
contact_phone,
|
||||
address,
|
||||
next_maintenance_time,
|
||||
CASE WHEN next_maintenance_mileage < 0 THEN 0 ELSE next_maintenance_mileage END AS next_maintenance_mileage,
|
||||
CASE WHEN next_maintenance_mileage = -1 THEN NULL WHEN next_maintenance_mileage < 0 THEN 0 ELSE next_maintenance_mileage END AS next_maintenance_mileage,
|
||||
attachments,
|
||||
remark
|
||||
FROM
|
||||
|
||||
+4
-4
@@ -36,10 +36,10 @@
|
||||
is_deleted,
|
||||
vehicle_type,
|
||||
vehicle_no,
|
||||
CASE WHEN previous_month_mileage < 0 THEN 0 ELSE previous_month_mileage END AS previous_month_mileage,
|
||||
CASE WHEN current_month_mileage < 0 THEN 0 ELSE current_month_mileage END AS current_month_mileage,
|
||||
CASE WHEN monthly_mileage < 0 THEN 0 ELSE monthly_mileage END AS monthly_mileage,
|
||||
CASE WHEN total_mileage < 0 THEN 0 ELSE total_mileage END AS total_mileage,
|
||||
CASE WHEN previous_month_mileage = -1 THEN NULL WHEN previous_month_mileage < 0 THEN 0 ELSE previous_month_mileage END AS previous_month_mileage,
|
||||
CASE WHEN current_month_mileage = -1 THEN NULL WHEN current_month_mileage < 0 THEN 0 ELSE current_month_mileage END AS current_month_mileage,
|
||||
CASE WHEN monthly_mileage = -1 THEN NULL WHEN monthly_mileage < 0 THEN 0 ELSE monthly_mileage END AS monthly_mileage,
|
||||
CASE WHEN total_mileage = -1 THEN NULL WHEN total_mileage < 0 THEN 0 ELSE total_mileage END AS total_mileage,
|
||||
mileage_unit,
|
||||
attachments,
|
||||
remark
|
||||
|
||||
+4
-4
@@ -48,10 +48,10 @@
|
||||
vehicle_no,
|
||||
card_holder,
|
||||
data_source,
|
||||
CASE WHEN quantity < 0 THEN 0 ELSE quantity END AS quantity,
|
||||
CASE WHEN unit_price < 0 THEN 0 ELSE unit_price END AS unit_price,
|
||||
CASE WHEN transaction_amount < 0 THEN 0 ELSE transaction_amount END AS transaction_amount,
|
||||
CASE WHEN balance < 0 THEN 0 ELSE balance END AS balance,
|
||||
CASE WHEN quantity = -1 THEN NULL WHEN quantity < 0 THEN 0 ELSE quantity END AS quantity,
|
||||
CASE WHEN unit_price = -1 THEN NULL WHEN unit_price < 0 THEN 0 ELSE unit_price END AS unit_price,
|
||||
CASE WHEN transaction_amount = -1 THEN NULL WHEN transaction_amount < 0 THEN 0 ELSE transaction_amount END AS transaction_amount,
|
||||
CASE WHEN balance = -1 THEN NULL WHEN balance < 0 THEN 0 ELSE balance END AS balance,
|
||||
station,
|
||||
attachments,
|
||||
remark
|
||||
|
||||
+2
-2
@@ -38,8 +38,8 @@
|
||||
handler,
|
||||
replacement_time,
|
||||
tire_brand,
|
||||
CASE WHEN tire_quantity < 0 THEN 0 ELSE tire_quantity END AS tire_quantity,
|
||||
CASE WHEN replacement_cost < 0 THEN 0 ELSE replacement_cost END AS replacement_cost,
|
||||
CASE WHEN tire_quantity = -1 THEN NULL WHEN tire_quantity < 0 THEN 0 ELSE tire_quantity END AS tire_quantity,
|
||||
CASE WHEN replacement_cost = -1 THEN NULL WHEN replacement_cost < 0 THEN 0 ELSE replacement_cost END AS replacement_cost,
|
||||
replacement_description,
|
||||
attachments,
|
||||
remark
|
||||
|
||||
+2
-2
@@ -46,8 +46,8 @@
|
||||
violation_item,
|
||||
violation_time,
|
||||
location,
|
||||
CASE WHEN fine_amount < 0 THEN 0 ELSE fine_amount END AS fine_amount,
|
||||
CASE WHEN deduct_points < 0 THEN 0 ELSE deduct_points END AS deduct_points,
|
||||
CASE WHEN fine_amount = -1 THEN NULL WHEN fine_amount < 0 THEN 0 ELSE fine_amount END AS fine_amount,
|
||||
CASE WHEN deduct_points = -1 THEN NULL WHEN deduct_points < 0 THEN 0 ELSE deduct_points END AS deduct_points,
|
||||
penalty_unit,
|
||||
process_status,
|
||||
process_description,
|
||||
|
||||
+4
-2
@@ -7,12 +7,14 @@ import org.springblade.transport.pojo.dto.WaybillImportBatchRequest;
|
||||
import org.springblade.transport.pojo.entity.WaybillImportBatch;
|
||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportBatchVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportValidateResultVO;
|
||||
|
||||
/** 运单批次服务。 */
|
||||
public interface IWaybillImportBatchService extends BaseService<WaybillImportBatch> {
|
||||
WaybillImportBatch saveDraft(WaybillImportBatchRequest request);
|
||||
void validate(WaybillImportBatchRequest request, HttpServletResponse response);
|
||||
void confirm(WaybillImportBatchRequest request, HttpServletResponse response);
|
||||
WaybillImportValidateResultVO validate(WaybillImportBatchRequest request);
|
||||
void exportFailures(WaybillImportBatchRequest request, HttpServletResponse response);
|
||||
WaybillImportBatchVO confirm(WaybillImportBatchRequest request);
|
||||
IPage<WaybillImportBatchVO> page(IPage<WaybillImportBatch> page, WaybillImportBatchRequest request);
|
||||
BusinessRemoveResultVO removeBatches(String ids);
|
||||
String nextBatchNo();
|
||||
|
||||
+15
-9
@@ -61,6 +61,8 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
private static final int REMARK_MAX_LENGTH = 200;
|
||||
private static final int ATTACHMENTS_MAX_LENGTH = 1000;
|
||||
private static final int MONEY_SCALE = 2;
|
||||
/** 非必填金额未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final String VEHICLE = "车辆";
|
||||
private static final String SHIP = "船舶";
|
||||
private static final Set<String> ACCIDENT_NATURES = Set.of("重大事故", "一般事故", "轻微事故", "其他");
|
||||
@@ -69,7 +71,11 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
@Override
|
||||
public IPage<AccidentRecordVO> selectAccidentRecordPage(IPage<AccidentRecordVO> page, AccidentRecordVO accidentRecord) {
|
||||
List<AccidentRecordVO> records = baseMapper.selectAccidentRecordPage(page, accidentRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setDirectEconomicLoss(normalizeEmptyAmount(record.getDirectEconomicLoss()));
|
||||
record.setInsuranceClaimAmount(normalizeEmptyAmount(record.getInsuranceClaimAmount()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -153,8 +159,8 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
public List<AccidentRecordExportExcel> exportAccidentRecord(Wrapper<AccidentRecord> queryWrapper) {
|
||||
return list(queryWrapper).stream().map(accidentRecord -> {
|
||||
AccidentRecordExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(accidentRecord, AccidentRecordExportExcel.class));
|
||||
excel.setDirectEconomicLoss(nonNegative(accidentRecord.getDirectEconomicLoss()));
|
||||
excel.setInsuranceClaimAmount(nonNegative(accidentRecord.getInsuranceClaimAmount()));
|
||||
excel.setDirectEconomicLoss(normalizeEmptyAmount(accidentRecord.getDirectEconomicLoss()));
|
||||
excel.setInsuranceClaimAmount(normalizeEmptyAmount(accidentRecord.getInsuranceClaimAmount()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(accidentRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -169,6 +175,9 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
accidentRecord.setAccidentReasonDamage(trimToNull(accidentRecord.getAccidentReasonDamage()));
|
||||
accidentRecord.setAttachments(trimToNull(accidentRecord.getAttachments()));
|
||||
accidentRecord.setRemark(trimToNull(accidentRecord.getRemark()));
|
||||
// 非必填金额未填写禁止落库 -1 占位值
|
||||
accidentRecord.setDirectEconomicLoss(normalizeEmptyAmount(accidentRecord.getDirectEconomicLoss()));
|
||||
accidentRecord.setInsuranceClaimAmount(normalizeEmptyAmount(accidentRecord.getInsuranceClaimAmount()));
|
||||
}
|
||||
|
||||
private void validate(AccidentRecord accidentRecord) {
|
||||
@@ -238,11 +247,8 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String normalizeVehicleType(String vehicleType) {
|
||||
@@ -256,7 +262,7 @@ public class AccidentRecordServiceImpl extends BaseServiceImpl<AccidentRecordMap
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-8
@@ -63,6 +63,8 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
private static final int REMARK_MAX_LENGTH = 200;
|
||||
private static final int ATTACHMENTS_MAX_LENGTH = 1000;
|
||||
private static final int MONEY_SCALE = 2;
|
||||
/** 费用等数值未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final String VEHICLE = "车辆";
|
||||
private static final String SHIP = "船舶";
|
||||
private static final Set<String> PASSENGER_TYPE_LEVELS = Set.of("一级", "二级", "其他");
|
||||
@@ -70,7 +72,10 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
@Override
|
||||
public IPage<AnnualInspectionRecordVO> selectAnnualInspectionRecordPage(IPage<AnnualInspectionRecordVO> page, AnnualInspectionRecordVO annualInspectionRecord) {
|
||||
List<AnnualInspectionRecordVO> records = baseMapper.selectAnnualInspectionRecordPage(page, annualInspectionRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setFee(normalizeEmptyAmount(record.getFee()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -176,7 +181,7 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
AnnualInspectionRecordExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(annualInspectionRecord, AnnualInspectionRecordExportExcel.class));
|
||||
excel.setVehicleTechnicalLevel(VEHICLE.equals(annualInspectionRecord.getVehicleType()) ? annualInspectionRecord.getVehicleTechnicalLevel() : null);
|
||||
excel.setShipInspectionType(SHIP.equals(annualInspectionRecord.getVehicleType()) ? annualInspectionRecord.getShipInspectionType() : null);
|
||||
excel.setFee(nonNegative(annualInspectionRecord.getFee()));
|
||||
excel.setFee(normalizeEmptyAmount(annualInspectionRecord.getFee()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(annualInspectionRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -192,6 +197,8 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
annualInspectionRecord.setAssessmentUnit(trimToNull(annualInspectionRecord.getAssessmentUnit()));
|
||||
annualInspectionRecord.setAttachments(trimToNull(annualInspectionRecord.getAttachments()));
|
||||
annualInspectionRecord.setRemark(trimToNull(annualInspectionRecord.getRemark()));
|
||||
// 费用必填,-1 占位转 null 后由校验拦截;展示侧同步为空
|
||||
annualInspectionRecord.setFee(normalizeEmptyAmount(annualInspectionRecord.getFee()));
|
||||
if (VEHICLE.equals(annualInspectionRecord.getVehicleType())) {
|
||||
annualInspectionRecord.setShipInspectionType(null);
|
||||
} else {
|
||||
@@ -268,11 +275,8 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String normalizeVehicleType(String vehicleType) {
|
||||
@@ -286,7 +290,7 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl<AnnualIns
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+13
-8
@@ -82,6 +82,7 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl<InsuranceRecordM
|
||||
private static final int OCR_TEMPLATE_MAX_LENGTH = 100;
|
||||
private static final int POLICY_FILE_MAX_LENGTH = 1000;
|
||||
private static final int REMARK_MAX_LENGTH = 200;
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final Set<String> INSURANCE_TYPES = Set.of("交强险", "商业险", "承运人责任险", "货运险", "船舶险");
|
||||
private static final Set<String> SUPPORT_FILE_TYPES = Set.of("jpg", "jpeg", "png", "bmp");
|
||||
private static final Pattern DATE_PATTERN = Pattern.compile("(\\d{4})[-/.年](\\d{1,2})[-/.月](\\d{1,2})日?");
|
||||
@@ -93,7 +94,11 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl<InsuranceRecordM
|
||||
@Override
|
||||
public IPage<InsuranceRecordVO> selectInsuranceRecordPage(IPage<InsuranceRecordVO> page, InsuranceRecordVO insuranceRecord) {
|
||||
List<InsuranceRecordVO> records = baseMapper.selectInsuranceRecordPage(page, insuranceRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setInsuredAmount(normalizeEmptyAmount(record.getInsuredAmount()));
|
||||
record.setPremium(normalizeEmptyAmount(record.getPremium()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -191,8 +196,8 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl<InsuranceRecordM
|
||||
public List<InsuranceRecordExportExcel> exportInsuranceRecord(Wrapper<InsuranceRecord> queryWrapper) {
|
||||
return list(queryWrapper).stream().map(insuranceRecord -> {
|
||||
InsuranceRecordExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(insuranceRecord, InsuranceRecordExportExcel.class));
|
||||
excel.setInsuredAmount(nonNegative(insuranceRecord.getInsuredAmount()));
|
||||
excel.setPremium(nonNegative(insuranceRecord.getPremium()));
|
||||
excel.setInsuredAmount(normalizeEmptyAmount(insuranceRecord.getInsuredAmount()));
|
||||
excel.setPremium(normalizeEmptyAmount(insuranceRecord.getPremium()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(insuranceRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -337,6 +342,9 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl<InsuranceRecordM
|
||||
insuranceRecord.setOcrTemplate(trimToNull(insuranceRecord.getOcrTemplate()));
|
||||
insuranceRecord.setPolicyFile(trimToNull(insuranceRecord.getPolicyFile()));
|
||||
insuranceRecord.setRemark(trimToNull(insuranceRecord.getRemark()));
|
||||
// 未填写金额禁止落库 -1 占位值,统一存 null
|
||||
insuranceRecord.setInsuredAmount(normalizeEmptyAmount(insuranceRecord.getInsuredAmount()));
|
||||
insuranceRecord.setPremium(normalizeEmptyAmount(insuranceRecord.getPremium()));
|
||||
}
|
||||
|
||||
private void validate(InsuranceRecord insuranceRecord) {
|
||||
@@ -422,11 +430,8 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl<InsuranceRecordM
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String normalizeVehicleType(String vehicleType) {
|
||||
|
||||
+15
-9
@@ -60,11 +60,17 @@ public class MaintenancePlanServiceImpl extends BaseServiceImpl<MaintenancePlanM
|
||||
private static final int MAINTENANCE_ITEM_MAX_LENGTH = 100;
|
||||
private static final int ADDRESS_MAX_LENGTH = 100;
|
||||
private static final int REMARK_MAX_LENGTH = 500;
|
||||
/** 非必填里程未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_MILEAGE_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
@Override
|
||||
public IPage<MaintenancePlanVO> selectMaintenancePlanPage(IPage<MaintenancePlanVO> page, MaintenancePlanVO maintenancePlan) {
|
||||
List<MaintenancePlanVO> records = baseMapper.selectMaintenancePlanPage(page, maintenancePlan);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setMileage(normalizeEmptyMileage(record.getMileage()));
|
||||
record.setNextMaintenanceMileage(normalizeEmptyMileage(record.getNextMaintenanceMileage()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -147,8 +153,8 @@ public class MaintenancePlanServiceImpl extends BaseServiceImpl<MaintenancePlanM
|
||||
return list(queryWrapper).stream().map(maintenancePlan -> {
|
||||
MaintenancePlanExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(maintenancePlan, MaintenancePlanExportExcel.class));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(maintenancePlan.getUpdateUser()));
|
||||
excel.setMileage(nonNegative(maintenancePlan.getMileage()));
|
||||
excel.setNextMaintenanceMileage(nonNegative(maintenancePlan.getNextMaintenanceMileage()));
|
||||
excel.setMileage(normalizeEmptyMileage(maintenancePlan.getMileage()));
|
||||
excel.setNextMaintenanceMileage(normalizeEmptyMileage(maintenancePlan.getNextMaintenanceMileage()));
|
||||
if (Func.isEmpty(excel.getMileageUnit())) {
|
||||
excel.setMileageUnit(defaultMileageUnit(maintenancePlan.getVehicleType()));
|
||||
}
|
||||
@@ -165,6 +171,9 @@ public class MaintenancePlanServiceImpl extends BaseServiceImpl<MaintenancePlanM
|
||||
maintenancePlan.setContactPhone(trimToNull(maintenancePlan.getContactPhone()));
|
||||
maintenancePlan.setAddress(trimToNull(maintenancePlan.getAddress()));
|
||||
maintenancePlan.setRemark(trimToNull(maintenancePlan.getRemark()));
|
||||
// 非必填里程未填写禁止落库 -1 占位值
|
||||
maintenancePlan.setMileage(normalizeEmptyMileage(maintenancePlan.getMileage()));
|
||||
maintenancePlan.setNextMaintenanceMileage(normalizeEmptyMileage(maintenancePlan.getNextMaintenanceMileage()));
|
||||
if (Func.isEmpty(maintenancePlan.getMileageUnit())) {
|
||||
maintenancePlan.setMileageUnit(defaultMileageUnit(maintenancePlan.getVehicleType()));
|
||||
}
|
||||
@@ -219,11 +228,8 @@ public class MaintenancePlanServiceImpl extends BaseServiceImpl<MaintenancePlanM
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyMileage(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_MILEAGE_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String defaultMileageUnit(String vehicleType) {
|
||||
@@ -236,7 +242,7 @@ public class MaintenancePlanServiceImpl extends BaseServiceImpl<MaintenancePlanM
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+130
-10
@@ -28,6 +28,8 @@ import org.springblade.transport.service.IProjectApplyService;
|
||||
import org.springblade.transport.service.ITransportPlanService;
|
||||
import org.springblade.transport.service.IWaybillService;
|
||||
import org.springblade.transport.support.TransportBusinessSupport;
|
||||
import org.springblade.transport.support.WaybillProcessSupport;
|
||||
import org.springblade.transport.wrapper.WaybillWrapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@@ -92,16 +94,42 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public MasterOrderVO submit(MasterOrderVO request, boolean draft) {
|
||||
boolean created = Func.isEmpty(request.getId());
|
||||
MasterOrder target = created ? new MasterOrder() : getRequired(request.getId());
|
||||
if (!created && "completed".equals(target.getBusinessStatus())) {
|
||||
assertRestrictedEdit(target, request);
|
||||
MasterOrder oldRecord = created ? null : getRequired(request.getId());
|
||||
MasterOrder target = created ? new MasterOrder()
|
||||
: Objects.requireNonNull(BeanUtil.copyProperties(oldRecord, MasterOrder.class));
|
||||
String previousStatus = oldRecord == null ? null : oldRecord.getBusinessStatus();
|
||||
if (!created && "closed".equals(previousStatus)) {
|
||||
throw new ServiceException("调度关闭的总单不能编辑");
|
||||
}
|
||||
// 非草稿编辑:基本信息与路线不可改
|
||||
if (!created && !"draft".equals(previousStatus)) {
|
||||
assertRestrictedEdit(oldRecord, request);
|
||||
}
|
||||
if (!created && "closed".equals(target.getBusinessStatus())) throw new ServiceException("调度关闭的总单不能编辑");
|
||||
copyWritable(request, target);
|
||||
if (created) target.setMasterNo(nextCode());
|
||||
if (!created && !"draft".equals(previousStatus)) {
|
||||
restoreBasicAndRoute(target, oldRecord);
|
||||
}
|
||||
if (created) {
|
||||
target.setMasterNo(nextCode());
|
||||
}
|
||||
target.setTransportOrganizationType("多式联运");
|
||||
target.setBusinessStatus(draft ? "draft" : ("dispatching".equals(target.getBusinessStatus()) ? "dispatching" : "waiting_dispatch"));
|
||||
if (draft) {
|
||||
// 仅新建或原草稿可暂存为 draft;已进入待调度及之后状态的编辑保持原状态
|
||||
if (created || Func.isEmpty(previousStatus) || "draft".equals(previousStatus)) {
|
||||
target.setBusinessStatus("draft");
|
||||
} else {
|
||||
target.setBusinessStatus(previousStatus);
|
||||
}
|
||||
} else if ("dispatching".equals(previousStatus) || "completed".equals(previousStatus)) {
|
||||
// 调度中 / 调度完成编辑后保持原状态,避免误回退为待调度
|
||||
target.setBusinessStatus(previousStatus);
|
||||
} else {
|
||||
target.setBusinessStatus("waiting_dispatch");
|
||||
}
|
||||
validate(target, draft);
|
||||
if (!created) {
|
||||
validateGoodsAgainstDispatched(oldRecord, target);
|
||||
}
|
||||
saveOrUpdate(target);
|
||||
return detail(target.getId());
|
||||
}
|
||||
@@ -210,8 +238,14 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
||||
row.setVehicleNo(waybill.getVehicleNo());
|
||||
row.setStartDate(waybill.getStartDate());
|
||||
row.setEndDate(waybill.getEndDate());
|
||||
row.setBusinessStatus(waybill.getBusinessStatus());
|
||||
// 与前端运单状态展示一致:先按接单配置校正,再转中文
|
||||
row.setBusinessStatus(WaybillWrapper.businessStatusName(
|
||||
WaybillProcessSupport.normalizeBusinessStatus(
|
||||
waybill.getBusinessStatus(),
|
||||
waybill.getProcessJson(),
|
||||
waybill.getDriverAcceptStatus())));
|
||||
row.setRemark(waybill.getRemark());
|
||||
row.setUpdateTime(waybill.getUpdateTime());
|
||||
row.setCreateTime(waybill.getCreateTime());
|
||||
result.add(row);
|
||||
}
|
||||
@@ -302,6 +336,7 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
||||
List<Waybill> boundWaybills = waybillsByMasterNo(entity.getMasterNo());
|
||||
vo.setBoundWaybills(boundWaybills);
|
||||
vo.setRouteProgress(buildProgress(entity, vo.getRoutes(), boundWaybills));
|
||||
vo.setDispatchedGoods(maxDispatchedGoodsByCategory(entity));
|
||||
vo.setCreateUserName(UserCache.getUserRealName(entity.getCreateUser())); vo.setUpdateUserName(UserCache.getUserRealName(entity.getUpdateUser()));
|
||||
return vo;
|
||||
}
|
||||
@@ -343,7 +378,89 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
||||
}
|
||||
|
||||
private void assertRestrictedEdit(MasterOrder oldRecord, MasterOrderVO request) {
|
||||
if (!Objects.equals(oldRecord.getProjectId(), request.getProjectId()) || !Objects.equals(oldRecord.getRouteJson(), JsonUtil.toJson(request.getRoutes()))) throw new ServiceException("调度完成的总单不能修改基本信息和路线");
|
||||
boolean basicChanged = !Objects.equals(oldRecord.getProjectId(), request.getProjectId())
|
||||
|| !Objects.equals(oldRecord.getContractId(), request.getContractId())
|
||||
|| !Objects.equals(normalizeText(oldRecord.getRemark()), normalizeText(request.getRemark()));
|
||||
boolean routeChanged = !Objects.equals(normalizeText(oldRecord.getDepartureName()), normalizeText(request.getDepartureName()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getDepartureAddress()), normalizeText(request.getDepartureAddress()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getDepartureContact()), normalizeText(request.getDepartureContact()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getDeparturePhone()), normalizeText(request.getDeparturePhone()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getArrivalName()), normalizeText(request.getArrivalName()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getArrivalAddress()), normalizeText(request.getArrivalAddress()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getArrivalContact()), normalizeText(request.getArrivalContact()))
|
||||
|| !Objects.equals(normalizeText(oldRecord.getArrivalPhone()), normalizeText(request.getArrivalPhone()))
|
||||
|| !Objects.equals(oldRecord.getPlanStartTime(), request.getPlanStartTime())
|
||||
|| !Objects.equals(oldRecord.getPlanEndTime(), request.getPlanEndTime())
|
||||
|| !Objects.equals(normalizeText(oldRecord.getRouteJson()), normalizeText(JsonUtil.toJson(request.getRoutes())));
|
||||
if (basicChanged || routeChanged) {
|
||||
throw new ServiceException("当前总单不能修改基本信息和路线");
|
||||
}
|
||||
}
|
||||
|
||||
/** 非草稿编辑时强制保留库中基本信息与路线,避免前端绕过禁用项提交 */
|
||||
private void restoreBasicAndRoute(MasterOrder target, MasterOrder oldRecord) {
|
||||
target.setProjectId(oldRecord.getProjectId());
|
||||
target.setProjectName(oldRecord.getProjectName());
|
||||
target.setContractId(oldRecord.getContractId());
|
||||
target.setContractName(oldRecord.getContractName());
|
||||
target.setCustomerName(oldRecord.getCustomerName());
|
||||
target.setRemark(oldRecord.getRemark());
|
||||
target.setDepartureName(oldRecord.getDepartureName());
|
||||
target.setDepartureAddress(oldRecord.getDepartureAddress());
|
||||
target.setDepartureContact(oldRecord.getDepartureContact());
|
||||
target.setDeparturePhone(oldRecord.getDeparturePhone());
|
||||
target.setArrivalName(oldRecord.getArrivalName());
|
||||
target.setArrivalAddress(oldRecord.getArrivalAddress());
|
||||
target.setArrivalContact(oldRecord.getArrivalContact());
|
||||
target.setArrivalPhone(oldRecord.getArrivalPhone());
|
||||
target.setPlanStartTime(oldRecord.getPlanStartTime());
|
||||
target.setPlanEndTime(oldRecord.getPlanEndTime());
|
||||
target.setRouteJson(oldRecord.getRouteJson());
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑时货物数量不得低于该品类已调度量(各分段已调度量取最大值)。
|
||||
*/
|
||||
private void validateGoodsAgainstDispatched(MasterOrder oldRecord, MasterOrder target) {
|
||||
Map<String, BigDecimal> maxDispatched = maxDispatchedGoodsByCategory(oldRecord);
|
||||
if (maxDispatched.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
Map<String, BigDecimal> newAvailable = availableGoods(target);
|
||||
for (Map.Entry<String, BigDecimal> entry : maxDispatched.entrySet()) {
|
||||
BigDecimal dispatched = entry.getValue();
|
||||
if (dispatched == null || dispatched.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
continue;
|
||||
}
|
||||
BigDecimal newQuantity = newAvailable.getOrDefault(entry.getKey(), BigDecimal.ZERO);
|
||||
if (newQuantity.compareTo(dispatched) < 0) {
|
||||
String cargoName = entry.getKey().contains("\u0000")
|
||||
? entry.getKey().substring(0, entry.getKey().indexOf('\u0000'))
|
||||
: entry.getKey();
|
||||
throw new ServiceException("货物【" + cargoName + "】数量不能低于已调度量("
|
||||
+ dispatched.stripTrailingZeros().toPlainString() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** 各品类已调度量:同一品类取各分段已调度量的最大值 */
|
||||
private Map<String, BigDecimal> maxDispatchedGoodsByCategory(MasterOrder masterOrder) {
|
||||
Map<String, BigDecimal> result = new LinkedHashMap<>();
|
||||
List<Map<String, Object>> routes = parseArray(masterOrder.getRouteJson());
|
||||
if (routes.isEmpty()) {
|
||||
return dispatchedGoods(masterOrder.getMasterNo(), null);
|
||||
}
|
||||
for (Map<String, Object> route : routes) {
|
||||
Map<String, BigDecimal> dispatched = dispatchedGoods(masterOrder.getMasterNo(), string(route, "segmentNo"));
|
||||
for (Map.Entry<String, BigDecimal> entry : dispatched.entrySet()) {
|
||||
result.merge(entry.getKey(), entry.getValue(), BigDecimal::max);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private String normalizeText(String value) {
|
||||
return value == null ? "" : value.trim();
|
||||
}
|
||||
|
||||
private void validate(MasterOrder masterOrder, boolean draft) {
|
||||
@@ -403,10 +520,13 @@ public class MasterOrderServiceImpl extends BaseServiceImpl<MasterOrderMapper, M
|
||||
String segmentNo = string(route, "segmentNo");
|
||||
BigDecimal requestQuantity = requestQuantityBySegment.get(segmentNo);
|
||||
if (requestQuantity == null) continue;
|
||||
BigDecimal dispatchTotal = routeDispatchedQuantity(masterOrder, route).add(requestQuantity);
|
||||
BigDecimal previousCompletedQuantity = completedQuantity(masterOrder.getMasterNo(), routes.get(index - 1));
|
||||
if (previousCompletedQuantity.compareTo(BigDecimal.ZERO) <= 0) {
|
||||
throw new ServiceException(segmentNo + "需等上一段运单完成到达后才能调度");
|
||||
}
|
||||
BigDecimal dispatchTotal = routeDispatchedQuantity(masterOrder, route).add(requestQuantity);
|
||||
if (dispatchTotal.compareTo(previousCompletedQuantity) > 0) {
|
||||
throw new ServiceException(segmentNo + "调度总量不能大于上一段已完成数量(" + previousCompletedQuantity.stripTrailingZeros().toPlainString() + ")");
|
||||
throw new ServiceException(segmentNo + "调度总量不能大于上一段已到达数量(" + previousCompletedQuantity.stripTrailingZeros().toPlainString() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-11
@@ -58,13 +58,21 @@ public class MileageRecordServiceImpl extends BaseServiceImpl<MileageRecordMappe
|
||||
private static final int REMARK_MAX_LENGTH = 200;
|
||||
private static final int ATTACHMENTS_MAX_LENGTH = 1000;
|
||||
private static final int MILEAGE_SCALE = 2;
|
||||
/** 非必填里程未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_MILEAGE_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final String VEHICLE_TYPE_VEHICLE = "车辆";
|
||||
private static final String MILEAGE_UNIT = "公里";
|
||||
|
||||
@Override
|
||||
public IPage<MileageRecordVO> selectMileageRecordPage(IPage<MileageRecordVO> page, MileageRecordVO mileageRecord) {
|
||||
List<MileageRecordVO> records = baseMapper.selectMileageRecordPage(page, mileageRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setPreviousMonthMileage(normalizeEmptyMileage(record.getPreviousMonthMileage()));
|
||||
record.setCurrentMonthMileage(normalizeEmptyMileage(record.getCurrentMonthMileage()));
|
||||
record.setMonthlyMileage(normalizeEmptyMileage(record.getMonthlyMileage()));
|
||||
record.setTotalMileage(normalizeEmptyMileage(record.getTotalMileage()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -145,10 +153,10 @@ public class MileageRecordServiceImpl extends BaseServiceImpl<MileageRecordMappe
|
||||
MileageRecordExportExcel excel = Objects.requireNonNull(
|
||||
BeanUtil.copyProperties(mileageRecord, MileageRecordExportExcel.class)
|
||||
);
|
||||
excel.setPreviousMonthMileage(nonNegative(mileageRecord.getPreviousMonthMileage()));
|
||||
excel.setCurrentMonthMileage(nonNegative(mileageRecord.getCurrentMonthMileage()));
|
||||
excel.setMonthlyMileage(nonNegative(mileageRecord.getMonthlyMileage()));
|
||||
excel.setTotalMileage(nonNegative(mileageRecord.getTotalMileage()));
|
||||
excel.setPreviousMonthMileage(normalizeEmptyMileage(mileageRecord.getPreviousMonthMileage()));
|
||||
excel.setCurrentMonthMileage(normalizeEmptyMileage(mileageRecord.getCurrentMonthMileage()));
|
||||
excel.setMonthlyMileage(normalizeEmptyMileage(mileageRecord.getMonthlyMileage()));
|
||||
excel.setTotalMileage(normalizeEmptyMileage(mileageRecord.getTotalMileage()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(mileageRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -160,6 +168,11 @@ public class MileageRecordServiceImpl extends BaseServiceImpl<MileageRecordMappe
|
||||
mileageRecord.setMileageUnit(MILEAGE_UNIT);
|
||||
mileageRecord.setRemark(trimToNull(mileageRecord.getRemark()));
|
||||
mileageRecord.setAttachments(trimToNull(mileageRecord.getAttachments()));
|
||||
// 非必填里程未填写禁止落库 -1 占位值
|
||||
mileageRecord.setPreviousMonthMileage(normalizeEmptyMileage(mileageRecord.getPreviousMonthMileage()));
|
||||
mileageRecord.setCurrentMonthMileage(normalizeEmptyMileage(mileageRecord.getCurrentMonthMileage()));
|
||||
mileageRecord.setMonthlyMileage(normalizeEmptyMileage(mileageRecord.getMonthlyMileage()));
|
||||
mileageRecord.setTotalMileage(normalizeEmptyMileage(mileageRecord.getTotalMileage()));
|
||||
if (mileageRecord.getMonthlyMileage() == null
|
||||
&& mileageRecord.getPreviousMonthMileage() != null
|
||||
&& mileageRecord.getCurrentMonthMileage() != null) {
|
||||
@@ -235,11 +248,8 @@ public class MileageRecordServiceImpl extends BaseServiceImpl<MileageRecordMappe
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyMileage(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_MILEAGE_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String normalizeVehicleNo(String vehicleNo) {
|
||||
@@ -252,7 +262,7 @@ public class MileageRecordServiceImpl extends BaseServiceImpl<MileageRecordMappe
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+21
-11
@@ -45,6 +45,8 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
private static final int ATTACHMENTS_MAX_LENGTH = 1000;
|
||||
private static final int MONEY_SCALE = 2;
|
||||
private static final int QUANTITY_SCALE = 2;
|
||||
/** 非必填数值未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final String VEHICLE = "车辆";
|
||||
private static final String SHIP = "船舶";
|
||||
private static final String FUEL = "加油";
|
||||
@@ -54,7 +56,13 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
@Override
|
||||
public IPage<OilElectricRecordVO> selectOilElectricRecordPage(IPage<OilElectricRecordVO> page, OilElectricRecordVO oilElectricRecord) {
|
||||
List<OilElectricRecordVO> records = baseMapper.selectOilElectricRecordPage(page, oilElectricRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setQuantity(normalizeEmptyAmount(record.getQuantity()));
|
||||
record.setUnitPrice(normalizeEmptyAmount(record.getUnitPrice()));
|
||||
record.setTransactionAmount(normalizeEmptyAmount(record.getTransactionAmount()));
|
||||
record.setBalance(normalizeEmptyAmount(record.getBalance()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -138,10 +146,10 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
public List<OilElectricRecordExportExcel> exportOilElectricRecord(Wrapper<OilElectricRecord> queryWrapper) {
|
||||
return list(queryWrapper).stream().map(oilElectricRecord -> {
|
||||
OilElectricRecordExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(oilElectricRecord, OilElectricRecordExportExcel.class));
|
||||
excel.setQuantity(nonNegative(oilElectricRecord.getQuantity()));
|
||||
excel.setUnitPrice(nonNegative(oilElectricRecord.getUnitPrice()));
|
||||
excel.setTransactionAmount(nonNegative(oilElectricRecord.getTransactionAmount()));
|
||||
excel.setBalance(nonNegative(oilElectricRecord.getBalance()));
|
||||
excel.setQuantity(normalizeEmptyAmount(oilElectricRecord.getQuantity()));
|
||||
excel.setUnitPrice(normalizeEmptyAmount(oilElectricRecord.getUnitPrice()));
|
||||
excel.setTransactionAmount(normalizeEmptyAmount(oilElectricRecord.getTransactionAmount()));
|
||||
excel.setBalance(normalizeEmptyAmount(oilElectricRecord.getBalance()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(oilElectricRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -161,6 +169,11 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
oilElectricRecord.setDataSource(defaultDataSource(oilElectricRecord.getDataSource()));
|
||||
oilElectricRecord.setAttachments(trimToNull(oilElectricRecord.getAttachments()));
|
||||
oilElectricRecord.setRemark(trimToNull(oilElectricRecord.getRemark()));
|
||||
// 非必填数值未填写禁止落库 -1;交易金额必填,-1 转 null 后由校验拦截
|
||||
oilElectricRecord.setQuantity(normalizeEmptyAmount(oilElectricRecord.getQuantity()));
|
||||
oilElectricRecord.setUnitPrice(normalizeEmptyAmount(oilElectricRecord.getUnitPrice()));
|
||||
oilElectricRecord.setTransactionAmount(normalizeEmptyAmount(oilElectricRecord.getTransactionAmount()));
|
||||
oilElectricRecord.setBalance(normalizeEmptyAmount(oilElectricRecord.getBalance()));
|
||||
if (ELECTRIC.equals(oilElectricRecord.getFeeType())) {
|
||||
oilElectricRecord.setOilProduct(null);
|
||||
}
|
||||
@@ -223,11 +236,8 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private String defaultDataSource(String dataSource) {
|
||||
@@ -246,7 +256,7 @@ public class OilElectricRecordServiceImpl extends BaseServiceImpl<OilElectricRec
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+18
-14
@@ -62,11 +62,18 @@ public class TireReplacementRecordServiceImpl extends BaseServiceImpl<TireReplac
|
||||
private static final int REMARK_MAX_LENGTH = 500;
|
||||
private static final int ATTACHMENTS_MAX_LENGTH = 1000;
|
||||
private static final int MONEY_SCALE = 2;
|
||||
/** 非必填数量/金额未填写时的历史占位值,统一转为 null */
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final Integer EMPTY_INTEGER_SENTINEL = -1;
|
||||
|
||||
@Override
|
||||
public IPage<TireReplacementRecordVO> selectTireReplacementRecordPage(IPage<TireReplacementRecordVO> page, TireReplacementRecordVO tireReplacementRecord) {
|
||||
List<TireReplacementRecordVO> records = baseMapper.selectTireReplacementRecordPage(page, tireReplacementRecord);
|
||||
records.forEach(record -> record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser())));
|
||||
records.forEach(record -> {
|
||||
record.setTireQuantity(normalizeEmptyInteger(record.getTireQuantity()));
|
||||
record.setReplacementCost(normalizeEmptyAmount(record.getReplacementCost()));
|
||||
record.setUpdateUserName(UserCache.getUserRealName(record.getUpdateUser()));
|
||||
});
|
||||
return page.setRecords(records);
|
||||
}
|
||||
|
||||
@@ -153,8 +160,8 @@ public class TireReplacementRecordServiceImpl extends BaseServiceImpl<TireReplac
|
||||
public List<TireReplacementRecordExportExcel> exportTireReplacementRecord(Wrapper<TireReplacementRecord> queryWrapper) {
|
||||
return list(queryWrapper).stream().map(tireReplacementRecord -> {
|
||||
TireReplacementRecordExportExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(tireReplacementRecord, TireReplacementRecordExportExcel.class));
|
||||
excel.setTireQuantity(validQuantity(tireReplacementRecord.getTireQuantity()));
|
||||
excel.setReplacementCost(nonNegative(tireReplacementRecord.getReplacementCost()));
|
||||
excel.setTireQuantity(normalizeEmptyInteger(tireReplacementRecord.getTireQuantity()));
|
||||
excel.setReplacementCost(normalizeEmptyAmount(tireReplacementRecord.getReplacementCost()));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(tireReplacementRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -167,6 +174,9 @@ public class TireReplacementRecordServiceImpl extends BaseServiceImpl<TireReplac
|
||||
tireReplacementRecord.setReplacementDescription(trimToNull(tireReplacementRecord.getReplacementDescription()));
|
||||
tireReplacementRecord.setAttachments(trimToNull(tireReplacementRecord.getAttachments()));
|
||||
tireReplacementRecord.setRemark(trimToNull(tireReplacementRecord.getRemark()));
|
||||
// 非必填数量及金额占位值 -1 统一存 null(费用必填,-1 转 null 后由校验拦截)
|
||||
tireReplacementRecord.setTireQuantity(normalizeEmptyInteger(tireReplacementRecord.getTireQuantity()));
|
||||
tireReplacementRecord.setReplacementCost(normalizeEmptyAmount(tireReplacementRecord.getReplacementCost()));
|
||||
}
|
||||
|
||||
private void validate(TireReplacementRecord tireReplacementRecord) {
|
||||
@@ -214,18 +224,12 @@ public class TireReplacementRecordServiceImpl extends BaseServiceImpl<TireReplac
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private Integer validQuantity(Integer value) {
|
||||
if (Func.isEmpty(value) || value > 0) {
|
||||
return value;
|
||||
}
|
||||
return null;
|
||||
private Integer normalizeEmptyInteger(Integer value) {
|
||||
return Func.isNotEmpty(value) && value.equals(EMPTY_INTEGER_SENTINEL) ? null : value;
|
||||
}
|
||||
|
||||
private String trimToEmpty(String value) {
|
||||
@@ -234,7 +238,7 @@ public class TireReplacementRecordServiceImpl extends BaseServiceImpl<TireReplac
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -192,7 +192,7 @@ public class TransportChangeRecordServiceImpl extends BaseServiceImpl<TransportC
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-8
@@ -69,6 +69,9 @@ public class ViolationRecordServiceImpl extends BaseServiceImpl<ViolationRecordM
|
||||
private static final String UNPROCESSED = "未处理";
|
||||
private static final String CAR = "车辆";
|
||||
private static final String SHIP = "船舶";
|
||||
/** 非必填数值未填写时的历史占位值,统一转为 null 落库/展示 */
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final Integer EMPTY_INTEGER_SENTINEL = -1;
|
||||
|
||||
@Override
|
||||
public IPage<ViolationRecordVO> selectViolationRecordPage(IPage<ViolationRecordVO> page, ViolationRecordVO violationRecord) {
|
||||
@@ -168,8 +171,8 @@ public class ViolationRecordServiceImpl extends BaseServiceImpl<ViolationRecordM
|
||||
public List<ViolationRecordExcel> exportViolationRecord(Wrapper<ViolationRecord> queryWrapper) {
|
||||
return list(queryWrapper).stream().map(violationRecord -> {
|
||||
ViolationRecordExcel excel = Objects.requireNonNull(BeanUtil.copyProperties(violationRecord, ViolationRecordExcel.class));
|
||||
excel.setFineAmount(nonNegative(violationRecord.getFineAmount()));
|
||||
excel.setDeductPoints(validDeductPoints(violationRecord.getDeductPoints()));
|
||||
excel.setFineAmount(normalizeEmptyAmount(violationRecord.getFineAmount()));
|
||||
excel.setDeductPoints(validDeductPoints(normalizeEmptyInteger(violationRecord.getDeductPoints())));
|
||||
excel.setUpdateUserName(UserCache.getUserRealName(violationRecord.getUpdateUser()));
|
||||
return excel;
|
||||
}).toList();
|
||||
@@ -187,6 +190,9 @@ public class ViolationRecordServiceImpl extends BaseServiceImpl<ViolationRecordM
|
||||
violationRecord.setProcessDescription(trimToEmpty(violationRecord.getProcessDescription()));
|
||||
violationRecord.setProcessResult(trimToNull(violationRecord.getProcessResult()));
|
||||
violationRecord.setAttachments(trimToNull(violationRecord.getAttachments()));
|
||||
// 非必填数值未填写禁止落库 -1 占位值
|
||||
violationRecord.setFineAmount(normalizeEmptyAmount(violationRecord.getFineAmount()));
|
||||
violationRecord.setDeductPoints(normalizeEmptyInteger(violationRecord.getDeductPoints()));
|
||||
if (UNPROCESSED.equals(violationRecord.getProcessStatus())) {
|
||||
violationRecord.setProcessResult(null);
|
||||
}
|
||||
@@ -290,11 +296,12 @@ public class ViolationRecordServiceImpl extends BaseServiceImpl<ViolationRecordM
|
||||
}
|
||||
}
|
||||
|
||||
private BigDecimal nonNegative(BigDecimal value) {
|
||||
if (Func.isEmpty(value) || value.compareTo(BigDecimal.ZERO) >= 0) {
|
||||
return value;
|
||||
}
|
||||
return BigDecimal.ZERO;
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return Func.isNotEmpty(value) && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private Integer normalizeEmptyInteger(Integer value) {
|
||||
return Func.isNotEmpty(value) && value.equals(EMPTY_INTEGER_SENTINEL) ? null : value;
|
||||
}
|
||||
|
||||
private Integer validDeductPoints(Integer value) {
|
||||
@@ -323,7 +330,7 @@ public class ViolationRecordServiceImpl extends BaseServiceImpl<ViolationRecordM
|
||||
|
||||
private String trimToNull(String value) {
|
||||
String trimValue = trimToEmpty(value);
|
||||
return trimValue.isEmpty() ? null : trimValue;
|
||||
return trimValue.isEmpty() || "-1".equals(trimValue) ? null : trimValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+62
-52
@@ -18,7 +18,6 @@ import org.springblade.core.tool.api.R;
|
||||
import org.springblade.core.tool.utils.BeanUtil;
|
||||
import org.springblade.core.tool.utils.DateUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springblade.core.tool.jackson.JsonUtil;
|
||||
import org.springblade.system.cache.DictCache;
|
||||
import org.springblade.system.cache.DictBizCache;
|
||||
@@ -36,6 +35,8 @@ import org.springblade.transport.pojo.entity.Waybill;
|
||||
import org.springblade.transport.pojo.entity.WaybillImportBatch;
|
||||
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportBatchVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportRowErrorVO;
|
||||
import org.springblade.transport.pojo.vo.WaybillImportValidateResultVO;
|
||||
import org.springblade.transport.service.ICustomerArchiveService;
|
||||
import org.springblade.transport.service.IProjectApplyService;
|
||||
import org.springblade.transport.service.IReceivablePayableDetailService;
|
||||
@@ -46,9 +47,7 @@ import org.springblade.transport.service.IWaybillService;
|
||||
import org.springblade.transport.support.TransportBusinessSupport;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@@ -98,89 +97,97 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
public WaybillImportValidateResultVO validate(WaybillImportBatchRequest request) {
|
||||
if (Func.isEmpty(request.getRows())) throw new ServiceException("请上传至少一条运单明细");
|
||||
|
||||
// 确定导入状态
|
||||
WaybillImportValidateResultVO result = new WaybillImportValidateResultVO();
|
||||
String importStatus = STATUS_DRAFT.equals(request.getStatus()) ? STATUS_DRAFT : STATUS_COMPLETED;
|
||||
boolean draft = STATUS_DRAFT.equals(importStatus);
|
||||
|
||||
// 草稿状态不校验,直接返回成功
|
||||
if (draft) {
|
||||
WebUtil.renderJson(response, R.success("校验通过"));
|
||||
return;
|
||||
result.setSuccess(Boolean.TRUE);
|
||||
return result;
|
||||
}
|
||||
|
||||
// 执行校验
|
||||
List<Map<String, Object>> rows = request.getRows();
|
||||
Map<Integer, String> validationErrors = validateImportRows(rows, importStatus);
|
||||
|
||||
// 如果有校验错误,导出错误明细Excel
|
||||
if (!validationErrors.isEmpty()) {
|
||||
List<WaybillImportBatchExcel> failureList = new ArrayList<>();
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
WaybillImportBatchExcel excel = mapToExcel(rows.get(i));
|
||||
String errorMessage = validationErrors.get(i);
|
||||
excel.setErrorMessage(Func.isNotEmpty(errorMessage) ? errorMessage : "");
|
||||
failureList.add(excel);
|
||||
}
|
||||
ImportFailureExcelUtil.export(response, "运单导入失败明细" + DateUtil.time(), "导入失败明细", failureList, WaybillImportBatchExcel.class);
|
||||
return;
|
||||
List<WaybillImportRowErrorVO> errors = new ArrayList<>();
|
||||
for (Map.Entry<Integer, String> entry : validationErrors.entrySet()) {
|
||||
WaybillImportRowErrorVO error = new WaybillImportRowErrorVO();
|
||||
error.setRowIndex(entry.getKey());
|
||||
error.setErrorMessage(entry.getValue());
|
||||
errors.add(error);
|
||||
}
|
||||
result.setErrors(errors);
|
||||
result.setSuccess(errors.isEmpty());
|
||||
return result;
|
||||
}
|
||||
|
||||
// 校验通过,返回成功响应
|
||||
WebUtil.renderJson(response, R.success("校验通过"));
|
||||
@Override
|
||||
public void exportFailures(WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
if (Func.isEmpty(request.getRows())) throw new ServiceException("请至少提供一条失败明细");
|
||||
List<WaybillImportBatchExcel> failureList = new ArrayList<>();
|
||||
for (Map<String, Object> row : request.getRows()) {
|
||||
WaybillImportBatchExcel excel = mapToExcel(row);
|
||||
excel.setErrorMessage(stringValue(row, "errorMessage", "导入失败原因", "失败原因"));
|
||||
failureList.add(excel);
|
||||
}
|
||||
ImportFailureExcelUtil.export(response, "运单导入失败明细" + DateUtil.time(), "导入失败明细", failureList, WaybillImportBatchExcel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void confirm(WaybillImportBatchRequest request, HttpServletResponse response) {
|
||||
public WaybillImportBatchVO confirm(WaybillImportBatchRequest request) {
|
||||
if (Func.isEmpty(request.getRows())) throw new ServiceException("请上传至少一条运单明细");
|
||||
|
||||
// 执行校验
|
||||
String importStatus = STATUS_DRAFT.equals(request.getStatus()) ? STATUS_DRAFT : STATUS_COMPLETED;
|
||||
boolean draft = STATUS_DRAFT.equals(importStatus);
|
||||
|
||||
if (!draft) {
|
||||
List<Map<String, Object>> rows = request.getRows();
|
||||
Map<Integer, String> validationErrors = validateImportRows(rows, importStatus);
|
||||
|
||||
// 如果有校验错误,导出错误明细Excel
|
||||
Map<Integer, String> validationErrors = validateImportRows(request.getRows(), importStatus);
|
||||
if (!validationErrors.isEmpty()) {
|
||||
List<WaybillImportBatchExcel> failureList = new ArrayList<>();
|
||||
for (int i = 0; i < rows.size(); i++) {
|
||||
WaybillImportBatchExcel excel = mapToExcel(rows.get(i));
|
||||
String errorMessage = validationErrors.get(i);
|
||||
excel.setErrorMessage(Func.isNotEmpty(errorMessage) ? errorMessage : "");
|
||||
failureList.add(excel);
|
||||
}
|
||||
ImportFailureExcelUtil.export(response, "运单导入失败明细" + DateUtil.time(), "导入失败明细", failureList, WaybillImportBatchExcel.class);
|
||||
return;
|
||||
String firstError = validationErrors.values().iterator().next();
|
||||
Integer firstIndex = validationErrors.keySet().iterator().next();
|
||||
throw new ServiceException("第" + (firstIndex + 1) + "行校验失败:" + firstError);
|
||||
}
|
||||
}
|
||||
|
||||
// 校验通过,执行导入
|
||||
WaybillImportBatch batch = persist(request, importStatus);
|
||||
|
||||
// 返回成功响应
|
||||
WebUtil.renderJson(response, R.success("操作成功"));
|
||||
return toVO(batch);
|
||||
}
|
||||
|
||||
/** 草稿与确认导入共用落库流程,差异仅在于运单是否走校验以及是否生成应收应付明细。 */
|
||||
private WaybillImportBatch persist(WaybillImportBatchRequest request, String importStatus) {
|
||||
boolean draft = STATUS_DRAFT.equals(importStatus);
|
||||
WaybillImportBatch batch = buildBatch(request, importStatus);
|
||||
if (Func.isNotEmpty(request.getId())) {
|
||||
boolean append = Boolean.TRUE.equals(request.getAppend());
|
||||
WaybillImportBatch batch;
|
||||
int existingWaybillCount = 0;
|
||||
|
||||
if (append) {
|
||||
if (Func.isEmpty(request.getId())) {
|
||||
throw new ServiceException("分批追加导入必须指定批次ID");
|
||||
}
|
||||
WaybillImportBatch oldBatch = getById(request.getId());
|
||||
if (oldBatch == null || Objects.equals(oldBatch.getIsDeleted(), 1)) throw new ServiceException("运单批次不存在");
|
||||
if (!STATUS_DRAFT.equals(oldBatch.getImportStatus())) throw new ServiceException("仅草稿状态的批次允许编辑");
|
||||
batch.setId(oldBatch.getId());
|
||||
batch.setBatchNo(oldBatch.getBatchNo());
|
||||
if (oldBatch == null || Objects.equals(oldBatch.getIsDeleted(), 1)) {
|
||||
throw new ServiceException("运单批次不存在");
|
||||
}
|
||||
batch = oldBatch;
|
||||
existingWaybillCount = Func.toInt(oldBatch.getWaybillCount(), 0);
|
||||
} else {
|
||||
batch = buildBatch(request, importStatus);
|
||||
if (Func.isNotEmpty(request.getId())) {
|
||||
WaybillImportBatch oldBatch = getById(request.getId());
|
||||
if (oldBatch == null || Objects.equals(oldBatch.getIsDeleted(), 1)) throw new ServiceException("运单批次不存在");
|
||||
if (!STATUS_DRAFT.equals(oldBatch.getImportStatus())) throw new ServiceException("仅草稿状态的批次允许编辑");
|
||||
batch.setId(oldBatch.getId());
|
||||
batch.setBatchNo(oldBatch.getBatchNo());
|
||||
}
|
||||
batch.setWaybillCount(0);
|
||||
saveOrUpdate(batch);
|
||||
// 重新落库前清理批次已生成的运单,避免草稿反复保存产生重复运单。
|
||||
clearBatchWaybills(batch.getId());
|
||||
}
|
||||
batch.setWaybillCount(0);
|
||||
saveOrUpdate(batch);
|
||||
// 重新落库前清理批次已生成的运单,避免草稿反复保存产生重复运单。
|
||||
clearBatchWaybills(batch.getId());
|
||||
|
||||
List<Map<String, Object>> rows = Func.isEmpty(request.getRows()) ? List.of() : request.getRows();
|
||||
|
||||
@@ -216,7 +223,10 @@ public class WaybillImportBatchServiceImpl extends BaseServiceImpl<WaybillImport
|
||||
}
|
||||
}
|
||||
loadingWaybills.forEach(loadingManageService::createFromImportedWaybills);
|
||||
batch.setWaybillCount(waybills.size());
|
||||
batch.setWaybillCount(existingWaybillCount + waybills.size());
|
||||
if (append && !draft) {
|
||||
batch.setImportStatus(STATUS_COMPLETED);
|
||||
}
|
||||
updateById(batch);
|
||||
// 导入完成且导入类型为运单时,按合同费用生成模式(系统生成)同步生成应收应付明细。
|
||||
if (!draft && IMPORT_TYPE_WAYBILL.equals(batch.getImportType())) {
|
||||
|
||||
+14
-1
@@ -685,6 +685,10 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public boolean submit(Waybill waybill) {
|
||||
boolean created = Func.isEmpty(waybill.getId());
|
||||
// 正式提交须脱离草稿:draft 在过程校正中被视为终态不会提升,需先清空再按接单配置校正为 pending/running
|
||||
if (STATUS_DRAFT.equals(waybill.getBusinessStatus())) {
|
||||
waybill.setBusinessStatus(null);
|
||||
}
|
||||
prepareForSave(waybill);
|
||||
validate(waybill);
|
||||
boolean result = saveOrUpdate(waybill);
|
||||
@@ -1309,7 +1313,16 @@ public class WaybillServiceImpl extends BaseServiceImpl<WaybillMapper, Waybill>
|
||||
queryWrapper.like(Waybill::getOriginalNo, waybill.getOriginalNo());
|
||||
}
|
||||
if (Func.isNotEmpty(waybill.getBusinessStatus())) {
|
||||
queryWrapper.eq(Waybill::getBusinessStatus, waybill.getBusinessStatus());
|
||||
List<String> businessStatuses = Arrays.stream(waybill.getBusinessStatus().split("[,,]"))
|
||||
.map(String::trim)
|
||||
.filter(Func::isNotEmpty)
|
||||
.distinct()
|
||||
.toList();
|
||||
if (businessStatuses.size() == 1) {
|
||||
queryWrapper.eq(Waybill::getBusinessStatus, businessStatuses.get(0));
|
||||
} else if (!businessStatuses.isEmpty()) {
|
||||
queryWrapper.in(Waybill::getBusinessStatus, businessStatuses);
|
||||
}
|
||||
}
|
||||
if (Func.isNotEmpty(waybill.getDataSource())) {
|
||||
queryWrapper.eq(Waybill::getDataSource, waybill.getDataSource());
|
||||
|
||||
+10
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.AccidentRecord;
|
||||
import org.springblade.transport.pojo.vo.AccidentRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class AccidentRecordWrapper extends BaseEntityWrapper<AccidentRecord, AccidentRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static AccidentRecordWrapper build() {
|
||||
return new AccidentRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +50,15 @@ public class AccidentRecordWrapper extends BaseEntityWrapper<AccidentRecord, Acc
|
||||
@Override
|
||||
public AccidentRecordVO entityVO(AccidentRecord accidentRecord) {
|
||||
AccidentRecordVO accidentRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(accidentRecord, AccidentRecordVO.class));
|
||||
// 未填写金额的占位值 -1 对外展示为空
|
||||
accidentRecordVO.setDirectEconomicLoss(normalizeEmptyAmount(accidentRecordVO.getDirectEconomicLoss()));
|
||||
accidentRecordVO.setInsuranceClaimAmount(normalizeEmptyAmount(accidentRecordVO.getInsuranceClaimAmount()));
|
||||
accidentRecordVO.setUpdateUserName(UserCache.getUserRealName(accidentRecord.getUpdateUser()));
|
||||
return accidentRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+9
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.AnnualInspectionRecord;
|
||||
import org.springblade.transport.pojo.vo.AnnualInspectionRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class AnnualInspectionRecordWrapper extends BaseEntityWrapper<AnnualInspectionRecord, AnnualInspectionRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static AnnualInspectionRecordWrapper build() {
|
||||
return new AnnualInspectionRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +50,14 @@ public class AnnualInspectionRecordWrapper extends BaseEntityWrapper<AnnualInspe
|
||||
@Override
|
||||
public AnnualInspectionRecordVO entityVO(AnnualInspectionRecord annualInspectionRecord) {
|
||||
AnnualInspectionRecordVO annualInspectionRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(annualInspectionRecord, AnnualInspectionRecordVO.class));
|
||||
// 费用占位值 -1 对外展示为空
|
||||
annualInspectionRecordVO.setFee(normalizeEmptyAmount(annualInspectionRecordVO.getFee()));
|
||||
annualInspectionRecordVO.setUpdateUserName(UserCache.getUserRealName(annualInspectionRecord.getUpdateUser()));
|
||||
return annualInspectionRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.InsuranceRecord;
|
||||
import org.springblade.transport.pojo.vo.InsuranceRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class InsuranceRecordWrapper extends BaseEntityWrapper<InsuranceRecord, InsuranceRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static InsuranceRecordWrapper build() {
|
||||
return new InsuranceRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +50,15 @@ public class InsuranceRecordWrapper extends BaseEntityWrapper<InsuranceRecord, I
|
||||
@Override
|
||||
public InsuranceRecordVO entityVO(InsuranceRecord insuranceRecord) {
|
||||
InsuranceRecordVO insuranceRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(insuranceRecord, InsuranceRecordVO.class));
|
||||
// 未填写保额等金额的占位值 -1 对外展示为空
|
||||
insuranceRecordVO.setInsuredAmount(normalizeEmptyAmount(insuranceRecordVO.getInsuredAmount()));
|
||||
insuranceRecordVO.setPremium(normalizeEmptyAmount(insuranceRecordVO.getPremium()));
|
||||
insuranceRecordVO.setUpdateUserName(UserCache.getUserRealName(insuranceRecord.getUpdateUser()));
|
||||
return insuranceRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.MaintenancePlan;
|
||||
import org.springblade.transport.pojo.vo.MaintenancePlanVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class MaintenancePlanWrapper extends BaseEntityWrapper<MaintenancePlan, MaintenancePlanVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_MILEAGE_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static MaintenancePlanWrapper build() {
|
||||
return new MaintenancePlanWrapper();
|
||||
}
|
||||
@@ -47,8 +50,15 @@ public class MaintenancePlanWrapper extends BaseEntityWrapper<MaintenancePlan, M
|
||||
@Override
|
||||
public MaintenancePlanVO entityVO(MaintenancePlan maintenancePlan) {
|
||||
MaintenancePlanVO maintenancePlanVO = Objects.requireNonNull(BeanUtil.copyProperties(maintenancePlan, MaintenancePlanVO.class));
|
||||
// 未填写里程的占位值 -1 对外展示为空
|
||||
maintenancePlanVO.setMileage(normalizeEmptyMileage(maintenancePlanVO.getMileage()));
|
||||
maintenancePlanVO.setNextMaintenanceMileage(normalizeEmptyMileage(maintenancePlanVO.getNextMaintenanceMileage()));
|
||||
maintenancePlanVO.setUpdateUserName(UserCache.getUserRealName(maintenancePlan.getUpdateUser()));
|
||||
return maintenancePlanVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyMileage(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_MILEAGE_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.MileageRecord;
|
||||
import org.springblade.transport.pojo.vo.MileageRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class MileageRecordWrapper extends BaseEntityWrapper<MileageRecord, MileageRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_MILEAGE_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static MileageRecordWrapper build() {
|
||||
return new MileageRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +50,17 @@ public class MileageRecordWrapper extends BaseEntityWrapper<MileageRecord, Milea
|
||||
@Override
|
||||
public MileageRecordVO entityVO(MileageRecord mileageRecord) {
|
||||
MileageRecordVO mileageRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(mileageRecord, MileageRecordVO.class));
|
||||
// 未填写里程的占位值 -1 对外展示为空
|
||||
mileageRecordVO.setPreviousMonthMileage(normalizeEmptyMileage(mileageRecordVO.getPreviousMonthMileage()));
|
||||
mileageRecordVO.setCurrentMonthMileage(normalizeEmptyMileage(mileageRecordVO.getCurrentMonthMileage()));
|
||||
mileageRecordVO.setMonthlyMileage(normalizeEmptyMileage(mileageRecordVO.getMonthlyMileage()));
|
||||
mileageRecordVO.setTotalMileage(normalizeEmptyMileage(mileageRecordVO.getTotalMileage()));
|
||||
mileageRecordVO.setUpdateUserName(UserCache.getUserRealName(mileageRecord.getUpdateUser()));
|
||||
return mileageRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyMileage(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_MILEAGE_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
@@ -12,6 +12,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.OilElectricRecord;
|
||||
import org.springblade.transport.pojo.vo.OilElectricRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -21,6 +22,8 @@ import java.util.Objects;
|
||||
*/
|
||||
public class OilElectricRecordWrapper extends BaseEntityWrapper<OilElectricRecord, OilElectricRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
|
||||
public static OilElectricRecordWrapper build() {
|
||||
return new OilElectricRecordWrapper();
|
||||
}
|
||||
@@ -28,8 +31,17 @@ public class OilElectricRecordWrapper extends BaseEntityWrapper<OilElectricRecor
|
||||
@Override
|
||||
public OilElectricRecordVO entityVO(OilElectricRecord oilElectricRecord) {
|
||||
OilElectricRecordVO oilElectricRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(oilElectricRecord, OilElectricRecordVO.class));
|
||||
// 未填写数量/金额的占位值 -1 对外展示为空
|
||||
oilElectricRecordVO.setQuantity(normalizeEmptyAmount(oilElectricRecordVO.getQuantity()));
|
||||
oilElectricRecordVO.setUnitPrice(normalizeEmptyAmount(oilElectricRecordVO.getUnitPrice()));
|
||||
oilElectricRecordVO.setTransactionAmount(normalizeEmptyAmount(oilElectricRecordVO.getTransactionAmount()));
|
||||
oilElectricRecordVO.setBalance(normalizeEmptyAmount(oilElectricRecordVO.getBalance()));
|
||||
oilElectricRecordVO.setUpdateUserName(UserCache.getUserRealName(oilElectricRecord.getUpdateUser()));
|
||||
return oilElectricRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.TireReplacementRecord;
|
||||
import org.springblade.transport.pojo.vo.TireReplacementRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,9 @@ import java.util.Objects;
|
||||
*/
|
||||
public class TireReplacementRecordWrapper extends BaseEntityWrapper<TireReplacementRecord, TireReplacementRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final Integer EMPTY_INTEGER_SENTINEL = -1;
|
||||
|
||||
public static TireReplacementRecordWrapper build() {
|
||||
return new TireReplacementRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +51,19 @@ public class TireReplacementRecordWrapper extends BaseEntityWrapper<TireReplacem
|
||||
@Override
|
||||
public TireReplacementRecordVO entityVO(TireReplacementRecord tireReplacementRecord) {
|
||||
TireReplacementRecordVO tireReplacementRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(tireReplacementRecord, TireReplacementRecordVO.class));
|
||||
// 未填写数量/费用的占位值 -1 对外展示为空
|
||||
tireReplacementRecordVO.setTireQuantity(normalizeEmptyInteger(tireReplacementRecordVO.getTireQuantity()));
|
||||
tireReplacementRecordVO.setReplacementCost(normalizeEmptyAmount(tireReplacementRecordVO.getReplacementCost()));
|
||||
tireReplacementRecordVO.setUpdateUserName(UserCache.getUserRealName(tireReplacementRecord.getUpdateUser()));
|
||||
return tireReplacementRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private Integer normalizeEmptyInteger(Integer value) {
|
||||
return value != null && value.equals(EMPTY_INTEGER_SENTINEL) ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
@@ -31,6 +31,7 @@ import org.springblade.system.cache.UserCache;
|
||||
import org.springblade.transport.pojo.entity.ViolationRecord;
|
||||
import org.springblade.transport.pojo.vo.ViolationRecordVO;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -40,6 +41,9 @@ import java.util.Objects;
|
||||
*/
|
||||
public class ViolationRecordWrapper extends BaseEntityWrapper<ViolationRecord, ViolationRecordVO> {
|
||||
|
||||
private static final BigDecimal EMPTY_AMOUNT_SENTINEL = BigDecimal.valueOf(-1);
|
||||
private static final Integer EMPTY_INTEGER_SENTINEL = -1;
|
||||
|
||||
public static ViolationRecordWrapper build() {
|
||||
return new ViolationRecordWrapper();
|
||||
}
|
||||
@@ -47,8 +51,19 @@ public class ViolationRecordWrapper extends BaseEntityWrapper<ViolationRecord, V
|
||||
@Override
|
||||
public ViolationRecordVO entityVO(ViolationRecord violationRecord) {
|
||||
ViolationRecordVO violationRecordVO = Objects.requireNonNull(BeanUtil.copyProperties(violationRecord, ViolationRecordVO.class));
|
||||
// 未填写罚款/扣分的占位值 -1 对外展示为空
|
||||
violationRecordVO.setFineAmount(normalizeEmptyAmount(violationRecordVO.getFineAmount()));
|
||||
violationRecordVO.setDeductPoints(normalizeEmptyInteger(violationRecordVO.getDeductPoints()));
|
||||
violationRecordVO.setUpdateUserName(UserCache.getUserRealName(violationRecord.getUpdateUser()));
|
||||
return violationRecordVO;
|
||||
}
|
||||
|
||||
private BigDecimal normalizeEmptyAmount(BigDecimal value) {
|
||||
return value != null && value.compareTo(EMPTY_AMOUNT_SENTINEL) == 0 ? null : value;
|
||||
}
|
||||
|
||||
private Integer normalizeEmptyInteger(Integer value) {
|
||||
return value != null && value.equals(EMPTY_INTEGER_SENTINEL) ? null : value;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -85,9 +85,10 @@ public class WaybillWrapper extends BaseEntityWrapper<Waybill, WaybillVO> {
|
||||
case "pending" -> "待执行";
|
||||
case "waiting_dispatch" -> "待调度";
|
||||
case "dispatching" -> "调度中";
|
||||
case "running" -> "进行中";
|
||||
case "running", "processing", "in_progress", "inProgress" -> "进行中";
|
||||
case "completed" -> "已完成";
|
||||
case "cancelled" -> "已取消";
|
||||
case "closed" -> "已关闭";
|
||||
default -> "未知";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ server:
|
||||
|
||||
#spring配置
|
||||
spring:
|
||||
codec:
|
||||
# 运单批量导入等大 JSON / 失败明细导出场景,默认 256KB 会触发网关 500
|
||||
max-in-memory-size: 20MB
|
||||
servlet:
|
||||
multipart:
|
||||
max-file-size: 500MB
|
||||
|
||||
-1379
File diff suppressed because it is too large
Load Diff
@@ -1,157 +0,0 @@
|
||||
#
|
||||
# A fatal error has been detected by the Java Runtime Environment:
|
||||
#
|
||||
# SIGBUS (0xa) at pc=0x0000000104d364c0, pid=22822, tid=5379
|
||||
#
|
||||
# JRE version: OpenJDK Runtime Environment Zulu17.44+15-CA (17.0.8+7) (build 17.0.8+7-LTS)
|
||||
# Java VM: OpenJDK 64-Bit Server VM Zulu17.44+15-CA (17.0.8+7-LTS, mixed mode, emulated-client, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, bsd-aarch64)
|
||||
# Problematic frame:
|
||||
# C [libzip.dylib+0x64c0] newEntry+0x68
|
||||
#
|
||||
# No core dump will be written. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
|
||||
#
|
||||
# If you would like to submit a bug report, please visit:
|
||||
# http://www.azul.com/support/
|
||||
# The crash happened outside the Java Virtual Machine in native code.
|
||||
# See problematic frame for where to report the bug.
|
||||
#
|
||||
|
||||
--------------- S U M M A R Y ------------
|
||||
|
||||
Command Line: -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:54448,suspend=y,server=n -javaagent:/Users/liangxin/Library/Caches/JetBrains/IntelliJIdea2026.1/captureAgent/debugger-agent.jar=file:///var/folders/pk/drq93rk10q733kk02fgp89xh0000gn/T/capture14073385024433055703.props -XX:TieredStopAtLevel=1 -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true -Dmanagement.endpoints.jmx.exposure.include=* -Dkotlinx.coroutines.debug.enable.creation.stack.trace=false -Ddebugger.agent.enable.coroutines=true -Dkotlinx.coroutines.debug.enable.flows.stack.trace=true -Dkotlinx.coroutines.debug.enable.mutable.state.flows.stack.trace=true -Ddebugger.async.stack.trace.for.all.threads=true -Dfile.encoding=UTF-8 org.springblade.admin.AdminApplication
|
||||
|
||||
Host: "Mac15,6" arm64, 12 cores, 36G, Darwin 25.6.0, macOS 26.6.2 (25G83)
|
||||
Time: Mon Sep 14 22:15:03 2026 CST elapsed time: 5.909458 seconds (0d 0h 0m 5s)
|
||||
|
||||
--------------- T H R E A D ---------------
|
||||
|
||||
Current thread (0x000000013601ac00): JavaThread "main" [_thread_in_native, id=5379, stack(0x000000016b250000,0x000000016b453000)]
|
||||
|
||||
Stack: [0x000000016b250000,0x000000016b453000], sp=0x000000016b450260, free space=2048k
|
||||
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
|
||||
C [libzip.dylib+0x64c0] newEntry+0x68
|
||||
C [libzip.dylib+0x6390] ZIP_GetEntry2+0x14c
|
||||
C [libzip.dylib+0x6d78] ZIP_FindEntry+0x3c
|
||||
V [libjvm.dylib+0x25a408] ClassPathZipEntry::open_entry(JavaThread*, char const*, int*, bool)+0xb4
|
||||
V [libjvm.dylib+0x25a53c] ClassPathZipEntry::open_stream(JavaThread*, char const*)+0x20
|
||||
V [libjvm.dylib+0x25d918] ClassLoader::load_class(Symbol*, bool, JavaThread*)+0x150
|
||||
V [libjvm.dylib+0x981d60] SystemDictionary::load_instance_class_impl(Symbol*, Handle, JavaThread*)+0x2d0
|
||||
V [libjvm.dylib+0x98063c] SystemDictionary::load_instance_class(unsigned int, Symbol*, Handle, JavaThread*)+0x30
|
||||
V [libjvm.dylib+0x97fd48] SystemDictionary::resolve_instance_class_or_null(Symbol*, Handle, Handle, JavaThread*)+0x4dc
|
||||
V [libjvm.dylib+0x97f334] SystemDictionary::resolve_or_fail(Symbol*, Handle, Handle, bool, JavaThread*)+0x80
|
||||
V [libjvm.dylib+0x2beb54] ConstantPool::klass_at_impl(constantPoolHandle const&, int, JavaThread*)+0x1e0
|
||||
V [libjvm.dylib+0x46d6f0] InterpreterRuntime::_new(JavaThread*, ConstantPool*, int)+0x94
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.createCapturedStack(Ljava/lang/Throwable;Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;)Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;+14
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.access$500(Ljava/lang/Throwable;Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;)Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;+2
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage$3.run()V+75
|
||||
j com.intellij.rt.debugger.agent.OverheadDetector$PerThread.runIfNoOverhead(Ljava/lang/Runnable;)Z+62
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.runWithOverheadTrackingAndWithoutThrowableCapture(Lcom/intellij/rt/debugger/agent/CaptureStorage$ThreadLocalContext;Ljava/lang/Runnable;)Z+15
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.capture(Ljava/lang/Object;)V+26
|
||||
j java.util.concurrent.FutureTask.<init>(Ljava/util/concurrent/Callable;)V+5 java.base@17.0.8
|
||||
j org.springframework.cglib.core.internal.LoadingCache.createEntry(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+27
|
||||
j org.springframework.cglib.core.internal.LoadingCache.get(Ljava/lang/Object;)Ljava/lang/Object;+39
|
||||
j org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(Lorg/springframework/cglib/core/AbstractClassGenerator;Z)Ljava/lang/Object;+11
|
||||
j org.springframework.cglib.core.AbstractClassGenerator.create(Ljava/lang/Object;)Ljava/lang/Object;+115
|
||||
j org.springframework.cglib.reflect.FastClass$Generator.create()Lorg/springframework/cglib/reflect/FastClass;+19
|
||||
j org.springframework.cglib.proxy.MethodProxy.helper(Lorg/springframework/cglib/proxy/MethodProxy$CreateInfo;Ljava/lang/Class;)Lorg/springframework/cglib/reflect/FastClass;+54
|
||||
j org.springframework.cglib.proxy.MethodProxy.init()V+40
|
||||
j org.springframework.cglib.proxy.MethodProxy.create(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/springframework/cglib/proxy/MethodProxy;+80
|
||||
j org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration$BlockingLoadBalancerRetryConfig$$SpringCGLIB$$0.CGLIB$STATICHOOK1()V+112
|
||||
j org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration$BlockingLoadBalancerRetryConfig$$SpringCGLIB$$0.<clinit>()V+3
|
||||
v ~StubRoutines::call_stub
|
||||
V [libjvm.dylib+0x4781f8] JavaCalls::call_helper(JavaValue*, methodHandle const&, JavaCallArguments*, JavaThread*)+0x394
|
||||
V [libjvm.dylib+0x457c84] InstanceKlass::call_class_initializer(JavaThread*)+0x1e8
|
||||
V [libjvm.dylib+0x456f48] InstanceKlass::initialize_impl(JavaThread*)+0x65c
|
||||
V [libjvm.dylib+0x51e020] JVM_FindClassFromCaller+0x340
|
||||
C [libjava.dylib+0x3a6c] Java_java_lang_Class_forName0+0x138
|
||||
J 1317 java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class; java.base@17.0.8 (0 bytes) @ 0x000000010ed5306c [0x000000010ed52fc0+0x00000000000000ac]
|
||||
V [libjvm.dylib+0x4715a0] InterpreterRuntime::resolve_from_cache(JavaThread*, Bytecodes::Code)+0x98
|
||||
|
||||
Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.createCapturedStack(Ljava/lang/Throwable;Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;)Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;+14
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.access$500(Ljava/lang/Throwable;Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;)Lcom/intellij/rt/debugger/agent/CaptureStorage$CapturedStack;+2
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage$3.run()V+75
|
||||
j com.intellij.rt.debugger.agent.OverheadDetector$PerThread.runIfNoOverhead(Ljava/lang/Runnable;)Z+62
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.runWithOverheadTrackingAndWithoutThrowableCapture(Lcom/intellij/rt/debugger/agent/CaptureStorage$ThreadLocalContext;Ljava/lang/Runnable;)Z+15
|
||||
j com.intellij.rt.debugger.agent.CaptureStorage.capture(Ljava/lang/Object;)V+26
|
||||
j java.util.concurrent.FutureTask.<init>(Ljava/util/concurrent/Callable;)V+5 java.base@17.0.8
|
||||
j org.springframework.cglib.core.internal.LoadingCache.createEntry(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+27
|
||||
j org.springframework.cglib.core.internal.LoadingCache.get(Ljava/lang/Object;)Ljava/lang/Object;+39
|
||||
j org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(Lorg/springframework/cglib/core/AbstractClassGenerator;Z)Ljava/lang/Object;+11
|
||||
j org.springframework.cglib.core.AbstractClassGenerator.create(Ljava/lang/Object;)Ljava/lang/Object;+115
|
||||
j org.springframework.cglib.reflect.FastClass$Generator.create()Lorg/springframework/cglib/reflect/FastClass;+19
|
||||
j org.springframework.cglib.proxy.MethodProxy.helper(Lorg/springframework/cglib/proxy/MethodProxy$CreateInfo;Ljava/lang/Class;)Lorg/springframework/cglib/reflect/FastClass;+54
|
||||
j org.springframework.cglib.proxy.MethodProxy.init()V+40
|
||||
j org.springframework.cglib.proxy.MethodProxy.create(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/springframework/cglib/proxy/MethodProxy;+80
|
||||
j org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration$BlockingLoadBalancerRetryConfig$$SpringCGLIB$$0.CGLIB$STATICHOOK1()V+112
|
||||
j org.springframework.cloud.loadbalancer.config.BlockingLoadBalancerClientAutoConfiguration$BlockingLoadBalancerRetryConfig$$SpringCGLIB$$0.<clinit>()V+3
|
||||
v ~StubRoutines::call_stub
|
||||
J 1317 java.lang.Class.forName0(Ljava/lang/String;ZLjava/lang/ClassLoader;Ljava/lang/Class;)Ljava/lang/Class; java.base@17.0.8 (0 bytes) @ 0x000000010ed5306c [0x000000010ed52fc0+0x00000000000000ac]
|
||||
J 1432 c1 java.lang.Class.forName(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class; java.base@17.0.8 (47 bytes) @ 0x000000010ed807c8 [0x000000010ed806c0+0x0000000000000108]
|
||||
j org.springframework.cglib.core.ReflectUtils.defineClass(Ljava/lang/String;[BLjava/lang/ClassLoader;Ljava/security/ProtectionDomain;Ljava/lang/Class;)Ljava/lang/Class;+460
|
||||
j org.springframework.cglib.core.AbstractClassGenerator.generate(Lorg/springframework/cglib/core/AbstractClassGenerator$ClassLoaderData;)Ljava/lang/Class;+209
|
||||
j org.springframework.cglib.proxy.Enhancer.generate(Lorg/springframework/cglib/core/AbstractClassGenerator$ClassLoaderData;)Ljava/lang/Class;+53
|
||||
j org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.lambda$new$1(Lorg/springframework/cglib/core/AbstractClassGenerator;)Ljava/lang/Object;+2
|
||||
j org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$$Lambda$857+0x00000070016c9418.apply(Ljava/lang/Object;)Ljava/lang/Object;+8
|
||||
j org.springframework.cglib.core.internal.LoadingCache.lambda$createEntry$1(Ljava/lang/Object;)Ljava/lang/Object;+5
|
||||
j org.springframework.cglib.core.internal.LoadingCache$$Lambda$859+0x00000070016c9a98.call()Ljava/lang/Object;+8
|
||||
j java.util.concurrent.FutureTask.run$$$capture()V+39 java.base@17.0.8
|
||||
j java.util.concurrent.FutureTask.run()V+5 java.base@17.0.8
|
||||
j org.springframework.cglib.core.internal.LoadingCache.createEntry(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+56
|
||||
j org.springframework.cglib.core.internal.LoadingCache.get(Ljava/lang/Object;)Ljava/lang/Object;+39
|
||||
j org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(Lorg/springframework/cglib/core/AbstractClassGenerator;Z)Ljava/lang/Object;+11
|
||||
j org.springframework.cglib.core.AbstractClassGenerator.create(Ljava/lang/Object;)Ljava/lang/Object;+115
|
||||
j org.springframework.cglib.proxy.Enhancer.createHelper()Ljava/lang/Object;+102
|
||||
j org.springframework.cglib.proxy.Enhancer.createClass()Ljava/lang/Class;+6
|
||||
j org.springframework.context.annotation.ConfigurationClassEnhancer.createClass(Lorg/springframework/cglib/proxy/Enhancer;Z)Ljava/lang/Class;+1
|
||||
j org.springframework.context.annotation.ConfigurationClassEnhancer.enhance(Ljava/lang/Class;Ljava/lang/ClassLoader;)Ljava/lang/Class;+134
|
||||
j org.springframework.context.annotation.ConfigurationClassPostProcessor.enhanceConfigurationClasses(Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;)V+418
|
||||
j org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanFactory(Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;)V+78
|
||||
j org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Ljava/util/Collection;Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;)V+61
|
||||
j org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;Ljava/util/List;)V+521
|
||||
j org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(Lorg/springframework/beans/factory/config/ConfigurableListableBeanFactory;)V+5
|
||||
j org.springframework.context.support.AbstractApplicationContext.refresh()V+62
|
||||
j org.springframework.boot.web.reactive.context.ReactiveWebServerApplicationContext.refresh()V+1
|
||||
j org.springframework.boot.SpringApplication.refresh(Lorg/springframework/context/ConfigurableApplicationContext;)V+1
|
||||
j org.springframework.boot.SpringApplication.refreshContext(Lorg/springframework/context/ConfigurableApplicationContext;)V+19
|
||||
j org.springframework.boot.SpringApplication.run([Ljava/lang/String;)Lorg/springframework/context/ConfigurableApplicationContext;+113
|
||||
j org.springframework.boot.builder.SpringApplicationBuilder.run([Ljava/lang/String;)Lorg/springframework/context/ConfigurableApplicationContext;+38
|
||||
j org.springblade.core.launch.BladeApplication.run(Ljava/lang/String;Ljava/lang/Class;[Ljava/lang/String;)Lorg/springframework/context/ConfigurableApplicationContext;+9
|
||||
j org.springblade.admin.AdminApplication.main([Ljava/lang/String;)V+5
|
||||
v ~StubRoutines::call_stub
|
||||
|
||||
siginfo: si_signo: 10 (SIGBUS), si_code: 1 (BUS_ADRALN), si_addr: 0x0000000104cfe958
|
||||
|
||||
Register to memory mapping:
|
||||
|
||||
x0=0x0000600001ebc820 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00
|
||||
x1=0x0 is NULL
|
||||
x2=0xfffffffffffffff0 is an unknown value
|
||||
x3=0x0000600001ebc830 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00
|
||||
x4=0x0000600001ebc880 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00
|
||||
x5=0x000000009b858ffb is an unknown value
|
||||
x6=0x000000001ba00000 is an unknown value
|
||||
x7=0x00000005c0183f80 is an oop: com.intellij.rt.debugger.agent.CaptureStorage$ConcurrentIdentityWeakHashMap$WeakKey
|
||||
{0x00000005c0183f80} - klass: 'com/intellij/rt/debugger/agent/CaptureStorage$ConcurrentIdentityWeakHashMap$WeakKey'
|
||||
- ---- fields (total size 4 words):
|
||||
- private 'referent' 'Ljava/lang/Object;' @12 a 'java/lang/Thread'{0x00000005c0203dc0} (b80407b8)
|
||||
- volatile 'queue' 'Ljava/lang/ref/ReferenceQueue;' @16 a 'java/lang/ref/ReferenceQueue'{0x00000005c0183ea0} (b80307d4)
|
||||
- volatile 'next' 'Ljava/lang/ref/Reference;' @20 NULL (0)
|
||||
- private transient 'discovered' 'Ljava/lang/ref/Reference;' @24 NULL (0)
|
||||
- private final 'myHash' 'I' @28 897913732 (35851384)
|
||||
x8=0x0000000104e2693c: getProcessHandle.procHandle+0x971c in /Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home/lib/libjava.dylib at 0x0000000104e00000
|
||||
x9=0x0000000000128000 is an unknown value
|
||||
x10=0x0000600001ebc000 points into unknown readable memory: 0x4c2800498af20001 | 01 00 f2 8a 49 00 28 4c
|
||||
x11=0x0000000000000820 is an unknown value
|
||||
x12=0x0000000000000050 is an unknown value
|
||||
x13=0x0000000000000001 is an unknown value
|
||||
x14=0x00000000ffffff4e is an unknown value
|
||||
x15=0x00000000000007fb is an unknown value
|
||||
x16=0x00000001829fd030: __bzero+0 in /usr/lib/system/libsystem_platform.dylib at 0x00000001829fa000
|
||||
x17=0x00000001f0a754a8 points into unknown readable memory: 0x00000001829fd030 | 30 d0 9f 82 01 00 00 00
|
||||
x18=0x0 is NULL
|
||||
x19=0x0000600001ebc820 points into unknown readable memory: 0x0000000000000000 | 00 00 00 00 00 00 00 00
|
||||
x20=0x0 is NULL
|
||||
x21=0x0000600000bf4240 points into unknown readable memory: 0x0000600001af00c0 | c0 00 af 01 00 60 00 00
|
||||
x22=0x0000000104cfe93c points into unknown readable memory: 50 4b 01 02
|
||||
x23=
|
||||
-1375
File diff suppressed because it is too large
Load Diff
-1368
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user