Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 3x 3x 3x 1x 1x 1x 3x 2x 2x 2x 2x 3x 1x 1x 3x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 2x | /**
* @file itemMutations.ts
* @module api/inventory/itemMutations
*
* @summary
* Item lifecycle mutations: create, update, rename, and delete.
* All operations are tolerant and return typed responses instead of throwing.
*
* @enterprise
* - CRUD operations with consistent response pattern
* - Tolerant error handling with detailed error messages
* - Support for create (POST) and update (PUT) patterns
* - Endpoint base centralized for easy backend path adjustments
*/
import http from '../httpClient';
import { normalizeInventoryRow } from './normalizers';
import type { UpsertItemRequest, UpsertItemResponse } from './types';
import { errorMessage } from './utils';
/** Centralized endpoint base (adjust to match your controller if needed). */
export const INVENTORY_BASE = '/api/inventory';
/**
* Create or update an inventory item.
* ID absent in request ⇒ create (POST); ID present ⇒ update (PUT).
*
* @param req - Upsert payload with optional id
* @returns Response object with ok status, normalized item, and optional error
*
* @example
* ```typescript
* // Create new item
* const result = await upsertItem({
* name: 'Widget A',
* supplierId: 'SUP-001',
* quantity: 100,
* price: 25.50
* });
*
* // Update existing item
* const updateResult = await upsertItem({
* id: 'ITEM-123',
* name: 'Widget A v2',
* supplierId: 'SUP-001',
* quantity: 50,
* price: 27.00
* });
* ```
*/
export async function upsertItem(req: UpsertItemRequest): Promise<UpsertItemResponse> {
try {
if (req.id) {
const res = await http.put(`${INVENTORY_BASE}/${encodeURIComponent(req.id)}`, req);
const row = normalizeInventoryRow(res?.data as unknown);
return { ok: true, item: row ?? undefined };
} else {
const res = await http.post(`${INVENTORY_BASE}`, req);
const row = normalizeInventoryRow(res?.data as unknown);
return { ok: true, item: row ?? undefined };
}
} catch (e: unknown) {
return { ok: false, error: errorMessage(e) };
}
}
/**
* Rename an inventory item (change item name).
* Only ADMIN users can rename items.
*
* @param req - Rename payload with item id and new name
* @returns Response object with ok status, normalized item, and optional error
*
* @note Backend validates that the new name is not a duplicate for the same supplier
* @note ADMIN-only operation
*
* @example
* ```typescript
* const result = await renameItem({
* id: 'ITEM-123',
* newName: 'Updated Widget Name'
* });
* ```
*/
export async function renameItem(req: { id: string; newName: string }): Promise<UpsertItemResponse> {
try {
const res = await http.patch(
`${INVENTORY_BASE}/${encodeURIComponent(req.id)}/name`,
null,
{ params: { name: req.newName } }
);
const row = normalizeInventoryRow(res?.data as unknown);
return { ok: true, item: row ?? undefined };
} catch (e: unknown) {
return { ok: false, error: errorMessage(e) };
}
}
/**
* Delete an inventory item by ID.
* Item can only be deleted if quantity is 0 (no stock remaining).
* Only ADMIN users can delete items.
*
* @param id - Item identifier to delete
* @param reason - Business reason for deletion (SCRAPPED, DESTROYED, DAMAGED, EXPIRED, LOST, RETURNED_TO_SUPPLIER)
* @returns Response object with ok status and optional error message
*
* @note ADMIN-only operation
* @note Backend validates that item quantity is 0 before deletion
* @note Backend may return error: "You still have merchandise in stock"
*
* @example
* ```typescript
* const result = await deleteItem('ITEM-123', 'EXPIRED');
* if (!result.ok) {
* console.error('Deletion failed:', result.error);
* }
* ```
*/
export async function deleteItem(id: string, reason: string): Promise<UpsertItemResponse> {
try {
await http.delete(
`${INVENTORY_BASE}/${encodeURIComponent(id)}`,
{ params: { reason } }
);
return { ok: true };
} catch (e: unknown) {
return { ok: false, error: errorMessage(e) };
}
}
|