后端迁移后台管理库存写操作

This commit is contained in:
yml
2026-05-21 16:53:08 +08:00
parent a27467bfad
commit 2d3a279805
2 changed files with 44 additions and 38 deletions
@@ -1,5 +1,3 @@
// @ts-check
import { import {
createInventoryItems, createInventoryItems,
invalidateInventoryItem, invalidateInventoryItem,
@@ -13,17 +11,27 @@ import {
mapAdminInventoryListItem, mapAdminInventoryListItem,
} from '../admin-inventory-read-helpers.js' } from '../admin-inventory-read-helpers.js'
/** @typedef {import('../../../types/admin-read-inputs.js').AdminEntityIdInput} AdminEntityIdInput */ import type { AdminEntityIdInput } from '../../../types/admin-read-inputs.js'
/** @typedef {import('../../../types/admin-write-inputs.js').AdminInventoryCreateInput} AdminInventoryCreateInput */ import type {
/** @typedef {import('../../../types/admin-write-inputs.js').AdminInventoryImportInput} AdminInventoryImportInput */ AdminInventoryCreateInput,
/** @typedef {import('../../../types/admin-write-inputs.js').AdminInventoryImportRowInput} AdminInventoryImportRowInput */ AdminInventoryImportInput,
/** @typedef {import('../../../types/admin-write-inputs.js').AdminInventoryInvalidateInput} AdminInventoryInvalidateInput */ AdminInventoryImportRowInput,
/** @typedef {import('../../../types/admin-write-models.js').AdminInventoryImportResponse} AdminInventoryImportResponse */ AdminInventoryInvalidateInput,
/** @typedef {import('../../../types/admin-write-models.js').AdminInventoryMutationResponse} AdminInventoryMutationResponse */ } from '../../../types/admin-write-inputs.js'
import type {
AdminInventoryImportResponse,
AdminInventoryMutationResponse,
} from '../../../types/admin-write-models.js'
import type { InventoryItemRow } from '../../../types/repository-rows.js'
/** @returns {Promise<AdminInventoryMutationResponse>} */ type NormalizedInventoryImportRow = Required<Pick<
/** @param {AdminInventoryCreateInput} [payload] */ AdminInventoryImportRowInput,
export async function createAdminInventoryItem(payload = /** @type {AdminInventoryCreateInput} */ ({})) { 'skuCode' | 'displayValue' | 'batchNo' | 'credentialType' | 'inventoryGroupCode'
>>
export async function createAdminInventoryItem(
payload: AdminInventoryCreateInput = {},
): Promise<AdminInventoryMutationResponse> {
const skuCode = String(payload.skuCode || '').trim() const skuCode = String(payload.skuCode || '').trim()
const displayValue = String(payload.displayValue || '').trim() const displayValue = String(payload.displayValue || '').trim()
const batchNo = String(payload.batchNo || '').trim() const batchNo = String(payload.batchNo || '').trim()
@@ -70,9 +78,9 @@ export async function createAdminInventoryItem(payload = /** @type {AdminInvento
} }
} }
/** @returns {Promise<AdminInventoryImportResponse>} */ export async function importAdminInventoryItems(
/** @param {AdminInventoryImportInput} [payload] */ payload: AdminInventoryImportInput = {},
export async function importAdminInventoryItems(payload = /** @type {AdminInventoryImportInput} */ ({})) { ): Promise<AdminInventoryImportResponse> {
const rows = normalizeInventoryImportRows(payload) const rows = normalizeInventoryImportRows(payload)
if (rows.length === 0) { if (rows.length === 0) {
@@ -102,9 +110,9 @@ export async function importAdminInventoryItems(payload = /** @type {AdminInvent
} }
} }
/** @returns {Promise<AdminInventoryMutationResponse>} */ export async function releaseAdminInventoryItem(
/** @param {AdminEntityIdInput} inventoryItemId */ inventoryItemId: AdminEntityIdInput,
export async function releaseAdminInventoryItem(inventoryItemId) { ): Promise<AdminInventoryMutationResponse> {
const inventoryItem = await getRequiredInventoryItem(inventoryItemId) const inventoryItem = await getRequiredInventoryItem(inventoryItemId)
if (inventoryItem.status !== 'reserved') { if (inventoryItem.status !== 'reserved') {
@@ -117,17 +125,14 @@ export async function releaseAdminInventoryItem(inventoryItemId) {
const updated = await releaseReservedInventoryItem(inventoryItem.id, nowIso()) const updated = await releaseReservedInventoryItem(inventoryItem.id, nowIso())
return { return {
inventoryItem: await mapAdminInventoryListItem(updated), inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
} }
} }
/** @returns {Promise<AdminInventoryMutationResponse>} */
/** @param {AdminEntityIdInput} inventoryItemId */
/** @param {AdminInventoryInvalidateInput} [payload] */
export async function invalidateAdminInventoryItem( export async function invalidateAdminInventoryItem(
inventoryItemId, inventoryItemId: AdminEntityIdInput,
payload = /** @type {AdminInventoryInvalidateInput} */ ({}), payload: AdminInventoryInvalidateInput = {},
) { ): Promise<AdminInventoryMutationResponse> {
const inventoryItem = await getRequiredInventoryItem(inventoryItemId) const inventoryItem = await getRequiredInventoryItem(inventoryItemId)
if (inventoryItem.status !== 'available') { if (inventoryItem.status !== 'available') {
@@ -141,16 +146,12 @@ export async function invalidateAdminInventoryItem(
const updated = await invalidateInventoryItem(inventoryItem.id, reason, nowIso()) const updated = await invalidateInventoryItem(inventoryItem.id, reason, nowIso())
return { return {
inventoryItem: await mapAdminInventoryListItem(updated), inventoryItem: await mapAdminInventoryListItem(updated as InventoryItemRow),
} }
} }
/** function normalizeInventoryImportRows(payload: AdminInventoryImportInput): NormalizedInventoryImportRow[] {
* @param {AdminInventoryImportInput} payload const rows: NormalizedInventoryImportRow[] = []
* @returns {Array<Required<Pick<AdminInventoryImportRowInput, 'skuCode' | 'displayValue' | 'batchNo' | 'credentialType' | 'inventoryGroupCode'>>>}
*/
function normalizeInventoryImportRows(payload) {
const rows = []
const directRows = Array.isArray(payload.rows) ? payload.rows : [] const directRows = Array.isArray(payload.rows) ? payload.rows : []
const bulkCodes = Array.isArray(payload.codes) ? payload.codes : [] const bulkCodes = Array.isArray(payload.codes) ? payload.codes : []
@@ -195,12 +196,9 @@ function normalizeInventoryImportRows(payload) {
return dedupeRows(rows) return dedupeRows(rows)
} }
/** function dedupeRows(rows: NormalizedInventoryImportRow[]): NormalizedInventoryImportRow[] {
* @param {Array<Required<Pick<AdminInventoryImportRowInput, 'skuCode' | 'displayValue' | 'batchNo' | 'credentialType' | 'inventoryGroupCode'>>>} rows const seen = new Set<string>()
*/ const output: NormalizedInventoryImportRow[] = []
function dedupeRows(rows) {
const seen = new Set()
const output = []
for (const row of rows) { for (const row of rows) {
const key = `${row.skuCode}::${row.credentialType || 'tencent_code'}::${row.displayValue}` const key = `${row.skuCode}::${row.credentialType || 'tencent_code'}::${row.displayValue}`
@@ -735,6 +735,14 @@
- `npm run typecheck` - `npm run typecheck`
- `npm run build` - `npm run build`
- `npm test` 共 139 个用例通过 - `npm test` 共 139 个用例通过
183. 后台 Admin 库存写操作迁移到 `.ts`
- `src/services/admin/write/inventory.ts`
184. Admin 库存新增、批量导入、释放预占库存、作废库存与导入行去重已进入 TS 编译链路;创建 / 导入 / 作废输入、entity id、mutation response、导入行规范化结果与库存 row 补齐类型
185. Docker 内验证通过:
- `src/services/admin/*.test.js` 共 8 个用例通过
- `npm run typecheck`
- `npm run build`
- `npm test` 共 139 个用例通过
## 下一步建议 ## 下一步建议