diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java index 434c164..0fc9777 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerArchive.java @@ -61,6 +61,10 @@ public class CustomerArchive extends TenantEntity { @Schema(description = "客商性质") private String customerNature; + @Schema(description = "是否广西百强:0否,1是") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private Integer guangxiTop100; + @Schema(description = "统一社会信用代码") private String unifiedCreditCode; @@ -101,6 +105,10 @@ public class CustomerArchive extends TenantEntity { @Schema(description = "经营范围") private String businessScope; + @Schema(description = "网络货运平台:0否,1是") + @TableField(updateStrategy = FieldStrategy.ALWAYS) + private Integer networkFreightPlatform; + @Schema(description = "营业期限类型") private String businessTermType; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceContact.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceContact.java new file mode 100644 index 0000000..c27d5e5 --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceContact.java @@ -0,0 +1,71 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.pojo.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.core.tenant.mp.TenantEntity; + +import java.io.Serial; + +/** + * 客商发票联系信息实体类 + * + * @author Chill + */ +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("blade_customer_invoice_contact") +@Schema(description = "客商发票联系信息") +public class CustomerInvoiceContact extends TenantEntity { + + @Serial + private static final long serialVersionUID = 1L; + + @JsonSerialize(using = ToStringSerializer.class) + @Schema(description = "发票信息ID") + private Long invoiceId; + + @Schema(description = "联系人") + private String contactName; + + @Schema(description = "联系电话") + private String contactPhone; + + @Schema(description = "邮箱地址") + private String email; + + @Schema(description = "所属部门ID集合") + private String deptIds; + + @Schema(description = "所属部门") + private String deptNames; + + @Schema(description = "备注") + private String remark; + +} diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceInfo.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceInfo.java index 896a10c..e24a93a 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceInfo.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/CustomerInvoiceInfo.java @@ -50,21 +50,15 @@ public class CustomerInvoiceInfo extends TenantEntity { @Schema(description = "客商ID") private Long customerId; - @Schema(description = "受票方名称") + @Schema(description = "企业全称") private String invoiceTitle; - @Schema(description = "发票类型") - private String invoiceType; - @Schema(description = "纳税人识别号") private String taxNo; @Schema(description = "开户行名称") private String bankName; - @Schema(description = "注册电话") - private String registeredPhone; - @Schema(description = "银行账号") private String bankAccount; @@ -77,24 +71,6 @@ public class CustomerInvoiceInfo extends TenantEntity { @Schema(description = "注册地址详细地址") private String registeredDetailAddress; - @Schema(description = "邮箱") - private String email; - - @Schema(description = "收件人姓名") - private String receiverName; - - @Schema(description = "收件人电话") - private String receiverPhone; - - @Schema(description = "收件人地址") - private String receiverAddress; - - @Schema(description = "收件人地址行政区划") - private String receiverRegionName; - - @Schema(description = "收件人详细地址") - private String receiverDetailAddress; - @Schema(description = "是否默认") private Integer isDefault; diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/InsuranceOcrTemplate.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/InsuranceOcrTemplate.java index 6fe108d..a67969d 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/InsuranceOcrTemplate.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/entity/InsuranceOcrTemplate.java @@ -52,6 +52,11 @@ public class InsuranceOcrTemplate extends TenantEntity { @Schema(description = "模板名称") private String name; + /** 车船类型:车辆/船舶。 */ + @TableField("vehicle_type") + @Schema(description = "车船类型:车辆/船舶") + private String vehicleType; + /** 字段映射配置JSON。 */ @TableField("mapping_config") @Schema(description = "字段映射配置JSON") diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordExpiryStatVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordExpiryStatVO.java new file mode 100644 index 0000000..645035e --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordExpiryStatVO.java @@ -0,0 +1,55 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is + * not liable for any claims arising from secondary or illegal development. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +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; + +/** + * 年检记录有效期统计 + * + * @author Chill + */ +@Data +@Schema(description = "年检记录有效期统计") +public class AnnualInspectionRecordExpiryStatVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + @Schema(description = "全部") + private Long total; + + @Schema(description = "30天内") + private Long within30; + + @Schema(description = "已过期") + private Long expired; + +} diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordVO.java index d1d3c96..b76896a 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/AnnualInspectionRecordVO.java @@ -72,4 +72,18 @@ public class AnnualInspectionRecordVO extends AnnualInspectionRecord { @Schema(description = "更新人姓名") private String updateUserName; + @TableField(exist = false) + @Schema(description = "有效期状态:within30-30天内,expired-已过期") + private String expireStatus; + + @TableField(exist = false) + @Schema(description = "当天日期") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate today; + + @TableField(exist = false) + @Schema(description = "预警截止日期") + @DateTimeFormat(pattern = "yyyy-MM-dd") + private LocalDate warningDate; + } diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerArchiveVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerArchiveVO.java index a413eeb..1a2f0eb 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerArchiveVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerArchiveVO.java @@ -77,4 +77,12 @@ public class CustomerArchiveVO extends CustomerArchive { @Schema(description = "变更记录") private List changeRecords = new ArrayList<>(); + @TableField(exist = false) + @Schema(description = "是否保存变更记录(仅提交时为 true,保存时不记录)") + private Boolean recordChange; + + @TableField(exist = false) + @Schema(description = "客商类型:external外部客商,internal内部组织") + private String customerKind; + } diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceContactVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceContactVO.java new file mode 100644 index 0000000..73a4c77 --- /dev/null +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceContactVO.java @@ -0,0 +1,45 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * 1. This software is for development use only under a valid license + * from BladeX. + *

+ * 2. Redistribution of this software's source code to any third party + * without a commercial license is strictly prohibited. + *

+ * 3. Licensees may copyright their own code but cannot use segments + * from this software for such purposes. Copyright of this software + * remains with BladeX. + *

+ * Using this software signifies agreement to this License, and the software + * must not be used for illegal purposes. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.pojo.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.springblade.transport.pojo.entity.CustomerInvoiceContact; + +import java.io.Serial; + +/** + * 客商发票联系信息视图实体类 + * + * @author Chill + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Schema(description = "客商发票联系信息") +public class CustomerInvoiceContactVO extends CustomerInvoiceContact { + + @Serial + private static final long serialVersionUID = 1L; + +} diff --git a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceInfoVO.java b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceInfoVO.java index 0d88697..a8d539d 100644 --- a/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceInfoVO.java +++ b/blade-service-api/blade-transport-api/src/main/java/org/springblade/transport/pojo/vo/CustomerInvoiceInfoVO.java @@ -22,12 +22,15 @@ */ package org.springblade.transport.pojo.vo; +import com.baomidou.mybatisplus.annotation.TableField; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import org.springblade.transport.pojo.entity.CustomerInvoiceInfo; import java.io.Serial; +import java.util.ArrayList; +import java.util.List; /** * 客商发票信息视图实体类 @@ -42,4 +45,8 @@ public class CustomerInvoiceInfoVO extends CustomerInvoiceInfo { @Serial private static final long serialVersionUID = 1L; + @TableField(exist = false) + @Schema(description = "联系信息") + private List contacts = new ArrayList<>(); + } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java index dc23249..39398f0 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictBizServiceImpl.java @@ -136,7 +136,10 @@ public class DictBizServiceImpl extends ServiceImpl impl @Override public IPage parentList(Map dict, Query query) { - IPage page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, DictBiz.class).lambda().eq(DictBiz::getParentId, CommonConstant.TOP_PARENT_ID).orderByAsc(DictBiz::getSort)); + IPage page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, DictBiz.class).lambda() + .eq(DictBiz::getParentId, CommonConstant.TOP_PARENT_ID) + .orderByAsc(DictBiz::getSort) + .orderByDesc(DictBiz::getId)); return DictBizWrapper.build().pageVO(page); } diff --git a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictServiceImpl.java b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictServiceImpl.java index bdd5b15..3b0bf98 100644 --- a/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictServiceImpl.java +++ b/blade-service/blade-system/src/main/java/org/springblade/system/service/impl/DictServiceImpl.java @@ -123,7 +123,10 @@ public class DictServiceImpl extends ServiceImpl implements ID @Override public IPage parentList(Map dict, Query query) { - IPage page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, Dict.class).lambda().eq(Dict::getParentId, CommonConstant.TOP_PARENT_ID).orderByAsc(Dict::getSort)); + IPage page = this.page(Condition.getPage(query), Condition.getQueryWrapper(dict, Dict.class).lambda() + .eq(Dict::getParentId, CommonConstant.TOP_PARENT_ID) + .orderByAsc(Dict::getSort) + .orderByDesc(Dict::getId)); return DictWrapper.build().pageVO(page); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/AnnualInspectionRecordController.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/AnnualInspectionRecordController.java index 988f72c..e97fa2d 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/AnnualInspectionRecordController.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/controller/AnnualInspectionRecordController.java @@ -47,6 +47,7 @@ import org.springblade.transport.excel.AnnualInspectionRecordExcel; import org.springblade.transport.excel.AnnualInspectionRecordExportExcel; import org.springblade.transport.excel.AnnualInspectionRecordImporter; import org.springblade.transport.pojo.entity.AnnualInspectionRecord; +import org.springblade.transport.pojo.vo.AnnualInspectionRecordExpiryStatVO; import org.springblade.transport.pojo.vo.AnnualInspectionRecordVO; import org.springblade.transport.service.IAnnualInspectionRecordService; import org.springblade.transport.wrapper.AnnualInspectionRecordWrapper; @@ -58,6 +59,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import java.time.LocalDate; import java.util.ArrayList; import java.util.List; @@ -91,6 +93,7 @@ public class AnnualInspectionRecordController extends BladeController { @ApiOperationSupport(order = 2) @Operation(summary = "分页", description = "传入annualInspectionRecord") public R> list(AnnualInspectionRecordVO annualInspectionRecord, Query query) { + fillExpiryDate(annualInspectionRecord); IPage pages = annualInspectionRecordService.selectAnnualInspectionRecordPage(Condition.getPage(normalizeQuery(query)), annualInspectionRecord); return R.data(pages); } @@ -109,8 +112,17 @@ public class AnnualInspectionRecordController extends BladeController { return R.status(annualInspectionRecordService.deleteLogic(Func.toLongList(ids))); } - @PostMapping("/import-annual-inspection-record") + @GetMapping("/expiry-stat") @ApiOperationSupport(order = 5) + @Operation(summary = "有效期统计", description = "传入annualInspectionRecord") + public R expiryStat(AnnualInspectionRecordVO annualInspectionRecord) { + fillExpiryDate(annualInspectionRecord); + annualInspectionRecord.setExpireStatus(null); + return R.data(annualInspectionRecordService.expiryStat(annualInspectionRecord)); + } + + @PostMapping("/import-annual-inspection-record") + @ApiOperationSupport(order = 6) @Operation(summary = "导入年检记录", description = "传入excel") public R importAnnualInspectionRecord(MultipartFile file, HttpServletResponse response) { List failureList = annualInspectionRecordService.importAnnualInspectionRecord(ExcelUtil.read(file, AnnualInspectionRecordExcel.class)); @@ -122,17 +134,18 @@ public class AnnualInspectionRecordController extends BladeController { } @GetMapping("/export-annual-inspection-record") - @ApiOperationSupport(order = 6) + @ApiOperationSupport(order = 7) @Operation(summary = "导出年检记录") public void exportAnnualInspectionRecord(AnnualInspectionRecordVO annualInspectionRecord, @RequestParam(required = false) String ids, HttpServletResponse response) { + fillExpiryDate(annualInspectionRecord); List list = annualInspectionRecordService.exportAnnualInspectionRecord(buildExportQuery(annualInspectionRecord, ids)); ExcelUtil.export(response, "年检记录" + DateUtil.time(), "年检记录表", list, AnnualInspectionRecordExportExcel.class); } @GetMapping("/export-template") - @ApiOperationSupport(order = 7) + @ApiOperationSupport(order = 8) @Operation(summary = "导出模板") public void exportTemplate(HttpServletResponse response) { List list = new ArrayList<>(); @@ -155,6 +168,15 @@ public class AnnualInspectionRecordController extends BladeController { return query; } + private void fillExpiryDate(AnnualInspectionRecordVO annualInspectionRecord) { + if (annualInspectionRecord.getToday() == null) { + annualInspectionRecord.setToday(LocalDate.now()); + } + if (annualInspectionRecord.getWarningDate() == null) { + annualInspectionRecord.setWarningDate(annualInspectionRecord.getToday().plusDays(30)); + } + } + private LambdaQueryWrapper buildExportQuery(AnnualInspectionRecordVO annualInspectionRecord, String ids) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .eq(AnnualInspectionRecord::getIsDeleted, 0) @@ -183,6 +205,15 @@ public class AnnualInspectionRecordController extends BladeController { if (Func.isNotEmpty(annualInspectionRecord.getCreateTimeEnd())) { queryWrapper.le(AnnualInspectionRecord::getCreateTime, annualInspectionRecord.getCreateTimeEnd()); } + if ("within30".equals(annualInspectionRecord.getExpireStatus())) { + queryWrapper.isNotNull(AnnualInspectionRecord::getValidUntilDate) + .ge(AnnualInspectionRecord::getValidUntilDate, annualInspectionRecord.getToday()) + .le(AnnualInspectionRecord::getValidUntilDate, annualInspectionRecord.getWarningDate()); + } + if ("expired".equals(annualInspectionRecord.getExpireStatus())) { + queryWrapper.isNotNull(AnnualInspectionRecord::getValidUntilDate) + .lt(AnnualInspectionRecord::getValidUntilDate, annualInspectionRecord.getToday()); + } return queryWrapper; } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.java index 477a993..887d05d 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.java @@ -27,7 +27,9 @@ package org.springblade.transport.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import org.apache.ibatis.annotations.Param; import org.springblade.transport.pojo.entity.AnnualInspectionRecord; +import org.springblade.transport.pojo.vo.AnnualInspectionRecordExpiryStatVO; import org.springblade.transport.pojo.vo.AnnualInspectionRecordVO; import java.util.List; @@ -46,6 +48,14 @@ public interface AnnualInspectionRecordMapper extends BaseMapper selectAnnualInspectionRecordPage(IPage page, AnnualInspectionRecordVO annualInspectionRecord); + List selectAnnualInspectionRecordPage(IPage page, @Param("annualInspectionRecord") AnnualInspectionRecordVO annualInspectionRecord); + + /** + * 有效期统计 + * + * @param annualInspectionRecord 查询参数 + * @return 统计结果 + */ + AnnualInspectionRecordExpiryStatVO selectExpiryStat(@Param("annualInspectionRecord") AnnualInspectionRecordVO annualInspectionRecord); } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.xml index 53f87e9..30fa5f3 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.xml +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/AnnualInspectionRecordMapper.xml @@ -26,6 +26,49 @@ + + valid_until_date IS NOT NULL + AND valid_until_date >= #{annualInspectionRecord.today} + AND valid_until_date <= #{annualInspectionRecord.warningDate} + + + + valid_until_date IS NOT NULL + AND valid_until_date < #{annualInspectionRecord.today} + + + + is_deleted = 0 + + AND create_dept = #{annualInspectionRecord.createDept} + + + AND vehicle_type = #{annualInspectionRecord.vehicleType} + + + + AND vehicle_no LIKE #{vehicleNoLike} + + + AND inspection_assessment_date >= #{annualInspectionRecord.inspectionAssessmentDateStart} + + + AND inspection_assessment_date <= #{annualInspectionRecord.inspectionAssessmentDateEnd} + + + AND create_time >= #{annualInspectionRecord.createTimeStart} + + + AND create_time <= #{annualInspectionRecord.createTimeEnd} + + + AND + + + AND + + + + + diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml index a9f80c3..d9df135 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerArchiveMapper.xml @@ -16,6 +16,7 @@ + @@ -29,6 +30,7 @@ + @@ -61,6 +63,7 @@ short_name, full_name, customer_nature, + guangxi_top100, unified_credit_code, customer_type, project_name, @@ -74,6 +77,7 @@ dept_name, invoice_tax_rate, business_scope, + network_freight_platform, business_term_type, business_end_date, registered_capital, diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerInvoiceContactMapper.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerInvoiceContactMapper.java new file mode 100644 index 0000000..fe40da6 --- /dev/null +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/mapper/CustomerInvoiceContactMapper.java @@ -0,0 +1,21 @@ +/** + * BladeX Commercial License Agreement + * Copyright (c) 2018-2099, https://bladex.cn. All rights reserved. + *

+ * Use of this software is governed by the Commercial License Agreement + * obtained after purchasing a license from BladeX. + *

+ * Author: Chill Zhuang (bladejava@qq.com) + */ +package org.springblade.transport.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.springblade.transport.pojo.entity.CustomerInvoiceContact; + +/** + * 客商发票联系信息 Mapper 接口 + * + * @author Chill + */ +public interface CustomerInvoiceContactMapper extends BaseMapper { +} diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IAnnualInspectionRecordService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IAnnualInspectionRecordService.java index b114a0f..61889b3 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IAnnualInspectionRecordService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/IAnnualInspectionRecordService.java @@ -31,6 +31,7 @@ import org.springblade.core.mp.base.BaseService; import org.springblade.transport.excel.AnnualInspectionRecordExcel; import org.springblade.transport.excel.AnnualInspectionRecordExportExcel; import org.springblade.transport.pojo.entity.AnnualInspectionRecord; +import org.springblade.transport.pojo.vo.AnnualInspectionRecordExpiryStatVO; import org.springblade.transport.pojo.vo.AnnualInspectionRecordVO; import java.util.List; @@ -44,6 +45,8 @@ public interface IAnnualInspectionRecordService extends BaseService selectAnnualInspectionRecordPage(IPage page, AnnualInspectionRecordVO annualInspectionRecord); + AnnualInspectionRecordExpiryStatVO expiryStat(AnnualInspectionRecordVO annualInspectionRecord); + boolean submit(AnnualInspectionRecord annualInspectionRecord); List importAnnualInspectionRecord(List data); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ICustomerArchiveService.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ICustomerArchiveService.java index 64b88d0..73ddd1a 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ICustomerArchiveService.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/ICustomerArchiveService.java @@ -68,6 +68,7 @@ public interface ICustomerArchiveService extends BaseService { /** * 新增或修改客商档案 + *

仅当 {@code customer.recordChange = true}(前端点「提交」)时写入变更记录;「保存」不落变更记录。

* * @param customer 客商档案 * @return 是否成功 diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/AnnualInspectionRecordServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/AnnualInspectionRecordServiceImpl.java index d760205..563555b 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/AnnualInspectionRecordServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/AnnualInspectionRecordServiceImpl.java @@ -36,13 +36,13 @@ import org.springblade.transport.excel.AnnualInspectionRecordExcel; import org.springblade.transport.excel.AnnualInspectionRecordExportExcel; import org.springblade.transport.mapper.AnnualInspectionRecordMapper; import org.springblade.transport.pojo.entity.AnnualInspectionRecord; +import org.springblade.transport.pojo.vo.AnnualInspectionRecordExpiryStatVO; import org.springblade.transport.pojo.vo.AnnualInspectionRecordVO; import org.springblade.transport.service.IAnnualInspectionRecordService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; -import java.time.LocalDate; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -74,6 +74,24 @@ public class AnnualInspectionRecordServiceImpl extends BaseServiceImpl> records = parseChangeRecords(contractManage.getChangeRecordJson()); + for (int index = records.size() - 1; index >= 0; index--) { + String changeReason = TransportBusinessSupport.trimToNull( + records.get(index).get("changeReason") == null ? null : String.valueOf(records.get(index).get("changeReason"))); + if (Func.isNotEmpty(changeReason)) { + return changeReason; + } + } + return "重新提交变更"; + } + private boolean canResubmitTemporary(ContractManage contractManage) { String stage = contractManage.getContractStage(); String status = contractManage.getApprovalStatus(); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java index 4231efa..1a783a6 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/CustomerArchiveServiceImpl.java @@ -46,6 +46,7 @@ import org.springblade.transport.mapper.CustomerChangeRecordMapper; import org.springblade.transport.mapper.CustomerContactMapper; import org.springblade.transport.mapper.CustomerCreditScoreDetailMapper; import org.springblade.transport.mapper.CustomerCreditScoreMapper; +import org.springblade.transport.mapper.CustomerInvoiceContactMapper; import org.springblade.transport.mapper.CustomerInvoiceInfoMapper; import org.springblade.transport.mapper.CustomerReceiptAccountMapper; import org.springblade.transport.mapper.UserCustomerScopeMapper; @@ -59,6 +60,7 @@ import org.springblade.transport.pojo.entity.CustomerChangeRecord; import org.springblade.transport.pojo.entity.CustomerContact; import org.springblade.transport.pojo.entity.CustomerCreditScore; import org.springblade.transport.pojo.entity.CustomerCreditScoreDetail; +import org.springblade.transport.pojo.entity.CustomerInvoiceContact; import org.springblade.transport.pojo.entity.CustomerInvoiceInfo; import org.springblade.transport.pojo.entity.CustomerReceiptAccount; import org.springblade.transport.pojo.vo.CustomerArchiveVO; @@ -67,6 +69,7 @@ import org.springblade.transport.pojo.vo.CustomerContactVO; import org.springblade.transport.pojo.vo.CustomerCreditScoreDetailVO; import org.springblade.transport.pojo.vo.CustomerCreditScoreVO; import org.springblade.transport.pojo.vo.CreditRatingStandardVO; +import org.springblade.transport.pojo.vo.CustomerInvoiceContactVO; import org.springblade.transport.pojo.vo.CustomerInvoiceInfoVO; import org.springblade.transport.pojo.vo.CustomerReceiptAccountVO; import org.springblade.transport.service.ICustomerArchiveService; @@ -108,6 +111,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl invoices) { + private void insertInvoices(Long customerId, CustomerArchiveVO customer) { + List invoices = customer.getInvoices(); + if (Func.isEmpty(invoices)) { + return; + } + boolean internal = isInternalCustomer(customer); for (CustomerInvoiceInfoVO invoiceVO : invoices) { if (Func.isEmpty(invoiceVO.getInvoiceTitle()) && Func.isEmpty(invoiceVO.getTaxNo())) { continue; } - if (Func.isEmpty(invoiceVO.getInvoiceType())) { - throw new ServiceException("发票类型不能为空"); + if (Func.isEmpty(invoiceVO.getInvoiceTitle())) { + throw new ServiceException("企业全称不能为空"); } - if (!List.of("增值税专用发票", "普通发票").contains(invoiceVO.getInvoiceType())) { - throw new ServiceException("发票类型不合法"); + if (Func.isEmpty(invoiceVO.getTaxNo())) { + throw new ServiceException("纳税人识别号不能为空"); + } + if (Func.isEmpty(invoiceVO.getBankName())) { + throw new ServiceException("开户行名称不能为空"); + } + if (Func.isEmpty(invoiceVO.getBankAccount())) { + throw new ServiceException("银行账号不能为空"); + } + if (Func.isEmpty(invoiceVO.getRegisteredRegionName()) && Func.isEmpty(invoiceVO.getRegisteredAddress())) { + throw new ServiceException("注册地址不能为空"); + } + if (Func.isEmpty(invoiceVO.getRegisteredDetailAddress())) { + throw new ServiceException("详细地址不能为空"); } invoiceVO.setRegisteredAddress(buildAddress(invoiceVO.getRegisteredRegionName(), invoiceVO.getRegisteredDetailAddress(), invoiceVO.getRegisteredAddress())); - invoiceVO.setReceiverAddress(buildAddress(invoiceVO.getReceiverRegionName(), invoiceVO.getReceiverDetailAddress(), invoiceVO.getReceiverAddress())); CustomerInvoiceInfo invoice = Objects.requireNonNull(BeanUtil.copyProperties(invoiceVO, CustomerInvoiceInfo.class)); invoice.setId(IdWorker.getId()); invoice.setCustomerId(customerId); invoice.setStatus(STATUS_ENABLED); invoiceInfoMapper.insert(invoice); + insertInvoiceContacts(invoice.getId(), invoiceVO.getContacts(), internal, customer); } } + private void insertInvoiceContacts(Long invoiceId, List contacts, boolean internal, + CustomerArchiveVO customer) { + if (Func.isEmpty(contacts)) { + return; + } + for (CustomerInvoiceContactVO contactVO : contacts) { + if (isBlankInvoiceContact(contactVO)) { + continue; + } + if (Func.isEmpty(contactVO.getContactName())) { + throw new ServiceException("发票联系人不能为空"); + } + if (Func.isEmpty(contactVO.getContactPhone())) { + throw new ServiceException("发票联系电话不能为空"); + } + validateInvoiceContactEmail(contactVO.getEmail()); + if (Func.isNotEmpty(contactVO.getRemark()) && contactVO.getRemark().length() > 200) { + throw new ServiceException("发票联系信息备注最多200个字"); + } + if (internal && Func.isEmpty(contactVO.getDeptIds()) && Func.isEmpty(contactVO.getDeptNames())) { + throw new ServiceException("内部组织客商必须选择发票联系信息所属部门"); + } + if (!internal) { + if (Func.isEmpty(contactVO.getDeptIds())) { + contactVO.setDeptIds(customer.getDeptIds()); + } + if (Func.isEmpty(contactVO.getDeptNames())) { + contactVO.setDeptNames(Func.isNotEmpty(customer.getFullName()) ? customer.getFullName() : customer.getDeptName()); + } + } + CustomerInvoiceContact contact = Objects.requireNonNull(BeanUtil.copyProperties(contactVO, CustomerInvoiceContact.class)); + contact.setId(IdWorker.getId()); + contact.setInvoiceId(invoiceId); + contact.setStatus(STATUS_ENABLED); + invoiceContactMapper.insert(contact); + } + } + + private boolean isBlankInvoiceContact(CustomerInvoiceContactVO contactVO) { + return Func.isEmpty(contactVO.getContactName()) + && Func.isEmpty(contactVO.getContactPhone()) + && Func.isEmpty(contactVO.getEmail()) + && Func.isEmpty(contactVO.getDeptIds()) + && Func.isEmpty(contactVO.getDeptNames()) + && Func.isEmpty(contactVO.getRemark()); + } + + private void validateInvoiceContactEmail(String email) { + if (Func.isEmpty(email)) { + return; + } + if (email.length() > 100) { + throw new ServiceException("发票联系邮箱不能超过100个字"); + } + if (!email.matches("^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$")) { + throw new ServiceException("发票联系邮箱格式不正确"); + } + } + + private boolean isInternalCustomer(CustomerArchiveVO customer) { + String customerKind = customer.getCustomerKind(); + if (Func.isNotEmpty(customerKind)) { + return "internal".equals(customerKind) || "内部组织".equals(customerKind); + } + return "internal".equals(customer.getCustomerNature()) || "内部组织".equals(customer.getCustomerNature()); + } + private void insertScores(Long customerId, List scores) { for (CustomerCreditScoreVO scoreVO : scores) { if (Func.isEmpty(scoreVO.getQuantificationId()) && Func.isEmpty(scoreVO.getScoreDate())) { @@ -529,6 +619,15 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl customerIds, boolean deleteScores) { contactMapper.update(null, Wrappers.lambdaUpdate().in(CustomerContact::getCustomerId, customerIds).set(CustomerContact::getIsDeleted, 1)); receiptAccountMapper.update(null, Wrappers.lambdaUpdate().in(CustomerReceiptAccount::getCustomerId, customerIds).set(CustomerReceiptAccount::getIsDeleted, 1)); + List invoices = invoiceInfoMapper.selectList(Wrappers.lambdaQuery() + .in(CustomerInvoiceInfo::getCustomerId, customerIds) + .eq(CustomerInvoiceInfo::getIsDeleted, 0)); + if (Func.isNotEmpty(invoices)) { + List invoiceIds = invoices.stream().map(CustomerInvoiceInfo::getId).toList(); + invoiceContactMapper.update(null, Wrappers.lambdaUpdate() + .in(CustomerInvoiceContact::getInvoiceId, invoiceIds) + .set(CustomerInvoiceContact::getIsDeleted, 1)); + } invoiceInfoMapper.update(null, Wrappers.lambdaUpdate().in(CustomerInvoiceInfo::getCustomerId, customerIds).set(CustomerInvoiceInfo::getIsDeleted, 1)); if (deleteScores) { deleteScores(customerIds); @@ -565,12 +664,27 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl loadInvoices(Long customerId) { - return invoiceInfoMapper.selectList(Wrappers.lambdaQuery() - .eq(CustomerInvoiceInfo::getCustomerId, customerId) - .eq(CustomerInvoiceInfo::getIsDeleted, 0) - .orderByDesc(CustomerInvoiceInfo::getIsDefault) - .orderByAsc(CustomerInvoiceInfo::getCreateTime)) - .stream().map(invoice -> Objects.requireNonNull(BeanUtil.copyProperties(invoice, CustomerInvoiceInfoVO.class))).toList(); + List invoices = invoiceInfoMapper.selectList(Wrappers.lambdaQuery() + .eq(CustomerInvoiceInfo::getCustomerId, customerId) + .eq(CustomerInvoiceInfo::getIsDeleted, 0) + .orderByDesc(CustomerInvoiceInfo::getIsDefault) + .orderByAsc(CustomerInvoiceInfo::getCreateTime)); + if (Func.isEmpty(invoices)) { + return new ArrayList<>(); + } + List invoiceIds = invoices.stream().map(CustomerInvoiceInfo::getId).toList(); + Map> contactMap = invoiceContactMapper.selectList(Wrappers.lambdaQuery() + .in(CustomerInvoiceContact::getInvoiceId, invoiceIds) + .eq(CustomerInvoiceContact::getIsDeleted, 0) + .orderByAsc(CustomerInvoiceContact::getCreateTime)) + .stream() + .map(contact -> Objects.requireNonNull(BeanUtil.copyProperties(contact, CustomerInvoiceContactVO.class))) + .collect(Collectors.groupingBy(CustomerInvoiceContactVO::getInvoiceId)); + return invoices.stream().map(invoice -> { + CustomerInvoiceInfoVO invoiceVO = Objects.requireNonNull(BeanUtil.copyProperties(invoice, CustomerInvoiceInfoVO.class)); + invoiceVO.setContacts(contactMap.getOrDefault(invoice.getId(), new ArrayList<>())); + return invoiceVO; + }).toList(); } private List loadScores(Long customerId) { @@ -621,6 +735,16 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl(); @@ -928,6 +1052,7 @@ public class CustomerArchiveServiceImpl extends BaseServiceImpl VEHICLE_TYPES = List.of("车辆", "船舶"); private static final List INSURANCE_FIELD_KEYS = List.of( "保险类型", "保单号", "开始日期", "结束日期", "保额", "保费", "发票号", "开票日期", "备注" ); @@ -64,6 +65,7 @@ public class InsuranceOcrTemplateServiceImpl extends BaseServiceImpl queryWrapper = Wrappers.lambdaQuery() .eq(InsuranceOcrTemplate::getIsDeleted, 0) .like(StringUtil.isNotBlank(insuranceOcrTemplate.getName()), InsuranceOcrTemplate::getName, insuranceOcrTemplate.getName()) + .eq(StringUtil.isNotBlank(insuranceOcrTemplate.getVehicleType()), InsuranceOcrTemplate::getVehicleType, insuranceOcrTemplate.getVehicleType()) .orderByDesc(InsuranceOcrTemplate::getCreateTime); return InsuranceOcrTemplateWrapper.build().pageVO(page(page, queryWrapper)); } @@ -79,6 +81,7 @@ public class InsuranceOcrTemplateServiceImpl extends BaseServiceImpl NAME_MAX_LENGTH) { throw new ServiceException("模板名称不能超过100个字符"); } + if (StringUtil.isBlank(insuranceOcrTemplate.getVehicleType())) { + throw new ServiceException("请选择车船类型"); + } + if (!VEHICLE_TYPES.contains(insuranceOcrTemplate.getVehicleType())) { + throw new ServiceException("车船类型仅支持车辆或船舶"); + } Long nameCount = count(Wrappers.lambdaQuery() .eq(InsuranceOcrTemplate::getIsDeleted, 0) .eq(InsuranceOcrTemplate::getName, insuranceOcrTemplate.getName()) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InsuranceRecordServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InsuranceRecordServiceImpl.java index 53136b5..3c0ed29 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InsuranceRecordServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/InsuranceRecordServiceImpl.java @@ -85,6 +85,7 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl INSURANCE_TYPES = Set.of("交强险", "商业险", "承运人责任险", "货运险", "船舶险"); private static final Set 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})日?"); + private static final Pattern POLICY_NO_PATTERN = Pattern.compile("^[a-zA-Z0-9]+$"); private final IBaiduOcrService baiduOcrService; private final IInsuranceOcrTemplateService insuranceOcrTemplateService; @@ -157,6 +158,11 @@ public class InsuranceRecordServiceImpl extends BaseServiceImpl invoiceInfos = customer == null ? List.of() : activeInvoiceInfos(customer.getId()); + List invoiceInfos = customer == null ? List.of() : activeInvoiceInfoVOs(customer.getId()); Map result = new LinkedHashMap<>(); result.put("issuerName", first.getPayeeName()); result.put("receiverName", first.getPayerName()); @@ -321,8 +327,8 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl invoiceInfos = activeInvoiceInfos(customer.getId()); - CustomerInvoiceInfo invoiceInfo = invoiceInfos.stream() + List invoiceInfos = activeInvoiceInfoVOs(customer.getId()); + CustomerInvoiceInfoVO invoiceInfo = invoiceInfos.stream() .filter(item -> Objects.equals(item.getId(), request.getReceiverInvoiceInfoId())) .findFirst().orElseThrow(() -> new ServiceException("请选择受票方有效的开票信息")); String departmentEmails = normalizeDepartmentEmails(request.getDepartmentEmails(), invoiceInfos); @@ -655,8 +661,32 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl invoiceInfoEmails(List invoiceInfos) { - return invoiceInfos.stream().map(CustomerInvoiceInfo::getEmail).filter(Func::isNotEmpty) + private List activeInvoiceInfoVOs(Long customerId) { + List invoiceInfos = activeInvoiceInfos(customerId); + if (Func.isEmpty(invoiceInfos)) { + return List.of(); + } + List invoiceIds = invoiceInfos.stream().map(CustomerInvoiceInfo::getId).toList(); + Map> contactMap = customerInvoiceContactMapper.selectList( + Wrappers.lambdaQuery() + .in(CustomerInvoiceContact::getInvoiceId, invoiceIds) + .eq(CustomerInvoiceContact::getIsDeleted, 0) + .orderByAsc(CustomerInvoiceContact::getCreateTime)) + .stream() + .map(contact -> Objects.requireNonNull(BeanUtil.copyProperties(contact, CustomerInvoiceContactVO.class))) + .collect(Collectors.groupingBy(CustomerInvoiceContactVO::getInvoiceId)); + return invoiceInfos.stream().map(invoice -> { + CustomerInvoiceInfoVO invoiceVO = Objects.requireNonNull(BeanUtil.copyProperties(invoice, CustomerInvoiceInfoVO.class)); + invoiceVO.setContacts(contactMap.getOrDefault(invoice.getId(), new ArrayList<>())); + return invoiceVO; + }).toList(); + } + + private List invoiceInfoEmails(List invoiceInfos) { + return invoiceInfos.stream() + .flatMap(invoice -> (invoice.getContacts() == null ? List.of() : invoice.getContacts()).stream()) + .map(CustomerInvoiceContactVO::getEmail) + .filter(Func::isNotEmpty) .flatMap(value -> splitEmails(value).stream()) .collect(Collectors.toMap(email -> email.toLowerCase(Locale.ROOT), Function.identity(), (first, duplicate) -> first, LinkedHashMap::new)).values().stream().toList(); @@ -708,7 +738,7 @@ public class InvoiceApplicationServiceImpl extends BaseServiceImpl invoiceInfos) { + private String normalizeDepartmentEmails(String value, List invoiceInfos) { Map configuredEmails = invoiceInfoEmails(invoiceInfos).stream() .collect(Collectors.toMap(email -> email.toLowerCase(Locale.ROOT), Function.identity(), (first, duplicate) -> first, LinkedHashMap::new)); diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/OtherExpenseRecordServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/OtherExpenseRecordServiceImpl.java index 9d5de88..e854595 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/OtherExpenseRecordServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/OtherExpenseRecordServiceImpl.java @@ -12,7 +12,9 @@ import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; +import org.springblade.system.cache.DictBizCache; import org.springblade.system.cache.UserCache; +import org.springblade.system.pojo.entity.DictBiz; import org.springblade.transport.excel.OtherExpenseRecordExcel; import org.springblade.transport.excel.OtherExpenseRecordExportExcel; import org.springblade.transport.mapper.OtherExpenseRecordMapper; @@ -28,6 +30,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Set; +import java.util.stream.Collectors; /** * 其他费用记录 服务实现类 @@ -43,7 +46,7 @@ public class OtherExpenseRecordServiceImpl extends BaseServiceImpl EXPENSE_TYPES = Set.of("过路费", "停车费", "维修费", "保险费", "年检费", "装卸费", "其他"); + private static final String EXPENSE_TYPE_DICT_CODE = "other_fee_category"; @Override public IPage selectOtherExpenseRecordPage(IPage page, OtherExpenseRecordVO otherExpenseRecord) { @@ -103,7 +106,7 @@ public class OtherExpenseRecordServiceImpl extends BaseServiceImpl validationErrors = new ArrayList<>(); org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isEmpty(otherExpenseRecord.getExpenseDate()), "费用日期不能为空"); org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isEmpty(otherExpenseRecord.getExpenseType()), "费用类型不能为空"); - org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isNotEmpty(otherExpenseRecord.getExpenseType()) && !EXPENSE_TYPES.contains(otherExpenseRecord.getExpenseType()), "费用类型不正确"); + org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isNotEmpty(otherExpenseRecord.getExpenseType()) && !loadExpenseTypeValues().contains(otherExpenseRecord.getExpenseType()), "费用类型不正确"); org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isEmpty(otherExpenseRecord.getVehicleType()), "车船类型不能为空"); org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isNotEmpty(otherExpenseRecord.getVehicleType()) && !VEHICLE.equals(otherExpenseRecord.getVehicleType()) && !SHIP.equals(otherExpenseRecord.getVehicleType()), "车船类型不正确"); org.springblade.common.excel.ImportFailureExcelUtil.addValidationError(validationErrors, Func.isEmpty(otherExpenseRecord.getVehicleNo()), "车牌号/船号不能为空"); @@ -152,7 +155,7 @@ public class OtherExpenseRecordServiceImpl extends BaseServiceImpl loadExpenseTypeValues() { + List expenseTypes = DictBizCache.getList(EXPENSE_TYPE_DICT_CODE); + if (Func.isEmpty(expenseTypes)) { + return Set.of(); + } + return expenseTypes.stream() + .map(DictBiz::getDictValue) + .filter(Objects::nonNull) + .map(String::trim) + .filter(Func::isNotEmpty) + .collect(Collectors.toSet()); + } + } diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java index d5f0187..50749f1 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/ReceivablePayableDetailServiceImpl.java @@ -1565,11 +1565,11 @@ public class ReceivablePayableDetailServiceImpl private BigDecimal calculateRule(Map rule, Waybill waybill) { String element = stringValue(rule, "billingElement", ""); String type = stringValue(rule, "billingType", ""); - BigDecimal base = measure(rule, waybill); BigDecimal unit = decimal(rule.get("unitPrice")); + BigDecimal measuredBase = measure(rule, waybill); BigDecimal unit = decimal(rule.get("unitPrice")); List> ranges = ranges(rule); boolean intervalUnitPrice = "区间单价".equals(type); boolean intervalFlatPrice = type.contains("区间") && type.contains("一口价"); - if (!intervalUnitPrice && !intervalFlatPrice) base = applyMinimum(base, rule, waybill); + BigDecimal base = (!intervalUnitPrice && !intervalFlatPrice) ? applyMinimum(measuredBase, rule, waybill) : measuredBase; if ("固定一口价".equals(type)) return unit.setScale(2, RoundingMode.HALF_UP); if (ranges.isEmpty() || "固定单价".equals(type)) return base.multiply(unit).setScale(2, RoundingMode.HALF_UP); if (intervalFlatPrice) return range(ranges, base).map(r -> decimal(r.get("unitPrice")).signum() == 0 ? unit : decimal(r.get("unitPrice"))).orElse(BigDecimal.ZERO).setScale(2, RoundingMode.HALF_UP); diff --git a/doc/sql/transport/blade_customer_archive.sql b/doc/sql/transport/blade_customer_archive.sql index 680e9fc..640af81 100644 --- a/doc/sql/transport/blade_customer_archive.sql +++ b/doc/sql/transport/blade_customer_archive.sql @@ -9,6 +9,7 @@ CREATE TABLE `blade_customer_archive` ( `short_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '客商简称', `full_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客商全称', `customer_nature` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客商性质', + `guangxi_top100` tinyint NULL DEFAULT NULL COMMENT '是否广西百强:0否,1是', `unified_credit_code` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '统一社会信用代码', `customer_type` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '客商类型', `project_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属项目', @@ -22,6 +23,7 @@ CREATE TABLE `blade_customer_archive` ( `dept_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '所属组织', `invoice_tax_rate` decimal(6,2) NULL DEFAULT NULL COMMENT '开票税点', `business_scope` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '经营范围', + `network_freight_platform` tinyint NULL DEFAULT NULL COMMENT '网络货运平台:0否,1是', `business_term_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '营业期限类型', `business_end_date` date NULL DEFAULT NULL COMMENT '营业期限截止日', `registered_capital` decimal(18,2) NULL DEFAULT NULL COMMENT '注册资金(万元)', @@ -116,21 +118,13 @@ CREATE TABLE `blade_customer_invoice_info` ( `id` bigint NOT NULL COMMENT '主键', `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '000000' COMMENT '租户ID', `customer_id` bigint NOT NULL COMMENT '客商ID', - `invoice_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '受票方名称', - `invoice_type` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发票类型', + `invoice_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '企业全称', `tax_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '纳税人识别号', `bank_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '开户行名称', - `registered_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册电话', `bank_account` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '银行账号', `registered_address` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册地址', `registered_region_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册地址行政区划', `registered_detail_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '注册地址详细地址', - `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱', - `receiver_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人姓名', - `receiver_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人电话', - `receiver_address` varchar(400) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人地址', - `receiver_region_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人地址行政区划', - `receiver_detail_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '收件人详细地址', `is_default` int NULL DEFAULT 0 COMMENT '是否默认', `create_user` bigint NULL DEFAULT NULL COMMENT '创建人', `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门', @@ -143,6 +137,31 @@ CREATE TABLE `blade_customer_invoice_info` ( KEY `idx_customer_invoice_customer` (`tenant_id`, `customer_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客商发票信息'; +-- ---------------------------- +-- Table structure for blade_customer_invoice_contact +-- ---------------------------- +DROP TABLE IF EXISTS `blade_customer_invoice_contact`; +CREATE TABLE `blade_customer_invoice_contact` ( + `id` bigint NOT NULL COMMENT '主键', + `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '000000' COMMENT '租户ID', + `invoice_id` bigint NOT NULL COMMENT '发票信息ID', + `contact_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱地址', + `dept_ids` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门ID集合', + `dept_names` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_user` bigint NULL DEFAULT NULL COMMENT '创建人', + `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_user` bigint NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间', + `status` int NULL DEFAULT 1 COMMENT '状态', + `is_deleted` int NULL DEFAULT 0 COMMENT '是否已删除', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_customer_invoice_contact_invoice` (`tenant_id`, `invoice_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客商发票联系信息'; + -- ---------------------------- -- Table structure for blade_customer_credit_score -- ---------------------------- diff --git a/doc/sql/transport/blade_customer_archive_guangxi_top100_20260914.sql b/doc/sql/transport/blade_customer_archive_guangxi_top100_20260914.sql new file mode 100644 index 0000000..8f56222 --- /dev/null +++ b/doc/sql/transport/blade_customer_archive_guangxi_top100_20260914.sql @@ -0,0 +1,4 @@ +-- 客商档案:新增「是否广西百强」字段(是否,无默认值,未选择时保持 NULL) + +ALTER TABLE `blade_customer_archive` + ADD COLUMN `guangxi_top100` tinyint NULL DEFAULT NULL COMMENT '是否广西百强:0否,1是' AFTER `customer_nature`; diff --git a/doc/sql/transport/blade_customer_archive_network_freight_platform_20260914.sql b/doc/sql/transport/blade_customer_archive_network_freight_platform_20260914.sql new file mode 100644 index 0000000..d28f143 --- /dev/null +++ b/doc/sql/transport/blade_customer_archive_network_freight_platform_20260914.sql @@ -0,0 +1,4 @@ +-- 客商档案:新增「网络货运平台」字段(是否,无默认值) + +ALTER TABLE `blade_customer_archive` + ADD COLUMN `network_freight_platform` tinyint NULL DEFAULT NULL COMMENT '网络货运平台:0否,1是' AFTER `business_scope`; diff --git a/doc/sql/transport/blade_customer_invoice_contact_20260914.sql b/doc/sql/transport/blade_customer_invoice_contact_20260914.sql new file mode 100644 index 0000000..80d4cce --- /dev/null +++ b/doc/sql/transport/blade_customer_invoice_contact_20260914.sql @@ -0,0 +1,63 @@ +-- 客商发票信息:去掉邮寄信息/发票类型/注册电话,改为维护多个联系信息 + +CREATE TABLE IF NOT EXISTS `blade_customer_invoice_contact` ( + `id` bigint NOT NULL COMMENT '主键', + `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '000000' COMMENT '租户ID', + `invoice_id` bigint NOT NULL COMMENT '发票信息ID', + `contact_name` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系人', + `contact_phone` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '联系电话', + `email` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '邮箱地址', + `dept_ids` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门ID集合', + `dept_names` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '所属部门', + `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_user` bigint NULL DEFAULT NULL COMMENT '创建人', + `create_dept` bigint NULL DEFAULT NULL COMMENT '创建部门', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `update_user` bigint NULL DEFAULT NULL COMMENT '修改人', + `update_time` datetime NULL DEFAULT NULL COMMENT '修改时间', + `status` int NULL DEFAULT 1 COMMENT '状态', + `is_deleted` int NULL DEFAULT 0 COMMENT '是否已删除', + PRIMARY KEY (`id`) USING BTREE, + KEY `idx_customer_invoice_contact_invoice` (`tenant_id`, `invoice_id`) USING BTREE +) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '客商发票联系信息'; + +INSERT INTO `blade_customer_invoice_contact` ( + `id`, `tenant_id`, `invoice_id`, `contact_name`, `contact_phone`, `email`, + `dept_ids`, `dept_names`, `remark`, `create_user`, `create_dept`, `create_time`, + `update_user`, `update_time`, `status`, `is_deleted` +) +SELECT + invoice.`id`, + invoice.`tenant_id`, + invoice.`id`, + invoice.`receiver_name`, + invoice.`receiver_phone`, + invoice.`email`, + NULL, + NULL, + NULL, + invoice.`create_user`, + invoice.`create_dept`, + invoice.`create_time`, + invoice.`update_user`, + invoice.`update_time`, + IFNULL(invoice.`status`, 1), + IFNULL(invoice.`is_deleted`, 0) +FROM `blade_customer_invoice_info` invoice +WHERE (IFNULL(invoice.`receiver_name`, '') <> '' + OR IFNULL(invoice.`receiver_phone`, '') <> '' + OR IFNULL(invoice.`email`, '') <> '') + AND NOT EXISTS ( + SELECT 1 FROM `blade_customer_invoice_contact` contact WHERE contact.`id` = invoice.`id` + ); + +ALTER TABLE `blade_customer_invoice_info` + MODIFY COLUMN `invoice_title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '企业全称', + DROP COLUMN `invoice_type`, + DROP COLUMN `registered_phone`, + DROP COLUMN `email`, + DROP COLUMN `receiver_name`, + DROP COLUMN `receiver_phone`, + DROP COLUMN `receiver_address`, + DROP COLUMN `receiver_region_name`, + DROP COLUMN `receiver_detail_address`; diff --git a/doc/sql/transport/blade_insurance_ocr_template.sql b/doc/sql/transport/blade_insurance_ocr_template.sql index 8bd1f7f..7423078 100644 --- a/doc/sql/transport/blade_insurance_ocr_template.sql +++ b/doc/sql/transport/blade_insurance_ocr_template.sql @@ -6,6 +6,7 @@ CREATE TABLE `blade_insurance_ocr_template` ( `id` bigint(20) NOT NULL COMMENT '主键', `tenant_id` varchar(12) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '000000' COMMENT '租户ID', `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '模板名称', + `vehicle_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '车辆' COMMENT '车船类型:车辆/船舶', `mapping_config` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '字段映射配置JSON', `create_user` bigint(20) DEFAULT NULL COMMENT '创建人', `create_dept` bigint(20) DEFAULT NULL COMMENT '创建部门', @@ -16,6 +17,7 @@ CREATE TABLE `blade_insurance_ocr_template` ( `is_deleted` int(11) NOT NULL DEFAULT '0' COMMENT '是否已删除', PRIMARY KEY (`id`) USING BTREE, KEY `idx_insurance_ocr_template_name` (`tenant_id`, `name`) USING BTREE, + KEY `idx_insurance_ocr_template_vehicle_type` (`tenant_id`, `vehicle_type`) USING BTREE, KEY `idx_insurance_ocr_template_status` (`status`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='保险OCR识别模板'; diff --git a/doc/sql/transport/blade_insurance_ocr_template_vehicle_type_20260914.sql b/doc/sql/transport/blade_insurance_ocr_template_vehicle_type_20260914.sql new file mode 100644 index 0000000..141d93e --- /dev/null +++ b/doc/sql/transport/blade_insurance_ocr_template_vehicle_type_20260914.sql @@ -0,0 +1,5 @@ +-- 保险OCR识别模板:新增车船类型字段 + +ALTER TABLE `blade_insurance_ocr_template` + ADD COLUMN `vehicle_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '车辆' COMMENT '车船类型:车辆/船舶' AFTER `name`, + ADD KEY `idx_insurance_ocr_template_vehicle_type` (`tenant_id`, `vehicle_type`) USING BTREE; diff --git a/hs_err_pid22822.log b/hs_err_pid22822.log new file mode 100644 index 0000000..9cc29df --- /dev/null +++ b/hs_err_pid22822.log @@ -0,0 +1,157 @@ +# +# 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.(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.()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.(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.()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= \ No newline at end of file