贴标申请,仓储转运
This commit is contained in:
@@ -113,6 +113,43 @@ async function createPda(adminToken, warehouseId, onCreated) {
|
||||
throw new Error('Temporary PDA security projection did not converge')
|
||||
}
|
||||
|
||||
async function merchantSessionForTenant(adminToken, tenantId) {
|
||||
const ticket = await api(domestic, adminToken, 'POST',
|
||||
`/api/platform/v1/iam/tenants/${tenantId}/impersonation`, { reason: `${marker} 海外换标真实验收` })
|
||||
return api(domestic, '', 'POST', '/api/auth/impersonations/exchange', { code: ticket.code })
|
||||
}
|
||||
|
||||
async function findRelabelScope(adminToken, preferredMerchant = null) {
|
||||
const sessions = []
|
||||
if (preferredMerchant?.accessToken && preferredMerchant?.overseasAccessToken) sessions.push(preferredMerchant)
|
||||
if (!sessions.length) {
|
||||
const tenants = await api(domestic, adminToken, 'GET', '/api/platform/v1/iam/tenants?page=1&size=200&status=ACTIVE')
|
||||
for (const tenant of tenants.records || []) {
|
||||
try { sessions.push(await merchantSessionForTenant(adminToken, id(tenant.id))) } catch {}
|
||||
}
|
||||
}
|
||||
for (const session of sessions) {
|
||||
const customerId = jwtId(session.overseasAccessToken, 'tenant_id', 'tenantId')
|
||||
if (!customerId) continue
|
||||
let warehouses
|
||||
try { warehouses = await api(domestic, session.accessToken, 'GET', '/api/merchant/v1/warehouses?warehouseType=OVERSEAS&page=1&size=200') }
|
||||
catch { continue }
|
||||
for (const warehouse of warehouses.records || []) {
|
||||
if (warehouse.status !== 'ACTIVE') continue
|
||||
let candidates
|
||||
try { candidates = await api(overseas, session.overseasAccessToken, 'GET', `/api/merchant/v1/last-leg/relabel-applications/inventory-candidates?operationWarehouseId=${encodeURIComponent(id(warehouse.id))}`) }
|
||||
catch { continue }
|
||||
if (candidates.some((item) => String(item.inboundOrderNo || '').startsWith('DS-')
|
||||
&& Number(item.availablePackages) >= 5 && item.destinationFbaWarehouseCode
|
||||
&& item.positions?.some((position) => position.palletNo && position.palletNo !== 'UNBOUND'
|
||||
&& Number(position.availablePackages) >= 5))) {
|
||||
return { merchant: session, customerId, warehouse }
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new Error('No active customer has a destination warehouse and five cartons on a physical source pallet')
|
||||
}
|
||||
|
||||
await mkdir(outputDir, { recursive: true })
|
||||
let admin
|
||||
let pda
|
||||
@@ -124,29 +161,22 @@ try {
|
||||
}
|
||||
const storedMerchantToken = storedJwt('cc-client-overseas-access-token')
|
||||
const storedCustomerId = jwtId(storedMerchantToken, 'tenant_id', 'tenantId')
|
||||
let merchant
|
||||
let preferredMerchant = null
|
||||
try {
|
||||
merchant = await refreshStoredSession('cc-client-refresh-token', 'merchant')
|
||||
preferredMerchant = await refreshStoredSession('cc-client-refresh-token', 'merchant')
|
||||
} catch {
|
||||
assert(storedCustomerId, 'Current Codex merchant session does not contain a customer id')
|
||||
const ticket = await api(domestic, admin.accessToken, 'POST',
|
||||
`/api/platform/v1/iam/tenants/${storedCustomerId}/impersonation`, { reason: `${marker} 当前客户海外API验收` })
|
||||
merchant = await api(domestic, '', 'POST', '/api/auth/impersonations/exchange', { code: ticket.code })
|
||||
if (storedCustomerId) preferredMerchant = await merchantSessionForTenant(admin.accessToken, storedCustomerId)
|
||||
}
|
||||
assert(admin.accessToken && admin.overseasAccessToken && merchant.accessToken && merchant.overseasAccessToken, 'Refresh response did not contain both regional tokens')
|
||||
const customerId = jwtId(merchant.overseasAccessToken, 'tenant_id', 'tenantId')
|
||||
assert(customerId, 'Current merchant customer id is missing from the overseas token')
|
||||
const warehouses = await api(domestic, merchant.accessToken, 'GET', '/api/merchant/v1/warehouses?warehouseType=OVERSEAS&page=1&size=200')
|
||||
let selected = null
|
||||
for (const warehouse of warehouses.records || []) {
|
||||
if (warehouse.status !== 'ACTIVE') continue
|
||||
const candidates = await api(overseas, merchant.overseasAccessToken, 'GET', `/api/merchant/v1/last-leg/relabel-applications/inventory-candidates?operationWarehouseId=${encodeURIComponent(id(warehouse.id))}`)
|
||||
if (candidates.some((item) => String(item.inboundOrderNo || '').startsWith('DS-') && Number(item.availablePackages) >= 5 && item.destinationFbaWarehouseCode && item.positions?.some((position) => Number(position.availablePackages) >= 5))) {
|
||||
selected = warehouse; break
|
||||
}
|
||||
}
|
||||
assert(selected, 'Current merchant has no active overseas warehouse with a five-carton DS inventory source')
|
||||
await disableStalePdas(admin.accessToken)
|
||||
assert(admin.accessToken && admin.overseasAccessToken, 'Platform refresh response did not contain both regional tokens')
|
||||
const resume = process.env.OVERSEAS_RESUME_FULFILLMENT === 'true'
|
||||
if (resume && (!process.env.OVERSEAS_TEST_CUSTOMER_ID || !process.env.OVERSEAS_TEST_WAREHOUSE_ID)) throw new Error('Resume requires explicit customer and warehouse from the saved run')
|
||||
const scope = resume ? {
|
||||
merchant: await merchantSessionForTenant(admin.accessToken, process.env.OVERSEAS_TEST_CUSTOMER_ID),
|
||||
customerId: process.env.OVERSEAS_TEST_CUSTOMER_ID,
|
||||
warehouse: { id: process.env.OVERSEAS_TEST_WAREHOUSE_ID, warehouseCode: process.env.OVERSEAS_TEST_WAREHOUSE_CODE || null },
|
||||
} : await findRelabelScope(admin.accessToken, preferredMerchant)
|
||||
const { merchant, customerId, warehouse: selected } = scope
|
||||
// Do not disable accounts from another acceptance run; cleanup owns only this run's account.
|
||||
pda = await createPda(admin.accessToken, id(selected.id), (created) => { pda = created })
|
||||
|
||||
const relabelReport = join(outputDir, 'relabel.json')
|
||||
@@ -156,7 +186,10 @@ try {
|
||||
PDA_OVERSEAS_ACCESS_TOKEN: pda.token, OVERSEAS_TEST_CUSTOMER_ID: customerId,
|
||||
OVERSEAS_TEST_WAREHOUSE_ID: id(selected.id), OVERSEAS_ACCEPTANCE_OUTPUT: relabelReport,
|
||||
OVERSEAS_ACCEPTANCE_SOURCE: relabelReport, OVERSEAS_FULFILLMENT_OUTPUT: fulfillmentReport }
|
||||
for (const script of ['overseas-relabel-real-acceptance.mjs', 'overseas-relabel-fulfillment-acceptance.mjs']) {
|
||||
const scripts = process.env.OVERSEAS_CLOSURE_EXTRA === 'true' ? ['relabel-closure-local-acceptance.mjs'] : process.env.OVERSEAS_RESUME_FULFILLMENT === 'true'
|
||||
? ['overseas-relabel-fulfillment-acceptance.mjs']
|
||||
: ['overseas-relabel-real-acceptance.mjs', 'overseas-relabel-fulfillment-acceptance.mjs']
|
||||
for (const script of scripts) {
|
||||
const result = spawnSync(process.execPath, [resolve('scripts', script)], { cwd: resolve('.'), env: childEnv, stdio: 'inherit' })
|
||||
if (result.error) throw result.error
|
||||
if (result.status !== 0) throw new Error(`${script} failed with exit code ${result.status}`)
|
||||
|
||||
Reference in New Issue
Block a user