贴标申请,仓储转运
This commit is contained in:
@@ -6364,7 +6364,7 @@ INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id,
|
|||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306180,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:discard:list','货物废弃','/overseas-warehouse/cargo-disposal','GET',130,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306180,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:discard:list','货物废弃','/overseas-warehouse/cargo-disposal','GET',130,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306181,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:create','创建货物废弃申请',NULL,'POST',10,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306181,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:create','创建货物废弃申请',NULL,'POST',10,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306182,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请',NULL,'POST',20,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306182,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请',NULL,'POST',20,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306190,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:return-order:list','退货预报','/overseas-warehouse/return-relabel','GET',140,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306190,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:return-order:list','退货换标','/overseas-warehouse/return-relabel','GET',140,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306191,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:create','创建退货预报',NULL,'POST',10,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306191,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:create','创建退货预报',NULL,'POST',10,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306192,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:relabel','退货转换标申请',NULL,'POST',20,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
INSERT INTO iam_permission (id, tenant_id, app_code, permission_type, parent_id, permission_code, permission_name, route_path, http_method, sort_no, status, built_in, created_at, updated_at, deleted) VALUES (5306192,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:relabel','退货转换标申请',NULL,'POST',20,'ACTIVE',1,CURRENT_TIMESTAMP(3),CURRENT_TIMESTAMP(3),0);
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ VALUES
|
|||||||
(5306180,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:discard:list','货物废弃','/overseas-warehouse/cargo-disposal','GET',130,'ACTIVE',1,0),
|
(5306180,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:discard:list','货物废弃','/overseas-warehouse/cargo-disposal','GET',130,'ACTIVE',1,0),
|
||||||
(5306181,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:create','创建货物废弃申请',NULL,'POST',10,'ACTIVE',1,0),
|
(5306181,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:create','创建货物废弃申请',NULL,'POST',10,'ACTIVE',1,0),
|
||||||
(5306182,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请',NULL,'POST',20,'ACTIVE',1,0),
|
(5306182,0,'MERCHANT','BUTTON',5306180,'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请',NULL,'POST',20,'ACTIVE',1,0),
|
||||||
(5306190,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:return-order:list','退货预报','/overseas-warehouse/return-relabel','GET',140,'ACTIVE',1,0),
|
(5306190,0,'MERCHANT','MENU',0,'merchant:overseas-warehouse:return-order:list','退货换标','/overseas-warehouse/return-relabel','GET',140,'ACTIVE',1,0),
|
||||||
(5306191,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:create','创建退货预报',NULL,'POST',10,'ACTIVE',1,0),
|
(5306191,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:create','创建退货预报',NULL,'POST',10,'ACTIVE',1,0),
|
||||||
(5306192,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:relabel','退货转换标申请',NULL,'POST',20,'ACTIVE',1,0)
|
(5306192,0,'MERCHANT','BUTTON',5306190,'merchant:overseas-warehouse:return-order:relabel','退货转换标申请',NULL,'POST',20,'ACTIVE',1,0)
|
||||||
ON DUPLICATE KEY UPDATE permission_type=VALUES(permission_type), parent_id=VALUES(parent_id),
|
ON DUPLICATE KEY UPDATE permission_type=VALUES(permission_type), parent_id=VALUES(parent_id),
|
||||||
|
|||||||
+1
@@ -51,6 +51,7 @@ class OverseasCustomerPermissionSqlContractTest {
|
|||||||
"'merchant:cross-border:pallet-shipping:list','美本土散板','/cross-border/pallet-shipping'",
|
"'merchant:cross-border:pallet-shipping:list','美本土散板','/cross-border/pallet-shipping'",
|
||||||
"'merchant:warehouse:inbound:list','海外仓入库订单','/orders/inbound'",
|
"'merchant:warehouse:inbound:list','海外仓入库订单','/orders/inbound'",
|
||||||
"'merchant:overseas-warehouse:return-inventory:list','退货库存','/overseas-warehouse/return-inventory'",
|
"'merchant:overseas-warehouse:return-inventory:list','退货库存','/overseas-warehouse/return-inventory'",
|
||||||
|
"'merchant:overseas-warehouse:return-order:list','退货换标','/overseas-warehouse/return-relabel'",
|
||||||
"'merchant:overseas-warehouse:relabel:files','管理贴标文件'",
|
"'merchant:overseas-warehouse:relabel:files','管理贴标文件'",
|
||||||
"'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请'");
|
"'merchant:overseas-warehouse:discard:cancel','取消货物废弃申请'");
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -10,6 +10,8 @@ import com.baiyue.lastleg.security.OverseasPermissions;
|
|||||||
import jakarta.annotation.Resource;
|
import jakarta.annotation.Resource;
|
||||||
import jakarta.validation.Valid;
|
import jakarta.validation.Valid;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
import org.springframework.security.core.annotation.AuthenticationPrincipal;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
@@ -28,6 +30,14 @@ public class MerchantReturnOrderController {
|
|||||||
@GetMapping("/{returnNo}") @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RETURN_ORDER_LIST + "')")
|
@GetMapping("/{returnNo}") @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RETURN_ORDER_LIST + "')")
|
||||||
public ApiResponse<ReturnOrderResponses.Detail> detail(@AuthenticationPrincipal AuthenticatedUser user,
|
public ApiResponse<ReturnOrderResponses.Detail> detail(@AuthenticationPrincipal AuthenticatedUser user,
|
||||||
@PathVariable String returnNo) { return ApiResponse.success(service.detail(customer(user), returnNo)); }
|
@PathVariable String returnNo) { return ApiResponse.success(service.detail(customer(user), returnNo)); }
|
||||||
|
@GetMapping("/{returnNo}/photos/files/{fileId}/download")
|
||||||
|
@PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RETURN_ORDER_LIST + "')")
|
||||||
|
public ResponseEntity<byte[]> downloadPhoto(@AuthenticationPrincipal AuthenticatedUser user,
|
||||||
|
@PathVariable String returnNo, @PathVariable long fileId) {
|
||||||
|
var file = service.downloadPhoto(customer(user), returnNo, fileId);
|
||||||
|
return ResponseEntity.ok().contentType(MediaType.parseMediaType(file.contentType()))
|
||||||
|
.header("Cache-Control", "no-store").body(file.content());
|
||||||
|
}
|
||||||
@GetMapping("/{returnNo}/relabel-candidates") @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL + "')")
|
@GetMapping("/{returnNo}/relabel-candidates") @PreAuthorize("hasAuthority('" + OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL + "')")
|
||||||
public ApiResponse<java.util.List<ReturnOrderResponses.RelabelCandidate>> relabelCandidates(
|
public ApiResponse<java.util.List<ReturnOrderResponses.RelabelCandidate>> relabelCandidates(
|
||||||
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String returnNo) {
|
@AuthenticationPrincipal AuthenticatedUser user, @PathVariable String returnNo) {
|
||||||
|
|||||||
@@ -1516,6 +1516,17 @@ paths:
|
|||||||
security: [{ bearerAuth: [] }]
|
security: [{ bearerAuth: [] }]
|
||||||
parameters: [{ name: returnNo, in: path, required: true, schema: { type: string } }]
|
parameters: [{ name: returnNo, in: path, required: true, schema: { type: string } }]
|
||||||
responses: { '200': { description: 当前客户退货订单详情 }, '404': { description: 当前客户下退货订单不存在 } }
|
responses: { '200': { description: 当前客户退货订单详情 }, '404': { description: 当前客户下退货订单不存在 } }
|
||||||
|
/api/merchant/v1/last-leg/return-orders/{returnNo}/photos/files/{fileId}/download:
|
||||||
|
get:
|
||||||
|
summary: 客户下载退货签收打托照片
|
||||||
|
description: 权限 merchant:overseas-warehouse:return-order:list;仅允许下载当前客户、当前退货单关联的签收照片,响应为原始文件且禁止缓存。
|
||||||
|
security: [{ bearerAuth: [] }]
|
||||||
|
parameters:
|
||||||
|
- { name: returnNo, in: path, required: true, schema: { type: string } }
|
||||||
|
- { name: fileId, in: path, required: true, schema: { type: integer, format: int64 } }
|
||||||
|
responses:
|
||||||
|
'200': { description: 照片文件, content: { image/*: { schema: { type: string, format: binary } } } }
|
||||||
|
'404': { description: 当前客户下退货单或关联照片不存在 }
|
||||||
/api/merchant/v1/last-leg/return-orders/{returnNo}/relabel-candidates:
|
/api/merchant/v1/last-leg/return-orders/{returnNo}/relabel-candidates:
|
||||||
get:
|
get:
|
||||||
summary: 查询退货单可转换标候选
|
summary: 查询退货单可转换标候选
|
||||||
|
|||||||
+1
@@ -87,6 +87,7 @@ class MerchantOverseasCustomerApiContractTest {
|
|||||||
"create", OverseasPermissions.MERCHANT_RETURN_ORDER_CREATE,
|
"create", OverseasPermissions.MERCHANT_RETURN_ORDER_CREATE,
|
||||||
"page", OverseasPermissions.MERCHANT_RETURN_ORDER_LIST,
|
"page", OverseasPermissions.MERCHANT_RETURN_ORDER_LIST,
|
||||||
"detail", OverseasPermissions.MERCHANT_RETURN_ORDER_LIST,
|
"detail", OverseasPermissions.MERCHANT_RETURN_ORDER_LIST,
|
||||||
|
"downloadPhoto", OverseasPermissions.MERCHANT_RETURN_ORDER_LIST,
|
||||||
"relabelCandidates", OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL,
|
"relabelCandidates", OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL,
|
||||||
"createRelabel", OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL));
|
"createRelabel", OverseasPermissions.MERCHANT_RETURN_ORDER_RELABEL));
|
||||||
assertPermissions(MerchantRelabelApplicationController.class, Map.of(
|
assertPermissions(MerchantRelabelApplicationController.class, Map.of(
|
||||||
|
|||||||
+2
-1
@@ -32,7 +32,8 @@ class MerchantOverseasOpenApiContractTest {
|
|||||||
"/api/merchant/v1/last-leg/local-looseboard-orders:",
|
"/api/merchant/v1/last-leg/local-looseboard-orders:",
|
||||||
"/api/merchant/v1/last-leg/local-looseboard-orders/{orderNo}:",
|
"/api/merchant/v1/last-leg/local-looseboard-orders/{orderNo}:",
|
||||||
"/api/merchant/v1/last-leg/inbound-plans:",
|
"/api/merchant/v1/last-leg/inbound-plans:",
|
||||||
"/api/merchant/v1/last-leg/inbound-plans/{planNo}:"}) {
|
"/api/merchant/v1/last-leg/inbound-plans/{planNo}:",
|
||||||
|
"/api/merchant/v1/last-leg/return-orders/{returnNo}/photos/files/{fileId}/download:"}) {
|
||||||
assertThat(yaml).contains(path);
|
assertThat(yaml).contains(path);
|
||||||
assertThat(pathBlock(yaml, path)).doesNotContain("name: customerId");
|
assertThat(pathBlock(yaml, path)).doesNotContain("name: customerId");
|
||||||
}
|
}
|
||||||
|
|||||||
+26
@@ -22,6 +22,7 @@ import com.baiyue.lastleg.relabel.mapper.RelabelApplicationMapper;
|
|||||||
import com.baiyue.lastleg.relabel.mapper.RelabelItemMapper;
|
import com.baiyue.lastleg.relabel.mapper.RelabelItemMapper;
|
||||||
import com.baiyue.lastleg.relabel.entity.RelabelApplication;
|
import com.baiyue.lastleg.relabel.entity.RelabelApplication;
|
||||||
import com.baiyue.lastleg.relabel.entity.RelabelItem;
|
import com.baiyue.lastleg.relabel.entity.RelabelItem;
|
||||||
|
import com.baiyue.lastleg.relabel.pda.gateway.RelabelPhotoFileGateway;
|
||||||
import com.baiyue.lastleg.service.FbaWarehouseValidator;
|
import com.baiyue.lastleg.service.FbaWarehouseValidator;
|
||||||
import com.baiyue.lastleg.service.LastlegOrderNoGenerator;
|
import com.baiyue.lastleg.service.LastlegOrderNoGenerator;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
@@ -67,6 +68,7 @@ class ReturnReceiptServiceTest {
|
|||||||
@Mock RelabelApplicationMapper relabelApplications;
|
@Mock RelabelApplicationMapper relabelApplications;
|
||||||
@Mock RelabelItemMapper relabelItems;
|
@Mock RelabelItemMapper relabelItems;
|
||||||
@Mock FbaWarehouseValidator fbaWarehouseValidator;
|
@Mock FbaWarehouseValidator fbaWarehouseValidator;
|
||||||
|
@Mock RelabelPhotoFileGateway photoFiles;
|
||||||
|
|
||||||
ReturnReceiptService service;
|
ReturnReceiptService service;
|
||||||
PdaWarehouseIdentity identity;
|
PdaWarehouseIdentity identity;
|
||||||
@@ -91,6 +93,30 @@ class ReturnReceiptServiceTest {
|
|||||||
identity = new PdaWarehouseIdentity("operator-1", "仓管员", 10L);
|
identity = new PdaWarehouseIdentity("operator-1", "仓管员", 10L);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void merchantPhotoDownloadUsesAuthenticatedCustomerAndResolvedReturnOrder() {
|
||||||
|
ReflectionTestUtils.setField(service, "photoFiles", photoFiles);
|
||||||
|
ReturnOrder order = order("RT-1", "10", ReturnReceiptService.COMPLETED, 2, 2);
|
||||||
|
var downloaded = new RelabelPhotoFileGateway.DownloadedFile(new byte[] { 1, 2 }, "proof.jpg", "image/jpeg");
|
||||||
|
when(orders.findNo("customer-1", "RT-1")).thenReturn(order);
|
||||||
|
when(photoFiles.download("customer-1", 1L, 99L)).thenReturn(downloaded);
|
||||||
|
|
||||||
|
assertEquals(downloaded, service.downloadPhoto("customer-1", "RT-1", 99L));
|
||||||
|
verify(photoFiles).download("customer-1", 1L, 99L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void merchantPhotoDownloadRejectsUnknownCustomerOrderBeforeFileAccess() {
|
||||||
|
ReflectionTestUtils.setField(service, "photoFiles", photoFiles);
|
||||||
|
when(orders.findNo("other-customer", "RT-1")).thenReturn(null);
|
||||||
|
|
||||||
|
ResponseStatusException error = assertThrows(ResponseStatusException.class,
|
||||||
|
() -> service.downloadPhoto("other-customer", "RT-1", 99L));
|
||||||
|
|
||||||
|
assertEquals(404, error.getStatusCode().value());
|
||||||
|
verifyNoInteractions(photoFiles);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void multiSkuPartialRelabelLocksOnlyRequestedQuantities() {
|
void multiSkuPartialRelabelLocksOnlyRequestedQuantities() {
|
||||||
verifyMultiSkuRelabel(30, 15);
|
verifyMultiSkuRelabel(30, 15);
|
||||||
|
|||||||
Reference in New Issue
Block a user