new updates
This commit is contained in:
@@ -5,6 +5,7 @@ import { ApiResult, PagedResponse } from "@/types/common"
|
||||
import {
|
||||
CreateEmployeeRequest,
|
||||
EmployeeBankDetail,
|
||||
EmployeeDeleteResult,
|
||||
EmployeeDetail,
|
||||
EmployeeDocument,
|
||||
EmployeeListItem,
|
||||
@@ -59,9 +60,14 @@ export const employeesApi = {
|
||||
updateStatus(employeeId: number, status: EmployeeStatus): Promise<void> {
|
||||
return apiRequest<void>(`/employees/${employeeId}/status`, { method: "PATCH", body: { status } })
|
||||
},
|
||||
/** Permanently deletes the employee and every dependent HR record. Blocked (409) if payroll history exists. */
|
||||
remove(employeeId: number): Promise<void> {
|
||||
return apiRequest<void>(`/employees/${employeeId}`, { method: "DELETE" })
|
||||
/**
|
||||
* Permanently deletes the employee and every dependent HR record. Blocked (409) if payroll
|
||||
* history exists. `deleteUserAccount` asks for a linked login to be hard-deleted too, instead
|
||||
* of the default (deactivate) — the backend falls back to deactivating if the account has
|
||||
* real linked business/audit records, reflected in the returned result.
|
||||
*/
|
||||
remove(employeeId: number, deleteUserAccount = false): Promise<EmployeeDeleteResult> {
|
||||
return apiRequest<EmployeeDeleteResult>(`/employees/${employeeId}${buildQuery({ deleteUserAccount })}`, { method: "DELETE" })
|
||||
},
|
||||
|
||||
/** Advisory: does a System User already exist with this email? */
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
Item,
|
||||
ItemListItem,
|
||||
ItemReorderSetting,
|
||||
ItemScanResult,
|
||||
TrackingMode,
|
||||
UpdateItemReorderRequest,
|
||||
UpdateItemRequest,
|
||||
@@ -57,4 +58,16 @@ export const itemsApi = {
|
||||
body: request,
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* Resolves a scanned barcode/RFID code (HID scanner keyboard input) against an item SKU,
|
||||
* a batch number, or a serial number — whichever it matches. `itemId` narrows the lookup
|
||||
* to a specific item's own batches/serials (e.g. scanning a lot barcode for a line that
|
||||
* already has its item picked). Throws `ApiError` with status 404 when the code matches
|
||||
* nothing — callers should catch that case and show an inline "unknown barcode" message
|
||||
* rather than a generic error (see components/scanning/ScanInput.tsx usage).
|
||||
*/
|
||||
scan(code: string, itemId?: number): Promise<ItemScanResult> {
|
||||
return apiRequest<ItemScanResult>(`/items/scan${buildQuery({ code, itemId })}`)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { apiRequest } from "@/lib/api-client"
|
||||
import { NotificationFeed } from "@/types/notification-feed"
|
||||
|
||||
export const notificationsApi = {
|
||||
getFeed(take = 20): Promise<NotificationFeed> {
|
||||
return apiRequest<NotificationFeed>(`/notifications?take=${take}`)
|
||||
},
|
||||
|
||||
markAllRead(): Promise<void> {
|
||||
return apiRequest<void>("/notifications/mark-all-read", { method: "POST" })
|
||||
},
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
PurchaseOrder,
|
||||
PurchaseOrderStatus,
|
||||
PurchaseOrderSummary,
|
||||
RejectPurchaseOrderRequest,
|
||||
UpdatePurchaseOrderRequest,
|
||||
} from "@/types/procurement"
|
||||
|
||||
@@ -39,7 +40,7 @@ export const purchaseOrdersApi = {
|
||||
return apiRequestWithETag<PurchaseOrder>(`/purchase-orders/${poId}`)
|
||||
},
|
||||
|
||||
/** Auto-approved on creation in Phase 1 (approvalRequired defaults false, FR-PROC-04). */
|
||||
/** Non-draft is issued straight into PendingApproval (FR-PROC-04). */
|
||||
create(request: CreatePurchaseOrderRequest): Promise<ApiResult<PurchaseOrder>> {
|
||||
return apiRequestWithETag<PurchaseOrder>("/purchase-orders", { method: "POST", body: request })
|
||||
},
|
||||
@@ -49,12 +50,19 @@ export const purchaseOrdersApi = {
|
||||
return apiRequestWithETag<PurchaseOrder>(`/purchase-orders/${poId}`, { method: "PUT", body: request, ifMatch })
|
||||
},
|
||||
|
||||
/** No-op in Phase 1 unless approvals are enabled (FR-PROC-04). */
|
||||
/** PendingApproval → Approved. 403 PO_APPROVAL_FORBIDDEN if the caller isn't an Admin or
|
||||
* is the PO's own creator; 409 PO_NOT_PENDING_APPROVAL otherwise. */
|
||||
approve(poId: number): Promise<PurchaseOrder> {
|
||||
return apiRequest<PurchaseOrder>(`/purchase-orders/${poId}/approve`, { method: "POST" })
|
||||
},
|
||||
|
||||
/** Submit a Draft PO (Draft → Approved). 409 PO_NOT_EDITABLE if not Draft. */
|
||||
/** PendingApproval → Draft, so the requester can revise and resubmit. Same caller
|
||||
* restrictions as {@link approve}. */
|
||||
reject(poId: number, request: RejectPurchaseOrderRequest = {}): Promise<PurchaseOrder> {
|
||||
return apiRequest<PurchaseOrder>(`/purchase-orders/${poId}/reject`, { method: "POST", body: request })
|
||||
},
|
||||
|
||||
/** Submit a Draft PO (Draft → PendingApproval). 409 PO_NOT_EDITABLE if not Draft. */
|
||||
submit(poId: number): Promise<PurchaseOrder> {
|
||||
return apiRequest<PurchaseOrder>(`/purchase-orders/${poId}/submit`, { method: "POST" })
|
||||
},
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { apiRequest } from "@/lib/api-client"
|
||||
import { GlobalSearchResult } from "@/types/search"
|
||||
|
||||
export const searchApi = {
|
||||
search(q: string): Promise<GlobalSearchResult[]> {
|
||||
return apiRequest<GlobalSearchResult[]>(`/search?q=${encodeURIComponent(q)}`)
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { apiRequest, apiRequestWithETag } from "@/lib/api-client"
|
||||
import { ApiResult } from "@/types/common"
|
||||
import {
|
||||
AddSupportTicketMessageRequest,
|
||||
CreateSupportTicketRequest,
|
||||
SupportTicket,
|
||||
SupportTicketSummary,
|
||||
UpdateSupportTicketStatusRequest,
|
||||
} from "@/types/support"
|
||||
|
||||
export const supportTicketsApi = {
|
||||
list(): Promise<SupportTicketSummary[]> {
|
||||
return apiRequest<SupportTicketSummary[]>("/support-tickets")
|
||||
},
|
||||
|
||||
get(ticketId: number): Promise<ApiResult<SupportTicket>> {
|
||||
return apiRequestWithETag<SupportTicket>(`/support-tickets/${ticketId}`)
|
||||
},
|
||||
|
||||
create(request: CreateSupportTicketRequest): Promise<ApiResult<SupportTicket>> {
|
||||
return apiRequestWithETag<SupportTicket>("/support-tickets", { method: "POST", body: request })
|
||||
},
|
||||
|
||||
addMessage(ticketId: number, request: AddSupportTicketMessageRequest, ifMatch: string): Promise<ApiResult<SupportTicket>> {
|
||||
return apiRequestWithETag<SupportTicket>(`/support-tickets/${ticketId}/messages`, { method: "POST", body: request, ifMatch })
|
||||
},
|
||||
|
||||
updateStatus(ticketId: number, request: UpdateSupportTicketStatusRequest, ifMatch: string): Promise<ApiResult<SupportTicket>> {
|
||||
return apiRequestWithETag<SupportTicket>(`/support-tickets/${ticketId}/status`, { method: "PUT", body: request, ifMatch })
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// One typed client method per TaxRate endpoint (ERPCore Controllers/TaxRatesController.cs).
|
||||
import { apiRequest, apiRequestWithETag, buildQuery } from "@/lib/api-client"
|
||||
import { ApiResult, EntityStatus, PagedResponse } from "@/types/common"
|
||||
import { CreateTaxRateRequest, TaxRate, UpdateTaxRateRequest } from "@/types/master-data"
|
||||
|
||||
export interface ListTaxRatesParams {
|
||||
page?: number
|
||||
pageSize?: number
|
||||
q?: string
|
||||
status?: EntityStatus
|
||||
}
|
||||
|
||||
export const taxRatesApi = {
|
||||
list(params: ListTaxRatesParams = {}): Promise<PagedResponse<TaxRate>> {
|
||||
return apiRequest<PagedResponse<TaxRate>>(`/tax-rates${buildQuery(params)}`)
|
||||
},
|
||||
|
||||
get(taxRateId: number): Promise<ApiResult<TaxRate>> {
|
||||
return apiRequestWithETag<TaxRate>(`/tax-rates/${taxRateId}`)
|
||||
},
|
||||
|
||||
create(request: CreateTaxRateRequest): Promise<ApiResult<TaxRate>> {
|
||||
return apiRequestWithETag<TaxRate>("/tax-rates", { method: "POST", body: request })
|
||||
},
|
||||
|
||||
update(taxRateId: number, request: UpdateTaxRateRequest, ifMatch: string): Promise<ApiResult<TaxRate>> {
|
||||
return apiRequestWithETag<TaxRate>(`/tax-rates/${taxRateId}`, { method: "PUT", body: request, ifMatch })
|
||||
},
|
||||
|
||||
/** Deactivate/reactivate. There is no DELETE — masters referenced by items are deactivated, never removed. */
|
||||
updateStatus(taxRateId: number, status: EntityStatus): Promise<void> {
|
||||
return apiRequest<void>(`/tax-rates/${taxRateId}/status`, { method: "PATCH", body: { status } })
|
||||
},
|
||||
}
|
||||
@@ -3,7 +3,15 @@
|
||||
import { apiRequest, buildQuery } from "@/lib/api-client"
|
||||
import { EntityStatus, PagedResponse } from "@/types/common"
|
||||
import { LoginActivity } from "@/types/audit"
|
||||
import { CreateUserRequest, ManagedUser, UpdateUserRoleRequest, UpdateUserStatusRequest, UserTypeOption } from "@/types/users"
|
||||
import {
|
||||
CreateUserRequest,
|
||||
ManagedUser,
|
||||
PurgeAuthHexIdentityRequest,
|
||||
PurgeAuthHexIdentityResult,
|
||||
UpdateUserRoleRequest,
|
||||
UpdateUserStatusRequest,
|
||||
UserTypeOption,
|
||||
} from "@/types/users"
|
||||
|
||||
export interface ListUsersParams {
|
||||
page?: number
|
||||
@@ -43,4 +51,14 @@ export const usersApi = {
|
||||
loginDevices(userId: number, params: { page?: number; pageSize?: number } = {}): Promise<PagedResponse<LoginActivity>> {
|
||||
return apiRequest<PagedResponse<LoginActivity>>(`/users/${userId}/login-devices${buildQuery(params)}`)
|
||||
},
|
||||
|
||||
/**
|
||||
* Admin-only escape hatch: permanently deletes a stale AuthHex identity blocking new
|
||||
* registrations (e.g. an email/username that survived a local User delete because the
|
||||
* automatic purge on that delete failed or wasn't deployed). Doesn't touch ERPCore's
|
||||
* own `users` table — there may be nothing there to touch.
|
||||
*/
|
||||
purgeAuthHexIdentity(request: PurgeAuthHexIdentityRequest): Promise<PurgeAuthHexIdentityResult> {
|
||||
return apiRequest<PurgeAuthHexIdentityResult>("/users/purge-authhex-identity", { method: "POST", body: request })
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
// One typed client method per warehouse/bin endpoint (docs/11-BACKEND-PHASE1.md §2.5,
|
||||
// FR-MD-07/FR-WH-01).
|
||||
//
|
||||
// Warehouses are create-and-list only: there is no PUT, no status, and no ETag on them.
|
||||
// Warehouses have no status/ETag, but do support update and delete (hard delete, blocked
|
||||
// with a 409 if the warehouse is still referenced by bins/stock/documents).
|
||||
import { apiRequest, buildQuery } from "@/lib/api-client"
|
||||
import { PagedResponse } from "@/types/common"
|
||||
import { Bin, CreateBinRequest, CreateWarehouseRequest, Warehouse } from "@/types/master-data"
|
||||
import { Bin, CreateBinRequest, CreateWarehouseRequest, UpdateWarehouseRequest, Warehouse } from "@/types/master-data"
|
||||
|
||||
export type { CreateBinRequest, CreateWarehouseRequest }
|
||||
export type { CreateBinRequest, CreateWarehouseRequest, UpdateWarehouseRequest }
|
||||
|
||||
export interface ListWarehousesParams {
|
||||
page?: number
|
||||
@@ -29,6 +30,14 @@ export const warehousesApi = {
|
||||
return apiRequest<Warehouse>("/warehouses", { method: "POST", body: request })
|
||||
},
|
||||
|
||||
update(warehouseId: number, request: UpdateWarehouseRequest): Promise<Warehouse> {
|
||||
return apiRequest<Warehouse>(`/warehouses/${warehouseId}`, { method: "PUT", body: request })
|
||||
},
|
||||
|
||||
remove(warehouseId: number): Promise<void> {
|
||||
return apiRequest<void>(`/warehouses/${warehouseId}`, { method: "DELETE" })
|
||||
},
|
||||
|
||||
/** Returns a bare array, not a paged envelope — the server does not page bins. */
|
||||
listBins(warehouseId: number): Promise<Bin[]> {
|
||||
return apiRequest<Bin[]>(`/warehouses/${warehouseId}/bins`)
|
||||
|
||||
@@ -51,6 +51,8 @@ export interface ListWastageParams {
|
||||
|
||||
export interface RecordWastageInput {
|
||||
warehouseId: number
|
||||
/** Required when branching is enabled (mirrors `CreateAdjustmentRequest.branchId`). */
|
||||
branchId: number
|
||||
itemId: number
|
||||
binId?: number | null
|
||||
qty: number
|
||||
@@ -117,6 +119,7 @@ export const wastageApi = {
|
||||
record(input: RecordWastageInput): Promise<StockAdjustment> {
|
||||
return stockAdjustmentsApi.create({
|
||||
warehouseId: input.warehouseId,
|
||||
branchId: input.branchId,
|
||||
reasonCodeId: input.reasonCodeId,
|
||||
lines: [{ itemId: input.itemId, binId: input.binId ?? null, qtyDelta: -Math.abs(input.qty) }],
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user