2026-04-23 14:38:41 +03:00

111 lines
3.9 KiB
TypeScript

import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
import type { ApiListQueryParams, ApiBaseResponse } from "../contracts/types"
export const INVOICE_ROUTES = {
INDEX: "/api/invoices",
BY_ID: "/api/invoices/{id}",
ADD_ATTACHMENT: "/api/invoices/{id}/add-attachment",
DELETE_ATTACHMENT: "/api/invoices/{id}/delete-attachment",
DOCUMENTS: "/api/invoice-documents",
DOCUMENT_BY_ID: "/api/invoice-documents/{id}",
NOTES: "/api/invoice-notes",
NOTE_BY_ID: "/api/invoice-notes/{id}",
LABELS: "/api/invoice-labels",
LABEL_BY_ID: "/api/invoice-labels/{id}",
} as const satisfies Record<string, ApiPath>
// Enhanced invoice type with additional fields
export interface InvoiceShowData {
id?: string | number
amount?: string | number
received_payment?: string | number
customer?: {
id?: string | number
first_name?: string
last_name?: string
company_name?: string
}
customer_id?: string | number
customer_name?: string
[key: string]: any // Allow additional properties
}
export class InvoicesClient extends CrudClient<
typeof INVOICE_ROUTES.INDEX,
typeof INVOICE_ROUTES.BY_ID,
{
showResponse: ApiBaseResponse<InvoiceShowData>
}
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, INVOICE_ROUTES.INDEX, INVOICE_ROUTES.BY_ID)
}
// ── Attachments ──
async addAttachment(id: string, file: File) {
const fd = new FormData()
fd.append("attachments[]", file)
return this.postFormData(`/api/invoices/${id}/add-attachment`, fd)
}
async deleteAttachment(invoiceId: string, attachmentId: number) {
return this.delete(INVOICE_ROUTES.DELETE_ATTACHMENT, {
params: { id: invoiceId },
body: { attachment_id: attachmentId },
} as never)
}
// ── Documents ──
async listDocuments(query?: ApiListQueryParams & { invoice_id?: string | number }) {
return this.get(INVOICE_ROUTES.DOCUMENTS, query ? { query } as never : undefined)
}
async createDocument(payload: ApiRequestBody<typeof INVOICE_ROUTES.DOCUMENTS, "post">) {
return this.post(INVOICE_ROUTES.DOCUMENTS, payload)
}
async updateDocument(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.DOCUMENT_BY_ID, "put">) {
return this.put(INVOICE_ROUTES.DOCUMENT_BY_ID, payload, { params: { id } })
}
async destroyDocument(id: string) {
return this.delete(INVOICE_ROUTES.DOCUMENT_BY_ID, { params: { id } })
}
// ── Notes ──
async listNotes(query?: ApiListQueryParams & { invoice_id?: string | number }) {
return this.get(INVOICE_ROUTES.NOTES, query ? { query } as never : undefined)
}
async createNote(payload: ApiRequestBody<typeof INVOICE_ROUTES.NOTES, "post">) {
return this.post(INVOICE_ROUTES.NOTES, payload)
}
async updateNote(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.NOTE_BY_ID, "put">) {
return this.put(INVOICE_ROUTES.NOTE_BY_ID, payload, { params: { id } })
}
async destroyNote(id: string) {
return this.delete(INVOICE_ROUTES.NOTE_BY_ID, { params: { id } })
}
// ── Labels ──
async listLabels(query?: ApiListQueryParams) {
return this.get(INVOICE_ROUTES.LABELS, query ? { query } as never : undefined)
}
async createLabel(payload: ApiRequestBody<typeof INVOICE_ROUTES.LABELS, "post">) {
return this.post(INVOICE_ROUTES.LABELS, payload)
}
async updateLabel(id: string, payload: ApiRequestBody<typeof INVOICE_ROUTES.LABEL_BY_ID, "put">) {
return this.put(INVOICE_ROUTES.LABEL_BY_ID, payload, { params: { id } })
}
async destroyLabel(id: string) {
return this.delete(INVOICE_ROUTES.LABEL_BY_ID, { params: { id } })
}
}