🔀 合并 dev 分支到 master

解决 9 个文件的冲突,取舍如下:

- 导出模型:采用 dev 的 *ExportExcel 命名与拆分,并保留 master 的
  @DateTimeFormat(dev 改名时漏加,会导致时间列显示为 Date.toString)。
- PortTerminal 导入:保留 master 的两阶段导入 + ImportFailureException
  全量回滚(ImportFailureException 仅 master 有,合并后的 controller 依赖它),
  导出失败明细改用 dev 的 exportFailureReasonOnly(仅标红失败原因列)。
- PortTerminal 导入模板:采用 dev 的"港口编码/码头编码"两列结构,
  相应补上 resolveImportCode 归并规则,并在构建实体时显式赋 code/parentCode。
- PortTerminal 导出:采用 dev 的 PortTerminalExportExcel(接口已如此声明),
  并保留 updateUserName 审计人翻译。
- 违章记录导入:保留 dev 的多错误收集 + 导入失败明细导出流水线,
  删除已被拆列取代的 violationTypeOrItem 映射,补上 clearIrrelevantField,
  并为导入校验补齐"对侧字段应留空"规则以与表单校验一致。

验证:mvn compile -DskipTests 全模块 BUILD SUCCESS。
This commit is contained in:
2026-09-20 18:04:43 +08:00
762 changed files with 58612 additions and 3373 deletions
+16
View File
@@ -31,6 +31,10 @@
<groupId>org.springblade</groupId>
<artifactId>blade-transport-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-lbs-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-user-api</artifactId>
@@ -39,6 +43,18 @@
<groupId>org.springblade</groupId>
<artifactId>blade-system-api</artifactId>
</dependency>
<dependency>
<groupId>org.springblade</groupId>
<artifactId>blade-process-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
</dependency>
</dependencies>
<build>
@@ -0,0 +1,53 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
/**
* 凭证导入消息队列配置。
* RabbitMQ 连接参数由 Nacos 的 spring.rabbitmq 配置提供。
*/
@Configuration
public class VoucherImportRabbitConfig {
private final String exchange;
private final String queue;
private final String routingKey;
public VoucherImportRabbitConfig(
@Value("${voucher.import.rabbit.exchange:tms.voucher.import.exchange}") String exchange,
@Value("${voucher.import.rabbit.queue:tms.voucher.import.queue}") String queue,
@Value("${voucher.import.rabbit.routing-key:tms.voucher.import}") String routingKey) {
this.exchange = exchange;
this.queue = queue;
this.routingKey = routingKey;
}
public String getExchange() { return exchange; }
public String getQueue() { return queue; }
public String getRoutingKey() { return routingKey; }
@Bean
public DirectExchange voucherImportExchange() {
return new DirectExchange(exchange, true, false);
}
@Bean
public Queue voucherImportQueue() {
return new Queue(queue, true);
}
@Bean
public Binding voucherImportBinding(Queue voucherImportQueue, DirectExchange voucherImportExchange) {
return BindingBuilder.bind(voucherImportQueue).to(voucherImportExchange).with(routingKey);
}
}
@@ -0,0 +1,26 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 凭证图片 MinIO 客户端配置。
* 连接参数由 Nacos 的 file.storage.minio 配置提供。
*/
@Configuration
public class VoucherMinioConfig {
@Bean
public MinioClient voucherMinioClient(
@Value("${file.storage.minio.endpoint:${minio.endpoint:}}") String endpoint,
@Value("${file.storage.minio.access-key-id:${minio.access-key:}}") String accessKey,
@Value("${file.storage.minio.access-key-secret:${minio.secret-key:}}") String secretKey) {
return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
}
}
@@ -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<IPage<AnnualInspectionRecordVO>> list(AnnualInspectionRecordVO annualInspectionRecord, Query query) {
fillExpiryDate(annualInspectionRecord);
IPage<AnnualInspectionRecordVO> 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<AnnualInspectionRecordExpiryStatVO> 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<AnnualInspectionRecordExcel> 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<AnnualInspectionRecordExportExcel> 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<AnnualInspectionRecordExcel> 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<AnnualInspectionRecord> buildExportQuery(AnnualInspectionRecordVO annualInspectionRecord, String ids) {
LambdaQueryWrapper<AnnualInspectionRecord> queryWrapper = Wrappers.<AnnualInspectionRecord>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;
}
@@ -0,0 +1,119 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.tool.api.R;
import org.springblade.transport.ocr.constant.BaiduOcrType;
import org.springblade.transport.ocr.service.IBaiduOcrService;
import org.springblade.transport.pojo.vo.BaiduOcrResultVO;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
* 百度 OCR 控制器。
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@Slf4j
@RequestMapping("/baidu-ocr")
@Tag(name = "百度OCR", description = "百度OCR证件识别")
public class BaiduOcrController extends BladeController {
private final IBaiduOcrService baiduOcrService;
/**
* 识别上传的图片。
*
* @param file 图片文件
* @param type 证件类型:id_card、business_license、vehicle_license、driving_license、road_transport_certificate、general
* @param side 正副面:front或back,适用于身份证、行驶证、驾驶证,默认front
* @return OCR结果
*/
@PostMapping(value = "/recognize", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@ApiOperationSupport(order = 1)
@Operation(summary = "上传图片OCR识别", description = "支持身份证、营业执照、行驶证、驾驶证、道路运输证和通用文字识别")
public R<BaiduOcrResultVO> recognize(
@RequestPart("file") MultipartFile file,
@Parameter(description = "OCR证件类型", required = true) @RequestParam String type,
@Parameter(description = "正副面:front或back,适用于身份证、行驶证、驾驶证,默认front") @RequestParam(required = false) String side) {
if (file == null || file.isEmpty()) {
throw new ServiceException("OCR图片不能为空");
}
BaiduOcrType ocrType = resolveType(type);
if (file.getSize() > ocrType.getMaxRawSize()) {
throw new ServiceException("OCR图片过大,请压缩后重新上传");
}
try {
return R.data(baiduOcrService.recognize(ocrType, side, file.getBytes()));
} catch (IOException exception) {
log.error("读取OCR图片失败,type={}size={}", ocrType.name(), file.getSize(), exception);
throw new ServiceException("读取OCR图片失败");
}
}
/**
* 识别图片地址。
*
* @param imageUrl 图片地址
* @param type 证件类型
* @param side 正副面
* @return OCR结果
*/
@PostMapping("/recognize-url")
@ApiOperationSupport(order = 2)
@Operation(summary = "图片地址OCR识别", description = "图片地址必须是百度可访问的HTTP或HTTPS地址")
public R<BaiduOcrResultVO> recognizeUrl(
@Parameter(description = "图片地址", required = true) @RequestParam String imageUrl,
@Parameter(description = "OCR证件类型", required = true) @RequestParam String type,
@Parameter(description = "正副面:front或back,适用于身份证、行驶证、驾驶证,默认front") @RequestParam(required = false) String side) {
return R.data(baiduOcrService.recognizeUrl(resolveType(type), side, imageUrl));
}
private BaiduOcrType resolveType(String type) {
try {
return BaiduOcrType.from(type);
} catch (IllegalArgumentException exception) {
throw new ServiceException(exception.getMessage());
}
}
}
@@ -0,0 +1,91 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.BillLedgerSaveRequest;
import org.springblade.transport.pojo.vo.BillLedgerVO;
import org.springblade.transport.service.IBillLedgerService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/** 汇票台账控制器。 @author Chill */
@RestController
@AllArgsConstructor
@PreAuth(menu = "bill_ledger")
@RequestMapping("/bill-ledger")
@Tag(name = "汇票台账", description = "汇票票据信息及可用余额管理")
public class BillLedgerController extends BladeController {
private final IBillLedgerService billLedgerService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "汇票台账分页")
public R<IPage<BillLedgerVO>> list(BillLedgerVO query, Query pageQuery) {
return R.data(billLedgerService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "汇票台账详情")
public R<BillLedgerVO> detail(@RequestParam Long id) {
return R.data(billLedgerService.detail(id));
}
@GetMapping("/expiry-counts")
@ApiOperationSupport(order = 3)
@Operation(summary = "汇票到期快捷统计")
public R<Map<String, Long>> expiryCounts() {
return R.data(billLedgerService.expiryCounts());
}
@GetMapping("/available-options")
@ApiOperationSupport(order = 4)
@Operation(summary = "付款申请可用汇票")
public R<List<BillLedgerVO>> availableOptions(@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long deptId, @RequestParam(required = false) Long selectedId) {
return R.data(billLedgerService.availableOptions(keyword, deptId, selectedId));
}
@GetMapping("/available-page")
@ApiOperationSupport(order = 5)
@Operation(summary = "付款申请可用汇票分页")
public R<IPage<BillLedgerVO>> availablePage(Query pageQuery,
@RequestParam(required = false) String keyword, @RequestParam(required = false) Long deptId,
@RequestParam(required = false) Long selectedId) {
return R.data(billLedgerService.availablePage(Condition.getPage(pageQuery), keyword, deptId, selectedId));
}
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "新增或编辑汇票台账")
public R<Long> submit(@RequestBody BillLedgerSaveRequest request) {
return R.data(billLedgerService.submit(request));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除汇票台账")
public R remove(@RequestParam Long id) {
billLedgerService.removeLedger(id);
return R.success("删除成功");
}
}
@@ -0,0 +1,118 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.BillPaymentSaveRequest;
import org.springblade.transport.pojo.dto.BillPaymentStatusRequest;
import org.springblade.transport.pojo.vo.BillPaymentVO;
import org.springblade.transport.service.IBillPaymentService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/** 汇票付款控制器。 @author Chill */
@RestController
@AllArgsConstructor
@PreAuth(menu = "bill_payment")
@RequestMapping("/bill-payment")
@Tag(name = "汇票付款", description = "汇票付款单据管理")
public class BillPaymentController extends BladeController {
private final IBillPaymentService billPaymentService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "汇票付款分页")
public R<IPage<BillPaymentVO>> list(BillPaymentVO query, Query pageQuery) {
return R.data(billPaymentService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "汇票付款详情")
public R<BillPaymentVO> detail(@RequestParam Long id) {
return R.data(billPaymentService.detail(id));
}
@PostMapping("/save")
@ApiOperationSupport(order = 3)
@Operation(summary = "保存汇票付款")
public R<Long> save(@RequestBody BillPaymentSaveRequest request) {
return R.data(billPaymentService.saveDraft(request));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 4)
@Operation(summary = "删除汇票付款草稿")
public R remove(@RequestParam Long id) {
billPaymentService.removeDraft(id);
return R.success("删除成功");
}
@PostMapping("/submit")
@ApiOperationSupport(order = 5)
@Operation(summary = "提交汇票付款")
public R submit(@RequestBody BillPaymentStatusRequest request) {
billPaymentService.submit(request);
return R.success("提交成功");
}
@PostMapping("/approve")
@ApiOperationSupport(order = 6)
@Operation(summary = "审批通过汇票付款")
public R approve(@RequestBody BillPaymentStatusRequest request) {
billPaymentService.approve(request);
return R.success("审批通过");
}
@PostMapping("/return")
@ApiOperationSupport(order = 7)
@Operation(summary = "驳回汇票付款")
public R returnBill(@RequestBody BillPaymentStatusRequest request) {
billPaymentService.returnBill(request);
return R.success("已驳回");
}
@PostMapping("/void")
@ApiOperationSupport(order = 8)
@Operation(summary = "作废汇票付款")
public R voidBill(@RequestBody BillPaymentStatusRequest request) {
billPaymentService.voidBill(request);
return R.success("作废成功");
}
}
@@ -41,7 +41,7 @@ import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.excel.CommonAddressExcel;
import org.springblade.transport.excel.CommonAddressExportExcel;
import org.springblade.transport.pojo.entity.CommonAddress;
import org.springblade.transport.pojo.vo.CommonAddressRemoveResultVO;
import org.springblade.transport.pojo.vo.CommonAddressVO;
@@ -136,8 +136,8 @@ public class CommonAddressController extends BladeController {
public void exportCommonAddress(CommonAddressVO commonAddress,
@RequestParam(required = false) String ids,
HttpServletResponse response) {
List<CommonAddressExcel> list = commonAddressService.exportCommonAddress(buildExportQuery(commonAddress, ids));
ExcelUtil.export(response, "常用地址" + DateUtil.time(), "常用地址", list, CommonAddressExcel.class);
List<CommonAddressExportExcel> list = commonAddressService.exportCommonAddress(buildExportQuery(commonAddress, ids));
ExcelUtil.export(response, "常用地址" + DateUtil.time(), "常用地址", list, CommonAddressExportExcel.class);
}
private Query normalizeQuery(Query query) {
@@ -112,7 +112,7 @@ public class CommonCargoController extends BladeController {
public R importCommonCargo(MultipartFile file, HttpServletResponse response) {
List<CommonCargoImportFailureExcel> failureList = commonCargoService.importCommonCargo(ExcelUtil.read(file, CommonCargoExcel.class));
if (Func.isNotEmpty(failureList)) {
ImportFailureExcelUtil.export(response, "常用货物导入失败明细" + DateUtil.time(), "导入失败明细", failureList, CommonCargoExcel.class);
ImportFailureExcelUtil.export(response, "常用货物导入失败明细" + DateUtil.time(), "导入失败明细", failureList, CommonCargoImportFailureExcel.class);
return null;
}
return R.success("导入数据成功");
@@ -38,7 +38,7 @@ import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.common.excel.ImportFailureExcelUtil;
import org.springblade.transport.excel.CommonRouteExcel;
import org.springblade.transport.excel.CommonRouteExportExcel;
import org.springblade.transport.excel.CommonRouteImportExcel;
import org.springblade.transport.pojo.entity.CommonRoute;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
@@ -101,8 +101,8 @@ public class CommonRouteController extends BladeController {
@ApiOperationSupport(order = 5)
@Operation(summary = "导出常用线路")
public void exportCommonRoute(CommonRouteVO commonRoute, @RequestParam(required = false) String ids, HttpServletResponse response) {
List<CommonRouteExcel> list = commonRouteService.exportCommonRoute(commonRoute, ids);
ExcelUtil.export(response, "常用线路" + DateUtil.time(), "常用线路", list, CommonRouteExcel.class);
List<CommonRouteExportExcel> list = commonRouteService.exportCommonRoute(commonRoute, ids);
ExcelUtil.export(response, "常用线路" + DateUtil.time(), "常用线路", list, CommonRouteExportExcel.class);
}
@PostMapping("/import-common-route")
@@ -131,11 +131,17 @@ public class ContractManageController extends BladeController {
@ApiOperationSupport(order = 10)
@Operation(summary = "发起变更", description = "传入id、changeContent和changeReason")
public R startChange(@Parameter(description = "主键", required = true) @RequestParam Long id,
@RequestParam String changeContent,
@RequestParam String changeReason) {
@RequestParam(required = false) String changeContent,
@RequestParam(required = false) String changeReason) {
return R.status(contractManageService.startChange(id, changeContent, changeReason));
}
@PostMapping("/submit-change")
@Operation(summary = "提交合同变更")
public R submitChange(@RequestBody ContractManage contractManage) {
return R.status(contractManageService.submitChange(contractManage));
}
@PostMapping("/terminate")
@ApiOperationSupport(order = 11)
@Operation(summary = "终止合同", description = "传入id和reason")
@@ -0,0 +1,152 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.secure.constant.AuthConstant;
import org.springblade.core.tenant.annotation.TenantIgnore;
import org.springblade.core.tool.api.FR;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.process.feign.IBusinessProcessClient;
import org.springblade.transport.pojo.vo.CustomerArchiveVO;
import org.springblade.transport.pojo.vo.CustomerChangeRecordVO;
import org.springblade.transport.service.ICustomerArchiveService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* 客商档案公开查看 控制器
*
* @author Chill
*/
@Slf4j
@RestController
@AllArgsConstructor
@TenantIgnore
@PreAuth(AuthConstant.PERMIT_ALL)
@RequestMapping("/customer-archive/public")
@Tag(name = "客商档案公开查看", description = "客商档案公开查看")
public class CustomerArchivePublicController {
private final ICustomerArchiveService customerArchiveService;
private final IBusinessProcessClient businessProcessClient;
/**
* 公开详情
*/
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "公开详情", description = "传入id,无需登录")
public R<CustomerArchiveVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(customerArchiveService.publicDetail(id));
}
/**
* 公开变更记录分页
*/
@GetMapping("/change-record/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "公开变更记录分页", description = "传入客商ID,无需登录")
public R<IPage<CustomerChangeRecordVO>> changeRecordList(
@Parameter(description = "客商ID", required = true) @RequestParam Long customerId, Query query) {
return R.data(customerArchiveService.publicChangeRecordPage(Condition.getPage(query), customerId));
}
/**
* 公开接收流程页 postMessage 数据(当前仅打印,便于联调)
*/
@PostMapping("/process-message")
@ApiOperationSupport(order = 3)
@Operation(summary = "公开接收流程消息", description = "无需登录,接收后查询当前节点并打印")
public R processMessage(@RequestBody Map<String, Object> body) {
log.info("客商公开页收到流程消息:{}", JSON.toJSONString(body));
Map<String, Object> formValues = asMap(body == null ? null : body.get("formValues"));
String processId = firstText(formValues, "processId");
if (StringUtil.isBlank(processId) && body != null) {
processId = firstText(body, "processId");
}
String loginName = firstText(formValues, "mkLoginName", "loginName");
if (StringUtil.isBlank(processId)) {
log.warn("客商公开页流程消息未找到 processId,跳过查询当前节点");
return R.success("ok");
}
try {
FR<Object> result = businessProcessClient.getCurrentNodes(processId, loginName);
log.info("客商公开页流程消息当前节点详情 processId={} loginName={} result={}",
processId, loginName, JSON.toJSONString(result == null ? null : result.getData()));
} catch (Exception e) {
log.error("客商公开页查询当前节点失败 processId={} loginName={}", processId, loginName, e);
}
return R.success("ok");
}
private static Map<String, Object> asMap(Object value) {
if (!(value instanceof Map<?, ?> map)) {
return Collections.emptyMap();
}
Map<String, Object> result = new HashMap<>();
map.forEach((key, nested) -> {
if (key != null) {
result.put(String.valueOf(key), nested);
}
});
return result;
}
private static String firstText(Map<String, Object> source, String... keys) {
if (source == null || keys == null) {
return null;
}
for (String key : keys) {
Object value = source.get(key);
if (value == null) {
continue;
}
String text = String.valueOf(value).trim();
if (StringUtil.isNotBlank(text) && !"null".equalsIgnoreCase(text)) {
return text;
}
}
return null;
}
}
@@ -0,0 +1,69 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.vo.DriverVehicleCardVO;
import org.springblade.transport.pojo.vo.DriverVO;
import org.springblade.transport.service.IDriverAppService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 司机端档案(小程序)
* <p>
* 对外路径:{@code /api/blade-transport/driver/**}
* 同时兼容未去前缀直连 {@code /blade-transport/driver/**}。
*/
@RestController
@AllArgsConstructor
@RequestMapping({"/driver", "/blade-transport/driver"})
@Tag(name = "司机端档案", description = "小程序司机个人档案")
public class DriverAppController extends BladeController {
private final IDriverAppService driverAppService;
@GetMapping("/mine")
@ApiOperationSupport(order = 1)
@Operation(summary = "当前登录司机档案", description = "按手机号匹配 blade_transport_driver.mobile;可传 mobile,未传则从登录态解析")
public R<DriverVO> mine(@RequestParam(required = false) String mobile) {
return R.data(driverAppService.currentByPhone(mobile));
}
@GetMapping("/vehicles")
@ApiOperationSupport(order = 2)
@Operation(summary = "当前司机车辆列表", description = "按司机 driving_vehicle 车牌匹配 blade_transport_vehicle")
public R<List<DriverVehicleCardVO>> vehicles() {
return R.data(driverAppService.myVehicles());
}
}
@@ -0,0 +1,156 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.pojo.dto.EnrouteSubmitDTO;
import org.springblade.transport.pojo.dto.NodeSubmitDTO;
import org.springblade.transport.pojo.vo.DriverEnrouteRecordVO;
import org.springblade.transport.pojo.vo.DriverNodePunchVO;
import org.springblade.transport.pojo.vo.DriverWaybillCardVO;
import org.springblade.transport.pojo.vo.DriverWaybillPreviewVO;
import org.springblade.transport.pojo.vo.DriverWaybillTabCountsVO;
import org.springblade.transport.service.IDriverWaybillService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 司机端运单接口(小程序)
* <p>
* 对外完整路径:{@code /api/blade-transport/waybill/**}
* (网关 StripPrefix 去掉 {@code blade-transport} 后落入 {@code /waybill/**})。
* 同时兼容未去前缀直连({@code /blade-transport/waybill/**}),避免 404。
* 不挂管理端菜单鉴权,仅需登录态(Blade Secure)。
*/
@RestController
@AllArgsConstructor
@RequestMapping({"/waybill", "/blade-transport/waybill"})
@Tag(name = "司机端运单", description = "小程序司机端运单")
public class DriverWaybillController extends BladeController {
private final IDriverWaybillService driverWaybillService;
@GetMapping("/current-task")
@ApiOperationSupport(order = 1)
@Operation(summary = "首页:当前运输中任务", description = "当前司机绑定车牌下 businessStatus=running 的最新一条运单")
public R<DriverWaybillCardVO> currentTask() {
return R.data(driverWaybillService.currentTask());
}
@GetMapping("/pending-preview")
@ApiOperationSupport(order = 2)
@Operation(summary = "首页:待接运单预览", description = "当前司机绑定车牌下 businessStatus=pending 的预览列表与总数")
public R<DriverWaybillPreviewVO> pendingPreview(
@Parameter(description = "预览条数,默认 2") @RequestParam(required = false) Integer size) {
return R.data(driverWaybillService.pendingPreview(size));
}
@GetMapping("/counts")
@ApiOperationSupport(order = 3)
@Operation(summary = "运单 Tab 统计", description = "仅统计当前司机绑定车牌对应的运单:全部 / 待接单 / 进行中 / 已完成")
public R<DriverWaybillTabCountsVO> counts() {
return R.data(driverWaybillService.tabCounts());
}
@GetMapping("/page")
@ApiOperationSupport(order = 4)
@Operation(summary = "运单分页列表", description = "仅返回当前司机绑定车牌(driving_vehicle)匹配运单 vehicleNo/trailerVehicleNo 的数据;status:空=全部,0待接单,1运输中,2已完成")
public R<IPage<DriverWaybillCardVO>> page(
@Parameter(description = "当前页") @RequestParam(required = false) Integer current,
@Parameter(description = "每页条数") @RequestParam(required = false) Integer size,
@Parameter(description = "状态:0待接单/1运输中/2已完成,不传为全部") @RequestParam(required = false) String status,
@Parameter(description = "关键字:运单号/起终点") @RequestParam(required = false) String keyword) {
Integer statusCode = parseStatus(status);
return R.data(driverWaybillService.page(current, size, statusCode, keyword));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 5)
@Operation(summary = "司机运单详情", description = "返回 requireAccept、在途打卡可见性(transitCheckinVisible / requireTransitCheckinToday)等字段")
public R<DriverWaybillCardVO> detail(
@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
return R.data(driverWaybillService.detail(id));
}
@PostMapping("/accept")
@ApiOperationSupport(order = 6)
@Operation(summary = "司机确认接单", description = "过程配置接单为「是」时,司机确认接单后运单进入进行中")
public R accept(@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
return R.status(driverWaybillService.accept(id));
}
@PostMapping("/reject")
@ApiOperationSupport(order = 7)
@Operation(summary = "司机拒绝接单", description = "过程配置接单为「是」时,司机可拒绝接单,运单保持待执行并记录拒单")
public R reject(
@Parameter(description = "运单ID", required = true) @RequestParam Long id,
@Parameter(description = "拒绝原因") @RequestParam(required = false) String reason) {
return R.status(driverWaybillService.reject(id, reason));
}
@PostMapping("/enroute/submit")
@ApiOperationSupport(order = 8)
@Operation(summary = "提交在途打卡", description = "过程配置在途节点 punch=是,且满足频次/时段时允许提交")
public R<DriverEnrouteRecordVO> submitEnroute(@RequestBody EnrouteSubmitDTO dto) {
return R.data(driverWaybillService.submitEnroute(dto));
}
@PostMapping("/node/submit")
@ApiOperationSupport(order = 9)
@Operation(summary = "提交过程节点打卡", description = "到场/装货/发货/到货/卸货/签收等 punch=是;在途请走 /enroute/submit")
public R<DriverNodePunchVO> submitNode(@RequestBody NodeSubmitDTO dto) {
return R.data(driverWaybillService.submitNode(dto));
}
@PostMapping("/complete")
@ApiOperationSupport(order = 10)
@Operation(summary = "司机完成运单", description = "校验司机归属后改状态为已完成,并检查生成应收应付明细(与管理端一致)")
public R complete(@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
return R.status(driverWaybillService.complete(id));
}
/** 前端可能传空字符串表示「全部」 */
private Integer parseStatus(String status) {
if (Func.isEmpty(status)) {
return null;
}
try {
return Integer.valueOf(status.trim());
} catch (NumberFormatException ex) {
return null;
}
}
}
@@ -30,9 +30,9 @@ import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.ExceptionDisposalFollowRequest;
import org.springblade.transport.pojo.entity.ExceptionDisposal;
import org.springblade.transport.pojo.vo.ExceptionDisposalVO;
import org.springblade.transport.service.IExceptionDisposalService;
import org.springframework.web.bind.annotation.GetMapping;
@@ -44,13 +44,14 @@ import org.springframework.web.bind.annotation.RestController;
/**
* 异常处置控制器
*
* @author Chill
* <p>
* 对外路径:{@code /api/blade-transport/exception-disposal/**}
* 同时兼容未去前缀直连 {@code /blade-transport/exception-disposal/**}。
* 列表 / 详情 / 上报 / 跟进 / 完成均仅需登录态(小程序调度端与司机端共用)。
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "exception_disposal")
@RequestMapping("/exception-disposal")
@RequestMapping({"/exception-disposal", "/blade-transport/exception-disposal"})
@Tag(name = "异常处置", description = "异常处置")
public class ExceptionDisposalController extends BladeController {
@@ -70,25 +71,32 @@ public class ExceptionDisposalController extends BladeController {
return R.data(exceptionDisposalService.detail(id));
}
@PostMapping("/follow")
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "异常跟进")
@Operation(summary = "异常上报", description = "司机端上报异常;上报人取登录态,运单信息按 waybillId/waybillNo 回填")
public R<ExceptionDisposalVO> submit(@RequestBody ExceptionDisposal request) {
return R.data(exceptionDisposalService.submitReport(request));
}
@PostMapping("/follow")
@ApiOperationSupport(order = 4)
@Operation(summary = "异常跟进", description = "调度端跟进;仅需登录态")
public R follow(@RequestBody ExceptionDisposalFollowRequest request) {
exceptionDisposalService.follow(request);
return R.success("跟进成功");
}
@PostMapping("/complete")
@ApiOperationSupport(order = 4)
@Operation(summary = "完成异常")
@ApiOperationSupport(order = 5)
@Operation(summary = "完成异常", description = "调度端结案;仅需登录态")
public R complete(@RequestBody ExceptionDisposalFollowRequest request) {
exceptionDisposalService.complete(request.getId());
return R.success("完成成功");
}
@PostMapping("/batch-complete")
@ApiOperationSupport(order = 5)
@Operation(summary = "批量完成异常")
@ApiOperationSupport(order = 6)
@Operation(summary = "批量完成异常", description = "调度端批量结案;仅需登录态")
public R batchComplete(@RequestParam String ids) {
exceptionDisposalService.batchComplete(ids);
return R.success("批量完成成功");
@@ -0,0 +1,253 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.transport.pojo.dto.FormalSettlementSaveRequest;
import org.springblade.transport.pojo.dto.FormalSettlementPaymentRequest;
import org.springblade.transport.pojo.dto.FormalSettlementBatchPaymentRequest;
import org.springblade.transport.pojo.dto.FormalSettlementStatusRequest;
import org.springblade.transport.pojo.dto.FormalSettlementInvoiceClaimRequest;
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
import org.springblade.transport.pojo.vo.FormalSettlementVO;
import org.springblade.transport.excel.FormalSettlementExcel;
import org.springblade.transport.pojo.vo.PreSettlementVO;
import org.springblade.transport.service.IFormalSettlementService;
import org.springblade.transport.service.IPreSettlementService;
import org.springblade.transport.service.IReceiptFlowService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* 正式结算单控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "formal_settlement")
@RequestMapping("/formal-settlement")
@Tag(name = "正式结算单", description = "正式结算单管理")
public class FormalSettlementController extends BladeController {
private final IFormalSettlementService formalSettlementService;
private final IPreSettlementService preSettlementService;
private final IReceiptFlowService receiptFlowService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "正式结算单分页")
public R<IPage<FormalSettlementVO>> list(FormalSettlementVO query, Query pageQuery) {
return R.data(formalSettlementService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/export")
@ApiOperationSupport(order = 20)
@Operation(summary = "导出正式结算单")
public void export(FormalSettlementVO query, @RequestParam(required = false) String ids,
HttpServletResponse response) {
query.setIds(ids);
IPage<FormalSettlementVO> page = formalSettlementService.selectPage(new Page<>(1, 100000), query);
List<FormalSettlementExcel> rows = page.getRecords().stream().map(this::toExcel).toList();
ExcelUtil.export(response, "正式结算单" + DateUtil.time(), "正式结算单", rows, FormalSettlementExcel.class);
}
private FormalSettlementExcel toExcel(FormalSettlementVO vo) {
FormalSettlementExcel excel = new FormalSettlementExcel();
excel.setFormalSettlementNo(vo.getFormalSettlementNo());
excel.setPreSettlementNos(vo.getPreSettlementNos());
excel.setSourceType(vo.getSourceType());
excel.setPayerName(vo.getPayerName());
excel.setPayeeName(vo.getPayeeName());
excel.setProjectName(vo.getProjectName());
excel.setDeptName(vo.getDeptName());
excel.setContractNo(vo.getContractNo());
excel.setContractName(vo.getContractName());
excel.setSettlementAmount(formatMoney(vo.getSettlementAmount(), vo.getCurrency()));
excel.setLocalSettlementAmount(formatMoney(vo.getLocalSettlementAmount(), vo.getLocalCurrency()));
excel.setExchangeRate(vo.getExchangeRate() == null ? "" : vo.getExchangeRate().stripTrailingZeros().toPlainString());
excel.setInvoiceStatusName(invoiceStatusName(vo.getInvoiceStatus(), vo.getSettlementType()));
excel.setPaymentStatusName(paymentStatusName(vo.getPaymentStatus()));
excel.setApprovalStatusName(vo.getApprovalStatusName());
excel.setKingdeeBillNo(vo.getKingdeeBillNo());
excel.setCreateUserName(vo.getCreateUserName());
excel.setCreateTime(vo.getCreateTime());
return excel;
}
private String formatMoney(BigDecimal value, String currency) {
if (value == null) return "";
return value.setScale(2, RoundingMode.HALF_UP).toPlainString() + " "
+ (currency == null || currency.isBlank() ? "RMB" : currency);
}
private String invoiceStatusName(String value, String settlementType) {
boolean payable = "payable".equals(settlementType);
return switch (value == null ? "" : value) {
case "unreceived" -> payable ? "未收票" : "未开票";
case "partial" -> payable ? "部分收票" : "部分开票";
case "completed" -> payable ? "已收票" : "已开票";
default -> value == null || value.isBlank() ? "-" : value;
};
}
private String paymentStatusName(String value) {
return switch (value == null ? "" : value) {
case "unpaid" -> "未收/付款";
case "partial" -> "部分收/付款";
case "paid" -> "已收/付款";
default -> value == null || value.isBlank() ? "-" : value;
};
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "正式结算单详情")
public R<FormalSettlementVO> detail(@RequestParam Long id) { return R.data(formalSettlementService.detail(id)); }
@GetMapping("/candidate-pre-settlements")
@ApiOperationSupport(order = 3)
@Operation(summary = "可合并的预结算单")
public R<IPage<PreSettlementVO>> candidates(PreSettlementVO query, Query pageQuery) {
return R.data(formalSettlementService.candidatePreSettlements(Condition.getPage(pageQuery), query));
}
@GetMapping("/contract-options")
@ApiOperationSupport(order = 4)
@Operation(summary = "可选合同")
public R<List<Map<String, Object>>> contractOptions(@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long projectId) {
return R.data(preSettlementService.contractOptions(keyword, projectId));
}
@GetMapping("/next-no")
@ApiOperationSupport(order = 5)
@Operation(summary = "获取最新正式结算单号")
public R<String> nextNo(@RequestParam String settlementType) {
return R.data(formalSettlementService.nextNo(settlementType));
}
@GetMapping("/fee-options")
@ApiOperationSupport(order = 6)
@Operation(summary = "可选费用类型及费用项")
public R<List<Map<String, Object>>> feeOptions() {
return R.data(preSettlementService.feeOptions());
}
@GetMapping("/candidate-details")
@ApiOperationSupport(order = 7)
@Operation(summary = "可选应收应付明细")
public R<IPage<Map<String, Object>>> candidateDetails(Query query, @RequestParam Long contractId,
@RequestParam(required = false) String settlementType, @RequestParam(required = false) String batchNo,
@RequestParam(required = false) String createStartDate, @RequestParam(required = false) String createEndDate) {
return R.data(preSettlementService.candidateDetailsByCreateTime(Condition.getPage(query), contractId,
settlementType, batchNo, createStartDate, createEndDate));
}
@PostMapping("/save")
@ApiOperationSupport(order = 8)
@Operation(summary = "保存正式结算草稿")
public R<Long> save(@RequestBody FormalSettlementSaveRequest request) { return R.data(formalSettlementService.saveDraft(request)); }
@PostMapping("/remove")
@ApiOperationSupport(order = 9)
@Operation(summary = "删除正式结算草稿")
public R remove(@RequestParam Long id) { formalSettlementService.removeDraft(id); return R.success("删除成功"); }
@PostMapping("/submit")
@ApiOperationSupport(order = 10)
@Operation(summary = "提交审批")
public R submit(@RequestBody FormalSettlementStatusRequest request) { formalSettlementService.submit(request); return R.success("提交成功"); }
@PostMapping("/approve")
@ApiOperationSupport(order = 11)
@Operation(summary = "审批通过")
public R approve(@RequestBody FormalSettlementStatusRequest request) { formalSettlementService.approve(request); return R.success("审批通过"); }
@PostMapping("/return")
@ApiOperationSupport(order = 12)
@Operation(summary = "审批驳回")
public R returnBill(@RequestBody FormalSettlementStatusRequest request) { formalSettlementService.returnBill(request); return R.success("已驳回"); }
@PostMapping("/void")
@ApiOperationSupport(order = 13)
@Operation(summary = "作废正式结算单")
public R voidBill(@RequestBody FormalSettlementStatusRequest request) { formalSettlementService.voidBill(request); return R.success("作废成功"); }
@PostMapping("/sync-kingdee")
@ApiOperationSupport(order = 14)
@Operation(summary = "推送金蝶应付单")
public R<String> syncKingdee(@RequestParam Long id) { return R.data(formalSettlementService.syncKingdee(id)); }
@GetMapping("/detail-fees")
@ApiOperationSupport(order = 15)
@Operation(summary = "正式结算货物费用快照")
public R<List<FormalSettlementDetailFee>> detailFees(@RequestParam Long detailId) {
return R.data(formalSettlementService.detailFees(detailId));
}
@PostMapping("/adjust-detail")
@ApiOperationSupport(order = 16)
@Operation(summary = "调整草稿结算明细")
public R adjustDetail(@RequestBody PreSettlementDetailAdjustRequest request) {
formalSettlementService.adjustDetail(request);
return R.success("保存成功");
}
@PostMapping("/apply-payment")
@ApiOperationSupport(order = 17)
@Operation(summary = "发起尾款付款申请")
public R<String> applyPayment(@RequestBody FormalSettlementPaymentRequest request) {
return R.data(formalSettlementService.applyPayment(request));
}
@PostMapping("/apply-payments")
@ApiOperationSupport(order = 18)
@Operation(summary = "批量发起尾款付款申请")
public R<List<String>> applyPayments(@RequestBody FormalSettlementBatchPaymentRequest request) {
return R.data(formalSettlementService.applyPayments(request));
}
@PostMapping("/claim-invoices")
@ApiOperationSupport(order = 18)
@Operation(summary = "认领发票并同步付款申请")
public R claimInvoices(@RequestBody FormalSettlementInvoiceClaimRequest request) {
formalSettlementService.claimInvoices(request);
return R.success("发票认领成功");
}
@GetMapping("/receipt-claims")
@ApiOperationSupport(order = 19)
@Operation(summary = "应收正式结算单收款认领信息")
public R<List<Map<String, Object>>> receiptClaims(@RequestParam Long formalSettlementId) {
return R.data(receiptFlowService.settlementClaims(formalSettlementId));
}
}
@@ -0,0 +1,98 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.pojo.entity.InsuranceOcrTemplate;
import org.springblade.transport.pojo.vo.InsuranceOcrTemplateVO;
import org.springblade.transport.service.IInsuranceOcrTemplateService;
import org.springblade.transport.wrapper.InsuranceOcrTemplateWrapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
* 保险OCR识别模板控制器。
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "insurance_ocr_template")
@RequestMapping("/insurance-ocr-template")
@Tag(name = "保险OCR识别模板", description = "保险OCR识别模板")
public class InsuranceOcrTemplateController extends BladeController {
private final IInsuranceOcrTemplateService insuranceOcrTemplateService;
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入id")
public R<InsuranceOcrTemplateVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
InsuranceOcrTemplate insuranceOcrTemplate = insuranceOcrTemplateService.getById(id);
if (insuranceOcrTemplate == null || insuranceOcrTemplate.getIsDeleted() == 1) {
throw new ServiceException("保险OCR识别模板不存在");
}
return R.data(InsuranceOcrTemplateWrapper.build().entityVO(insuranceOcrTemplate));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入insuranceOcrTemplate")
public R<IPage<InsuranceOcrTemplateVO>> list(InsuranceOcrTemplateVO insuranceOcrTemplate, Query query) {
return R.data(insuranceOcrTemplateService.selectInsuranceOcrTemplatePage(Condition.getPage(query), insuranceOcrTemplate));
}
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增或修改", description = "传入insuranceOcrTemplate")
public R submit(@RequestBody InsuranceOcrTemplate insuranceOcrTemplate) {
return R.status(insuranceOcrTemplateService.submit(insuranceOcrTemplate));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 4)
@Operation(summary = "逻辑删除", description = "传入ids")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(insuranceOcrTemplateService.deleteLogic(Func.toLongList(ids)));
}
}
@@ -166,7 +166,7 @@ public class InsuranceRecordController extends BladeController {
*/
@PostMapping("/recognize")
@ApiOperationSupport(order = 8)
@Operation(summary = "OCR识别保单", description = "上传保单图片或PDF")
@Operation(summary = "OCR识别保单", description = "上传保单图片")
public R<InsuranceRecord> recognize(MultipartFile file,
@RequestParam(required = false) String vehicleType,
@RequestParam(required = false) String ocrTemplate) {
@@ -0,0 +1,159 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.InvoiceApplicationSaveRequest;
import org.springblade.transport.pojo.dto.InvoiceApplicationStatusRequest;
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
import org.springblade.transport.pojo.vo.InvoiceApplicationVO;
import org.springblade.transport.service.IInvoiceApplicationService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 开票申请控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "invoice_application")
@RequestMapping("/invoice-application")
@Tag(name = "开票管理", description = "开票申请管理")
public class InvoiceApplicationController extends BladeController {
private final IInvoiceApplicationService invoiceApplicationService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "开票申请分页")
public R<IPage<InvoiceApplicationVO>> list(InvoiceApplicationVO query, Query pageQuery) {
return R.data(invoiceApplicationService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "开票申请详情")
public R<InvoiceApplicationVO> detail(@RequestParam Long id) {
return R.data(invoiceApplicationService.detail(id));
}
@GetMapping("/settlement-candidates")
@ApiOperationSupport(order = 3)
@Operation(summary = "可开票正式结算单")
public R<IPage<Map<String, Object>>> settlementCandidates(Query query,
@RequestParam(required = false) String keyword,
@RequestParam(required = false) String contractCategory,
@RequestParam(defaultValue = "receivable") String settlementType,
@RequestParam(defaultValue = "unreceived") String invoiceStatus) {
return R.data(invoiceApplicationService.settlementCandidates(
Condition.getPage(query), keyword, contractCategory, settlementType, invoiceStatus));
}
@GetMapping("/settlement-details")
@ApiOperationSupport(order = 4)
@Operation(summary = "结算单可选明细")
public R<List<FormalSettlementDetail>> settlementDetails(@RequestParam String settlementIds) {
return R.data(invoiceApplicationService.settlementDetails(settlementIds));
}
@GetMapping("/receiver-information")
@ApiOperationSupport(order = 5)
@Operation(summary = "受票方开票信息")
public R<Map<String, Object>> receiverInformation(@RequestParam String settlementIds) {
return R.data(invoiceApplicationService.receiverInformation(settlementIds));
}
@PostMapping("/save")
@ApiOperationSupport(order = 6)
@Operation(summary = "保存开票申请")
public R<Long> save(@RequestBody InvoiceApplicationSaveRequest request) {
return R.data(invoiceApplicationService.saveDraft(request));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除开票申请草稿")
public R remove(@RequestParam Long id) {
invoiceApplicationService.removeDraft(id);
return R.success("删除成功");
}
@PostMapping("/submit")
@ApiOperationSupport(order = 8)
@Operation(summary = "提交开票申请")
public R submit(@RequestBody InvoiceApplicationStatusRequest request) {
invoiceApplicationService.submit(request);
return R.success("提交成功");
}
@PostMapping("/approve")
@ApiOperationSupport(order = 9)
@Operation(summary = "审批通过开票申请")
public R approve(@RequestBody InvoiceApplicationStatusRequest request) {
invoiceApplicationService.approve(request);
return R.success("审批通过");
}
@PostMapping("/return")
@ApiOperationSupport(order = 10)
@Operation(summary = "驳回开票申请")
public R returnBill(@RequestBody InvoiceApplicationStatusRequest request) {
invoiceApplicationService.returnBill(request);
return R.success("已驳回");
}
@PostMapping("/void")
@ApiOperationSupport(order = 11)
@Operation(summary = "作废开票申请")
public R voidBill(@RequestBody InvoiceApplicationStatusRequest request) {
invoiceApplicationService.voidBill(request);
return R.success("作废成功");
}
@PostMapping("/sync-kingdee")
@ApiOperationSupport(order = 12)
@Operation(summary = "同步金蝶开票申请")
public R<String> syncKingdee(@RequestParam Long id) {
return R.data(invoiceApplicationService.syncKingdee(id));
}
}
@@ -0,0 +1,157 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.InvoiceReceiptSaveRequest;
import org.springblade.transport.pojo.dto.InvoiceReceiptStatusRequest;
import org.springblade.transport.pojo.entity.KingdeeInvoicePool;
import org.springblade.transport.pojo.vo.InvoiceReceiptVO;
import org.springblade.transport.service.IInvoiceReceiptService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 收票登记控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "invoice_receipt")
@RequestMapping("/invoice-receipt")
@Tag(name = "收票管理", description = "进项发票登记认领管理")
public class InvoiceReceiptController extends BladeController {
private final IInvoiceReceiptService invoiceReceiptService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "收票登记分页")
public R<IPage<InvoiceReceiptVO>> list(InvoiceReceiptVO query, Query pageQuery) {
return R.data(invoiceReceiptService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "收票登记详情")
public R<InvoiceReceiptVO> detail(@RequestParam Long id) {
return R.data(invoiceReceiptService.detail(id));
}
@GetMapping("/invoice-pool")
@ApiOperationSupport(order = 3)
@Operation(summary = "查询金蝶进项发票票据池")
public R<List<KingdeeInvoicePool>> invoicePool(@RequestParam(required = false) String keyword) {
return R.data(invoiceReceiptService.invoicePool(keyword));
}
@GetMapping("/settlement-candidates")
@ApiOperationSupport(order = 4)
@Operation(summary = "可关联的应付正式结算单")
public R<List<Map<String, Object>>> settlementCandidates(
@RequestParam(required = false) String keyword,
@RequestParam(required = false) Long receiptId) {
return R.data(invoiceReceiptService.settlementCandidates(keyword, receiptId));
}
@GetMapping("/reference-information")
@ApiOperationSupport(order = 5)
@Operation(summary = "收票关联参考信息")
public R<Map<String, Object>> referenceInformation(@RequestParam String settlementIds) {
return R.data(invoiceReceiptService.referenceInformation(settlementIds));
}
@PostMapping("/save")
@ApiOperationSupport(order = 6)
@Operation(summary = "保存收票登记")
public R<Long> save(@RequestBody InvoiceReceiptSaveRequest request) {
return R.data(invoiceReceiptService.saveDraft(request));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 7)
@Operation(summary = "删除收票登记草稿")
public R remove(@RequestParam Long id) {
invoiceReceiptService.removeDraft(id);
return R.success("删除成功");
}
@PostMapping("/submit")
@ApiOperationSupport(order = 8)
@Operation(summary = "提交收票登记")
public R submit(@RequestBody InvoiceReceiptStatusRequest request) {
invoiceReceiptService.submit(request);
return R.success("提交成功");
}
@PostMapping("/approve")
@ApiOperationSupport(order = 9)
@Operation(summary = "审批通过收票登记")
public R approve(@RequestBody InvoiceReceiptStatusRequest request) {
invoiceReceiptService.approve(request);
return R.success("审批通过");
}
@PostMapping("/return")
@ApiOperationSupport(order = 10)
@Operation(summary = "驳回收票登记")
public R returnBill(@RequestBody InvoiceReceiptStatusRequest request) {
invoiceReceiptService.returnBill(request);
return R.success("已驳回");
}
@PostMapping("/void")
@ApiOperationSupport(order = 11)
@Operation(summary = "作废收票登记")
public R voidBill(@RequestBody InvoiceReceiptStatusRequest request) {
invoiceReceiptService.voidBill(request);
return R.success("作废成功");
}
@PostMapping("/sync-kingdee")
@ApiOperationSupport(order = 12)
@Operation(summary = "同步金蝶发票状态")
public R<String> syncKingdee(@RequestParam Long id) {
return R.data(invoiceReceiptService.syncKingdee(id));
}
}
@@ -21,6 +21,7 @@ import org.springblade.core.tool.utils.DateUtil;
import org.springblade.transport.excel.LoadingManageExcel;
import org.springblade.transport.pojo.entity.LoadingManage;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
import org.springblade.transport.pojo.vo.LoadingCarrierContractVO;
import org.springblade.transport.pojo.vo.LoadingManageVO;
import org.springblade.transport.service.ILoadingManageService;
import org.springframework.web.bind.annotation.GetMapping;
@@ -53,6 +54,13 @@ public class LoadingManageController extends BladeController {
return R.data(loadingManageService.detail(id));
}
@GetMapping("/carrier-contracts")
@ApiOperationSupport(order = 13)
@Operation(summary = "可选承运商合同", description = "查询已审核生效的承运商合同")
public R<List<LoadingCarrierContractVO>> carrierContracts(@RequestParam List<Long> projectIds) {
return R.data(loadingManageService.carrierContracts(projectIds));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入loadingManage")
@@ -111,22 +119,29 @@ public class LoadingManageController extends BladeController {
return R.status(loadingManageService.changeRoute(loadingManage));
}
@PostMapping("/cancel")
@PostMapping("/start")
@ApiOperationSupport(order = 10)
@Operation(summary = "改为进行中", description = "传入id")
public R start(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(loadingManageService.start(id));
}
@PostMapping("/cancel")
@ApiOperationSupport(order = 11)
@Operation(summary = "取消", description = "传入id")
public R cancel(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(loadingManageService.cancel(id));
}
@PostMapping("/complete")
@ApiOperationSupport(order = 11)
@ApiOperationSupport(order = 12)
@Operation(summary = "完成", description = "传入id")
public R complete(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(loadingManageService.complete(id));
}
@PostMapping("/batch-complete")
@ApiOperationSupport(order = 12)
@ApiOperationSupport(order = 13)
@Operation(summary = "批量完成", description = "传入ids")
public R<BusinessRemoveResultVO> batchComplete(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(loadingManageService.batchComplete(ids));
@@ -0,0 +1,143 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.AdminDriverOptionVO;
import org.springblade.transport.pojo.vo.AdminHomeStatsVO;
import org.springblade.transport.pojo.vo.AdminHomeVO;
import org.springblade.transport.pojo.vo.AdminVehicleOptionVO;
import org.springblade.transport.pojo.vo.AdminWaybillCardVO;
import org.springblade.transport.pojo.vo.AdminWaybillDetailVO;
import org.springblade.transport.service.IManageWaybillService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 调度端运单(小程序管理端)
* <p>
* 对外完整路径:{@code /api/blade-transport/waybill/manage/**}
* (网关 StripPrefix 去掉 {@code blade-transport} 后落入 {@code /waybill/manage/**})。
* 同时兼容未去前缀直连({@code /blade-transport/waybill/manage/**})。
* 仅需登录态,不挂管理端菜单鉴权。
*/
@RestController
@AllArgsConstructor
@RequestMapping({"/waybill/manage", "/blade-transport/waybill/manage"})
@Tag(name = "调度端运单", description = "小程序调度端首页统计与运单列表")
public class ManageWaybillController extends BladeController {
private final IManageWaybillService manageWaybillService;
@GetMapping("/stats")
@ApiOperationSupport(order = 1)
@Operation(summary = "运单状态统计", description = "待接单=pending,运输中=running,已完成=completed;租户内不过滤组织(小程序调度账号组织常与运单不一致);在途异常=异常处置状态≠已完成")
public R<AdminHomeStatsVO> stats() {
return R.data(manageWaybillService.stats());
}
@GetMapping("/home")
@ApiOperationSupport(order = 2)
@Operation(summary = "首页聚合", description = "统计 + 异常/风险角标 + 待处理事项(异常处置≠已完成)+ 当前用户名")
public R<AdminHomeVO> home() {
return R.data(manageWaybillService.home());
}
@GetMapping("/list")
@ApiOperationSupport(order = 3)
@Operation(summary = "运单分页列表", description = "当前组织运单;status:0待接单/1运输中/2已完成;exceptionexception/normaltransportTypecommon/load")
public R<IPage<AdminWaybillCardVO>> list(
@Parameter(description = "当前页") @RequestParam(required = false) Integer current,
@Parameter(description = "每页条数") @RequestParam(required = false) Integer size,
@Parameter(description = "关键字:运单号/司机/车牌") @RequestParam(required = false) String keyword,
@Parameter(description = "状态:0待接单/1运输中/2已完成,不传为全部") @RequestParam(required = false) String status,
@Parameter(description = "异常:exception有异常/normal无异常") @RequestParam(required = false) String exception,
@Parameter(description = "运输组织:common普通/load配载") @RequestParam(required = false) String transportType,
@Parameter(description = "创建日起 YYYY-MM-DD") @RequestParam(required = false) String startDate,
@Parameter(description = "创建日止 YYYY-MM-DD") @RequestParam(required = false) String endDate) {
return R.data(manageWaybillService.pageList(
current, size, keyword, status, exception, transportType, startDate, endDate));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 4)
@Operation(summary = "运单详情", description = "调度端查看运单详情(含 punchNodes / enrouteRecords),不校验司机归属与组织;字段对齐小程序 pages/waybill/detail")
public R<AdminWaybillDetailVO> detail(
@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
return R.data(manageWaybillService.detail(id));
}
@GetMapping("/pending")
@ApiOperationSupport(order = 5)
@Operation(summary = "待处理运单", description = "待接单/运输中;needReassign=true 仅司机已拒单")
public R<IPage<AdminWaybillCardVO>> pending(
@Parameter(description = "当前页") @RequestParam(required = false) Integer current,
@Parameter(description = "每页条数") @RequestParam(required = false) Integer size,
@Parameter(description = "关键字:运单号/司机/车牌") @RequestParam(required = false) String keyword,
@Parameter(description = "是否需重新派单") @RequestParam(required = false) Boolean needReassign) {
return R.data(manageWaybillService.pendingList(current, size, keyword, needReassign));
}
@PostMapping("/reassign")
@ApiOperationSupport(order = 6)
@Operation(summary = "重新派单", description = "小程序调度端:跳过组织校验,仅需登录态;传入运单ID及新司机、手机号、车牌")
public R reassign(@RequestBody Waybill waybill) {
return R.status(manageWaybillService.reassign(
waybill.getId(),
waybill.getDriverId(),
waybill.getDriverName(),
waybill.getDriverPhone(),
waybill.getVehicleNo()));
}
@GetMapping("/driver-search")
@ApiOperationSupport(order = 7)
@Operation(summary = "搜索司机", description = "按姓名/手机号模糊搜索,供重新派单选用")
public R<List<AdminDriverOptionVO>> driverSearch(
@Parameter(description = "关键字") @RequestParam(required = false) String keyword) {
return R.data(manageWaybillService.searchDrivers(keyword));
}
@GetMapping("/vehicle-search")
@ApiOperationSupport(order = 8)
@Operation(summary = "搜索车牌", description = "按车牌模糊搜索(来自司机绑定车牌)")
public R<List<AdminVehicleOptionVO>> vehicleSearch(
@Parameter(description = "关键字") @RequestParam(required = false) String keyword) {
return R.data(manageWaybillService.searchVehicles(keyword));
}
}
@@ -14,6 +14,8 @@ import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.MasterOrderDispatchRequest;
import org.springblade.transport.excel.MasterOrderWaybillExcel;
import org.springblade.transport.pojo.vo.MasterOrderCarrierVO;
import org.springblade.transport.pojo.vo.MasterOrderVO;
import org.springblade.transport.service.IMasterOrderService;
import org.springframework.web.bind.annotation.GetMapping;
@@ -23,6 +25,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* 多联总单控制器
*
@@ -37,6 +41,7 @@ public class MasterOrderController extends BladeController {
private final IMasterOrderService masterOrderService;
@GetMapping("/detail") @ApiOperationSupport(order = 1) @Operation(summary = "详情") public R<MasterOrderVO> detail(@RequestParam Long id) { return R.data(masterOrderService.detail(id)); }
@GetMapping("/carriers") @ApiOperationSupport(order = 2) @Operation(summary = "调度可选承运商") public R<List<MasterOrderCarrierVO>> carriers(@RequestParam Long id) { return R.data(masterOrderService.carriers(id)); }
@GetMapping("/list") @ApiOperationSupport(order = 2) @Operation(summary = "分页") public R<IPage<MasterOrderVO>> list(MasterOrderVO query, Query page) { return R.data(masterOrderService.selectPage(Condition.getPage(page), query)); }
@PostMapping("/submit") @ApiOperationSupport(order = 3) @Operation(summary = "确认创建或编辑") public R<MasterOrderVO> submit(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, false)); }
@PostMapping("/draft") @ApiOperationSupport(order = 4) @Operation(summary = "暂存草稿") public R<MasterOrderVO> draft(@RequestBody MasterOrderVO data) { return R.data(masterOrderService.submit(data, true)); }
@@ -44,5 +49,5 @@ public class MasterOrderController extends BladeController {
@PostMapping("/remove") @ApiOperationSupport(order = 6) @Operation(summary = "删除") public R status(@RequestParam Long id) { return R.status(masterOrderService.removeMasterOrder(id)); }
@PostMapping("/close-dispatch") @ApiOperationSupport(order = 7) @Operation(summary = "关闭调度") public R closeDispatch(@RequestParam Long id) { return R.status(masterOrderService.closeDispatch(id)); }
@PostMapping("/dispatch") @ApiOperationSupport(order = 8) @Operation(summary = "确认调度") public R<MasterOrderVO> dispatch(@RequestBody MasterOrderDispatchRequest data) { return R.data(masterOrderService.dispatch(data)); }
@GetMapping("/export") @ApiOperationSupport(order = 9) @Operation(summary = "按运单导出") public void export(MasterOrderVO query, HttpServletResponse response) { ExcelUtil.export(response, "总单运单明细", "运单明细", masterOrderService.exportWaybills(query), MasterOrderVO.class); }
@GetMapping("/export") @ApiOperationSupport(order = 9) @Operation(summary = "按运单导出") public void export(MasterOrderVO query, HttpServletResponse response) { ExcelUtil.export(response, "总单运单明细", "运单明细", masterOrderService.exportWaybills(query), MasterOrderWaybillExcel.class); }
}
@@ -76,6 +76,7 @@ public class MileageRecordController extends BladeController {
private static final int DEFAULT_CURRENT = 1;
private static final int DEFAULT_SIZE = 10;
private static final int MAX_SIZE = 100;
private static final String VEHICLE_TYPE = "车辆";
private final IMileageRecordService mileageRecordService;
@@ -83,6 +84,7 @@ public class MileageRecordController extends BladeController {
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入mileageRecord")
public R<MileageRecordVO> detail(MileageRecord mileageRecord) {
mileageRecord.setVehicleType(VEHICLE_TYPE);
MileageRecord detail = mileageRecordService.getOne(Condition.getQueryWrapper(mileageRecord));
return R.data(MileageRecordWrapper.build().entityVO(detail));
}
@@ -91,6 +93,7 @@ public class MileageRecordController extends BladeController {
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入mileageRecord")
public R<IPage<MileageRecordVO>> list(MileageRecordVO mileageRecord, Query query) {
mileageRecord.setVehicleType(VEHICLE_TYPE);
IPage<MileageRecordVO> pages = mileageRecordService.selectMileageRecordPage(Condition.getPage(normalizeQuery(query)), mileageRecord);
return R.data(pages);
}
@@ -158,6 +161,7 @@ public class MileageRecordController extends BladeController {
private LambdaQueryWrapper<MileageRecord> buildExportQuery(MileageRecordVO mileageRecord, String ids) {
LambdaQueryWrapper<MileageRecord> queryWrapper = Wrappers.<MileageRecord>lambdaQuery()
.eq(MileageRecord::getIsDeleted, 0)
.eq(MileageRecord::getVehicleType, VEHICLE_TYPE)
.orderByDesc(MileageRecord::getCreateTime);
if (Func.isNotEmpty(ids)) {
queryWrapper.in(MileageRecord::getId, Func.toLongList(ids));
@@ -165,9 +169,6 @@ public class MileageRecordController extends BladeController {
if (Func.isNotEmpty(mileageRecord.getCreateDept())) {
queryWrapper.eq(MileageRecord::getCreateDept, mileageRecord.getCreateDept());
}
if (Func.isNotEmpty(mileageRecord.getVehicleType())) {
queryWrapper.eq(MileageRecord::getVehicleType, mileageRecord.getVehicleType());
}
if (Func.isNotEmpty(mileageRecord.getVehicleNo())) {
queryWrapper.like(MileageRecord::getVehicleNo, mileageRecord.getVehicleNo());
}
@@ -0,0 +1,103 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments from this software for such purposes.
* Copyright of this software remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.PaymentApplicationSaveRequest;
import org.springblade.transport.pojo.dto.PaymentApplicationStatusRequest;
import org.springblade.transport.pojo.vo.PaymentApplicationReferenceAmountVO;
import org.springblade.transport.pojo.vo.PaymentApplicationVO;
import org.springblade.transport.service.IPaymentApplicationService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/** 付款申请控制器。 @author Chill */
@RestController
@AllArgsConstructor
@PreAuth(menu = "payment_application")
@RequestMapping("/payment-application")
@Tag(name = "付款管理", description = "付款申请管理")
public class PaymentApplicationController extends BladeController {
private final IPaymentApplicationService paymentApplicationService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "付款申请分页")
public R<IPage<PaymentApplicationVO>> list(PaymentApplicationVO query, Query pageQuery) { return R.data(paymentApplicationService.selectPage(Condition.getPage(pageQuery), query)); }
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "付款申请详情")
public R<PaymentApplicationVO> detail(@RequestParam Long id) { return R.data(paymentApplicationService.detail(id)); }
@GetMapping("/reference-amount")
@ApiOperationSupport(order = 3)
@Operation(summary = "动态计算结算单可付款金额")
public R<PaymentApplicationReferenceAmountVO> referenceAmount(@RequestParam String paymentType,
@RequestParam Long referenceId, @RequestParam(required = false) Long excludeId) {
return R.data(paymentApplicationService.referenceAmount(paymentType, referenceId, excludeId));
}
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "保存付款申请")
public R<Long> save(@RequestBody PaymentApplicationSaveRequest request) { return R.data(paymentApplicationService.saveDraft(request)); }
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@Operation(summary = "删除付款申请草稿")
public R remove(@RequestParam Long id) { paymentApplicationService.removeDraft(id); return R.success("删除成功"); }
@PostMapping("/submit")
@ApiOperationSupport(order = 6)
@Operation(summary = "提交付款申请")
public R submit(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.submit(request); return R.success("提交成功"); }
@PostMapping("/approve")
@ApiOperationSupport(order = 7)
@Operation(summary = "审批通过付款申请")
public R approve(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.approve(request); return R.success("审批通过"); }
@PostMapping("/return")
@ApiOperationSupport(order = 8)
@Operation(summary = "驳回付款申请")
public R returnBill(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.returnBill(request); return R.success("已驳回"); }
@PostMapping("/void")
@ApiOperationSupport(order = 9)
@Operation(summary = "作废付款申请")
public R voidBill(@RequestBody PaymentApplicationStatusRequest request) { paymentApplicationService.voidBill(request); return R.success("作废成功"); }
@PostMapping("/sync-kingdee")
@ApiOperationSupport(order = 10)
@Operation(summary = "生成金蝶付款单")
public R<String> syncKingdee(@RequestParam Long id) { return R.data(paymentApplicationService.syncKingdee(id)); }
@PostMapping("/sync-kingdee-batch")
@ApiOperationSupport(order = 11)
@Operation(summary = "批量生成金蝶付款单并同步付款信息")
public R<List<String>> syncKingdeeBatch(@RequestBody List<Long> ids) {
return R.data(paymentApplicationService.syncKingdeeBatch(ids));
}
}
@@ -0,0 +1,264 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.transport.excel.PreSettlementExcel;
import org.springblade.transport.pojo.dto.PreSettlementAdvanceRequest;
import org.springblade.transport.pojo.dto.PreSettlementDetailAdjustRequest;
import org.springblade.transport.pojo.dto.PreSettlementSaveRequest;
import org.springblade.transport.pojo.dto.PreSettlementStatusRequest;
import org.springblade.transport.pojo.entity.PreSettlementDetailFee;
import org.springblade.transport.pojo.vo.PreSettlementVO;
import org.springblade.transport.service.IPreSettlementService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
/**
* 预结算单控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "pre_settlement")
@RequestMapping("/pre-settlement")
@Tag(name = "预结算单", description = "预结算单管理")
public class PreSettlementController extends BladeController {
private final IPreSettlementService preSettlementService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "预结算单分页")
public R<IPage<PreSettlementVO>> list(PreSettlementVO query, Query pageQuery) {
return R.data(preSettlementService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "预结算单详情")
public R<PreSettlementVO> detail(@RequestParam Long id) {
return R.data(preSettlementService.detail(id));
}
@GetMapping("/contract-options")
@ApiOperationSupport(order = 3)
@Operation(summary = "可选合同")
public R<List<Map<String, Object>>> contractOptions(@RequestParam(required = false) String keyword) {
return R.data(preSettlementService.contractOptions(keyword));
}
@GetMapping("/fee-options")
@ApiOperationSupport(order = 4)
@Operation(summary = "费用类型及费用项")
public R<List<Map<String, Object>>> feeOptions() {
return R.data(preSettlementService.feeOptions());
}
@GetMapping("/candidate-details")
@ApiOperationSupport(order = 5)
@Operation(summary = "可选应收应付明细")
public R<IPage<Map<String, Object>>> candidateDetails(Query query, @RequestParam Long contractId,
@RequestParam String settlementType, @RequestParam(required = false) String batchNo,
@RequestParam(required = false) String feeStartDate,
@RequestParam(required = false) String feeEndDate) {
return R.data(preSettlementService.candidateDetails(Condition.getPage(query), contractId,
settlementType, batchNo, feeStartDate, feeEndDate));
}
@PostMapping("/save")
@ApiOperationSupport(order = 5)
@Operation(summary = "保存预结算草稿")
public R<Long> save(@RequestBody PreSettlementSaveRequest request) {
return R.data(preSettlementService.saveDraft(request));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@Operation(summary = "删除预结算草稿")
public R remove(@RequestParam Long id) {
preSettlementService.removeDraft(id);
return R.success("删除成功");
}
@PostMapping("/remove-detail")
@ApiOperationSupport(order = 7)
@Operation(summary = "移除预结算明细")
public R removeDetail(@RequestParam Long id, @RequestParam Long detailId) {
preSettlementService.removeDetail(id, detailId);
return R.success("移除成功");
}
@PostMapping("/submit")
@ApiOperationSupport(order = 8)
@Operation(summary = "提交预结算审批")
public R submit(@RequestBody PreSettlementStatusRequest request) {
preSettlementService.submit(request);
return R.success("审批流程已发起");
}
@PostMapping("/approve")
@ApiOperationSupport(order = 9)
@Operation(summary = "预结算审批通过")
public R approve(@RequestBody PreSettlementStatusRequest request) {
preSettlementService.approve(request);
return R.success("审批通过");
}
@PostMapping("/return")
@ApiOperationSupport(order = 10)
@Operation(summary = "预结算审批驳回")
public R returnBill(@RequestBody PreSettlementStatusRequest request) {
preSettlementService.returnBill(request);
return R.success("已驳回");
}
@PostMapping("/void")
@ApiOperationSupport(order = 11)
@Operation(summary = "作废预结算单")
public R voidBill(@RequestBody PreSettlementStatusRequest request) {
preSettlementService.voidBill(request);
return R.success("作废成功");
}
@PostMapping("/apply-advance")
@ApiOperationSupport(order = 12)
@Operation(summary = "发起预付申请")
public R applyAdvance(@RequestBody PreSettlementAdvanceRequest request) {
preSettlementService.applyAdvance(request);
return R.success("预付申请提交成功");
}
@PostMapping("/update-advance-paid")
@ApiOperationSupport(order = 13)
@Operation(summary = "回写预付付款金额")
public R updateAdvancePaid(@RequestParam Long advanceId, @RequestParam BigDecimal paidAmount,
@RequestParam(required = false) String kingdeeAdvanceNo) {
preSettlementService.updateAdvancePaidAmount(advanceId, paidAmount, kingdeeAdvanceNo);
return R.success("付款金额更新成功");
}
@PostMapping("/void-advance")
@ApiOperationSupport(order = 14)
@Operation(summary = "作废预付申请")
public R voidAdvance(@RequestParam Long advanceId, @RequestParam(required = false) String reason) {
preSettlementService.voidAdvance(advanceId, reason);
return R.success("预付申请作废成功");
}
@PostMapping("/formal-settlement")
@ApiOperationSupport(order = 16)
@Operation(summary = "尾款结算")
public R<String> formalSettlement(@RequestParam Long id) {
return R.data(preSettlementService.formalSettlement(id));
}
@GetMapping("/detail-fees")
@ApiOperationSupport(order = 15)
@Operation(summary = "结算明细费用")
public R<List<PreSettlementDetailFee>> detailFees(@RequestParam Long detailId) {
return R.data(preSettlementService.detailFees(detailId));
}
@PostMapping("/adjust-detail")
@ApiOperationSupport(order = 17)
@Operation(summary = "调整结算明细")
public R adjustDetail(@RequestBody PreSettlementDetailAdjustRequest request) {
preSettlementService.adjustDetail(request);
return R.success("保存成功");
}
@GetMapping("/print-templates")
@ApiOperationSupport(order = 18)
@Operation(summary = "预结算打印模板")
public R<List<Map<String, String>>> printTemplates(@RequestParam Long id) {
return R.data(preSettlementService.printTemplates(id));
}
@GetMapping("/export")
@ApiOperationSupport(order = 19)
@Operation(summary = "导出预结算单")
public void export(PreSettlementVO query, @RequestParam(required = false) String ids,
HttpServletResponse response) {
query.setIds(ids);
IPage<PreSettlementVO> page = preSettlementService.selectPage(new Page<>(1, 100000), query);
List<PreSettlementExcel> rows = page.getRecords().stream().map(this::toExcel).toList();
ExcelUtil.export(response, "预结算单" + DateUtil.time(), "预结算单", rows, PreSettlementExcel.class);
}
private PreSettlementExcel toExcel(PreSettlementVO vo) {
PreSettlementExcel excel = new PreSettlementExcel();
excel.setPreSettlementNo(vo.getPreSettlementNo());
excel.setSourceType(vo.getSourceType());
excel.setPayerName(vo.getPayerName());
excel.setPayeeName(vo.getPayeeName());
excel.setProjectName(vo.getProjectName());
excel.setDeptName(vo.getDeptName());
excel.setContractNo(vo.getContractNo());
excel.setContractName(vo.getContractName());
excel.setSettlementAmount(formatMoney(vo.getSettlementAmount(), vo.getCurrency()));
excel.setLocalSettlementAmount(formatMoney(vo.getLocalSettlementAmount(), vo.getLocalCurrency()));
excel.setExchangeRate(vo.getExchangeRate() == null ? "" : vo.getExchangeRate().stripTrailingZeros().toPlainString());
excel.setAdvanceAppliedAmount(formatMoney(vo.getAdvanceAppliedAmount(), vo.getCurrency()));
excel.setAdvancePaidAmount(formatMoney(vo.getAdvancePaidAmount(), vo.getCurrency()));
excel.setApprovalStatusName(vo.getApprovalStatusName());
excel.setCurrentNode(vo.getCurrentNode());
excel.setCurrentProcessor(vo.getCurrentProcessor());
excel.setCreateUserName(vo.getCreateUserName());
excel.setCreateTime(vo.getCreateTime());
return excel;
}
private String formatMoney(BigDecimal value, String currency) {
if (value == null) return "";
return value.setScale(2, RoundingMode.HALF_UP).toPlainString() + " " +
(currency == null || currency.isBlank() ? "RMB" : currency);
}
}
@@ -24,11 +24,13 @@ package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.http.Method;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
@@ -37,11 +39,20 @@ import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.excel.ProcessConfigExcel;
import org.springblade.transport.excel.ProcessConfigExportExcel;
import org.springblade.transport.mapper.VoucherFileMapper;
import org.springblade.transport.mapper.VoucherImageMapper;
import org.springblade.transport.mapper.VoucherManageMapper;
import org.springblade.transport.mapper.WaybillMapper;
import org.springblade.transport.pojo.entity.ProcessConfig;
import org.springblade.transport.pojo.entity.VoucherFile;
import org.springblade.transport.pojo.entity.VoucherImage;
import org.springblade.transport.pojo.entity.VoucherManage;
import org.springblade.transport.pojo.entity.Waybill;
import org.springblade.transport.pojo.vo.BusinessRemoveResultVO;
import org.springblade.transport.pojo.vo.ProcessConfigVO;
import org.springblade.transport.service.IProcessConfigService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -50,7 +61,11 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* 过程配置 控制器
@@ -58,19 +73,232 @@ import java.util.List;
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "process_config")
@RequestMapping("/process-config")
@Tag(name = "过程配置", description = "过程配置")
public class ProcessConfigController extends BladeController {
private final IProcessConfigService processConfigService;
private final WaybillMapper waybillMapper;
private final VoucherFileMapper voucherFileMapper;
private final VoucherImageMapper voucherImageMapper;
private final VoucherManageMapper voucherManageMapper;
private final MinioClient minioClient;
@Value("${file.storage.minio.bucket-name:${minio.bucket-name:}}")
private String minioBucketName;
public ProcessConfigController(IProcessConfigService processConfigService, WaybillMapper waybillMapper,
VoucherFileMapper voucherFileMapper, VoucherImageMapper voucherImageMapper,
VoucherManageMapper voucherManageMapper,
MinioClient minioClient) {
this.processConfigService = processConfigService;
this.waybillMapper = waybillMapper;
this.voucherFileMapper = voucherFileMapper;
this.voucherImageMapper = voucherImageMapper;
this.voucherManageMapper = voucherManageMapper;
this.minioClient = minioClient;
}
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情", description = "传入id")
public R<ProcessConfigVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(processConfigService.detail(id));
public R<ProcessConfigVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id,
@Parameter(description = "运单主键") @RequestParam(required = false) Long waybillId) {
ProcessConfigVO detail = processConfigService.detail(id);
detail.setHasRelatedVoucher(waybillId != null && voucherImageMapper.selectCount(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherImage>()
.eq(VoucherImage::getWaybillId, waybillId)
.eq(VoucherImage::getMatched, 1)
.eq(VoucherImage::getIsDeleted, 0)) > 0);
return R.data(detail);
}
@GetMapping("/voucher-images")
@ApiOperationSupport(order = 2)
@Operation(summary = "查询运单已关联凭证图片")
public R<List<Map<String, Object>>> voucherImages(
@Parameter(description = "运单主键", required = true) @RequestParam Long waybillId,
@Parameter(description = "凭证批次主键,点击文件夹时传入") @RequestParam(required = false) Long voucherId,
@Parameter(description = "文件夹名称,点击文件夹时传入") @RequestParam(required = false) String folderName) {
List<VoucherImage> imageRecords = voucherImageMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherImage>()
.eq(VoucherImage::getWaybillId, waybillId)
.eq(VoucherImage::getMatched, 1)
.eq(VoucherImage::getIsDeleted, 0)
.orderByDesc(VoucherImage::getCreateTime));
if (voucherId != null && Func.isNotEmpty(folderName)) {
return R.data(folderImages(waybillId, folderName));
}
List<Long> voucherIds = imageRecords.stream()
.map(VoucherImage::getVoucherId).filter(Objects::nonNull).distinct().toList();
Map<Long, VoucherManage> voucherMap = voucherIds.isEmpty() ? Map.of() : voucherManageMapper.selectBatchIds(voucherIds).stream()
.collect(java.util.stream.Collectors.toMap(VoucherManage::getId, item -> item, (left, right) -> left));
List<Map<String, Object>> images = imageRecords.stream()
// 承运商上传的凭证只允许审核通过后在运单详情展示,内部上传保持原有展示规则。
.filter(image -> {
VoucherManage voucher = voucherMap.get(image.getVoucherId());
return voucher == null || !"承运商".equals(voucher.getUploadSource())
|| "审核通过".equals(voucher.getAuditStatus());
}).map(image -> {
Map<String, Object> result = new LinkedHashMap<>();
result.put("id", image.getId());
result.put("imageName", image.getImageName());
result.put("plateNo", image.getPlateNo());
result.put("waybillNo", image.getWaybillNo());
result.put("objectKey", image.getObjectKey());
try {
result.put("url", minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET).bucket(minioBucketName).object(image.getObjectKey())
.expiry(1, TimeUnit.HOURS).build()));
} catch (Exception e) {
throw new IllegalStateException("生成凭证图片预览地址失败", e);
}
return result;
}).toList();
return R.data(images.isEmpty() ? fallbackVoucherFolders(waybillId) : images);
}
private List<Map<String, Object>> fallbackVoucherFolders(Long waybillId) {
Waybill waybill = waybillMapper.selectById(waybillId);
if (waybill == null || Func.isEmpty(waybill.getBatchNo())) {
return List.of();
}
List<VoucherManage> vouchers = voucherManageMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherManage>()
.eq(VoucherManage::getTenantId, waybill.getTenantId())
.eq(VoucherManage::getIsDeleted, 0));
Map<String, List<VoucherImageRecord>> folderRecords = new LinkedHashMap<>();
Map<String, List<VoucherManage>> folderVouchers = new LinkedHashMap<>();
for (VoucherManage voucher : vouchers) {
if (!containsBatchNo(voucher.getWaybillBatchNo(), waybill.getBatchNo()) || !visibleVoucher(voucher)) {
continue;
}
Map<String, List<VoucherImageRecord>> grouped = new LinkedHashMap<>();
for (VoucherFile file : voucherFileMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherFile>()
.eq(VoucherFile::getTenantId, voucher.getTenantId())
.eq(VoucherFile::getVoucherId, voucher.getId())
.eq(VoucherFile::getIsDeleted, 0))) {
if ("image".equals(file.getFileType())) {
String key = Func.isEmpty(file.getFolderName()) ? "未命名文件夹" : file.getFolderName();
grouped.computeIfAbsent(key, ignored -> new ArrayList<>()).add(VoucherImageRecord.from(file));
}
}
if (grouped.isEmpty()) {
for (VoucherImage image : voucherImageMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherImage>()
.eq(VoucherImage::getTenantId, voucher.getTenantId())
.eq(VoucherImage::getVoucherId, voucher.getId())
.eq(VoucherImage::getIsDeleted, 0))) {
String key = Func.isEmpty(image.getPlateNo()) ? "未命名文件夹" : image.getPlateNo();
grouped.computeIfAbsent(key, ignored -> new ArrayList<>()).add(VoucherImageRecord.from(image));
}
}
for (Map.Entry<String, List<VoucherImageRecord>> entry : grouped.entrySet()) {
folderRecords.computeIfAbsent(entry.getKey(), ignored -> new ArrayList<>()).addAll(entry.getValue());
folderVouchers.computeIfAbsent(entry.getKey(), ignored -> new ArrayList<>()).add(voucher);
}
}
List<Map<String, Object>> folders = new ArrayList<>();
for (Map.Entry<String, List<VoucherImageRecord>> entry : folderRecords.entrySet()) {
Map<String, Object> folder = new LinkedHashMap<>();
folder.put("type", "folder");
folder.put("isFolder", true);
folder.put("waybillId", waybillId);
folder.put("waybillBatchNo", waybill.getBatchNo());
List<VoucherManage> relatedVouchers = folderVouchers.get(entry.getKey());
folder.put("voucherId", relatedVouchers.get(0).getId());
folder.put("voucherIds", relatedVouchers.stream().map(VoucherManage::getId).toList());
folder.put("voucherBatchNo", relatedVouchers.get(0).getVoucherBatchNo());
folder.put("voucherBatchNos", relatedVouchers.stream().map(VoucherManage::getVoucherBatchNo).toList());
folder.put("folderName", entry.getKey());
folder.put("plateNo", entry.getKey());
folder.put("name", entry.getKey());
folder.put("imageCount", entry.getValue().size());
folder.put("icon", "/img/文件夹.png");
folders.add(folder);
}
return folders;
}
private List<Map<String, Object>> folderImages(Long waybillId, String folderName) {
Waybill waybill = waybillMapper.selectById(waybillId);
if (waybill == null || Func.isEmpty(waybill.getBatchNo()) || Func.isEmpty(folderName)) {
return List.of();
}
List<VoucherManage> vouchers = voucherManageMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherManage>()
.eq(VoucherManage::getTenantId, waybill.getTenantId())
.eq(VoucherManage::getIsDeleted, 0));
Map<String, VoucherImageRecord> recordMap = new LinkedHashMap<>();
for (VoucherManage voucher : vouchers) {
if (!containsBatchNo(voucher.getWaybillBatchNo(), waybill.getBatchNo()) || !visibleVoucher(voucher)) {
continue;
}
List<VoucherImageRecord> voucherRecords = voucherFileMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherFile>()
.eq(VoucherFile::getTenantId, voucher.getTenantId())
.eq(VoucherFile::getVoucherId, voucher.getId())
.eq(VoucherFile::getFolderName, folderName)
.eq(VoucherFile::getFileType, "image")
.eq(VoucherFile::getIsDeleted, 0)).stream().map(VoucherImageRecord::from).toList();
if (voucherRecords.isEmpty()) {
voucherRecords = voucherImageMapper.selectList(
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<VoucherImage>()
.eq(VoucherImage::getTenantId, voucher.getTenantId())
.eq(VoucherImage::getVoucherId, voucher.getId())
.eq(VoucherImage::getPlateNo, folderName)
.eq(VoucherImage::getIsDeleted, 0)).stream().map(VoucherImageRecord::from).toList();
}
for (VoucherImageRecord record : voucherRecords) {
String key = record.id() != null ? String.valueOf(record.id()) : record.objectKey();
recordMap.putIfAbsent(key, record);
}
}
return recordMap.values().stream().map(this::imageMap).toList();
}
private Map<String, Object> imageMap(VoucherImageRecord image) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("type", "image");
result.put("isFolder", false);
result.put("id", image.id());
result.put("imageName", image.fileName());
result.put("voucherBatchNo", image.voucherBatchNo());
result.put("waybillNo", image.waybillNo());
result.put("folderName", image.folderName());
result.put("objectKey", image.objectKey());
result.put("matched", image.matched());
try {
result.put("url", minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
.method(Method.GET).bucket(minioBucketName).object(image.objectKey())
.expiry(1, TimeUnit.HOURS).build()));
} catch (Exception exception) {
throw new IllegalStateException("生成凭证图片预览地址失败", exception);
}
return result;
}
private boolean visibleVoucher(VoucherManage voucher) {
return voucher == null || !"承运商".equals(voucher.getUploadSource()) || "审核通过".equals(voucher.getAuditStatus());
}
private boolean containsBatchNo(String batchNos, String batchNo) {
return Func.isNotEmpty(batchNos) && Func.isNotEmpty(batchNo)
&& java.util.Arrays.stream(batchNos.split(",")).map(String::trim).anyMatch(batchNo::equals);
}
private record VoucherImageRecord(Long id, String voucherBatchNo, String waybillNo, String fileName,
String folderName, String objectKey, Integer matched) {
private static VoucherImageRecord from(VoucherFile file) {
return new VoucherImageRecord(file.getId(), file.getVoucherBatchNo(), file.getWaybillNo(), file.getFileName(),
file.getFolderName(), file.getObjectKey(), file.getMatched());
}
private static VoucherImageRecord from(VoucherImage image) {
return new VoucherImageRecord(image.getId(), image.getVoucherBatchNo(), image.getWaybillNo(), image.getImageName(),
image.getPlateNo(), image.getObjectKey(), image.getMatched());
}
}
@GetMapping("/list")
@@ -98,8 +326,8 @@ public class ProcessConfigController extends BladeController {
@ApiOperationSupport(order = 5)
@Operation(summary = "导出过程配置")
public void exportProcessConfig(ProcessConfigVO processConfig, @RequestParam(required = false) String ids, HttpServletResponse response) {
List<ProcessConfigExcel> list = processConfigService.exportProcessConfig(processConfig, ids);
ExcelUtil.export(response, "过程配置" + DateUtil.time(), "过程配置", list, ProcessConfigExcel.class);
List<ProcessConfigExportExcel> list = processConfigService.exportProcessConfig(processConfig, ids);
ExcelUtil.export(response, "过程配置" + DateUtil.time(), "过程配置", list, ProcessConfigExportExcel.class);
}
@PostMapping("/copy")
@@ -48,6 +48,7 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 项目立项 控制器
@@ -70,6 +71,22 @@ public class ProjectApplyController extends BladeController {
return R.data(projectApplyService.detail(id));
}
@GetMapping("/fund-risk-stats")
@ApiOperationSupport(order = 2)
@Operation(summary = "资金使用风险统计", description = "传入项目筛选条件")
public R<Map<String, Integer>> fundRiskStats(ProjectApplyVO projectApply) {
return R.data(projectApplyService.fundRiskStats(projectApply));
}
@GetMapping("/change-record/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "变更记录详情", description = "传入项目ID和变更记录序号")
public R<Map<String, Object>> changeRecordDetail(
@Parameter(description = "项目ID", required = true) @RequestParam Long id,
@Parameter(description = "变更记录序号,从0开始", required = true) @RequestParam Integer recordIndex) {
return R.data(projectApplyService.changeRecordDetail(id, recordIndex));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入projectApply")
@@ -0,0 +1,90 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.ReceiptClaimAttachmentsRequest;
import org.springblade.transport.pojo.vo.ReceiptClaimRecordVO;
import org.springblade.transport.service.IReceiptClaimRecordService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
/**
* 认领记录控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "receipt_claim_record")
@RequestMapping("/receipt-claim-record")
@Tag(name = "认领记录", description = "当前用户收款认领记录查询与作废")
public class ReceiptClaimRecordController extends BladeController {
private final IReceiptClaimRecordService receiptClaimRecordService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "当前用户认领记录分页")
public R<IPage<ReceiptClaimRecordVO>> list(ReceiptClaimRecordVO query, Query pageQuery) {
return R.data(receiptClaimRecordService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "认领记录详情")
public R<ReceiptClaimRecordVO> detail(@RequestParam Long id) {
return R.data(receiptClaimRecordService.detail(id));
}
@PostMapping("/attachments")
@ApiOperationSupport(order = 3)
@Operation(summary = "维护本人认领记录附件")
public R<Void> updateAttachments(@RequestBody ReceiptClaimAttachmentsRequest request) {
receiptClaimRecordService.updateAttachments(request);
return R.success();
}
@PostMapping("/void")
@ApiOperationSupport(order = 4)
@Operation(summary = "作废认领记录并生成金蝶认领冲单")
public R<String> voidClaim(@RequestParam Long id) {
return R.data(receiptClaimRecordService.voidClaim(id));
}
}
@@ -0,0 +1,102 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.ReceiptClaimRequest;
import org.springblade.transport.pojo.dto.ReceiptFlowSyncRequest;
import org.springblade.transport.pojo.vo.ReceiptFlowVO;
import org.springblade.transport.service.IReceiptFlowService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* 收款流水控制器
*
* @author Chill
*/
@RestController
@AllArgsConstructor
@PreAuth(menu = "receipt_flow")
@RequestMapping("/receipt-flow")
@Tag(name = "收款流水", description = "金蝶收款流水同步与认领管理")
public class ReceiptFlowController extends BladeController {
private final IReceiptFlowService receiptFlowService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "收款流水分页")
public R<IPage<ReceiptFlowVO>> list(ReceiptFlowVO query, Query pageQuery) {
return R.data(receiptFlowService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "收款流水详情")
public R<ReceiptFlowVO> detail(@RequestParam Long id) {
return R.data(receiptFlowService.detail(id));
}
@GetMapping("/settlement-candidates")
@ApiOperationSupport(order = 3)
@Operation(summary = "可关联的应收正式结算单")
public R<List<Map<String, Object>>> settlementCandidates(
@RequestParam(required = false) String keyword,
@RequestParam Long flowId) {
return R.data(receiptFlowService.settlementCandidates(keyword, flowId));
}
@PostMapping("/claim")
@ApiOperationSupport(order = 4)
@Operation(summary = "认领收款流水")
public R<Long> claim(@RequestBody ReceiptClaimRequest request) {
return R.data(receiptFlowService.claim(request));
}
@PostMapping("/sync")
@ApiOperationSupport(order = 5)
@Operation(summary = "手动同步金蝶收款流水")
public R<Integer> sync(@RequestBody(required = false) ReceiptFlowSyncRequest request) {
return R.data(receiptFlowService.sync(request));
}
}
@@ -24,24 +24,28 @@ package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import cn.idev.excel.FastExcel;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import jakarta.servlet.http.HttpServletResponse;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.transport.pojo.dto.ReceivablePayableAdjustFeeRequest;
import org.springblade.transport.pojo.dto.ReceivablePayableFeeCalculateRequest;
import org.springblade.transport.pojo.dto.ReceivablePayableGenerateRequest;
import org.springblade.transport.pojo.dto.ReceivablePayableTransferRequest;
import org.springblade.transport.pojo.dto.ReceivablePayableUpdateFeeRequest;
import org.springblade.transport.pojo.vo.ReceivablePayableChangeRecordVO;
import org.springblade.transport.pojo.vo.ReceivablePayableCargoFeeVO;
import org.springblade.transport.pojo.vo.ReceivablePayableDetailVO;
import org.springblade.transport.pojo.vo.ReceivablePayableFeeDetailVO;
import org.springblade.transport.service.IReceivablePayableDetailService;
import org.springblade.system.cache.DictCache;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -49,7 +53,14 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* 应收应付明细控制器
@@ -94,17 +105,42 @@ public class ReceivablePayableDetailController extends BladeController {
return R.success("更新成功");
}
@GetMapping("/transfer-candidates")
@GetMapping("/update-fee-contracts")
@ApiOperationSupport(order = 5)
@Operation(summary = "更新费用可选合同")
public R<List<Map<String, Object>>> updateFeeContracts(
@RequestParam(required = false) String settlementType) {
return R.data(detailService.updateFeeContracts(settlementType));
}
@PostMapping("/adjust-fee")
@ApiOperationSupport(order = 6)
@Operation(summary = "调整费用")
public R adjustFee(@RequestBody ReceivablePayableAdjustFeeRequest request) {
detailService.adjustFee(request);
return R.success("保存成功");
}
@PostMapping("/calculate-adjusted-fee")
@ApiOperationSupport(order = 7)
@Operation(summary = "调整费用试算")
public R<ReceivablePayableCargoFeeVO> calculateAdjustedFee(
@RequestBody ReceivablePayableFeeCalculateRequest request) {
return R.data(detailService.calculateAdjustedFee(request));
}
@GetMapping("/transfer-candidates")
@ApiOperationSupport(order = 8)
@Operation(summary = "转结算候选明细")
public R<IPage<Map<String, Object>>> transferCandidates(Query query,
@RequestParam(required = false) String contractName,
@RequestParam(required = false) String batchNo,
@RequestParam(required = false) String generateStartDate,
@RequestParam(required = false) String generateEndDate,
@RequestParam(required = false) String settlementBillType) {
@RequestParam(required = false) String generateStartDate,
@RequestParam(required = false) String generateEndDate,
@RequestParam(required = false) String settlementBillType,
@RequestParam(required = false) String settlementType) {
return R.data(detailService.transferCandidates(Condition.getPage(query), contractName, batchNo,
generateStartDate, generateEndDate, settlementBillType));
generateStartDate, generateEndDate, settlementBillType, settlementType));
}
@PostMapping("/transfer-settlement")
@@ -141,7 +177,56 @@ public class ReceivablePayableDetailController extends BladeController {
@ApiOperationSupport(order = 10)
@Operation(summary = "导出应收应付明细")
public void exportReceivablePayableDetail(ReceivablePayableDetailVO query, HttpServletResponse response) {
IPage<ReceivablePayableDetailVO> page = detailService.selectPage(Condition.getPage(new Query()), query);
ExcelUtil.export(response, "应收应付明细" + DateUtil.time(), "应收应付明细", page.getRecords(), ReceivablePayableDetailVO.class);
List<ReceivablePayableDetailVO> records = detailService.selectList(query);
Set<String> feeItemNames = new LinkedHashSet<>();
records.forEach(row -> {
if (row.getFeeItems() != null) feeItemNames.addAll(row.getFeeItems().keySet());
});
List<List<String>> head = new ArrayList<>();
String[] baseHeaders = {"单据号", "项目名称", "所属组织", "费用日期", "客商名称", "合同编号", "合同名称", "来源",
"预结算单号", "正式结算单号", "运单号", "车号", "运输类型", "货物名称", "货物类型", "运输总量", "里程(KM",
"批次号", "运输单价"};
for (String header : baseHeaders) head.add(List.of(header));
feeItemNames.forEach(name -> head.add(List.of(name)));
for (String header : new String[] {"费用合计", "状态", "创建人", "创建时间"}) head.add(List.of(header));
List<List<Object>> rows = records.stream().map(row -> {
List<Object> values = new ArrayList<>();
values.add(row.getDocumentNo()); values.add(row.getProjectName()); values.add(row.getDeptName()); values.add(row.getFeeDate());
values.add(row.getCustomerName()); values.add(row.getContractNo()); values.add(row.getContractName()); values.add(row.getSourceType());
values.add(row.getPreSettlementNo()); values.add(row.getFormalSettlementNo()); values.add(row.getWaybillNo()); values.add(row.getVehicleNo());
values.add(transportTypeName(row.getTransportType())); values.add(row.getCargoName()); values.add(row.getCargoType());
values.add(row.getTransportQuantity()); values.add(row.getMileage() != null && row.getMileage().compareTo(BigDecimal.valueOf(-1)) == 0 ? null : row.getMileage());
values.add(row.getBatchNo()); values.add(money(row.getUnitPrice(), row.getCurrency()));
feeItemNames.forEach(name -> values.add(money(decimal(row.getFeeItems() == null ? null : row.getFeeItems().get(name)), row.getCurrency())));
values.add(money(row.getTotalAmount(), row.getCurrency())); values.add(row.getSettlementStatusName()); values.add(row.getCreateUserName()); values.add(row.getCreateTime());
return values;
}).toList();
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("应收应付明细" + DateUtil.time(), StandardCharsets.UTF_8) + ".xlsx");
try {
FastExcel.write(response.getOutputStream()).head(head).sheet("应收应付明细").doWrite(rows);
} catch (Exception exception) {
throw new IllegalStateException("导出应收应付明细失败", exception);
}
}
private String transportTypeName(String value) {
if (value == null || value.isBlank()) return value;
String name = DictCache.getValue("transport_type", value);
return name == null || name.isBlank() ? value : name;
}
private String money(BigDecimal value, String currency) {
if (value == null) return "-";
return value.setScale(2, java.math.RoundingMode.HALF_UP).toPlainString() + " " + (currency == null || currency.isBlank() ? "RMB" : currency);
}
private BigDecimal decimal(Object value) {
if (value == null || String.valueOf(value).isBlank()) return null;
try { return new BigDecimal(String.valueOf(value)); } catch (NumberFormatException ignored) { return null; }
}
}
@@ -0,0 +1,39 @@
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.SettlementAdjustmentSaveRequest;
import org.springblade.transport.pojo.dto.SettlementAdjustmentStatusRequest;
import org.springblade.transport.pojo.entity.SettlementAdjustment;
import org.springblade.transport.pojo.vo.SettlementAdjustmentVO;
import org.springblade.transport.service.IPreSettlementService;
import org.springblade.transport.service.ISettlementAdjustmentService;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.Map;
@RestController
@AllArgsConstructor
@PreAuth(menu = "settlement_adjustment")
@RequestMapping("/settlement-adjustment")
public class SettlementAdjustmentController extends BladeController {
private final ISettlementAdjustmentService service;
private final IPreSettlementService preSettlementService;
@GetMapping("/list") public R<IPage<SettlementAdjustmentVO>> list(SettlementAdjustmentVO query, Query page) { return R.data(service.selectPage(Condition.getPage(page), query)); }
@GetMapping("/detail") public R<SettlementAdjustmentVO> detail(@RequestParam Long id) { return R.data(service.detail(id)); }
@GetMapping("/candidate-formal-settlements") public R<List<Map<String, Object>>> candidates(@RequestParam(required = false) String keyword) { return R.data(service.candidateFormalSettlements(keyword)); }
@GetMapping("/formal-details") public R<List<Map<String, Object>>> formalDetails(@RequestParam Long formalSettlementId) { return R.data(service.formalDetails(formalSettlementId)); }
@GetMapping("/fee-options") public R<List<Map<String, Object>>> feeOptions() { return R.data(preSettlementService.feeOptions()); }
@PostMapping("/save") public R<Long> save(@RequestBody SettlementAdjustmentSaveRequest request) { return R.data(service.saveDraft(request)); }
@PostMapping("/remove") public R remove(@RequestParam Long id) { service.removeDraft(id); return R.success("删除成功"); }
@PostMapping("/submit") public R submit(@RequestBody SettlementAdjustmentStatusRequest request) { service.submit(request); return R.success("提交成功"); }
@PostMapping("/approve") public R approve(@RequestBody SettlementAdjustmentStatusRequest request) { service.approve(request); return R.success("审批通过"); }
@PostMapping("/return") public R returnBill(@RequestBody SettlementAdjustmentStatusRequest request) { service.returnBill(request); return R.success("已驳回"); }
@PostMapping("/repush") public R<String> repush(@RequestParam Long id) { return R.data(service.repush(id)); }
}
@@ -126,6 +126,21 @@ public class TransportPlanController extends BladeController {
ExcelUtil.export(response, "运输计划模板", "运输计划导入模板", List.of(template), TransportPlanImportExcel.class);
}
@PostMapping("/validate-transport-plan")
@ApiOperationSupport(order = 6)
@Operation(summary = "校验运输计划导入数据", description = "传入 Excel、项目和客户合同")
public R validateTransportPlan(MultipartFile file, @RequestParam Long projectId, @RequestParam String projectName,
@RequestParam Long contractId, @RequestParam String contractName, @RequestParam String customerName,
HttpServletResponse response) {
List<TransportPlanImportExcel> failureList = transportPlanService.validateTransportPlan(
ExcelUtil.read(file, TransportPlanImportExcel.class), projectId, projectName, contractId, contractName, customerName);
if (Func.isNotEmpty(failureList)) {
ImportFailureExcelUtil.export(response, "运输计划导入失败明细" + DateUtil.time(), "导入失败明细", failureList, TransportPlanImportExcel.class);
return null;
}
return R.success("校验通过");
}
@PostMapping("/import-transport-plan")
@ApiOperationSupport(order = 7)
@Operation(summary = "导入运输计划", description = "传入 Excel、项目和客户合同")
@@ -0,0 +1,217 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.</p>
* <p>Author: Chill Zhuang (bladejava@qq.com)</p>
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.springblade.common.excel.ImportFailureExcelUtil;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.transport.excel.CargoReconciliationExcel;
import org.springblade.transport.excel.CargoReconciliationFeeReader;
import org.springblade.transport.excel.CargoReconciliationFailureExcel;
import org.springblade.transport.excel.ReconciliationImportTemplateExcel;
import org.springblade.transport.excel.VehicleReconciliationExcel;
import org.springblade.transport.excel.VehicleReconciliationFeeReader;
import org.springblade.transport.excel.VehicleReconciliationFailureExcel;
import org.springblade.transport.excel.TransportReconciliationExportExcel;
import org.springblade.transport.pojo.dto.TransportReconciliationManualMatchRequest;
import org.springblade.transport.pojo.dto.TransportReconciliationSaveRequest;
import org.springblade.transport.pojo.entity.FormalSettlement;
import org.springblade.transport.pojo.entity.TransportReconciliationInternal;
import org.springblade.transport.pojo.vo.TransportReconciliationVO;
import org.springblade.transport.service.ITransportReconciliationService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import jakarta.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Map;
/** 运输对账单控制器。 @author Chill */
@RestController
@AllArgsConstructor
@PreAuth(menu = "transport_reconciliation")
@RequestMapping("/transport-reconciliation")
@Tag(name = "运输对账", description = "运输对账管理")
public class TransportReconciliationController extends BladeController {
private final ITransportReconciliationService reconciliationService;
@GetMapping("/list")
@ApiOperationSupport(order = 1)
@Operation(summary = "运输对账分页")
public R<IPage<TransportReconciliationVO>> list(TransportReconciliationVO query, Query pageQuery) {
return R.data(reconciliationService.selectPage(Condition.getPage(pageQuery), query));
}
@GetMapping("/export")
@ApiOperationSupport(order = 15)
@Operation(summary = "导出运输对账单")
public void export(TransportReconciliationVO query, @RequestParam(required = false) String ids,
HttpServletResponse response) {
query.setIds(ids);
IPage<TransportReconciliationVO> page = reconciliationService.selectPage(new Page<>(1, 100000), query);
List<TransportReconciliationExportExcel> rows = page.getRecords().stream().map(this::toExcel).toList();
ExcelUtil.export(response, "运输对账" + DateUtil.time(), "运输对账", rows, TransportReconciliationExportExcel.class);
}
private TransportReconciliationExportExcel toExcel(TransportReconciliationVO vo) {
TransportReconciliationExportExcel excel = new TransportReconciliationExportExcel();
excel.setReconciliationNo(vo.getReconciliationNo());
excel.setPayerName(vo.getPayerName());
excel.setPayeeName(vo.getPayeeName());
excel.setProjectName(vo.getProjectName());
excel.setDeptName(vo.getDeptName());
excel.setContractNo(vo.getContractNo());
excel.setContractName(vo.getContractName());
excel.setSettlementAmount(formatMoney(vo.getSettlementAmount()));
excel.setReconciliationModeName(vo.getReconciliationModeName());
excel.setExternalBillCount(vo.getExternalBillCount());
excel.setMatchedCount(vo.getMatchedCount());
excel.setReconciliationStatusName(vo.getReconciliationStatusName());
excel.setCreateUserName(vo.getCreateUserName());
excel.setCreateTime(vo.getCreateTime());
return excel;
}
private String formatMoney(BigDecimal value) {
return value == null ? "0.00" : value.setScale(2, RoundingMode.HALF_UP).toPlainString();
}
@GetMapping("/detail")
@ApiOperationSupport(order = 2)
@Operation(summary = "运输对账详情")
public R<TransportReconciliationVO> detail(@RequestParam Long id) { return R.data(reconciliationService.detail(id)); }
@GetMapping("/formal-options")
@ApiOperationSupport(order = 3)
@Operation(summary = "可选正式结算单")
public R<IPage<FormalSettlement>> formalOptions(Query pageQuery, @RequestParam(required = false) String settlementType,
@RequestParam(required = false) String keyword) {
return R.data(reconciliationService.formalOptions(Condition.getPage(pageQuery), settlementType, keyword));
}
@PostMapping("/save")
@ApiOperationSupport(order = 4)
@Operation(summary = "保存运输对账草稿")
public R<Long> save(@RequestBody TransportReconciliationSaveRequest request) { return R.data(reconciliationService.saveDraft(request)); }
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@Operation(summary = "删除运输对账草稿")
public R remove(@RequestParam Long id) { reconciliationService.removeDraft(id); return R.success("删除成功"); }
@PostMapping("/import-vehicle")
@ApiOperationSupport(order = 6)
@Operation(summary = "导入整车总额外部账单")
public R importVehicle(@RequestParam Long id, MultipartFile file, HttpServletResponse response) {
List<VehicleReconciliationExcel> rows = ExcelUtil.read(file, VehicleReconciliationExcel.class);
List<Map<String, BigDecimal>> feeItems = VehicleReconciliationFeeReader.read(file);
for (int index = 0; index < rows.size() && index < feeItems.size(); index++) rows.get(index).setFeeItems(feeItems.get(index));
List<VehicleReconciliationFailureExcel> failures = reconciliationService.importVehicles(id, rows);
if (!failures.isEmpty()) {
ImportFailureExcelUtil.export(response, "运输对账导入失败明细" + DateUtil.time(), "导入失败明细", failures, VehicleReconciliationFailureExcel.class);
return null;
}
return R.success("导入数据成功");
}
@PostMapping("/import-cargo")
@ApiOperationSupport(order = 7)
@Operation(summary = "导入货物明细外部账单")
public R importCargo(@RequestParam Long id, MultipartFile file, HttpServletResponse response) {
List<CargoReconciliationExcel> rows = ExcelUtil.read(file, CargoReconciliationExcel.class);
List<Map<String, BigDecimal>> feeItems = CargoReconciliationFeeReader.read(file);
for (int index = 0; index < rows.size() && index < feeItems.size(); index++) rows.get(index).setFeeItems(feeItems.get(index));
List<CargoReconciliationFailureExcel> failures = reconciliationService.importCargoes(id, rows);
if (!failures.isEmpty()) {
ImportFailureExcelUtil.export(response, "运输对账导入失败明细" + DateUtil.time(), "导入失败明细", failures, CargoReconciliationFailureExcel.class);
return null;
}
return R.success("导入数据成功");
}
@GetMapping("/template")
@ApiOperationSupport(order = 8)
@Operation(summary = "下载运输对账模板")
public void template(@RequestParam String mode, @RequestParam(required = false) Long id,
@RequestParam(required = false) Long formalSettlementId, @RequestParam(required = false) String feeItems,
HttpServletResponse response) {
List<String> extraFeeItems = reconciliationService.templateFeeItems(id, formalSettlementId, feeItems);
if ("cargo".equals(mode)) ReconciliationImportTemplateExcel.exportCargo(response, extraFeeItems);
else ReconciliationImportTemplateExcel.exportVehicle(response, extraFeeItems);
}
@PostMapping("/match")
@ApiOperationSupport(order = 9)
@Operation(summary = "自动匹配内部账单")
public R match(@RequestParam Long id) { reconciliationService.autoMatch(id); return R.success("匹配完成"); }
@PostMapping("/match-preview")
@ApiOperationSupport(order = 9)
@Operation(summary = "预览自动匹配内部账单")
public R<TransportReconciliationVO> matchPreview(@RequestBody TransportReconciliationVO request) {
return R.data(reconciliationService.matchPreview(request));
}
@PostMapping("/manual-match")
@ApiOperationSupport(order = 10)
@Operation(summary = "人工匹配账单明细")
public R manualMatch(@RequestBody TransportReconciliationManualMatchRequest request) { reconciliationService.manualMatch(request); return R.success("人工匹配成功"); }
@PostMapping("/unmatch")
@ApiOperationSupport(order = 11)
@Operation(summary = "取消明细匹配")
public R unmatch(@RequestParam Long internalId) { reconciliationService.unmatch(internalId); return R.success("已取消匹配"); }
@PostMapping("/adjust")
@ApiOperationSupport(order = 12)
@Operation(summary = "调整内部账单明细")
public R adjust(@RequestBody TransportReconciliationInternal row) { reconciliationService.adjustInternal(row); return R.success("调整成功"); }
@PostMapping("/update-by-match")
@ApiOperationSupport(order = 13)
@Operation(summary = "按匹配结果更新账单")
public R updateByMatch(@RequestParam Long id,
@RequestBody(required = false) TransportReconciliationVO request) {
if (request == null) {
request = new TransportReconciliationVO();
}
request.setId(id);
reconciliationService.updateByMatch(request);
return R.success("账单更新完成");
}
@PostMapping("/complete")
@ApiOperationSupport(order = 14)
@Operation(summary = "完成运输对账")
public R complete(@RequestParam Long id) { reconciliationService.complete(id); return R.success("对账单确认完成"); }
@PostMapping("/complete-with-data")
@ApiOperationSupport(order = 14)
@Operation(summary = "保存明细并完成运输对账")
public R<TransportReconciliationVO> completeWithData(@RequestBody TransportReconciliationVO request) {
return R.data(reconciliationService.completeWithData(request));
}
}
@@ -0,0 +1,105 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.transport.excel.VehicleDispatchExcel;
import org.springblade.transport.pojo.entity.VehicleDispatch;
import org.springblade.transport.pojo.vo.VehicleDispatchVO;
import org.springblade.transport.service.IVehicleDispatchService;
import org.springblade.transport.wrapper.VehicleDispatchWrapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/** 车辆调度申请控制器。 */
@RestController
@AllArgsConstructor
@PreAuth(menu = "vehicle_dispatch")
@RequestMapping("/vehicle-dispatch")
@Tag(name = "车辆调度", description = "车辆调度申请")
public class VehicleDispatchController extends BladeController {
private final IVehicleDispatchService vehicleDispatchService;
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@Operation(summary = "详情")
public R<VehicleDispatchVO> detail(@Parameter(description = "主键", required = true) @RequestParam Long id) {
VehicleDispatch entity = vehicleDispatchService.getById(id);
if (entity == null) return R.fail("记录不存在");
return R.data(VehicleDispatchWrapper.build().entityVO(entity));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页")
public R<IPage<VehicleDispatchVO>> list(VehicleDispatchVO dispatch, Query query) {
return R.data(vehicleDispatchService.selectVehicleDispatchPage(Condition.getPage(query), dispatch));
}
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "新增或修改")
public R submit(@RequestBody VehicleDispatch dispatch) {
return R.status(vehicleDispatchService.submit(dispatch));
}
@PostMapping("/submit-approval")
@ApiOperationSupport(order = 4)
@Operation(summary = "提交审批")
public R submitApproval(@RequestParam Long id) {
return R.status(vehicleDispatchService.submitApproval(id));
}
@PostMapping("/approve")
@ApiOperationSupport(order = 5)
@Operation(summary = "审批通过")
public R approve(@RequestParam Long id) {
return R.status(vehicleDispatchService.approve(id));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 6)
@Operation(summary = "逻辑删除")
public R remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.status(vehicleDispatchService.deleteLogic(Func.toLongList(ids)));
}
@GetMapping("/export-vehicle-dispatch")
@ApiOperationSupport(order = 7)
@Operation(summary = "导出车辆调度")
public void export(VehicleDispatchVO dispatch, HttpServletResponse response) {
List<VehicleDispatchExcel> list = vehicleDispatchService.exportList(dispatch).stream().map(VehicleDispatchExcel::from).toList();
ExcelUtil.export(response, "车辆调度" + DateUtil.time(), "车辆调度", list, VehicleDispatchExcel.class);
}
}
@@ -10,11 +10,14 @@ import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.annotation.PreAuth;
import org.springblade.core.tool.api.R;
import org.springblade.transport.pojo.dto.VoucherManageChangeBatchRequest;
import org.springblade.transport.pojo.dto.VoucherManageSubmitRequest;
import org.springblade.transport.pojo.dto.VoucherUploadDraftRequest;
import org.springblade.transport.pojo.dto.VoucherFileCompleteRequest;
import org.springblade.transport.pojo.entity.VoucherManage;
import org.springblade.transport.pojo.vo.VoucherManageVO;
import org.springblade.transport.pojo.vo.VoucherFolderVO;
import org.springframework.web.multipart.MultipartFile;
import org.springblade.transport.service.IVoucherManageService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -46,13 +49,58 @@ public class VoucherManageController extends BladeController {
@Operation(summary = "凭证详情")
public R<VoucherManageVO> detail(@RequestParam Long id) { return R.data(voucherManageService.detail(id)); }
@GetMapping("/folder-page")
@Operation(summary = "执行凭证文件夹分页")
public R<IPage<VoucherFolderVO>> folderPage(@RequestParam Long voucherId, Query query,
@RequestParam(required = false) String plateNo, @RequestParam(required = false) Integer matched) {
return R.data(voucherManageService.folderPage(Condition.getPage(query), voucherId, plateNo, matched));
}
@GetMapping("/folder-detail")
@Operation(summary = "执行凭证文件夹详情")
public R<VoucherFolderVO> folderDetail(@RequestParam Long voucherId, @RequestParam String plateNo) {
return R.data(voucherManageService.folderDetail(voucherId, plateNo));
}
@PostMapping(value = "/folder-replace", consumes = "multipart/form-data")
@Operation(summary = "替换单个车牌凭证")
public R replaceFolder(@RequestParam Long voucherId, @RequestParam String plateNo,
@RequestParam("file") MultipartFile file) {
voucherManageService.replaceFolder(voucherId, plateNo, file);
return R.success("上传成功");
}
@PostMapping("/folder-replace-object")
@Operation(summary = "替换单个车牌凭证(分片上传文件处理)")
public R replaceFolderByObject(@RequestParam Long voucherId, @RequestParam String plateNo,
@RequestParam String objectKey, @RequestParam String fileName,
@RequestParam(required = false) Long size, @RequestParam(required = false) String contentType) {
voucherManageService.replaceFolderByObject(voucherId, plateNo, objectKey, fileName, size, contentType);
return R.success("处理成功");
}
@PostMapping("/folder-remove")
@Operation(summary = "删除车牌凭证")
public R removeFolder(@RequestParam Long voucherId, @RequestParam String plateNo) {
voucherManageService.removeFolder(voucherId, plateNo);
return R.success("删除成功");
}
@PostMapping("/submit")
@ApiOperationSupport(order = 3)
@Operation(summary = "上传凭证或更换运输批次")
public R submit(@RequestBody VoucherManageSubmitRequest request) { voucherManageService.submit(request); return R.success("提交成功"); }
@PostMapping("/upload-draft")
@PostMapping("/change-waybill-batch")
@ApiOperationSupport(order = 4)
@Operation(summary = "更换运单批次并重新匹配凭证")
public R changeWaybillBatch(@RequestBody VoucherManageChangeBatchRequest request) {
voucherManageService.changeWaybillBatch(request);
return R.success("运单批次更换成功");
}
@PostMapping("/upload-draft")
@ApiOperationSupport(order = 5)
@Operation(summary = "创建凭证上传草稿")
public R<VoucherManage> createUploadDraft(@RequestBody VoucherUploadDraftRequest request) {
return R.data(voucherManageService.createUploadDraft(request));
@@ -65,17 +113,40 @@ public class VoucherManageController extends BladeController {
return R.success("文件已更新");
}
@PostMapping("/reprocess")
@Operation(summary = "重新处理已上传凭证")
public R reprocess(@RequestParam Long id) {
voucherManageService.reprocessUploadedVoucher(id);
return R.success("重新处理完成");
}
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@ApiOperationSupport(order = 6)
@Operation(summary = "删除凭证")
public R remove(@RequestParam Long id) { voucherManageService.removeVoucher(id); return R.success("删除成功"); }
@GetMapping("/waybill-batches")
@ApiOperationSupport(order = 6)
@ApiOperationSupport(order = 7)
@Operation(summary = "可关联运输批次")
public R<IPage<Map<String, Object>>> waybillBatches(Query query, @RequestParam(required = false) String batchNo,
@RequestParam(required = false) String createUser, @RequestParam(required = false) Integer waybillCount,
@RequestParam(required = false) String createTimeStart, @RequestParam(required = false) String createTimeEnd) {
return R.data(voucherManageService.selectableWaybillBatches(Condition.getPage(query), batchNo, createUser, waybillCount, createTimeStart, createTimeEnd));
}
@PostMapping("/audit-pass")
@ApiOperationSupport(order = 8)
@Operation(summary = "审核通过")
public R auditPass(@RequestParam Long id) {
voucherManageService.auditPass(id);
return R.success("审核通过");
}
@PostMapping("/audit-reject")
@ApiOperationSupport(order = 9)
@Operation(summary = "审核驳回")
public R auditReject(@RequestParam Long id, @RequestParam(required = false) String rejectReason) {
voucherManageService.auditReject(id, rejectReason);
return R.success("审核驳回");
}
}
@@ -24,11 +24,15 @@ package org.springblade.transport.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import cn.idev.excel.write.handler.SheetWriteHandler;
import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletResponse;
import lombok.AllArgsConstructor;
import org.apache.poi.ss.usermodel.CellStyle;
import org.springblade.common.excel.ImportFailureExcelUtil;
import org.springblade.core.boot.ctrl.BladeController;
import org.springblade.core.excel.util.ExcelUtil;
@@ -45,14 +49,21 @@ import org.springblade.transport.pojo.entity.CustomerArchive;
import org.springblade.transport.pojo.entity.ProjectApply;
import org.springblade.transport.pojo.entity.TransportPlan;
import org.springblade.transport.pojo.entity.Waybill;
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.WaybillLocateVO;
import org.springblade.transport.pojo.vo.WaybillTrackVO;
import org.springblade.transport.pojo.vo.WaybillPunchRecordsVO;
import org.springblade.transport.pojo.vo.WaybillVO;
import org.springblade.transport.pojo.dto.WaybillMileageRequest;
import org.springblade.transport.service.IContractManageService;
import org.springblade.transport.service.ICustomerArchiveService;
import org.springblade.transport.service.IProjectApplyService;
import org.springblade.transport.service.ITransportPlanService;
import org.springblade.transport.service.IWaybillService;
import org.springblade.transport.service.IWaybillImportBatchService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -83,6 +94,7 @@ public class WaybillController extends BladeController {
private final IContractManageService contractManageService;
private final ICustomerArchiveService customerArchiveService;
private final ITransportPlanService transportPlanService;
private final IWaybillImportBatchService waybillImportBatchService;
@GetMapping("/detail")
@ApiOperationSupport(order = 1)
@@ -91,6 +103,31 @@ public class WaybillController extends BladeController {
return R.data(waybillService.detail(id));
}
@GetMapping("/punch-records")
@ApiOperationSupport(order = 1)
@Operation(summary = "打卡记录与司机上传", description = "返回节点/在途打卡流水,以及司机上传凭证图(label=节点-凭证类型)")
public R<WaybillPunchRecordsVO> punchRecords(
@Parameter(description = "运单ID", required = true) @RequestParam Long waybillId) {
return R.data(waybillService.listPunchRecords(waybillId));
}
@PostMapping("/locate")
@ApiOperationSupport(order = 1)
@Operation(summary = "车辆实时定位", description = "按运单绑定车牌调用 LBS_LOCATE")
public R<WaybillLocateVO> locate(@Parameter(description = "运单ID", required = true) @RequestParam Long id) {
return R.data(waybillService.locateVehicle(id));
}
@PostMapping("/track")
@ApiOperationSupport(order = 1)
@Operation(summary = "车辆历史轨迹", description = "按运单绑定车牌 + 日期区间调用 LBS_TRACK")
public R<WaybillTrackVO> track(
@Parameter(description = "运单ID", required = true) @RequestParam Long id,
@Parameter(description = "开始日期 YYYY-MM-DD", required = true) @RequestParam String startDate,
@Parameter(description = "结束日期 YYYY-MM-DD", required = true) @RequestParam String endDate) {
return R.data(waybillService.trackVehicle(id, startDate, endDate));
}
@GetMapping("/list")
@ApiOperationSupport(order = 2)
@Operation(summary = "分页", description = "传入waybill")
@@ -122,22 +159,79 @@ public class WaybillController extends BladeController {
return R.data(options);
}
@PostMapping("/submit")
@GetMapping("/import-batch/next-code")
@ApiOperationSupport(order = 4)
@Operation(summary = "下一个运单批次号")
public R<String> importBatchNextCode() {
return R.data(waybillImportBatchService.nextBatchNo());
}
@GetMapping("/import-batch/list")
@ApiOperationSupport(order = 5)
@Operation(summary = "运单批量导入批次分页")
public R<IPage<WaybillImportBatchVO>> importBatchList(WaybillImportBatchRequest request, Query query) {
return R.data(waybillImportBatchService.page(Condition.getPage(query), request));
}
@GetMapping("/import-batch/details")
@ApiOperationSupport(order = 5)
@Operation(summary = "运单批量导入明细分页")
public R<IPage<WaybillVO>> importBatchDetails(@RequestParam Long batchId, WaybillVO waybill, Query query) {
waybill.setImportBatchId(batchId);
return R.data(waybillService.selectWaybillPage(Condition.getPage(query), waybill));
}
@PostMapping("/import-batch/draft")
@ApiOperationSupport(order = 6)
@Operation(summary = "保存运单批量导入草稿")
public R saveImportBatchDraft(@RequestBody WaybillImportBatchRequest request) {
return R.data(waybillImportBatchService.saveDraft(request));
}
@PostMapping("/import-batch/validate")
@ApiOperationSupport(order = 6)
@Operation(summary = "校验运单批量导入数据")
public void validateImportBatch(@RequestBody WaybillImportBatchRequest request, HttpServletResponse response) {
waybillImportBatchService.validate(request, response);
}
@PostMapping("/import-batch/confirm")
@ApiOperationSupport(order = 7)
@Operation(summary = "确认运单批量导入")
public void confirmImportBatch(@RequestBody WaybillImportBatchRequest request, HttpServletResponse response) {
waybillImportBatchService.confirm(request, response);
}
@PostMapping("/import-batch/remove")
@ApiOperationSupport(order = 8)
@Operation(summary = "删除运单批量导入批次")
public R<BusinessRemoveResultVO> removeImportBatches(@RequestParam String ids) {
return R.data(waybillImportBatchService.removeBatches(ids));
}
@PostMapping("/submit")
@ApiOperationSupport(order = 9)
@Operation(summary = "新增或修改", description = "传入waybill")
public R submit(@RequestBody Waybill waybill) {
return R.status(waybillService.submit(waybill));
}
@PostMapping("/save-draft")
@ApiOperationSupport(order = 10)
@Operation(summary = "保存草稿", description = "传入waybill")
public R saveDraft(@RequestBody Waybill waybill) {
return R.status(waybillService.saveDraft(waybill));
}
@PostMapping("/remove")
@ApiOperationSupport(order = 5)
@ApiOperationSupport(order = 11)
@Operation(summary = "逻辑删除", description = "传入ids")
public R<BusinessRemoveResultVO> remove(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(waybillService.removeWaybill(ids));
}
@GetMapping("/export-waybill-manage")
@ApiOperationSupport(order = 6)
@ApiOperationSupport(order = 12)
@Operation(summary = "导出运单管理")
public void exportWaybill(WaybillVO waybill, @RequestParam(required = false) String ids, HttpServletResponse response) {
List<WaybillExcel> list = waybillService.exportWaybill(waybill, ids);
@@ -145,7 +239,7 @@ public class WaybillController extends BladeController {
}
@PostMapping("/import-waybill-manage")
@ApiOperationSupport(order = 7)
@ApiOperationSupport(order = 13)
@Operation(summary = "导入运单管理", description = "传入excel")
public R importWaybill(MultipartFile file, HttpServletResponse response) {
List<WaybillExcel> failureList = waybillService.importWaybill(ExcelUtil.read(file, WaybillExcel.class));
@@ -157,56 +251,77 @@ public class WaybillController extends BladeController {
}
@GetMapping("/export-template")
@ApiOperationSupport(order = 8)
@ApiOperationSupport(order = 14)
@Operation(summary = "导出模板")
public void exportTemplate(HttpServletResponse response) {
ExcelUtil.export(response, "运单管理模板", "运单管理导入模板", new ArrayList<WaybillExcel>(), WaybillExcel.class);
}
@GetMapping("/import-batch/export-template")
@ApiOperationSupport(order = 9)
@ApiOperationSupport(order = 15)
@Operation(summary = "导出运单批量导入模板")
public void exportImportBatchTemplate(HttpServletResponse response) {
ExcelUtil.export(response, "运单批量导入模板", "运单批量导入模板", new ArrayList<WaybillImportBatchExcel>(), WaybillImportBatchExcel.class);
ExcelUtil.export(
response,
"运单批量导入模板",
"运单批量导入模板",
new ArrayList<WaybillImportBatchExcel>(),
new TextColumnStyleHandler(13, 14),
WaybillImportBatchExcel.class
);
}
@PostMapping("/copy")
@ApiOperationSupport(order = 10)
@ApiOperationSupport(order = 16)
@Operation(summary = "复制", description = "传入id")
public R<WaybillVO> copy(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.data(waybillService.copy(id));
}
@PostMapping("/change-route")
@ApiOperationSupport(order = 17)
@Operation(summary = "变更运输路线", description = "传入运单路线与变更记录")
public R changeRoute(@RequestBody Waybill waybill) {
return R.status(waybillService.changeRoute(waybill));
}
@PostMapping("/maintain-mileage")
@ApiOperationSupport(order = 18)
@Operation(summary = "维护里程", description = "仅已完成且未生成结算单的运单允许维护")
public R maintainMileage(@RequestBody WaybillMileageRequest request) {
return R.status(waybillService.maintainMileage(request));
}
@PostMapping("/cancel")
@ApiOperationSupport(order = 11)
@ApiOperationSupport(order = 19)
@Operation(summary = "取消", description = "传入id")
public R cancel(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.cancel(id));
}
@PostMapping("/reassign")
@ApiOperationSupport(order = 12)
@Operation(summary = "重新派单", description = "传入id")
public R reassign(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.reassign(id));
@ApiOperationSupport(order = 20)
@Operation(summary = "重新派单", description = "传入运单ID及新的司机、手机号、车牌")
public R reassign(@RequestBody Waybill waybill) {
return R.status(waybillService.reassign(waybill));
}
@PostMapping("/complete")
@ApiOperationSupport(order = 13)
@ApiOperationSupport(order = 21)
@Operation(summary = "完成", description = "传入id")
public R complete(@Parameter(description = "主键", required = true) @RequestParam Long id) {
return R.status(waybillService.complete(id));
}
@PostMapping("/batch-complete")
@ApiOperationSupport(order = 14)
@ApiOperationSupport(order = 22)
@Operation(summary = "批量完成", description = "传入ids")
public R<BusinessRemoveResultVO> batchComplete(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(waybillService.batchComplete(ids));
}
@PostMapping("/road-loading")
@ApiOperationSupport(order = 15)
@ApiOperationSupport(order = 23)
@Operation(summary = "公路配载", description = "传入ids")
public R<LoadingManageVO> roadLoading(@Parameter(description = "主键集合", required = true) @RequestParam String ids) {
return R.data(waybillService.roadLoading(ids));
@@ -222,4 +337,23 @@ public class WaybillController extends BladeController {
return option;
}
private static final class TextColumnStyleHandler implements SheetWriteHandler {
private final int[] columnIndexes;
private TextColumnStyleHandler(int... columnIndexes) {
this.columnIndexes = columnIndexes;
}
@Override
public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) {
CellStyle textStyle = writeWorkbookHolder.getWorkbook().createCellStyle();
short textFormat = writeWorkbookHolder.getWorkbook().createDataFormat().getFormat("@");
textStyle.setDataFormat(textFormat);
for (int columnIndex : columnIndexes) {
writeSheetHolder.getSheet().setDefaultColumnStyle(columnIndex, textStyle);
}
}
}
}
@@ -0,0 +1,24 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.event;
import org.springframework.context.ApplicationEvent;
/**
* 凭证压缩包上传完成事件。
*/
public class VoucherUploadCompletedEvent extends ApplicationEvent {
private final Long voucherId;
public VoucherUploadCompletedEvent(Long voucherId) {
super(voucherId);
this.voucherId = voucherId;
}
public Long getVoucherId() {
return voucherId;
}
}
@@ -0,0 +1,43 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.</p>
* <p>Author: Chill Zhuang (bladejava@qq.com)</p>
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Map;
/** 货物明细对账导入模型。 @author Chill */
@Data
@ColumnWidth(22)
public class CargoReconciliationExcel implements Serializable {
@Serial private static final long serialVersionUID = 1L;
@ExcelProperty("车牌号") private String vehicleNo;
@ExcelProperty("发货地址") private String departureAddress;
@ExcelProperty("到货地址") private String arrivalAddress;
@ExcelProperty("实际发货时间") private String actualDepartureTime;
@ExcelProperty("实际完成时间") private String actualCompletionTime;
@ExcelProperty("货物名称") private String cargoName;
@ExcelProperty("货物类型") private String cargoType;
@ExcelProperty("规格") private String specification;
@ExcelProperty("型号") private String model;
@ExcelProperty("运输总量") @NumberFormat("0.000000") private BigDecimal transportQuantity;
@ExcelProperty("运输单价") @NumberFormat("0.00") private BigDecimal unitPrice;
@ExcelProperty("里程(KM") @NumberFormat("0.00") private BigDecimal mileage;
@ExcelProperty("运输费") @NumberFormat("0.00") private BigDecimal freightAmount;
@ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemOne;
@ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemTwo;
@ExcelProperty("结算费用合计") @NumberFormat("0.00") private BigDecimal settlementAmount;
@ExcelIgnore private Map<String, BigDecimal> feeItems;
@ExcelIgnore private String errorMessage;
}
@@ -0,0 +1,13 @@
/** BladeX Commercial License Agreement. Copyright (c) 2018-2099, https://bladex.cn. Author: Chill Zhuang. */
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/** 货物明细对账导入失败模型。 @author Chill */
@Data
@EqualsAndHashCode(callSuper = true)
public class CargoReconciliationFailureExcel extends CargoReconciliationExcel {
@ExcelProperty("导入失败原因") private String errorMessage;
}
@@ -0,0 +1,106 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.FastExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import cn.idev.excel.metadata.data.ReadCellData;
import org.springblade.core.log.exception.ServiceException;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** 货物明细对账动态费用读取器。 @author Chill */
public final class CargoReconciliationFeeReader {
private CargoReconciliationFeeReader() {
}
public static List<Map<String, BigDecimal>> read(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
FeeListener listener = new FeeListener();
FastExcel.read(inputStream)
.useDefaultListener(false)
.registerReadListener(listener)
.sheet()
.doRead();
return listener.getFeeItems();
} catch (IOException exception) {
throw new ServiceException("读取货物明细对账费用列失败");
}
}
private static final class FeeListener extends AnalysisEventListener<Map<Integer, ReadCellData<?>>> {
private final List<Map<String, BigDecimal>> feeItems = new ArrayList<>();
private Map<Integer, String> headers = Map.of();
private int freightColumn = -1;
private int settlementColumn = -1;
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
headers = headMap;
freightColumn = findColumn("运输费");
settlementColumn = findColumn("结算费用合计");
}
@Override
public void invoke(Map<Integer, ReadCellData<?>> row, AnalysisContext context) {
Map<String, BigDecimal> values = new LinkedHashMap<>();
if (freightColumn >= 0 && settlementColumn > freightColumn) {
for (int column = freightColumn + 1; column < settlementColumn; column++) {
String name = headers.get(column);
if (name != null && !name.isBlank()) values.put(name.trim(), decimal(row.get(column)));
}
}
feeItems.add(values);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
private int findColumn(String header) {
return headers.entrySet().stream()
.filter(entry -> header.equals(entry.getValue()))
.mapToInt(Map.Entry::getKey)
.findFirst().orElse(-1);
}
private BigDecimal decimal(ReadCellData<?> cellData) {
if (cellData == null) return BigDecimal.ZERO.setScale(2);
Object value = cellData.getData();
if (value == null) {
value = switch (cellData.getType()) {
case NUMBER -> cellData.getNumberValue();
case STRING, DIRECT_STRING, ERROR -> cellData.getStringValue();
case BOOLEAN -> cellData.getBooleanValue();
default -> null;
};
}
if (value == null || String.valueOf(value).isBlank()) return BigDecimal.ZERO.setScale(2);
try {
return new BigDecimal(String.valueOf(value).trim()).setScale(2);
} catch (NumberFormatException exception) {
return BigDecimal.ZERO.setScale(2);
}
}
private List<Map<String, BigDecimal>> getFeeItems() {
return feeItems;
}
}
}
@@ -1,99 +1,99 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 常用地址 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(18)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonAddressExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelIgnore
private Long id;
@ExcelProperty("地址名称")
private String addressName;
@ExcelProperty("地址编号")
private String addressCode;
@ExcelProperty("类型")
private String addressType;
@ExcelProperty("站点编码")
private String siteCodeDisplay;
@ExcelProperty("详细地址")
private String detailAddress;
@ExcelProperty("经度")
private BigDecimal longitude;
@ExcelProperty("纬度")
private BigDecimal latitude;
@ExcelProperty("行政区划")
private String regionName;
@ExcelProperty("联系人")
private String contactName;
@ExcelProperty("联系方式")
private String contactPhone;
@ExcelProperty("组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 常用地址导出 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(18)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonAddressExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelIgnore
private Long id;
@ExcelProperty("地址名称")
private String addressName;
@ExcelProperty("地址编号")
private String addressCode;
@ExcelProperty("类型")
private String addressType;
@ExcelProperty("站点编码")
private String siteCodeDisplay;
@ExcelProperty("详细地址")
private String detailAddress;
@ExcelProperty("经度")
private BigDecimal longitude;
@ExcelProperty("纬度")
private BigDecimal latitude;
@ExcelProperty("行政区划")
private String regionName;
@ExcelProperty("联系人")
private String contactName;
@ExcelProperty("联系方式")
private String contactPhone;
@ExcelProperty("组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -49,46 +49,43 @@ public class CommonCargoExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("*一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("*二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("*货物名称")
private String cargoName;
@ExcelProperty("*货物编号后缀")
private String cargoCodeSuffix;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("*一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("*二级货物类型")
private String secondCargoTypeName;
@ExcelProperty("*二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("包装")
private String packageType;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("单价")
@NumberFormat("0.00")
private BigDecimal cargoValue;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("型号")
private String model;
@ExcelProperty("说明1")
@ExcelProperty("说明")
private String descriptionOne;
@ExcelProperty("尺寸")
private String sizeText;
@ExcelProperty("说明2")
private String descriptionTwo;
@ExcelProperty("备注")
private String remark;
@@ -1,107 +1,104 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 常用货物导出 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(24)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonCargoExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("货物编号")
private String cargoCode;
@ExcelProperty("一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("二级货物类型")
private String secondCargoTypeName;
@ExcelProperty("二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("包装品牌")
private String packageBrand;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("单价")
@NumberFormat("0.00")
private BigDecimal cargoValue;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("尺寸")
private String sizeText;
@ExcelProperty("其他说明1")
private String descriptionOne;
@ExcelProperty("其他说明2")
private String descriptionTwo;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("组织")
private String deptName;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 常用货物导出 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(24)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonCargoExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("货物编号后缀")
private String cargoCodeSuffix;
@ExcelProperty("一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("二级货物类型")
private String secondCargoTypeName;
@ExcelProperty("二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("包装")
private String packageType;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("单价")
@NumberFormat("0.00")
private BigDecimal cargoValue;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("说明")
private String descriptionOne;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("组织")
private String deptName;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -49,46 +49,43 @@ public class CommonCargoImportFailureExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("*一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("*二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("*货物名称")
private String cargoName;
@ExcelProperty("*货物编号后缀")
private String cargoCodeSuffix;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("*一级货物类型")
private String firstCargoTypeName;
@ExcelProperty("*二级货物类型")
private String secondCargoTypeName;
@ExcelProperty("*二级货物类型编码")
private String secondCargoTypeCode;
@ExcelProperty("包装")
private String packageType;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("单价")
@NumberFormat("0.00")
private BigDecimal cargoValue;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("型号")
private String model;
@ExcelProperty("说明1")
@ExcelProperty("说明")
private String descriptionOne;
@ExcelProperty("尺寸")
private String sizeText;
@ExcelProperty("说明2")
private String descriptionTwo;
@ExcelProperty("备注")
private String remark;
@@ -1,85 +1,85 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 常用线路 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonRouteExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("线路编号")
private String routeCode;
@ExcelProperty("线路名称")
private String routeName;
@ExcelProperty("发货地")
private String departureName;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("收货地")
private String arrivalName;
@ExcelProperty("收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 常用线路导出 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class CommonRouteExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("线路编号")
private String routeCode;
@ExcelProperty("线路名称")
private String routeName;
@ExcelProperty("发货地")
private String departureName;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("收货地")
private String arrivalName;
@ExcelProperty("收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -1,98 +1,121 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Date;
/**
* 合同管理 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ContractManageExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("合同编号")
private String contractNo;
@ExcelProperty("合同名称")
private String contractName;
@ExcelProperty("所属项目")
private String projectName;
@ExcelProperty("所属组织")
private String organizationName;
@ExcelProperty("合同类别")
private String contractCategory;
@ExcelProperty("签约类型")
private String signType;
@ExcelProperty("甲方")
private String partyA;
@ExcelProperty("")
private String partyB;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("临时效力起")
private LocalDate temporaryStartDate;
@ExcelProperty("临时效力")
private LocalDate temporaryEndDate;
@ExcelProperty("经办人")
private String handlerUserName;
@ExcelProperty("合同阶段")
private String contractStage;
@ExcelProperty("审核状态")
private String approvalStatus;
@ExcelProperty("当前节点")
private String currentNode;
@ExcelProperty("当前处理人")
private String currentProcessor;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
/**
* 合同管理 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ContractManageExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("合同编号")
private String contractNo;
@ExcelProperty("合同名称")
private String contractName;
@ExcelProperty("所属项目")
private String projectName;
@ExcelProperty("所属组织")
private String organizationName;
@ExcelProperty("合同类别")
private String contractCategory;
@ExcelProperty("签约类型")
private String signType;
@ExcelProperty("")
private String partyA;
@ExcelProperty("乙方")
private String partyB;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("临时效力")
private LocalDate temporaryStartDate;
@ExcelProperty("临时效力止")
private LocalDate temporaryEndDate;
@ExcelProperty("经办人")
private String handlerUserName;
@ExcelProperty("合同阶段")
private String contractStage;
@ExcelProperty("审核状态")
private String approvalStatus;
@ExcelProperty("归档状态")
private String archiveStatus;
@ExcelProperty("结算币种")
private String settlementCurrency;
@ExcelProperty("结算方式")
private String settlementMode;
@ExcelProperty("开票周期(天)")
private Integer invoiceCycle;
@ExcelProperty("一式份数")
private Integer copyCount;
@ExcelProperty("回款账期(天)")
private Integer paymentDays;
@ExcelProperty("合同金额")
@NumberFormat("0.00")
private BigDecimal contractAmount;
@ExcelProperty("是否范本")
private Integer templateFlag;
@ExcelProperty("原件合同编号")
private String originalContractNo;
@ExcelProperty("是否电子章")
private Integer electronicSealFlag;
@ExcelProperty("当前节点")
private String currentNode;
@ExcelProperty("当前处理人")
private String currentProcessor;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
@@ -54,36 +54,24 @@ public class CustomerArchiveExcel implements Serializable {
@ExcelProperty("客商简称")
private String shortName;
@ExcelProperty("*客商名称")
@ExcelProperty("客商名称")
private String fullName;
@ExcelProperty("*客商类型")
@ExcelProperty("客商类型")
private String customerType;
@ExcelProperty("*客商性质")
@ExcelProperty("客商性质")
private String customerNature;
@ExcelProperty("*统一信用代码")
@ExcelProperty("统一信用代码")
private String unifiedCreditCode;
@ExcelProperty("*所属组织")
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("准入类型")
private String accessTypeName;
@ExcelProperty("审批状态")
private String approvalStatusName;
@ExcelProperty("当前节点")
private String currentNode;
@ExcelProperty("当前处理人")
private String currentProcessor;
@ExcelProperty("审核通过时间")
private LocalDateTime approvedTime;
@ExcelProperty("状态")
private String statusName;
@@ -96,13 +84,25 @@ public class CustomerArchiveExcel implements Serializable {
@ExcelProperty("申请总资金使用额度(万元)")
private BigDecimal applyCreditLimit;
@ExcelProperty("*联系电话")
@ExcelProperty("联系电话")
private String contactPhone;
@ExcelProperty("*法人/负责人")
@ExcelProperty("法人/负责人")
private String legalPerson;
@ExcelProperty("创建时间")
private Date createTime;
@ExcelProperty("审批状态")
private String approvalStatusName;
@ExcelProperty("当前节点")
private String currentNode;
@ExcelProperty("当前处理人")
private String currentProcessor;
@ExcelProperty("审核通过时间")
private LocalDateTime approvedTime;
}
@@ -74,6 +74,9 @@ public class DriverExcel implements Serializable {
@ExcelProperty("住址")
private String address;
@ExcelProperty("驾驶车辆")
private String drivingVehicle;
@ExcelProperty("岗位 *")
private String posts;
@@ -8,6 +8,7 @@ package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
@@ -37,13 +38,15 @@ public class EtcRecordExcel implements Serializable {
@ExcelProperty("*车牌号")
private String vehicleNo;
@ExcelProperty("入口时间")
@ExcelProperty(value = "入口时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private LocalDateTime entryTime;
@ExcelProperty("*ETC卡号")
private String etcCardNo;
@ExcelProperty("*出口时间")
@ExcelProperty(value = "*出口时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private LocalDateTime exitTime;
@ExcelProperty("入口站")
@@ -0,0 +1,58 @@
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class FormalSettlementExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("结算单号")
private String formalSettlementNo;
@ExcelProperty("预结算单号")
private String preSettlementNos;
@ExcelProperty("来源")
private String sourceType;
@ExcelProperty("付款方")
private String payerName;
@ExcelProperty("收款方")
private String payeeName;
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("合同编号")
private String contractNo;
@ExcelProperty("合同名称")
private String contractName;
@ExcelProperty("原币结算金额")
private String settlementAmount;
@ExcelProperty("本位币结算金额")
private String localSettlementAmount;
@ExcelProperty("结算汇率")
private String exchangeRate;
@ExcelProperty("发票状态")
private String invoiceStatusName;
@ExcelProperty("收付款状态")
private String paymentStatusName;
@ExcelProperty("审核状态")
private String approvalStatusName;
@ExcelProperty("金蝶单据号")
private String kingdeeBillNo;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("创建时间")
private Date createTime;
}
@@ -42,15 +42,15 @@ public class LoadingManageExcel implements Serializable {
private String driverPhone;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商")
private String carrierName;
@ExcelProperty("发货地")
private String departureAddress;
@ExcelProperty("途经地")
private String transitAddress;
@ExcelProperty("到货地")
private String arrivalAddress;
@ExcelProperty("运输类型")
@ExcelProperty("承运商")
private String carrierName;
@ExcelProperty("运输方式")
private String transportType;
@ExcelProperty("数据来源")
private String dataSource;
@@ -0,0 +1,94 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import cn.idev.excel.util.DateUtils;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
/**
* 保养记录日期转换器,兼容日期文本、日期时间文本和 Excel 数值日期。
*
* @author Chill
*/
public class MaintenancePlanDateTimeConverter implements Converter<LocalDateTime> {
private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter DATE_TIME_MINUTE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT);
@Override
public Class<?> supportJavaTypeKey() {
return LocalDateTime.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public LocalDateTime convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getType() == CellDataTypeEnum.NUMBER) {
return DateUtils.getLocalDateTime(cellData.getNumberValue().doubleValue(),
globalConfiguration.getUse1904windowing());
}
String value = cellData.getStringValue();
if (value == null || value.trim().isEmpty()) {
return null;
}
String normalizedValue = value.trim();
try {
return LocalDateTime.parse(normalizedValue, DATE_TIME_FORMATTER);
} catch (DateTimeParseException ignored) {
try {
return LocalDateTime.parse(normalizedValue, DATE_TIME_MINUTE_FORMATTER);
} catch (DateTimeParseException ignoredMinute) {
return LocalDate.parse(normalizedValue, DATE_FORMATTER).atStartOfDay();
}
}
}
@Override
public WriteCellData<?> convertToExcelData(LocalDateTime value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
String format = contentProperty != null && contentProperty.getDateTimeFormatProperty() != null
? contentProperty.getDateTimeFormatProperty().getFormat() : DEFAULT_DATE_FORMAT;
return new WriteCellData<>(DateUtils.format(value, format, globalConfiguration.getLocale()));
}
}
@@ -27,6 +27,7 @@ package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
@@ -63,7 +64,8 @@ public class MaintenancePlanExcel implements Serializable {
@ExcelProperty("保养人")
private String maintainer;
@ExcelProperty("*保养时间")
@ExcelProperty(value = "*保养时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd")
private LocalDateTime maintenanceTime;
@ExcelProperty("里程/航程数")
@@ -88,7 +90,8 @@ public class MaintenancePlanExcel implements Serializable {
@ExcelProperty("地址")
private String address;
@ExcelProperty("下次保养时间")
@ExcelProperty(value = "下次保养时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd")
private LocalDateTime nextMaintenanceTime;
@ExcelProperty("下次保养里程/航程")
@@ -65,7 +65,7 @@ public class MaintenanceRecordExcel implements Serializable {
@ExcelProperty("维修人")
private String maintainer;
@ExcelProperty("*维修时间")
@ExcelProperty(value = "*维修时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd")
private LocalDateTime maintenanceTime;
@@ -88,7 +88,7 @@ public class MaintenanceRecordExcel implements Serializable {
@ExcelProperty("地址")
private String address;
@ExcelProperty("出厂时间")
@ExcelProperty(value = "出厂时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd")
private LocalDateTime factoryTime;
@@ -96,14 +96,14 @@ public class MaintenanceRecordExcel implements Serializable {
@NumberFormat("0.00")
private BigDecimal mileage;
@ExcelProperty("创建时间")
@ExcelProperty(value = "创建时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("更新时间")
@ExcelProperty(value = "更新时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@@ -0,0 +1,74 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
/** 总单运单明细导出模型。 */
@Data
@ColumnWidth(20)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class MasterOrderWaybillExcel {
@ExcelProperty("总单号")
private String masterNo;
@ExcelProperty("运单号")
private String waybillNo;
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("客户合同")
private String contractName;
@ExcelProperty("客户名称")
private String customerName;
@ExcelProperty("运输类型")
private String transportType;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("货物类型")
private String cargoType;
@ExcelProperty("数量")
private BigDecimal quantity;
@ExcelProperty("数量单位")
private String quantityUnit;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系人电话")
private String departurePhone;
@ExcelProperty("收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系人电话")
private String arrivalPhone;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商")
private String carrierName;
@ExcelProperty("司机")
private String driverName;
@ExcelProperty("车牌号/航班号/船号/班列号")
private String vehicleNo;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("业务状态")
private String businessStatus;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建时间")
private Date createTime;
}
@@ -53,10 +53,7 @@ public class MileageRecordExcel implements Serializable {
@ExcelIgnore
private Long id;
@ExcelProperty("*车船类型")
private String vehicleType;
@ExcelProperty("*车牌号/船号")
@ExcelProperty("*车牌号")
private String vehicleNo;
@ExcelProperty("上月统计里程数")
@@ -51,10 +51,7 @@ public class MileageRecordExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("船类型")
private String vehicleType;
@ExcelProperty("车牌号/船号")
@ExcelProperty("牌号")
private String vehicleNo;
@ExcelProperty("上月统计里程数")
@@ -11,6 +11,7 @@ package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
@@ -37,10 +38,11 @@ public class OilElectricRecordExcel implements Serializable {
@ExcelIgnore
private Long id;
@ExcelIgnore
@ExcelProperty("卡号")
private String cardNo;
@ExcelProperty("*交易时间")
@ExcelProperty(value = "*交易时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private LocalDateTime transactionTime;
@ExcelProperty("*车船类型")
@@ -0,0 +1,72 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 预结算单 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class PreSettlementExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("预结算单号")
private String preSettlementNo;
@ExcelProperty("来源")
private String sourceType;
@ExcelProperty("付款方")
private String payerName;
@ExcelProperty("收款方")
private String payeeName;
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("合同编号")
private String contractNo;
@ExcelProperty("合同名称")
private String contractName;
@ExcelProperty("原币结算金额")
private String settlementAmount;
@ExcelProperty("本位币结算金额")
private String localSettlementAmount;
@ExcelProperty("结算汇率")
private String exchangeRate;
@ExcelProperty("申请预付金额")
private String advanceAppliedAmount;
@ExcelProperty("已付款金额")
private String advancePaidAmount;
@ExcelProperty("审核状态")
private String approvalStatusName;
@ExcelProperty("当前节点")
private String currentNode;
@ExcelProperty("当前处理人")
private String currentProcessor;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("创建时间")
private Date createTime;
}
@@ -1,79 +1,79 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 过程配置 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ProcessConfigExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("配置编号")
private String configCode;
@ExcelProperty("配置名称")
private String configName;
@ExcelProperty("项目ID集合")
private String projectIds;
@ExcelProperty("项目")
private String projectNames;
@ExcelProperty("包含过程节点")
private String includedNodes;
@ExcelProperty("默认后台完成运输天数")
private Integer defaultFinishDays;
@ExcelProperty("状态")
private Integer status;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/**
* 过程配置导出 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class ProcessConfigExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("配置编号")
private String configCode;
@ExcelProperty("配置名称")
private String configName;
@ExcelProperty("项目ID集合")
private String projectIds;
@ExcelProperty("项目")
private String projectNames;
@ExcelProperty("包含过程节点")
private String includedNodes;
@ExcelProperty("默认后台完成运输天数")
private Integer defaultFinishDays;
@ExcelProperty("状态")
private Integer status;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -62,7 +62,7 @@ public class ProjectApplyExcel implements Serializable {
private String projectType;
@ExcelProperty("业务部门")
private String businessDeptName;
@ExcelProperty("承办部门")
@ExcelProperty("平台公司")
private String undertakeDeptName;
@ExcelProperty("项目由来")
private String projectSource;
@@ -88,10 +88,14 @@ public class ProjectApplyExcel implements Serializable {
private String transportType;
@ExcelProperty("业务类型")
private String businessType;
@ExcelProperty("业务模式")
private String businessMode;
@ExcelProperty("项目规模(万元)")
private BigDecimal projectScale;
@ExcelProperty("预计利润(万元)")
private BigDecimal estimatedProfit;
@ExcelProperty("利润率(%)")
private BigDecimal profitRate;
@ExcelProperty("资金需求(万元)")
private BigDecimal fundDemand;
@ExcelProperty("结算方式")
@@ -0,0 +1,71 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.</p>
* <p>Author: Chill Zhuang (bladejava@qq.com)</p>
*/
package org.springblade.transport.excel;
import cn.idev.excel.FastExcel;
import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
/** 运输对账导入模板导出。费用列按当前内部账单收费项动态生成。 */
public final class ReconciliationImportTemplateExcel {
private static final List<String> VEHICLE_HEADERS = List.of(
"车牌号", "发货地址", "到货地址", "实际发货时间", "实际完成时间", "运输类型",
"货物名称", "货物类型", "运输总量", "里程(KM", "批次号", "运输单价", "运输费"
);
private static final List<String> CARGO_HEADERS = List.of(
"车牌号", "发货地址", "到货地址", "实际发货时间", "实际完成时间", "货物名称",
"货物类型", "规格", "型号", "运输总量", "运输单价", "里程(KM", "运输费"
);
private static final String SETTLEMENT_AMOUNT = "结算费用合计";
private ReconciliationImportTemplateExcel() {
}
public static void exportVehicle(HttpServletResponse response, List<String> extraFeeItems) {
export(response, "整车总额对账模板", VEHICLE_HEADERS, extraFeeItems);
}
public static void exportCargo(HttpServletResponse response, List<String> extraFeeItems) {
export(response, "货物明细对账模板", CARGO_HEADERS, extraFeeItems);
}
private static void export(HttpServletResponse response, String fileName, List<String> baseHeaders,
List<String> extraFeeItems) {
List<List<String>> head = new ArrayList<>();
for (String header : baseHeaders) {
head.add(List.of(header));
}
if (extraFeeItems != null) {
for (String feeItem : extraFeeItems) {
if (feeItem != null && !feeItem.isBlank()) {
head.add(List.of(feeItem.trim()));
}
}
}
head.add(List.of(SETTLEMENT_AMOUNT));
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setHeader("Content-disposition",
"attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8) + ".xlsx");
try {
FastExcel.write(response.getOutputStream())
.head(head)
.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
.sheet(fileName)
.doWrite(List.of());
} catch (IOException exception) {
throw new IllegalStateException("导出" + fileName + "失败", exception);
}
}
}
@@ -0,0 +1,75 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.converters.Converter;
import cn.idev.excel.enums.CellDataTypeEnum;
import cn.idev.excel.metadata.GlobalConfiguration;
import cn.idev.excel.metadata.data.ReadCellData;
import cn.idev.excel.metadata.data.WriteCellData;
import cn.idev.excel.metadata.property.ExcelContentProperty;
import cn.idev.excel.util.DateUtils;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
/**
* 换胎日期文本转换器,保留非法日期原值并兼容 Excel 数值日期。
*
* @author Chill
*/
public class TireReplacementDateStringConverter implements Converter<String> {
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ISO_LOCAL_DATE;
@Override
public Class<?> supportJavaTypeKey() {
return String.class;
}
@Override
public CellDataTypeEnum supportExcelTypeKey() {
return CellDataTypeEnum.STRING;
}
@Override
public String convertToJavaData(ReadCellData<?> cellData, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
if (cellData.getType() == CellDataTypeEnum.NUMBER) {
LocalDate date = DateUtils.getLocalDateTime(cellData.getNumberValue().doubleValue(),
globalConfiguration.getUse1904windowing()).toLocalDate();
return date.format(DATE_FORMATTER);
}
return cellData.getStringValue();
}
@Override
public WriteCellData<?> convertToExcelData(String value, ExcelContentProperty contentProperty,
GlobalConfiguration globalConfiguration) {
return new WriteCellData<>(value);
}
}
@@ -36,7 +36,6 @@ import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
/**
* 换胎记录 Excel
@@ -60,8 +59,8 @@ public class TireReplacementRecordExcel implements Serializable {
@ExcelProperty("处理人")
private String handler;
@ExcelProperty("*换胎时间")
private LocalDate replacementTime;
@ExcelProperty(value = "*换胎时间", converter = TireReplacementDateStringConverter.class)
private String replacementTime;
@ExcelProperty("轮胎品牌")
private String tireBrand;
@@ -49,46 +49,44 @@ public class TransportPlanImportExcel implements Serializable {
@ExcelProperty("*计划名称")
private String planName;
@ExcelProperty("*运输方式")
@ExcelProperty("*运输类型")
private String transportType;
@ExcelProperty("*计划开始日期")
private String planStartDate;
@ExcelProperty("*计划结束日期")
private String planEndDate;
@ExcelProperty("*发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系人电话")
private String departurePhone;
@ExcelProperty("*到货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系人电话")
private String arrivalPhone;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("*货物类型")
private String cargoType;
@ExcelProperty("数量")
private BigDecimal quantity;
@ExcelProperty("量单位")
@ExcelProperty("量单位")
private String quantityUnit;
@ExcelProperty("包装")
private String packageType;
@ExcelProperty("品牌")
private String brand;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("物料编码")
private String materialCode;
@ExcelProperty("设备编码")
private String deviceCode;
@ExcelProperty("*发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("*收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("里程(km)")
private BigDecimal mileage;
@ExcelProperty("计划开始时间")
private String planStartDate;
@ExcelProperty("计划结束时间")
private String planEndDate;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("同一计划标识号")
private String planGroupId;
@ExcelIgnore
private String errorMessage;
@@ -0,0 +1,50 @@
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class TransportReconciliationExportExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("对账单号")
private String reconciliationNo;
@ExcelProperty("付款方")
private String payerName;
@ExcelProperty("收款方")
private String payeeName;
@ExcelProperty("项目名称")
private String projectName;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("合同编号")
private String contractNo;
@ExcelProperty("合同名称")
private String contractName;
@ExcelProperty("结算金额")
private String settlementAmount;
@ExcelProperty("对账模式")
private String reconciliationModeName;
@ExcelProperty("账单总数")
private Integer externalBillCount;
@ExcelProperty("匹配数")
private Integer matchedCount;
@ExcelProperty("对账状态")
private String reconciliationStatusName;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("创建时间")
private Date createTime;
}
@@ -59,6 +59,9 @@ public class TransportVehicleExcel implements Serializable {
@ExcelProperty("所属组织 *")
private String organizationName;
@ExcelProperty("使用部门")
private String useDepartment;
@ExcelProperty("业务关系 *")
private String businessRelation;
@@ -0,0 +1,54 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Redistribution of this software's source code to any third party without a commercial license is strictly prohibited.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import org.springblade.transport.pojo.vo.VehicleDispatchVO;
import java.io.Serial;
import java.io.Serializable;
import java.util.Date;
/** 车辆调度导出模型。 */
@Data
@ColumnWidth(20)
public class VehicleDispatchExcel implements Serializable {
@Serial private static final long serialVersionUID = 1L;
@ExcelProperty("申请单号") private String applicationNo;
@ExcelProperty("车牌号") private String plateNo;
@ExcelProperty("所属组织") private String organizationName;
@ExcelProperty("使用部门") private String useDepartment;
@ExcelProperty("车辆类型") private String vehicleType;
@ExcelProperty("审批状态") private String approvalStatusName;
@ExcelProperty("当前节点") private String currentNode;
@ExcelProperty("当前处理人") private String currentProcessor;
@ExcelProperty("创建人") private String createUserName;
@ExcelProperty("创建时间") private Date createTime;
public static VehicleDispatchExcel from(VehicleDispatchVO source) {
VehicleDispatchExcel target = new VehicleDispatchExcel();
target.applicationNo = source.getApplicationNo();
target.plateNo = source.getPlateNo();
target.organizationName = source.getOrganizationName();
target.useDepartment = source.getUseDepartment();
target.vehicleType = source.getVehicleType();
target.approvalStatusName = source.getApprovalStatusName();
target.currentNode = source.getCurrentNode();
target.currentProcessor = source.getCurrentProcessor();
target.createUserName = source.getCreateUserName();
target.createTime = source.getCreateTime();
return target;
}
}
@@ -0,0 +1,42 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.</p>
* <p>Author: Chill Zhuang (bladejava@qq.com)</p>
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.NumberFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Map;
/** 整车总额对账导入模型。 @author Chill */
@Data
@ColumnWidth(22)
public class VehicleReconciliationExcel implements Serializable {
@Serial private static final long serialVersionUID = 1L;
@ExcelProperty("车牌号") private String vehicleNo;
@ExcelProperty("发货地址") private String departureAddress;
@ExcelProperty("到货地址") private String arrivalAddress;
@ExcelProperty("实际发货时间") private String actualDepartureTime;
@ExcelProperty("实际完成时间") private String actualCompletionTime;
@ExcelProperty("运输类型") private String transportType;
@ExcelProperty("货物名称") private String cargoName;
@ExcelProperty("货物类型") private String cargoType;
@ExcelProperty("运输总量") @NumberFormat("0.000000") private BigDecimal transportQuantity;
@ExcelProperty("里程(KM") @NumberFormat("0.00") private BigDecimal mileage;
@ExcelProperty("批次号") private String batchNo;
@ExcelProperty("运输单价") @NumberFormat("0.00") private BigDecimal unitPrice;
@ExcelProperty("运输费") @NumberFormat("0.00") private BigDecimal freightAmount;
@ExcelIgnore @NumberFormat("0.00") private BigDecimal feeItemOne;
@ExcelProperty("结算费用合计") @NumberFormat("0.00") private BigDecimal settlementAmount;
@ExcelIgnore private Map<String, BigDecimal> feeItems;
@ExcelIgnore private String errorMessage;
}
@@ -0,0 +1,13 @@
/** BladeX Commercial License Agreement. Copyright (c) 2018-2099, https://bladex.cn. Author: Chill Zhuang. */
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/** 整车对账导入失败模型。 @author Chill */
@Data
@EqualsAndHashCode(callSuper = true)
public class VehicleReconciliationFailureExcel extends VehicleReconciliationExcel {
@ExcelProperty("导入失败原因") private String errorMessage;
}
@@ -0,0 +1,106 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.FastExcel;
import cn.idev.excel.context.AnalysisContext;
import cn.idev.excel.event.AnalysisEventListener;
import cn.idev.excel.metadata.data.ReadCellData;
import org.springblade.core.log.exception.ServiceException;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/** 整车总额对账动态费用读取器。 @author Chill */
public final class VehicleReconciliationFeeReader {
private VehicleReconciliationFeeReader() {
}
public static List<Map<String, BigDecimal>> read(MultipartFile file) {
try (InputStream inputStream = file.getInputStream()) {
FeeListener listener = new FeeListener();
FastExcel.read(inputStream)
.useDefaultListener(false)
.registerReadListener(listener)
.sheet()
.doRead();
return listener.getFeeItems();
} catch (IOException exception) {
throw new ServiceException("读取整车总额对账费用列失败");
}
}
private static final class FeeListener extends AnalysisEventListener<Map<Integer, ReadCellData<?>>> {
private final List<Map<String, BigDecimal>> feeItems = new ArrayList<>();
private Map<Integer, String> headers = Map.of();
private int freightColumn = -1;
private int settlementColumn = -1;
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
headers = headMap;
freightColumn = findColumn("运输费");
settlementColumn = findColumn("结算费用合计");
}
@Override
public void invoke(Map<Integer, ReadCellData<?>> row, AnalysisContext context) {
Map<String, BigDecimal> values = new LinkedHashMap<>();
if (freightColumn >= 0 && settlementColumn > freightColumn) {
for (int column = freightColumn + 1; column < settlementColumn; column++) {
String name = headers.get(column);
if (name != null && !name.isBlank()) values.put(name.trim(), decimal(row.get(column)));
}
}
feeItems.add(values);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
}
private int findColumn(String header) {
return headers.entrySet().stream()
.filter(entry -> header.equals(entry.getValue()))
.mapToInt(Map.Entry::getKey)
.findFirst().orElse(-1);
}
private BigDecimal decimal(ReadCellData<?> cellData) {
if (cellData == null) return BigDecimal.ZERO.setScale(2);
Object value = cellData.getData();
if (value == null) {
value = switch (cellData.getType()) {
case NUMBER -> cellData.getNumberValue();
case STRING, DIRECT_STRING, ERROR -> cellData.getStringValue();
case BOOLEAN -> cellData.getBooleanValue();
default -> null;
};
}
if (value == null || String.valueOf(value).isBlank()) return BigDecimal.ZERO.setScale(2);
try {
return new BigDecimal(String.valueOf(value).trim()).setScale(2);
} catch (NumberFormatException exception) {
return BigDecimal.ZERO.setScale(2);
}
}
private List<Map<String, BigDecimal>> getFeeItems() {
return feeItems;
}
}
}
@@ -66,7 +66,7 @@ public class ViolationRecordImportExcel implements Serializable {
@ExcelProperty("*事项")
private String violationItem;
@ExcelProperty("*时间")
@ExcelProperty(value = "*时间", converter = MaintenancePlanDateTimeConverter.class)
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private LocalDateTime violationTime;
@@ -1,164 +1,163 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
import java.time.LocalDate;
/**
* 运单管理 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class WaybillExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("运单号")
private String waybillNo;
@ExcelProperty("项目")
private String projectName;
@ExcelProperty("客户合同")
private String contractName;
@ExcelProperty("客户名称")
private String customerName;
@ExcelProperty("运输类型")
private String transportType;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("货物类型")
private String cargoType;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("数量")
private BigDecimal quantity;
@ExcelProperty("数量单位")
private String quantityUnit;
@ExcelProperty("发货地")
private String departureName;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("收货地")
private String arrivalName;
@ExcelProperty("收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("任务录入模式")
private String taskEntryMode;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商名称")
private String carrierName;
@ExcelProperty("司机姓名")
private String driverName;
@ExcelProperty("司机手机号")
private String driverPhone;
@ExcelProperty("车/船/航班/班列号")
private String vehicleNo;
@ExcelProperty("挂车车牌号")
private String trailerVehicleNo;
@ExcelProperty("押运人")
private String escortName;
@ExcelProperty("押运人手机号")
private String escortPhone;
@ExcelProperty("里程(km)")
private BigDecimal mileage;
@ExcelProperty("预计发货日期")
private LocalDate estimatedStartTime;
@ExcelProperty("预计完成日期")
private LocalDate estimatedEndTime;
@ExcelProperty("单价")
private BigDecimal unitPrice;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("其他费用合计")
private BigDecimal otherFeeTotal;
@ExcelProperty("任务备注")
private String taskRemark;
@ExcelProperty("原始单号")
private String originalNo;
@ExcelProperty("业务状态")
private String businessStatus;
@ExcelProperty("数据来源")
private String dataSource;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("计划名称")
private String planName;
@ExcelProperty("多联总单")
private String masterNo;
@ExcelProperty("配载单号")
private String loadingNo;
@ExcelProperty("运单批次号")
private String batchNo;
@ExcelProperty("关联单号")
private String relationNo;
@ExcelProperty("当前过程节点")
private String currentProcessNode;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelIgnore
private String errorMessage;
}
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.excel;
import cn.idev.excel.annotation.ExcelProperty;
import cn.idev.excel.annotation.ExcelIgnore;
import cn.idev.excel.annotation.format.DateTimeFormat;
import cn.idev.excel.annotation.write.style.ColumnWidth;
import cn.idev.excel.annotation.write.style.ContentRowHeight;
import cn.idev.excel.annotation.write.style.HeadRowHeight;
import lombok.Data;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Date;
/**
* 运单管理 Excel
*
* @author Chill
*/
@Data
@ColumnWidth(22)
@HeadRowHeight(20)
@ContentRowHeight(18)
public class WaybillExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("运单号")
private String waybillNo;
@ExcelProperty("项目")
private String projectName;
@ExcelProperty("客户合同")
private String contractName;
@ExcelProperty("客户名称")
private String customerName;
@ExcelProperty("运输类型")
private String transportType;
@ExcelProperty("货物名称")
private String cargoName;
@ExcelProperty("货物类型")
private String cargoType;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("数量")
private BigDecimal quantity;
@ExcelProperty("数量单位")
private String quantityUnit;
@ExcelProperty("发货地")
private String departureName;
@ExcelProperty("发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系方式")
private String departurePhone;
@ExcelProperty("收货地")
private String arrivalName;
@ExcelProperty("收货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系方式")
private String arrivalPhone;
@ExcelProperty("任务录入模式")
private String taskEntryMode;
@ExcelProperty("承运类型")
private String carrierType;
@ExcelProperty("承运商名称")
private String carrierName;
@ExcelProperty("司机姓名")
private String driverName;
@ExcelProperty("司机手机号")
private String driverPhone;
@ExcelProperty("车/船/航班/班列号")
private String vehicleNo;
@ExcelProperty("挂车车牌号")
private String trailerVehicleNo;
@ExcelProperty("押运人")
private String escortName;
@ExcelProperty("押运人手机号")
private String escortPhone;
@ExcelProperty("里程(km)")
private BigDecimal mileage;
@ExcelProperty("预计发货日期")
private LocalDate estimatedStartTime;
@ExcelProperty("预计完成日期")
private LocalDate estimatedEndTime;
@ExcelProperty("单价")
private BigDecimal unitPrice;
@ExcelProperty("计价单位")
private String priceUnit;
@ExcelProperty("其他费用合计")
private BigDecimal otherFeeTotal;
@ExcelProperty("任务备注")
private String taskRemark;
@ExcelProperty("原始单号")
private String originalNo;
@ExcelProperty("业务状态")
private String businessStatus;
@ExcelProperty("数据来源")
private String dataSource;
@ExcelProperty("开始日期")
private LocalDate startDate;
@ExcelProperty("结束日期")
private LocalDate endDate;
@ExcelProperty("计划名称")
private String planName;
@ExcelProperty("多联总单")
private String masterNo;
@ExcelProperty("配载单号")
private String loadingNo;
@ExcelProperty("运单批次号")
private String batchNo;
@ExcelProperty("关联单号")
private String relationNo;
@ExcelProperty("当前过程节点")
private String currentProcessNode;
@ExcelProperty("所属组织")
private String deptName;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("创建人")
private String createUserName;
@ExcelProperty("更新人")
private String updateUserName;
@ExcelProperty("创建时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ExcelProperty("更新时间")
@DateTimeFormat("yyyy-MM-dd HH:mm:ss")
private Date updateTime;
@ExcelIgnore
private String errorMessage;
}
@@ -22,45 +22,70 @@ public class WaybillImportBatchExcel implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@ExcelProperty("序号")
private Integer serialNumber;
@ExcelProperty("原始单号")
private String originalNo;
@ExcelProperty("配载标识号")
private String loadingIdentifier;
@ExcelProperty("*车牌号/航班号/船号/班列号")
private String vehicleNo;
@ExcelProperty("*司机/船长")
private String driverName;
@ExcelProperty("*运输类型")
@ExcelProperty("*运输方式")
private String transportType;
@ExcelProperty("司机/船长姓名")
private String driverName;
@ExcelProperty("司机/船长手机号")
private String driverPhone;
@ExcelProperty("*发货地址")
private String departureAddress;
@ExcelProperty("发货联系人")
private String departureContact;
@ExcelProperty("发货联系人电话")
private String departurePhone;
@ExcelProperty("*到货地址")
private String arrivalAddress;
@ExcelProperty("收货联系人")
private String arrivalContact;
@ExcelProperty("收货联系人电话")
private String arrivalPhone;
@ExcelProperty("*货物名称")
private String cargoName;
@ExcelProperty("*货物类型")
private String cargoType;
@ExcelProperty("重量")
@ExcelProperty("包装")
private String packageType;
@ExcelProperty("*数量")
private BigDecimal quantity;
@ExcelProperty("*发货地址")
private String departureAddress;
@ExcelProperty("*发货联系人")
private String departureContact;
@ExcelProperty("*发货联系人电话")
private String departurePhone;
@ExcelProperty("*到货地址")
private String arrivalAddress;
@ExcelProperty("*到货联系人")
private String arrivalContact;
@ExcelProperty("*收货联系人电话")
private String arrivalPhone;
@ExcelProperty("*开始时间")
private String startDate;
@ExcelProperty("*结束时间")
private String endDate;
@ExcelProperty("*单价")
@ExcelProperty("*数量单位")
private String quantityUnit;
@ExcelProperty("规格")
private String specification;
@ExcelProperty("型号")
private String model;
@ExcelProperty("里程(km)")
private BigDecimal mileage;
@ExcelProperty("单价")
private BigDecimal unitPrice;
@ExcelProperty("*运费")
@ExcelProperty("运费")
private BigDecimal freight;
@ExcelProperty("其他费用合计")
private BigDecimal otherFeeTotal;
@ExcelProperty("运费合计")
private BigDecimal freightTotal;
@ExcelProperty("*实际发货时间")
private String actualStartDate;
@ExcelProperty("*实际完成时间")
private String actualEndDate;
@ExcelProperty("预计发货时间")
private String planStartDate;
@ExcelProperty("预计完成时间")
private String planEndDate;
@ExcelProperty("备注")
private String remark;
@ExcelProperty("同一运单标识号")
private String waybillIdentifier;
/** 导入失败原因(不导出到模板,仅用于失败明细) */
private String errorMessage;
}
@@ -0,0 +1,45 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.listener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.transport.config.VoucherImportRabbitConfig;
import org.springblade.transport.service.IVoucherManageService;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.listener.MessageListenerContainer;
import org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.stereotype.Component;
import org.springframework.context.event.EventListener;
/**
* 凭证压缩包后台处理消费者。
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class VoucherImportMessageListener {
private static final String LISTENER_ID = "voucherImportMessageListener";
private final IVoucherManageService voucherManageService;
private final VoucherImportRabbitConfig voucherImportRabbitConfig;
private final RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;
@EventListener(ApplicationReadyEvent.class)
public void logConsumerStatus() {
MessageListenerContainer container = rabbitListenerEndpointRegistry.getListenerContainer(LISTENER_ID);
log.info("[凭证MQ] 消费者状态 listenerId={}, queue={}, registered={}, running={}",
LISTENER_ID, voucherImportRabbitConfig.getQueue(), container != null, container != null && container.isRunning());
}
@RabbitListener(id = LISTENER_ID, queues = "${voucher.import.rabbit.queue:tms.voucher.import.queue}")
public void processVoucher(Long voucherId) {
log.info("[凭证MQ] 收到处理任务 queue={}, voucherId={}", voucherImportRabbitConfig.getQueue(), voucherId);
voucherManageService.processUploadedVoucher(voucherId);
log.info("[凭证MQ] 处理任务完成 voucherId={}", voucherId);
}
}
@@ -0,0 +1,34 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.listener;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.transport.config.VoucherImportRabbitConfig;
import org.springblade.transport.event.VoucherUploadCompletedEvent;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;
/**
* 凭证上传完成后投递后台处理消息。
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class VoucherUploadCompletedListener {
private final RabbitTemplate rabbitTemplate;
private final VoucherImportRabbitConfig voucherImportRabbitConfig;
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
public void publish(VoucherUploadCompletedEvent event) {
log.info("[凭证MQ] 投递处理任务 exchange={}, routingKey={}, voucherId={}",
voucherImportRabbitConfig.getExchange(), voucherImportRabbitConfig.getRoutingKey(), event.getVoucherId());
rabbitTemplate.convertAndSend(voucherImportRabbitConfig.getExchange(),
voucherImportRabbitConfig.getRoutingKey(), event.getVoucherId());
}
}
@@ -77,10 +77,10 @@
<if test="accidentRecord.accidentAssessmentDateEnd != null">
AND accident_date &lt;= #{accidentRecord.accidentAssessmentDateEnd}
</if>
<if test="accidentRecord.createTimeStart != null and accidentRecord.createTimeStart != ''">
<if test="accidentRecord.createTimeStart != null">
AND create_time &gt;= #{accidentRecord.createTimeStart}
</if>
<if test="accidentRecord.createTimeEnd != null and accidentRecord.createTimeEnd != ''">
<if test="accidentRecord.createTimeEnd != null">
AND create_time &lt;= #{accidentRecord.createTimeEnd}
</if>
ORDER BY create_time DESC
@@ -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<AnnualInspectio
* @param annualInspectionRecord 查询参数
* @return 年检记录分页
*/
List<AnnualInspectionRecordVO> selectAnnualInspectionRecordPage(IPage<AnnualInspectionRecordVO> page, AnnualInspectionRecordVO annualInspectionRecord);
List<AnnualInspectionRecordVO> selectAnnualInspectionRecordPage(IPage<AnnualInspectionRecordVO> page, @Param("annualInspectionRecord") AnnualInspectionRecordVO annualInspectionRecord);
/**
* 有效期统计
*
* @param annualInspectionRecord 查询参数
* @return 统计结果
*/
AnnualInspectionRecordExpiryStatVO selectExpiryStat(@Param("annualInspectionRecord") AnnualInspectionRecordVO annualInspectionRecord);
}
@@ -26,6 +26,49 @@
<result column="remark" property="remark"/>
</resultMap>
<sql id="ExpiryWithin30Condition">
valid_until_date IS NOT NULL
AND valid_until_date &gt;= #{annualInspectionRecord.today}
AND valid_until_date &lt;= #{annualInspectionRecord.warningDate}
</sql>
<sql id="ExpiryExpiredCondition">
valid_until_date IS NOT NULL
AND valid_until_date &lt; #{annualInspectionRecord.today}
</sql>
<sql id="QueryCondition">
is_deleted = 0
<if test="annualInspectionRecord.createDept != null">
AND create_dept = #{annualInspectionRecord.createDept}
</if>
<if test="annualInspectionRecord.vehicleType != null and annualInspectionRecord.vehicleType != ''">
AND vehicle_type = #{annualInspectionRecord.vehicleType}
</if>
<if test="annualInspectionRecord.vehicleNo != null and annualInspectionRecord.vehicleNo != ''">
<bind name="vehicleNoLike" value="'%' + annualInspectionRecord.vehicleNo + '%'"/>
AND vehicle_no LIKE #{vehicleNoLike}
</if>
<if test="annualInspectionRecord.inspectionAssessmentDateStart != null">
AND inspection_assessment_date &gt;= #{annualInspectionRecord.inspectionAssessmentDateStart}
</if>
<if test="annualInspectionRecord.inspectionAssessmentDateEnd != null">
AND inspection_assessment_date &lt;= #{annualInspectionRecord.inspectionAssessmentDateEnd}
</if>
<if test="annualInspectionRecord.createTimeStart != null">
AND create_time &gt;= #{annualInspectionRecord.createTimeStart}
</if>
<if test="annualInspectionRecord.createTimeEnd != null">
AND create_time &lt;= #{annualInspectionRecord.createTimeEnd}
</if>
<if test="annualInspectionRecord.expireStatus != null and annualInspectionRecord.expireStatus == 'within30'">
AND <include refid="ExpiryWithin30Condition"/>
</if>
<if test="annualInspectionRecord.expireStatus != null and annualInspectionRecord.expireStatus == 'expired'">
AND <include refid="ExpiryExpiredCondition"/>
</if>
</sql>
<select id="selectAnnualInspectionRecordPage" resultMap="annualInspectionRecordResultMap">
SELECT
id,
@@ -52,30 +95,19 @@
FROM
blade_annual_inspection_record
WHERE
is_deleted = 0
<if test="annualInspectionRecord.createDept != null">
AND create_dept = #{annualInspectionRecord.createDept}
</if>
<if test="annualInspectionRecord.vehicleType != null and annualInspectionRecord.vehicleType != ''">
AND vehicle_type = #{annualInspectionRecord.vehicleType}
</if>
<if test="annualInspectionRecord.vehicleNo != null and annualInspectionRecord.vehicleNo != ''">
<bind name="vehicleNoLike" value="'%' + annualInspectionRecord.vehicleNo + '%'"/>
AND vehicle_no LIKE #{vehicleNoLike}
</if>
<if test="annualInspectionRecord.inspectionAssessmentDateStart != null">
AND inspection_assessment_date &gt;= #{annualInspectionRecord.inspectionAssessmentDateStart}
</if>
<if test="annualInspectionRecord.inspectionAssessmentDateEnd != null">
AND inspection_assessment_date &lt;= #{annualInspectionRecord.inspectionAssessmentDateEnd}
</if>
<if test="annualInspectionRecord.createTimeStart != null and annualInspectionRecord.createTimeStart != ''">
AND create_time &gt;= #{annualInspectionRecord.createTimeStart}
</if>
<if test="annualInspectionRecord.createTimeEnd != null and annualInspectionRecord.createTimeEnd != ''">
AND create_time &lt;= #{annualInspectionRecord.createTimeEnd}
</if>
<include refid="QueryCondition"/>
ORDER BY create_time DESC
</select>
<select id="selectExpiryStat" resultType="org.springblade.transport.pojo.vo.AnnualInspectionRecordExpiryStatVO">
SELECT
COUNT(1) AS total,
SUM(CASE WHEN <include refid="ExpiryWithin30Condition"/> THEN 1 ELSE 0 END) AS within30,
SUM(CASE WHEN <include refid="ExpiryExpiredCondition"/> THEN 1 ELSE 0 END) AS expired
FROM
blade_annual_inspection_record
WHERE
<include refid="QueryCondition"/>
</select>
</mapper>
@@ -0,0 +1,14 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.BillLedger;
/** 汇票台账 Mapper。 @author Chill */
@Mapper
public interface BillLedgerMapper extends BaseMapper<BillLedger> {
}
@@ -0,0 +1,14 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.BillLedgerUsage;
/** 汇票使用记录 Mapper。 @author Chill */
@Mapper
public interface BillLedgerUsageMapper extends BaseMapper<BillLedgerUsage> {
}
@@ -0,0 +1,35 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.BillPayment;
/** 汇票付款 Mapper。 @author Chill */
@Mapper
public interface BillPaymentMapper extends BaseMapper<BillPayment> {
}
@@ -45,10 +45,10 @@
<if test="quantification.status != null">
AND csq.status = #{quantification.status}
</if>
<if test="quantification.createTimeStart != null and quantification.createTimeStart != ''">
<if test="quantification.createTimeStart != null">
AND csq.create_time &gt;= #{quantification.createTimeStart}
</if>
<if test="quantification.createTimeEnd != null and quantification.createTimeEnd != ''">
<if test="quantification.createTimeEnd != null">
AND csq.create_time &lt;= #{quantification.createTimeEnd}
</if>
ORDER BY csq.create_time DESC
@@ -16,6 +16,7 @@
<result column="short_name" property="shortName"/>
<result column="full_name" property="fullName"/>
<result column="customer_nature" property="customerNature"/>
<result column="guangxi_top100" property="guangxiTop100"/>
<result column="unified_credit_code" property="unifiedCreditCode"/>
<result column="customer_type" property="customerType"/>
<result column="project_name" property="projectName"/>
@@ -29,6 +30,7 @@
<result column="dept_name" property="deptName"/>
<result column="invoice_tax_rate" property="invoiceTaxRate"/>
<result column="business_scope" property="businessScope"/>
<result column="network_freight_platform" property="networkFreightPlatform"/>
<result column="business_term_type" property="businessTermType"/>
<result column="business_end_date" property="businessEndDate"/>
<result column="registered_capital" property="registeredCapital"/>
@@ -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,
@@ -135,10 +139,10 @@
<bind name="deptNameLike" value="'%' + customer.deptName + '%'"/>
AND dept_name LIKE #{deptNameLike}
</if>
<if test="customer.createTimeStart != null and customer.createTimeStart != ''">
<if test="customer.createTimeStart != null">
AND create_time &gt;= #{customer.createTimeStart}
</if>
<if test="customer.createTimeEnd != null and customer.createTimeEnd != ''">
<if test="customer.createTimeEnd != null">
AND create_time &lt;= #{customer.createTimeEnd}
</if>
ORDER BY create_time DESC
@@ -0,0 +1,21 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 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<CustomerInvoiceContact> {
}
@@ -41,6 +41,21 @@ import java.util.List;
*/
public interface DriverMapper extends BaseMapper<Driver> {
/**
* 按身份证号查询司机(包含逻辑删除记录,用于唯一性校验)。
*/
Driver selectByIdCardNoIncludingDeleted(@Param("idCardNo") String idCardNo);
/**
* 按主键查询司机(包含逻辑删除记录,用于提交前校验)。
*/
Driver selectByIdIncludingDeleted(@Param("id") Long id);
/**
* 恢复逻辑删除司机。
*/
int restoreById(@Param("id") Long id);
/**
* 自定义分页
*
@@ -20,6 +20,7 @@
<result column="education" property="education"/>
<result column="address_region" property="addressRegion"/>
<result column="address" property="address"/>
<result column="driving_vehicle" property="drivingVehicle"/>
<result column="posts" property="posts"/>
<result column="id_card_front" property="idCardFront"/>
<result column="id_card_back" property="idCardBack"/>
@@ -39,6 +40,7 @@
<result column="qualification_back" property="qualificationBack"/>
<result column="driver_type" property="driverType"/>
<result column="mobile" property="mobile"/>
<result column="user_id" property="userId"/>
<result column="contact_relation" property="contactRelation"/>
<result column="organization_name" property="organizationName"/>
<result column="emergency_contact_name" property="emergencyContactName"/>
@@ -64,6 +66,7 @@
education,
address_region,
address,
driving_vehicle,
posts,
id_card_front,
id_card_back,
@@ -83,6 +86,7 @@
qualification_back,
driver_type,
mobile,
user_id,
contact_relation,
organization_name,
emergency_contact_name,
@@ -90,6 +94,28 @@
remark
</sql>
<select id="selectByIdCardNoIncludingDeleted" resultType="org.springblade.transport.pojo.entity.Driver">
SELECT
<include refid="BaseColumn"/>
FROM blade_transport_driver
WHERE id_card_no = #{idCardNo}
LIMIT 1
</select>
<select id="selectByIdIncludingDeleted" resultType="org.springblade.transport.pojo.entity.Driver">
SELECT
<include refid="BaseColumn"/>
FROM blade_transport_driver
WHERE id = #{id}
LIMIT 1
</select>
<update id="restoreById">
UPDATE blade_transport_driver
SET is_deleted = 0
WHERE id = #{id}
</update>
<sql id="ExpiryExpiredCondition">
(
((driving_license_long_term IS NULL OR driving_license_long_term != 1) AND driving_license_end_date &lt; #{driver.today})
@@ -113,6 +139,10 @@
<bind name="driverNameLike" value="'%' + driver.driverName + '%'"/>
AND driver_name LIKE #{driverNameLike}
</if>
<if test="driver.posts != null and driver.posts != ''">
<bind name="postsLike" value="'%' + driver.posts + '%'"/>
AND posts LIKE #{postsLike}
</if>
<if test="driver.mobile != null and driver.mobile != ''">
<bind name="mobileLike" value="'%' + driver.mobile + '%'"/>
AND mobile LIKE #{mobileLike}
@@ -0,0 +1,16 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementChangeRecord;
/** 正式结算变更记录 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementChangeRecordMapper extends BaseMapper<FormalSettlementChangeRecord> {
}
@@ -0,0 +1,18 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementDetailFee;
/** 正式结算货物费用 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementDetailFeeMapper extends BaseMapper<FormalSettlementDetailFee> {
}
@@ -0,0 +1,18 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementDetail;
/** 正式结算明细 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementDetailMapper extends BaseMapper<FormalSettlementDetail> {
}
@@ -0,0 +1,22 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementInvoice;
/**
* 正式结算发票明细 Mapper
*
* @author Chill
*/
@Mapper
public interface FormalSettlementInvoiceMapper extends BaseMapper<FormalSettlementInvoice> {
}
@@ -0,0 +1,32 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springblade.transport.pojo.entity.FormalSettlement;
/** 正式结算单 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementMapper extends BaseMapper<FormalSettlement> {
/**
* 按正式结算单号查询,包含逻辑删除记录,用于新增时复用软删除单据。
*/
@Select("SELECT * FROM blade_formal_settlement WHERE tenant_id = #{tenantId} AND formal_settlement_no = #{formalSettlementNo} ORDER BY is_deleted ASC, id DESC LIMIT 1")
FormalSettlement selectByFormalSettlementNoIncludingDeleted(@Param("tenantId") String tenantId,
@Param("formalSettlementNo") String formalSettlementNo);
/** 恢复逻辑删除的正式结算单主记录。 */
@Update("UPDATE blade_formal_settlement SET is_deleted = 0 WHERE tenant_id = #{tenantId} AND id = #{id} AND is_deleted = 1")
int restoreByIdIncludingDeleted(@Param("tenantId") String tenantId, @Param("id") Long id);
}
@@ -0,0 +1,18 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementPayment;
/** 正式结算付款申请 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementPaymentMapper extends BaseMapper<FormalSettlementPayment> {
}
@@ -0,0 +1,18 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.FormalSettlementSource;
/** 正式结算来源 Mapper。 @author Chill */
@Mapper
public interface FormalSettlementSourceMapper extends BaseMapper<FormalSettlementSource> {
}
@@ -0,0 +1,20 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement obtained after purchasing a license from BladeX.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.FormalSettlementSummaryFee;
/**
* 正式结算合计费用 Mapper
*
* @author Chill
*/
public interface FormalSettlementSummaryFeeMapper extends BaseMapper<FormalSettlementSummaryFee> {
}
@@ -0,0 +1,38 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.springblade.transport.pojo.entity.InsuranceOcrTemplate;
/**
* 保险OCR识别模板Mapper接口。
*
* @author Chill
*/
public interface InsuranceOcrTemplateMapper extends BaseMapper<InsuranceOcrTemplate> {
}
@@ -68,10 +68,10 @@
<if test="insuranceRecord.insuranceType != null and insuranceRecord.insuranceType != ''">
AND insurance_type = #{insuranceRecord.insuranceType}
</if>
<if test="insuranceRecord.createTimeStart != null and insuranceRecord.createTimeStart != ''">
<if test="insuranceRecord.createTimeStart != null">
AND create_time &gt;= #{insuranceRecord.createTimeStart}
</if>
<if test="insuranceRecord.createTimeEnd != null and insuranceRecord.createTimeEnd != ''">
<if test="insuranceRecord.createTimeEnd != null">
AND create_time &lt;= #{insuranceRecord.createTimeEnd}
</if>
ORDER BY create_time DESC
@@ -0,0 +1,39 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.InvoiceApplicationDetail;
/**
* 开票申请结算明细 Mapper 接口
*
* @author Chill
*/
@Mapper
public interface InvoiceApplicationDetailMapper extends BaseMapper<InvoiceApplicationDetail> {
}
@@ -0,0 +1,39 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.transport.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.springblade.transport.pojo.entity.InvoiceApplicationLine;
/**
* 开票申请商品行 Mapper 接口
*
* @author Chill
*/
@Mapper
public interface InvoiceApplicationLineMapper extends BaseMapper<InvoiceApplicationLine> {
}

Some files were not shown because too many files have changed in this diff Show More