This commit is contained in:
2026-08-26 11:05:26 +08:00
parent 3bf68c1083
commit 270372f56a
13 changed files with 290 additions and 2 deletions
@@ -7,6 +7,7 @@ import com.baiyue.common.security.AuthenticatedUser;
import com.baiyue.lastleg.dto.LastlegOrderDetailResponse;
import com.baiyue.lastleg.dto.LastlegOrderRequests;
import com.baiyue.lastleg.dto.LastlegOrderSummary;
import com.baiyue.lastleg.entity.LastlegOrderFee;
import com.baiyue.lastleg.security.InternalServiceTokenGuard;
import com.baiyue.lastleg.security.OverseasPermissions;
import com.baiyue.lastleg.service.LastlegOrderService;
@@ -81,6 +82,17 @@ public class LastlegOrderController {
return ApiResponse.success(orderService.detail(platformScope(user, customerId), id));
}
@PostMapping("/api/platform/v1/last-leg/orders/{id}/fees")
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EDIT + "')")
@Operation(summary = "Add a fee to one tail-leg order", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EDIT)
public ApiResponse<LastlegOrderFee> createFee(
@AuthenticationPrincipal AuthenticatedUser user,
@RequestParam(required = false) String customerId,
@PathVariable long id,
@Valid @RequestBody LastlegOrderRequests.CreateFee request) {
return ApiResponse.success(orderService.createFee(platformScope(user, customerId), id, request, operatorName(user)));
}
@GetMapping(value = "/api/platform/v1/last-leg/orders/export", produces = "text/csv")
@PreAuthorize("hasAuthority('" + OverseasPermissions.LAST_MILE_ORDER_EXPORT + "')")
@Operation(summary = "Export filtered tail-leg orders as UTF-8 CSV", description = "Required authority: " + OverseasPermissions.LAST_MILE_ORDER_EXPORT)
@@ -126,4 +138,8 @@ public class LastlegOrderController {
return requestedCustomer == null || requestedCustomer.isBlank() || "0".equals(requestedCustomer)
? null : requestedCustomer.trim();
}
private String operatorName(AuthenticatedUser user) {
return user.username() == null || user.username().isBlank() ? String.valueOf(user.userId()) : user.username();
}
}
@@ -1,6 +1,7 @@
package com.baiyue.lastleg.dto;
import com.baiyue.lastleg.entity.LastlegOrderDetail;
import com.baiyue.lastleg.entity.LastlegOrderFee;
import java.time.LocalDateTime;
@@ -9,7 +10,10 @@ import java.util.List;
public record LastlegOrderDetailResponse(
LastlegOrderSummary order,
List<LastlegOrderDetail> cargo,
List<History> statusHistory
List<History> statusHistory,
List<LastlegOrderFee> fees,
List<Operation> operationHistory
) {
public record History(Long id, String fromStatus, String toStatus, String remark, LocalDateTime createdAt) {}
public record Operation(Long id, String operationNode, String operatorName, String result, LocalDateTime createdAt) {}
}
@@ -5,7 +5,11 @@ import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@@ -55,4 +59,13 @@ public final class LastlegOrderRequests {
return new TransferDestination(List.of(orderId), warehouseId, warehouseCode, warehouseName, remark);
}
}
public record CreateFee(
@NotBlank @Size(max = 128) String feeItem,
@NotBlank @Pattern(regexp = "[A-Z]{3}") String currency,
@NotNull @DecimalMin(value = "0.01") BigDecimal amount,
@NotBlank @Pattern(regexp = "PENDING_REVIEW|APPROVED|REJECTED") String status,
@Size(max = 500) String supplierDescription
) {
}
}
@@ -0,0 +1,25 @@
package com.baiyue.lastleg.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("ll_order_fee")
public class LastlegOrderFee {
@TableId(type = IdType.INPUT) private Long id;
private String customerId;
private Long orderId;
private String feeItem;
private String currency;
private BigDecimal amount;
private String status;
private String supplierDescription;
private String createdBy;
private LocalDateTime createdAt;
private LocalDateTime updatedAt;
}
@@ -0,0 +1,20 @@
package com.baiyue.lastleg.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("ll_order_operation_log")
public class LastlegOrderOperationLog {
@TableId(type = IdType.INPUT) private Long id;
private String customerId;
private Long orderId;
private String operationNode;
private String operatorName;
private String result;
private LocalDateTime createdAt;
}
@@ -0,0 +1,9 @@
package com.baiyue.lastleg.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.lastleg.entity.LastlegOrderFee;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LastlegOrderFeeMapper extends BaseMapper<LastlegOrderFee> {
}
@@ -0,0 +1,9 @@
package com.baiyue.lastleg.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baiyue.lastleg.entity.LastlegOrderOperationLog;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LastlegOrderOperationLogMapper extends BaseMapper<LastlegOrderOperationLog> {
}
@@ -1,6 +1,7 @@
package com.baiyue.lastleg.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baiyue.common.core.api.PageResult;
import com.baiyue.lastleg.dto.LastlegOrderDetailResponse;
@@ -9,11 +10,15 @@ import com.baiyue.lastleg.dto.LastlegOrderSummary;
import com.baiyue.lastleg.entity.LastlegOrder;
import com.baiyue.lastleg.entity.LastlegOrderDetail;
import com.baiyue.lastleg.entity.LastlegOrderStatusHistory;
import com.baiyue.lastleg.entity.LastlegOrderFee;
import com.baiyue.lastleg.entity.LastlegOrderOperationLog;
import com.baiyue.lastleg.inboundplan.entity.InboundPlanCarton;
import com.baiyue.lastleg.inboundplan.mapper.InboundPlanCartonMapper;
import com.baiyue.lastleg.mapper.LastlegOrderDetailMapper;
import com.baiyue.lastleg.mapper.LastlegOrderMapper;
import com.baiyue.lastleg.mapper.LastlegOrderStatusHistoryMapper;
import com.baiyue.lastleg.mapper.LastlegOrderFeeMapper;
import com.baiyue.lastleg.mapper.LastlegOrderOperationLogMapper;
import com.baiyue.lastleg.model.LastlegOrderType;
import jakarta.annotation.Resource;
import org.springframework.http.HttpStatus;
@@ -37,6 +42,8 @@ public class LastlegOrderService {
@Resource private LastlegOrderMapper orderMapper;
@Resource private LastlegOrderDetailMapper detailMapper;
@Resource private LastlegOrderStatusHistoryMapper historyMapper;
@Resource private LastlegOrderFeeMapper feeMapper;
@Resource private LastlegOrderOperationLogMapper operationLogMapper;
@Resource private InboundPlanCartonMapper cartonMapper;
public PageResult<LastlegOrderSummary> page(String customerId, LastlegOrderRequests.Query query) {
@@ -56,9 +63,51 @@ public class LastlegOrderService {
.eq(LastlegOrderStatusHistory::getCustomerId, order.getCustomerId())
.eq(LastlegOrderStatusHistory::getOrderId, orderId)
.orderByAsc(LastlegOrderStatusHistory::getCreatedAt));
List<LastlegOrderFee> fees = feeMapper.selectList(new LambdaQueryWrapper<LastlegOrderFee>()
.eq(LastlegOrderFee::getCustomerId, order.getCustomerId())
.eq(LastlegOrderFee::getOrderId, orderId).orderByAsc(LastlegOrderFee::getCreatedAt));
List<LastlegOrderOperationLog> operations = operationLogMapper.selectList(
new LambdaQueryWrapper<LastlegOrderOperationLog>()
.eq(LastlegOrderOperationLog::getCustomerId, order.getCustomerId())
.eq(LastlegOrderOperationLog::getOrderId, orderId)
.orderByAsc(LastlegOrderOperationLog::getCreatedAt));
return new LastlegOrderDetailResponse(summary(order), cargo, history.stream()
.map(value -> new LastlegOrderDetailResponse.History(value.getId(), value.getFromStatus(),
value.getToStatus(), value.getRemark(), value.getCreatedAt())).toList());
value.getToStatus(), value.getRemark(), value.getCreatedAt())).toList(), fees, operations.stream()
.map(value -> new LastlegOrderDetailResponse.Operation(value.getId(), value.getOperationNode(),
value.getOperatorName(), value.getResult(), value.getCreatedAt())).toList());
}
@Transactional
public LastlegOrderFee createFee(String customerId, long orderId, LastlegOrderRequests.CreateFee request,
String operatorName) {
LastlegOrder order = findOwned(customerId, orderId);
LocalDateTime now = LocalDateTime.now();
LastlegOrderFee fee = new LastlegOrderFee();
fee.setId(IdWorker.getId());
fee.setCustomerId(order.getCustomerId());
fee.setOrderId(orderId);
fee.setFeeItem(request.feeItem().trim());
fee.setCurrency(request.currency());
fee.setAmount(request.amount());
fee.setStatus(request.status());
fee.setSupplierDescription(StringUtils.hasText(request.supplierDescription())
? request.supplierDescription().trim() : null);
fee.setCreatedBy(operatorName);
fee.setCreatedAt(now);
fee.setUpdatedAt(now);
feeMapper.insert(fee);
LastlegOrderOperationLog operation = new LastlegOrderOperationLog();
operation.setId(IdWorker.getId());
operation.setCustomerId(order.getCustomerId());
operation.setOrderId(orderId);
operation.setOperationNode("新增费用");
operation.setOperatorName(operatorName);
operation.setResult("新增" + fee.getFeeItem() + ":" + fee.getCurrency() + " " + fee.getAmount().toPlainString());
operation.setCreatedAt(now);
operationLogMapper.insert(operation);
return fee;
}
@Transactional