diff --git a/deploy/sql/头程数据库统一增量-MySQL8.sql b/deploy/sql/头程数据库统一增量-MySQL8.sql index d8e2f65e0..71f896806 100644 --- a/deploy/sql/头程数据库统一增量-MySQL8.sql +++ b/deploy/sql/头程数据库统一增量-MySQL8.sql @@ -16352,6 +16352,7 @@ VALUES (5107063,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:delete','删除海外库位',NULL,'DELETE',763,'ACTIVE',1,0), (5107090,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:outbound:list','海外出库单','/overseas-warehouse/outbounds','GET',765,'ACTIVE',1,0), (5107091,0,'PLATFORM','BUTTON',5107090,'platform:overseas-warehouse:outbound:create','创建海外出库单',NULL,'POST',766,'ACTIVE',1,0), + (5107092,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:delivery:list','海外派送单','/overseas-warehouse/delivery-orders','GET',767,'ACTIVE',1,0), (5107100,0,'PLATFORM','MENU',0,'platform:overseas-business:purchase:list','海外采购订单','/overseas-business/purchases','GET',800,'ACTIVE',1,0), (5107101,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:edit','编辑海外采购订单',NULL,'PATCH',801,'ACTIVE',1,0), (5107102,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:review','审核海外采购订单',NULL,'POST',802,'ACTIVE',1,0), @@ -16530,7 +16531,10 @@ INSERT IGNORE INTO baiyue_iam.iam_role_permission (tenant_id, role_id, permissio SELECT 0, role.id, permission.id, NOW(3) FROM baiyue_iam.iam_role role JOIN baiyue_iam.iam_permission permission ON permission.tenant_id=0 AND permission.app_code='PLATFORM' - AND permission.permission_code='platform:overseas-warehouse:outbound:list' + AND permission.permission_code IN ( + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:delivery:list' + ) WHERE role.tenant_id=0 AND role.app_code='PLATFORM' AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN' AND role.status='ACTIVE' AND role.deleted=0 AND permission.status='ACTIVE' AND permission.deleted=0; diff --git a/iam/src/main/resources/db/lastleg-permissions.sql b/iam/src/main/resources/db/lastleg-permissions.sql index bea660488..37f3c274f 100644 --- a/iam/src/main/resources/db/lastleg-permissions.sql +++ b/iam/src/main/resources/db/lastleg-permissions.sql @@ -41,6 +41,7 @@ VALUES (5107063,0,'PLATFORM','BUTTON',5107060,'platform:overseas-warehouse:location:delete','删除海外库位',NULL,'DELETE',763,'ACTIVE',1,0), (5107090,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:outbound:list','海外出库单','/overseas-warehouse/outbounds','GET',765,'ACTIVE',1,0), (5107091,0,'PLATFORM','BUTTON',5107090,'platform:overseas-warehouse:outbound:create','创建海外出库单',NULL,'POST',766,'ACTIVE',1,0), + (5107092,0,'PLATFORM','MENU',0,'platform:overseas-warehouse:delivery:list','海外派送单','/overseas-warehouse/delivery-orders','GET',767,'ACTIVE',1,0), (5107100,0,'PLATFORM','MENU',0,'platform:overseas-business:purchase:list','海外采购订单','/overseas-business/purchases','GET',800,'ACTIVE',1,0), (5107101,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:edit','编辑海外采购订单',NULL,'PATCH',801,'ACTIVE',1,0), (5107102,0,'PLATFORM','BUTTON',5107100,'platform:overseas-business:purchase:review','审核海外采购订单',NULL,'POST',802,'ACTIVE',1,0), @@ -215,12 +216,15 @@ WHERE role.tenant_id=0 AND role.app_code='PLATFORM' AND UPPER(role.role_code) IN ('PLATFORM_ADMIN','PLATFORM_CUSTOM_ADMIN') AND role.status='ACTIVE' AND role.deleted=0 AND permission.status='ACTIVE' AND permission.deleted=0; --- PLATFORM_CUSTOM_ADMIN needs access to the overseas outbound list shown in the admin navigation. +-- PLATFORM_CUSTOM_ADMIN needs access to the overseas outbound and delivery lists shown in the admin navigation. INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at) SELECT 0, role.id, permission.id, NOW(3) FROM iam_role role JOIN iam_permission permission ON permission.tenant_id=0 AND permission.app_code='PLATFORM' - AND permission.permission_code IN ('platform:overseas-warehouse:outbound:list') + AND permission.permission_code IN ( + 'platform:overseas-warehouse:outbound:list', + 'platform:overseas-warehouse:delivery:list' + ) WHERE role.tenant_id=0 AND role.app_code='PLATFORM' AND UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN' AND role.status='ACTIVE' AND role.deleted=0 AND permission.status='ACTIVE' AND permission.deleted=0; diff --git a/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java b/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java index 2182c43f1..3ab88262a 100644 --- a/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java +++ b/iam/src/test/java/com/baiyue/iam/repository/OverseasPhase4PermissionSqlContractTest.java @@ -41,10 +41,12 @@ class OverseasPhase4PermissionSqlContractTest { assertThat(sql).contains(REQUIRED.toArray(String[]::new)); assertThat(sql).contains("'lastleg:pda:operate'"); assertPdaPickerGrant(sql); - assertThat(catalog).hasSize(53).noneMatch(code -> code.endsWith(":view")); + assertThat(catalog).hasSize(54).noneMatch(code -> code.endsWith(":view")); assertThat(sql).contains("permission_code LIKE 'platform:lastleg:%'", "status='INACTIVE'", "deleted=1"); - assertThat(sql).doesNotContain(":carton:", ":product:", ":outbound:", ":delivery:"); + assertThat(sql).doesNotContain(":carton:", ":product:"); + assertThat(catalog).contains("platform:overseas-warehouse:delivery:list"); assertCustomAdminGrant(sql); + assertCustomAdminNavigationGrant(sql); } @Test @@ -58,6 +60,7 @@ class OverseasPhase4PermissionSqlContractTest { assertThat(sql).contains("baiyue_iam.iam_permission", "baiyue_iam.iam_role_permission", "'lastleg:pda:operate'"); assertPdaPickerGrant(sql); assertCustomAdminGrant(sql); + assertCustomAdminNavigationGrant(sql); } @Test @@ -138,6 +141,17 @@ class OverseasPhase4PermissionSqlContractTest { assertThat(sql.substring(grantStart, grantEnd)).contains("lastleg:pda:operate"); } + private static void assertCustomAdminNavigationGrant(String sql) { + int permissionIndex = sql.indexOf("'platform:overseas-warehouse:delivery:list'", sql.indexOf("PLATFORM_CUSTOM_ADMIN needs access")); + assertThat(permissionIndex).isGreaterThanOrEqualTo(0); + int grantStart = sql.lastIndexOf("INSERT IGNORE INTO", permissionIndex); + int grantEnd = sql.indexOf(';', permissionIndex); + assertThat(sql.substring(grantStart, grantEnd)).contains( + "UPPER(role.role_code)='PLATFORM_CUSTOM_ADMIN'", + "platform:overseas-warehouse:outbound:list", + "platform:overseas-warehouse:delivery:list"); + } + private static String matrixBlock(String sql) { int start = sql.indexOf("INSERT INTO tmp_phase4_warehouse_role_permission"); int end = sql.indexOf("DELETE grant_row FROM", start); diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/DeliveryTransferController.java b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/DeliveryTransferController.java index 24d02b3d3..5557f75f8 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/DeliveryTransferController.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/delivery/controller/DeliveryTransferController.java @@ -6,6 +6,7 @@ import com.baiyue.common.security.AuthenticatedUser; import com.baiyue.lastleg.delivery.dto.DeliveryRequests; import com.baiyue.lastleg.delivery.dto.DeliveryResponses; import com.baiyue.lastleg.delivery.service.DeliveryTransferService; +import com.baiyue.lastleg.security.OverseasPermissions; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -13,6 +14,7 @@ import jakarta.validation.Valid; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.http.HttpStatus; import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; @@ -65,6 +67,7 @@ public class DeliveryTransferController { } @GetMapping("/delivery-orders") + @PreAuthorize("hasAuthority('" + OverseasPermissions.DELIVERY_LIST + "')") public ApiResponse> deliveryPage( @AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId, @Valid DeliveryRequests.Query query) { @@ -72,6 +75,7 @@ public class DeliveryTransferController { } @GetMapping("/delivery-orders/{deliveryNo}") + @PreAuthorize("hasAuthority('" + OverseasPermissions.DELIVERY_LIST + "')") public ApiResponse deliveryDetail( @AuthenticationPrincipal AuthenticatedUser user, @RequestParam(required = false) String customerId, @PathVariable String deliveryNo, @Valid DeliveryRequests.PalletQuery query) { diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/dto/OverseasProcurementResponses.java b/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/dto/OverseasProcurementResponses.java index 638245829..06bd0242f 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/dto/OverseasProcurementResponses.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/dto/OverseasProcurementResponses.java @@ -14,7 +14,7 @@ public final class OverseasProcurementResponses { String purchaseCategory, String productName, String productSpecification, long purchaseQuantity, BigDecimal budgetUnitPrice, String currency, String purchaseWarehouseId, String purchaseWarehouseName, - long inboundQuantity, long inventoryQuantity, + long inboundQuantity, long outboundQuantity, long inventoryQuantity, String status, long version, LocalDateTime createdAt, LocalDateTime updatedAt) {} public record CustomerOption(String customerId, String customerName) {} diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/service/OverseasProcurementService.java b/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/service/OverseasProcurementService.java index 9ef5d938c..9d3becfb7 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/service/OverseasProcurementService.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/procurement/service/OverseasProcurementService.java @@ -232,11 +232,15 @@ public class OverseasProcurementService { private OverseasProcurementResponses.Summary summary(OverseasProcurementOrder order) { long inbound = value(order.getInboundQuantity()); long outbound = outboundDetails(order).stream().mapToLong(OverseasProcurementResponses.OutboundDetail::quantity).sum(); + String displayStatus = order.getStatus(); + if (APPROVED.equals(order.getStatus()) && inbound > 0) { + displayStatus = outbound == 0 ? "PENDING_OUTBOUND" : outbound < inbound ? "PARTIALLY_OUTBOUND" : "OUTBOUNDED"; + } return new OverseasProcurementResponses.Summary(order.getId(), order.getOrderNo(), order.getCustomerId(), order.getCustomerName(), order.getPurchaseCategory(), order.getProductName(), order.getProductSpecification(), value(order.getPurchaseQuantity()), order.getBudgetUnitPrice(), - order.getCurrency(), order.getPurchaseWarehouseId(), order.getPurchaseWarehouseName(), inbound, Math.max(0, inbound - outbound), - order.getStatus(), value(order.getVersion()), order.getCreatedAt(), order.getUpdatedAt()); + order.getCurrency(), order.getPurchaseWarehouseId(), order.getPurchaseWarehouseName(), inbound, outbound, Math.max(0, inbound - outbound), + displayStatus, value(order.getVersion()), order.getCreatedAt(), order.getUpdatedAt()); } private void history(OverseasProcurementOrder order, String operationType, String from, String to, diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java b/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java index 5ac51600c..4bd4f198f 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/security/OverseasPermissions.java @@ -19,6 +19,7 @@ public final class OverseasPermissions { public static final String INVENTORY_EXPORT = "platform:overseas-warehouse:inventory:export"; public static final String INVENTORY_EDIT = "platform:overseas-warehouse:inventory:edit"; public static final String INVENTORY_ADJUST = "platform:overseas-warehouse:inventory:adjust"; + public static final String DELIVERY_LIST = "platform:overseas-warehouse:delivery:list"; public static final String PURCHASE_LIST = "platform:overseas-business:purchase:list"; public static final String PURCHASE_EDIT = "platform:overseas-business:purchase:edit"; public static final String PURCHASE_REVIEW = "platform:overseas-business:purchase:review"; diff --git a/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml b/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml index 48cf108a2..e4e46e484 100644 --- a/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml +++ b/lastleg-service/src/main/resources/openapi/overseas-business-v1.yaml @@ -580,7 +580,7 @@ components: feeItem: { type: string, minLength: 1, maxLength: 128 } currency: { type: string, pattern: '^[A-Z]{3}$', example: USD } amount: { type: number, format: decimal, minimum: 0.01 } - status: { type: string, enum: [PENDING_REVIEW, APPROVED, REJECTED] } + status: { type: string, enum: [PENDING_REVIEW, APPROVED, REJECTED, PENDING_OUTBOUND, PARTIALLY_OUTBOUND, OUTBOUNDED] } supplierDescription: { type: string, maxLength: 500 } LastMileFee: type: object