openapi: 3.0.3 info: title: Cargo discard PDA photo evidence version: 1.0.0 description: >- Each approved pallet requires 1–20 JPG/PNG photos before actual disposal confirmation. Uploads persist as drafts and recover through the PDA list endpoint. Confirmation binds selected photos in the same transaction as inventory deduction. Completed quantities and photo sets are immutable; identical replay does not deduct stock or create evidence again. Platform and merchant details expose only submitted photos, including photos of completed pallets while other pallets are still pending. Historic applications are not backfilled. security: - bearerAuth: [] paths: /api/pda/v1/last-leg/cargo-discards/{discardNo}/pallets/{palletNo}/photos/files: parameters: - $ref: '#/components/parameters/DiscardNo' - $ref: '#/components/parameters/PalletNo' post: summary: Upload an approved, unfinished pallet photo (PDA bound warehouse only) x-permissions: [lastleg:pda:operate, ROLE_OVERSEAS_WAREHOUSE_PDA_OPERATOR] requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: { type: string, format: binary, description: Non-empty JPG/PNG up to 10 MiB with image signature validation } responses: '200': { description: ApiResponse with uploaded Photo metadata; business errors use body code } get: summary: Recover all uploaded photos for this application and pallet x-permissions: [lastleg:pda:operate, ROLE_OVERSEAS_WAREHOUSE_PDA_OPERATOR] responses: '200': { description: ApiResponse with a Photo array, including unsubmitted uploads } /api/pda/v1/last-leg/cargo-discards/{discardNo}/pallets/{palletNo}/photos/files/{fileId}/download: parameters: - $ref: '#/components/parameters/DiscardNo' - $ref: '#/components/parameters/PalletNo' - $ref: '#/components/parameters/FileId' get: summary: Download a photo associated with this pallet in the PDA bound warehouse x-permissions: [lastleg:pda:operate, ROLE_OVERSEAS_WAREHOUSE_PDA_OPERATOR] responses: '200': { description: Inline JPG/PNG bytes with Cache-Control no-store } /api/pda/v1/last-leg/cargo-discards/{discardNo}/pallets/{palletNo}/confirm: parameters: - $ref: '#/components/parameters/DiscardNo' - $ref: '#/components/parameters/PalletNo' post: summary: Confirm actual disposal with owned pallet photos x-permissions: [lastleg:pda:operate, ROLE_OVERSEAS_WAREHOUSE_PDA_OPERATOR] requestBody: required: true content: application/json: schema: type: object required: [lines, photoFileIds] properties: lines: type: array minItems: 1 items: type: object required: [itemId, actualPackages] properties: itemId: { type: string, pattern: '^[1-9][0-9]*$' } actualPackages: { type: integer, minimum: 0 } photoFileIds: type: array minItems: 1 maxItems: 20 uniqueItems: true items: { type: string, pattern: '^[1-9][0-9]*$' } responses: '200': { description: ApiResponse containing the completed PalletTask; conflicts use business body code } /api/platform/v1/last-leg/cargo-discards/{discardNo}/photos/files/{fileId}/download: parameters: - $ref: '#/components/parameters/DiscardNo' - $ref: '#/components/parameters/FileId' - name: customerId in: query required: true schema: { type: string, pattern: '^[1-9][0-9]*$' } get: summary: Download a submitted photo after application/customer ownership validation x-permissions: [platform:overseas-warehouse:discard:list] responses: '200': { description: Inline JPG/PNG bytes with Cache-Control no-store } /api/merchant/v1/last-leg/cargo-discards/{discardNo}/photos/files/{fileId}/download: parameters: - $ref: '#/components/parameters/DiscardNo' - $ref: '#/components/parameters/FileId' get: summary: Download a submitted photo belonging to the authenticated customer only x-permissions: [merchant:overseas-warehouse:discard:list] responses: '200': { description: Inline JPG/PNG bytes with Cache-Control no-store; no customer override allowed } components: securitySchemes: bearerAuth: { type: http, scheme: bearer, bearerFormat: JWT } parameters: DiscardNo: { name: discardNo, in: path, required: true, schema: { type: string } } PalletNo: { name: palletNo, in: path, required: true, schema: { type: string } } FileId: { name: fileId, in: path, required: true, schema: { type: string, pattern: '^[1-9][0-9]*$' } } schemas: Photo: type: object required: [fileId, palletNo, fileName, contentType, sizeBytes, operatorId, createdAt] properties: fileId: { type: string } palletNo: { type: string } fileName: { type: string } contentType: { type: string, enum: [image/jpeg, image/png] } sizeBytes: { type: integer, format: int64, maximum: 10485760 } operatorId: { type: string } createdAt: { type: string, format: date-time } submittedAt: { type: string, format: date-time, nullable: true }