api.ts 7.18 KB
// vibe_erp REST API types.
//
// Hand-written rather than codegen'd from /v3/api-docs to keep the
// build pipeline simple — the framework already has springdoc-openapi
// serving the live spec, but adding @openapitools/openapi-generator-cli
// would pull in another Java toolchain into the npm build. v1 SPA can
// stay typed by hand; v1.x can revisit codegen if drift becomes a
// real problem. Every type here mirrors the matching @RestController's
// response DTO under pbc/*/http/.
//
// **BigDecimal as string.** The Spring Boot Jackson default serializes
// java.math.BigDecimal as a JSON number, which JavaScript would coerce
// to a 64-bit float and lose precision on quantities like 12345.6789.
// In practice the framework configures `spring.jackson.write-bigdecimal-as-plain`
// (default for Spring Boot 3) which still emits a JSON *number*; the SPA
// stores them as `string` because we never do client-side arithmetic on
// them — display only. If a future SPA needs sums it should round-trip
// through decimal.js, not Number().

export interface MetaInfo {
  name: string
  apiVersion: string
  implementationVersion: string
  buildTime: string | null
  activeProfiles: string[]
}

// ─── Auth (pbc-identity AuthController) ──────────────────────────────

export interface LoginRequest {
  username: string
  password: string
}

export interface TokenPair {
  accessToken: string
  accessExpiresAt: string
  refreshToken: string
  refreshExpiresAt: string
  tokenType: string
}

// ─── Identity (pbc-identity) ─────────────────────────────────────────

export interface User {
  id: string
  username: string
  displayName: string
  email: string | null
  enabled: boolean
}

export interface Role {
  id: string
  code: string
  name: string
  description: string | null
}

// ─── Catalog (pbc-catalog) ───────────────────────────────────────────

export type ItemType = 'GOOD' | 'SERVICE' | 'DIGITAL'

export interface Item {
  id: string
  code: string
  name: string
  description: string | null
  itemType: ItemType
  baseUomCode: string
  active: boolean
  ext: Record<string, unknown>
}

export interface Uom {
  id: string
  code: string
  name: string
  dimension: string
}

// ─── Partners (pbc-partners) ─────────────────────────────────────────

export type PartnerType = 'CUSTOMER' | 'SUPPLIER' | 'BOTH'

export interface Partner {
  id: string
  code: string
  name: string
  type: PartnerType
  taxId: string | null
  website: string | null
  email: string | null
  phone: string | null
  active: boolean
  ext: Record<string, unknown>
}

// ─── Inventory (pbc-inventory) ───────────────────────────────────────

export type LocationType = 'WAREHOUSE' | 'BIN' | 'VIRTUAL'

export interface Location {
  id: string
  code: string
  name: string
  type: LocationType
  active: boolean
  ext: Record<string, unknown>
}

// Note: balances/movements use a UUID `locationId`, not `locationCode`.
// The list pages join against `Location.id → code` client-side.

export interface StockBalance {
  id: string
  itemCode: string
  locationId: string
  quantity: string | number
}

export type MovementReason =
  | 'RECEIPT'
  | 'ISSUE'
  | 'ADJUSTMENT'
  | 'SALES_SHIPMENT'
  | 'PURCHASE_RECEIPT'
  | 'TRANSFER_OUT'
  | 'TRANSFER_IN'
  | 'MATERIAL_ISSUE'
  | 'PRODUCTION_RECEIPT'

export interface StockMovement {
  id: string
  itemCode: string
  locationId: string
  delta: string | number
  reason: MovementReason
  reference: string | null
  occurredAt: string
  resultingQuantity?: string | number
}

// ─── Sales orders (pbc-orders-sales) ─────────────────────────────────

export type SalesOrderStatus = 'DRAFT' | 'CONFIRMED' | 'SHIPPED' | 'CANCELLED'

export interface SalesOrderLine {
  id: string
  lineNo: number
  itemCode: string
  quantity: string | number
  unitPrice: string | number
  currencyCode: string
  lineTotal: string | number
}

export interface SalesOrder {
  id: string
  code: string
  partnerCode: string
  status: SalesOrderStatus
  orderDate: string
  currencyCode: string
  totalAmount: string | number
  lines: SalesOrderLine[]
  ext: Record<string, unknown>
}

// ─── Purchase orders (pbc-orders-purchase) ───────────────────────────

export type PurchaseOrderStatus = 'DRAFT' | 'CONFIRMED' | 'RECEIVED' | 'CANCELLED'

export interface PurchaseOrderLine {
  id: string
  lineNo: number
  itemCode: string
  quantity: string | number
  unitPrice: string | number
  currencyCode: string
  lineTotal: string | number
}

export interface PurchaseOrder {
  id: string
  code: string
  partnerCode: string
  status: PurchaseOrderStatus
  orderDate: string
  expectedDate: string | null
  currencyCode: string
  totalAmount: string | number
  lines: PurchaseOrderLine[]
  ext: Record<string, unknown>
}

// ─── Production (pbc-production) ─────────────────────────────────────

export type WorkOrderStatus = 'DRAFT' | 'IN_PROGRESS' | 'COMPLETED' | 'CANCELLED'
export type WorkOrderOperationStatus = 'PENDING' | 'IN_PROGRESS' | 'COMPLETED'

export interface WorkOrderInput {
  id: string
  lineNo: number
  itemCode: string
  quantityPerUnit: string | number
  sourceLocationCode: string
}

export interface WorkOrderOperation {
  id: string
  lineNo: number
  operationCode: string
  workCenter: string
  standardMinutes: string | number
  status: WorkOrderOperationStatus
  actualMinutes: string | number | null
  startedAt: string | null
  completedAt: string | null
}

export interface WorkOrder {
  id: string
  code: string
  outputItemCode: string
  outputQuantity: string | number
  status: WorkOrderStatus
  dueDate: string | null
  sourceSalesOrderCode: string | null
  inputs: WorkOrderInput[]
  operations: WorkOrderOperation[]
  ext: Record<string, unknown>
}

export interface ShopFloorEntry {
  workOrderId: string
  workOrderCode: string
  outputItemCode: string
  outputQuantity: string | number
  sourceSalesOrderCode: string | null
  currentOperationLineNo: number | null
  currentOperationCode: string | null
  currentWorkCenter: string | null
  currentOperationStatus: WorkOrderOperationStatus | null
  operationsCompleted: number
  operationsTotal: number
  totalStandardMinutes: string | number
  totalActualMinutes: string | number
}

// ─── Finance (pbc-finance) ───────────────────────────────────────────

export type JournalEntryType = 'AR' | 'AP'
export type JournalEntryStatus = 'POSTED' | 'SETTLED' | 'REVERSED'

export interface JournalEntry {
  id: string
  code: string
  type: JournalEntryType
  status: JournalEntryStatus
  partnerCode: string
  orderCode: string
  amount: string | number
  currencyCode: string
  postedAt: string
}