xxx
This commit is contained in:
@@ -0,0 +1,410 @@
|
||||
/**
|
||||
* Typed domain API client — wraps `apiRequest` with OpenAPI-generated types.
|
||||
*
|
||||
* Usage:
|
||||
* import { inventoryApi } from '@/shared/api-client'
|
||||
* const products = await inventoryApi.listProducts({ item_type: 'finished' })
|
||||
* // products is typed as Schema<'ProductResponse'>[]
|
||||
*/
|
||||
import { apiRequest } from './api'
|
||||
import type { Schema } from '@/types/schemas'
|
||||
|
||||
// ── Auth ───────────────────────────────────────────────────────
|
||||
export const authApi = {
|
||||
login(username: string, password: string) {
|
||||
const body = new URLSearchParams({ username, password })
|
||||
return apiRequest<Schema<'Token'>>('/api/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: body.toString(),
|
||||
})
|
||||
},
|
||||
|
||||
loginJson(username: string, password: string) {
|
||||
return apiRequest<Schema<'Token'>>('/api/auth/login/json', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password } satisfies Schema<'LoginRequest'>),
|
||||
})
|
||||
},
|
||||
|
||||
me() {
|
||||
return apiRequest<Schema<'UserResponse'>>('/api/auth/me')
|
||||
},
|
||||
|
||||
logout() {
|
||||
return apiRequest('/api/auth/logout', { method: 'POST' })
|
||||
},
|
||||
|
||||
// Users
|
||||
listUsers() {
|
||||
return apiRequest<Schema<'UserResponse'>[]>('/api/auth/users')
|
||||
},
|
||||
|
||||
createUser(data: Schema<'UserCreate'>) {
|
||||
return apiRequest<Schema<'UserResponse'>>('/api/auth/users', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateUser(userId: number, data: Schema<'UserUpdate'>) {
|
||||
return apiRequest<Schema<'UserResponse'>>(`/api/auth/users/${userId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteUser(userId: number) {
|
||||
return apiRequest(`/api/auth/users/${userId}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
resetPassword(userId: number, newPassword: string) {
|
||||
return apiRequest(`/api/auth/users/${userId}/reset-password`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ new_password: newPassword }),
|
||||
})
|
||||
},
|
||||
|
||||
// Roles
|
||||
listRoles() {
|
||||
return apiRequest<Schema<'RoleResponse'>[]>('/api/auth/roles')
|
||||
},
|
||||
|
||||
createRole(data: Schema<'RoleCreate'>) {
|
||||
return apiRequest<Schema<'RoleResponse'>>('/api/auth/roles', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateRole(roleId: number, data: Schema<'RoleCreate'>) {
|
||||
return apiRequest<Schema<'RoleResponse'>>(`/api/auth/roles/${roleId}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteRole(roleId: number) {
|
||||
return apiRequest(`/api/auth/roles/${roleId}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
setRolePermissions(roleId: number, permissionIds: number[]) {
|
||||
return apiRequest(`/api/auth/roles/${roleId}/permissions`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ permission_ids: permissionIds }),
|
||||
})
|
||||
},
|
||||
|
||||
// Permissions
|
||||
listPermissions() {
|
||||
return apiRequest<Schema<'PermissionResponse'>[]>('/api/auth/permissions')
|
||||
},
|
||||
}
|
||||
|
||||
// ── Inventory / ERP ────────────────────────────────────────────
|
||||
export const inventoryApi = {
|
||||
// Dashboard
|
||||
dashboard() {
|
||||
return apiRequest('/api/dashboard')
|
||||
},
|
||||
|
||||
// Products
|
||||
listProducts(params?: { item_type?: string; limit?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.item_type) q.set('item_type', params.item_type)
|
||||
if (params?.limit) q.set('limit', String(params.limit))
|
||||
const qs = q.toString()
|
||||
return apiRequest<Schema<'ProductResponse'>[]>(`/api/products${qs ? `?${qs}` : ''}`)
|
||||
},
|
||||
|
||||
createProduct(data: Schema<'ProductCreate'>) {
|
||||
return apiRequest<Schema<'ProductResponse'>>('/api/products', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateProduct(id: number, data: Partial<Schema<'ProductCreate'>>) {
|
||||
return apiRequest<Schema<'ProductResponse'>>(`/api/products/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteProduct(id: number) {
|
||||
return apiRequest(`/api/products/${id}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
getProductMaterials(productId: number) {
|
||||
return apiRequest<{ items: Schema<'ProductMaterialItemResponse'>[] }>(`/api/products/${productId}/materials`)
|
||||
},
|
||||
|
||||
// from-task (mold analysis → product)
|
||||
createProductFromTask(taskId: string) {
|
||||
return apiRequest<Schema<'ProductResponse'>>(`/api/products/from-task/${taskId}`, {
|
||||
method: 'POST',
|
||||
})
|
||||
},
|
||||
|
||||
// Warehouses
|
||||
listWarehouses() {
|
||||
return apiRequest<Schema<'WarehouseResponse'>[]>('/api/warehouses')
|
||||
},
|
||||
|
||||
createWarehouse(data: Schema<'WarehouseCreate'>) {
|
||||
return apiRequest<Schema<'WarehouseResponse'>>('/api/warehouses', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
// Inventory
|
||||
listInventory() {
|
||||
return apiRequest<{ items: Schema<'InventoryResponse'>[] }>('/api/inventory')
|
||||
},
|
||||
|
||||
// Stock Movements
|
||||
listStockMovements(params?: { limit?: number }) {
|
||||
const q = params?.limit ? `?limit=${params.limit}` : ''
|
||||
return apiRequest<{ items: Schema<'StockMovementResponse'>[] }>(`/api/stock-movements${q}`)
|
||||
},
|
||||
|
||||
// Suppliers
|
||||
listSuppliers() {
|
||||
return apiRequest<Schema<'SupplierResponse'>[]>('/api/suppliers')
|
||||
},
|
||||
|
||||
createSupplier(data: Schema<'SupplierCreate'>) {
|
||||
return apiRequest<Schema<'SupplierResponse'>>('/api/suppliers', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateSupplier(id: number, data: Partial<Schema<'SupplierCreate'>>) {
|
||||
return apiRequest<Schema<'SupplierResponse'>>(`/api/suppliers/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteSupplier(id: number) {
|
||||
return apiRequest(`/api/suppliers/${id}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
// Customers
|
||||
listCustomers() {
|
||||
return apiRequest<Schema<'CustomerResponse'>[]>('/api/customers')
|
||||
},
|
||||
|
||||
createCustomer(data: Schema<'CustomerCreate'>) {
|
||||
return apiRequest<Schema<'CustomerResponse'>>('/api/customers', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateCustomer(id: number, data: Partial<Schema<'CustomerCreate'>>) {
|
||||
return apiRequest<Schema<'CustomerResponse'>>(`/api/customers/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteCustomer(id: number) {
|
||||
return apiRequest(`/api/customers/${id}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
// Purchase Orders
|
||||
listPurchaseOrders(params?: { limit?: number }) {
|
||||
const q = params?.limit ? `?limit=${params.limit}` : ''
|
||||
return apiRequest<{ items: Schema<'PurchaseOrderResponse'>[] }>(`/api/purchase-orders${q}`)
|
||||
},
|
||||
|
||||
createPurchaseOrder(data: Schema<'PurchaseOrderCreate'>) {
|
||||
return apiRequest<Schema<'PurchaseOrderResponse'>>('/api/purchase-orders', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updatePurchaseOrder(id: number, data: Partial<Schema<'PurchaseOrderCreate'>>) {
|
||||
return apiRequest<Schema<'PurchaseOrderResponse'>>(`/api/purchase-orders/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
receivePurchaseOrder(id: number, data: Schema<'PurchaseOrderReceiveRequest'>) {
|
||||
return apiRequest<Schema<'PurchaseOrderResponse'>>(`/api/purchase-orders/${id}/receive`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updatePurchaseOrderStatus(id: number, status: string) {
|
||||
return apiRequest<Schema<'PurchaseOrderResponse'>>(`/api/purchase-orders/${id}/status`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ status }),
|
||||
})
|
||||
},
|
||||
|
||||
// Sales Orders
|
||||
listSalesOrders(params?: { limit?: number }) {
|
||||
const q = params?.limit ? `?limit=${params.limit}` : ''
|
||||
return apiRequest<{ items: Schema<'SalesOrderResponse'>[] }>(`/api/sales-orders${q}`)
|
||||
},
|
||||
|
||||
getSalesOrder(id: number) {
|
||||
return apiRequest<Schema<'SalesOrderDetailResponse'>>(`/api/sales-orders/${id}`)
|
||||
},
|
||||
|
||||
createSalesOrder(data: Schema<'SalesOrderCreate'>) {
|
||||
return apiRequest<Schema<'SalesOrderResponse'>>('/api/sales-orders', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
updateSalesOrder(id: number, data: Partial<Schema<'SalesOrderCreate'>>) {
|
||||
return apiRequest<Schema<'SalesOrderResponse'>>(`/api/sales-orders/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
deleteSalesOrder(id: number) {
|
||||
return apiRequest(`/api/sales-orders/${id}`, { method: 'DELETE' })
|
||||
},
|
||||
|
||||
// Purchase Demands (采购需求推导)
|
||||
calculatePurchaseDemands(salesOrderIds: number[]) {
|
||||
return apiRequest<Schema<'PurchaseDemandResponse'>>('/api/purchase-demands/calculate', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ sales_order_ids: salesOrderIds } satisfies Schema<'PurchaseDemandCalculateRequest'>),
|
||||
})
|
||||
},
|
||||
|
||||
// Finance
|
||||
financeSummary(params?: { year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<Schema<'FinanceSummaryResponse'>>(`/api/finance/summary?${q}`)
|
||||
},
|
||||
|
||||
financeTransactions(params?: { status?: string; limit?: number; year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.status) q.set('status', params.status)
|
||||
if (params?.limit) q.set('limit', String(params.limit))
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<{ items: Schema<'FinanceTransactionResponse'>[] }>(`/api/finance/transactions?${q}`)
|
||||
},
|
||||
|
||||
financeReceivables(params?: { limit?: number; year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.limit) q.set('limit', String(params.limit))
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<Schema<'ReceivableItemResponse'>[]>(`/api/finance/receivables?${q}`)
|
||||
},
|
||||
|
||||
financePayables(params?: { limit?: number; year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.limit) q.set('limit', String(params.limit))
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<Schema<'PayableItemResponse'>[]>(`/api/finance/payables?${q}`)
|
||||
},
|
||||
|
||||
financePartnerStatement(partnerType: 'customer' | 'supplier', params?: { year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<Schema<'FinancePartnerStatementResponse'>>(`/api/finance/partner-statement/${partnerType}?${q}`)
|
||||
},
|
||||
|
||||
financePartnerProductStatement(partnerType: 'customer' | 'supplier', params?: { year?: number; quarter?: number }) {
|
||||
const q = new URLSearchParams()
|
||||
if (params?.year) q.set('year', String(params.year))
|
||||
if (params?.quarter) q.set('quarter', String(params.quarter))
|
||||
return apiRequest<Schema<'FinancePartnerProductStatementResponse'>>(`/api/finance/partner-product-statement/${partnerType}?${q}`)
|
||||
},
|
||||
}
|
||||
|
||||
// ── MoldInsight ────────────────────────────────────────────────
|
||||
export const moldinsightApi = {
|
||||
uploadStp(formData: FormData) {
|
||||
return apiRequest<{ task_id: string }>('/api/upload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
},
|
||||
|
||||
getStatus(taskId: string) {
|
||||
return apiRequest<{
|
||||
task_id: string
|
||||
status: string
|
||||
progress: number
|
||||
result?: Record<string, unknown>
|
||||
error?: string
|
||||
}>(`/api/status/${taskId}`)
|
||||
},
|
||||
|
||||
batchUpload(formData: FormData) {
|
||||
return apiRequest<{
|
||||
batch_id: string
|
||||
accepted: number
|
||||
rejected: number
|
||||
task_ids: string[]
|
||||
}>('/api/batch-upload', {
|
||||
method: 'POST',
|
||||
body: formData,
|
||||
})
|
||||
},
|
||||
|
||||
getBatchStatus(batchId: string) {
|
||||
return apiRequest<{
|
||||
batch_id: string
|
||||
total: number
|
||||
completed: number
|
||||
failed: number
|
||||
processing: number
|
||||
progress_percent: number
|
||||
tasks: Array<{
|
||||
task_id: string
|
||||
filename: string
|
||||
status: string
|
||||
progress?: number
|
||||
error?: string
|
||||
html_file?: string
|
||||
}>
|
||||
}>(`/api/batch/${batchId}`)
|
||||
},
|
||||
|
||||
estimateCost(data: {
|
||||
task_id?: string
|
||||
material?: string
|
||||
mold_type?: string
|
||||
cavity_count?: number
|
||||
weight?: number
|
||||
dimensions?: { length: number; width: number; height: number }
|
||||
}) {
|
||||
return apiRequest<{
|
||||
mold_cost?: number
|
||||
part_cost?: number
|
||||
total_mold_cost?: number
|
||||
confidence?: number
|
||||
assumptions?: string[]
|
||||
currency?: string
|
||||
}>('/api/cost-estimate', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
})
|
||||
},
|
||||
|
||||
getAluminumPrice() {
|
||||
return apiRequest<{ price: number; unit: string; updated_at: string }>('/api/aluminum-price/')
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user