This commit is contained in:
2026-04-23 14:38:41 +03:00
parent f17dd1486c
commit c0f78c6e18
90 changed files with 10819 additions and 1583 deletions
+6 -8
View File
@@ -1,6 +1,6 @@
import { CrudClient } from "../infra/crud-client"
import type { ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiResponse } from "../infra/types"
import type { ApiPath, ApiRequestBody, ApiResponse } from "../infra/types"
export const ESTIMATE_ROUTES = {
INDEX: "/api/estimates",
@@ -12,6 +12,7 @@ export const ESTIMATE_ROUTES = {
EXPENSE_ITEMS: "/api/estimate/{id}/expense-items",
EXPENSE_ITEM_BY_ID: "/api/estimate/{id}/expense-items/{expense_item_id}",
STORE_AUTHORISATION: "/api/estimates/{id}/store-authorisation",
CONVERT_TO_JOB_CARD: "/api/estimates/{id}/convert-to-job-card",
} as const satisfies Record<string, ApiPath>
export class EstimatesClient extends CrudClient<
@@ -22,13 +23,6 @@ export class EstimatesClient extends CrudClient<
super(baseUrl, defaultOptions, ESTIMATE_ROUTES.INDEX, ESTIMATE_ROUTES.BY_ID)
}
// Note: GET /api/estimates/{id} is not in the OpenAPI schema.
// This method uses a type cast and relies on the backend supporting the route.
async getById(id: string) {
const data = await this.get(ESTIMATE_ROUTES.BY_ID, { params: { id } })
return data;
}
// ── Estimate Services ──
async listServices(estimateId: string) {
return this.get(ESTIMATE_ROUTES.SERVICES, { params: { id: estimateId } } as never)
@@ -91,4 +85,8 @@ export class EstimatesClient extends CrudClient<
}) {
return this.post(ESTIMATE_ROUTES.STORE_AUTHORISATION, payload as never, { params: { id: estimateId } } as never)
}
async convertToJobCard(estimateId: string, payload: ApiRequestBody<typeof ESTIMATE_ROUTES.CONVERT_TO_JOB_CARD, "post">) {
return this.post(ESTIMATE_ROUTES.CONVERT_TO_JOB_CARD, payload, { params: { id: estimateId } })
}
}
+4
View File
@@ -66,6 +66,10 @@ export class ExpensesClient extends CrudClient<
return this.list(query)
}
async getById(id: string) {
const res = await this.show(id)
return res;
}
async createExpense(payload: ApiRequestBody<typeof EXPENSE_ROUTES.EXPENSES, "post">) {
return this.create(payload)
}
+2 -2
View File
@@ -18,7 +18,7 @@ export { EstimatesClient, ESTIMATE_ROUTES } from "./estimates"
export { QuickRemarksClient, QUICK_REMARK_ROUTES } from "./quick-remarks"
export { QuickNotesClient, QUICK_NOTE_ROUTES } from "./quick-notes"
export { ShopRecommendationsClient, SHOP_RECOMMENDATION_ROUTES } from "./shop-recommendations"
export { JobCardsClient, JOB_CARD_ROUTES } from "./job-cards"
export { JobCardsClient, JOB_CARD_ROUTES, type JobCardShowData } from "./job-cards"
export { PaymentModesClient, PAYMENT_MODE_ROUTES } from "./payment-modes"
export { PaymentReceivedClient, PAYMENT_RECEIVED_ROUTES } from "./payment-received"
export { PartsClient, PARTS_ROUTES } from "./parts"
@@ -34,7 +34,7 @@ export { ShopTimingsClient, SHOP_TIMING_ROUTES } from "./shop-timings"
export { ShopCalendarsClient, SHOP_CALENDAR_ROUTES } from "./shop-calendars"
export { HolidayYearsClient, HOLIDAY_YEAR_ROUTES } from "./holiday-years"
export { TaxesClient, TAX_ROUTES } from "./taxes"
export { InvoicesClient, INVOICE_ROUTES } from "./invoices"
export { InvoicesClient, INVOICE_ROUTES, type InvoiceShowData } from "./invoices"
export { HomeClient, HOME_ROUTES, type HomeDashboardResponse } from "./home"
export { BillsClient, BILL_ROUTES } from "./bills"
export { ReasonsClient, REASON_ROUTES } from "./reasons"
+21 -2
View File
@@ -1,7 +1,7 @@
import { CrudClient } from "../infra/crud-client"
import { type ApiClientOptions } from "../infra/client"
import type { ApiPath, ApiRequestBody } from "../infra/types"
import type { ApiListQueryParams } from "../contracts/types"
import type { ApiListQueryParams, ApiBaseResponse } from "../contracts/types"
export const INVOICE_ROUTES = {
INDEX: "/api/invoices",
@@ -16,9 +16,28 @@ export const INVOICE_ROUTES = {
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
typeof INVOICE_ROUTES.BY_ID,
{
showResponse: ApiBaseResponse<InvoiceShowData>
}
> {
constructor(baseUrl?: string, defaultOptions?: ApiClientOptions) {
super(baseUrl, defaultOptions, INVOICE_ROUTES.INDEX, INVOICE_ROUTES.BY_ID)
+25
View File
@@ -30,6 +30,11 @@ export const JOB_CARD_ROUTES = {
DELETE_SERVICE: "/api/job-cards/{id}/delete-service",
ADD_SERVICE_ATTACHMENT: "/api/job-cards/{id}/add-service-attachment",
DELETE_SERVICE_ATTACHMENT: "/api/job-cards/{id}/delete-service-attachment",
GET_EXPENSE_ITEMS: "/api/job-cards/{id}/get-expense-items",
ADD_EXPENSE_ITEM: "/api/job-cards/{id}/add-expense-item",
UPDATE_EXPENSE_ITEM: "/api/job-cards/{id}/update-expense-item",
DELETE_EXPENSE_ITEM: "/api/job-cards/{id}/delete-expense-item",
CONVERT_TO_INVOICE: "/api/job-cards/{id}/convert-to-invoice",
} as const satisfies Record<string, ApiPath>
@@ -157,4 +162,24 @@ export class JobCardsClient extends CrudClient<
async deleteServiceAttachment(id: string, jobCardServiceId: number, attachmentId: number) {
return this.delete(JOB_CARD_ROUTES.DELETE_SERVICE_ATTACHMENT, { params: { id }, body: { job_card_service_id: jobCardServiceId, attachment_id: attachmentId } } as never)
}
async getExpenseItems(id: string, params?: Record<string, unknown>) {
return this.get(JOB_CARD_ROUTES.GET_EXPENSE_ITEMS, { params: { id }, query: params as any })
}
async addExpenseItem(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.ADD_EXPENSE_ITEM, "post">) {
return this.post(JOB_CARD_ROUTES.ADD_EXPENSE_ITEM, payload, { params: { id } })
}
async updateExpenseItem(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.UPDATE_EXPENSE_ITEM, "put">) {
return this.put(JOB_CARD_ROUTES.UPDATE_EXPENSE_ITEM, payload, { params: { id } })
}
async deleteExpenseItem(id: string, jobCardExpenseItemId: number) {
return this.delete(JOB_CARD_ROUTES.DELETE_EXPENSE_ITEM, { params: { id }, body: { job_card_expense_item_id: jobCardExpenseItemId } } as never)
}
async convertToInvoice(id: string, payload: ApiRequestBody<typeof JOB_CARD_ROUTES.CONVERT_TO_INVOICE, "post">) {
return this.post(JOB_CARD_ROUTES.CONVERT_TO_INVOICE, payload, { params: { id } })
}
}
+1 -1
View File
@@ -109,7 +109,7 @@ export const SellRatesTaxInclusive = ['Tax Inclusive', 'Tax Exclusive'] as const
export type SellRatesTaxInclusive = (typeof SellRatesTaxInclusive)[number];
// Tables
export const Tables= ['bills', 'expenses', 'invoices', 'job_cards', 'credit_notes', 'vendor_credits', 'estimates'] as const;
export const Tables= ['bills', 'payments', 'expenses', 'invoices', 'job_cards', 'credit_notes', 'vendor_credits', 'estimates','purchase-order'] as const;
export type Tables = (typeof Tables)[number];
export const GiveDiscounts = ['no', 'line_item_level', 'transaction_level'] as const;