1
0
This commit is contained in:
Ahmed Bouhuolia
2026-03-19 05:51:54 +02:00
parent 70e0fd6a89
commit d53271325c
40 changed files with 730 additions and 758 deletions
@@ -34,6 +34,7 @@ import { AcceptType } from '@/constants/accept-type';
import { PaymentReceivedResponseDto } from './dtos/PaymentReceivedResponse.dto';
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
import { PaymentReceivedStateResponseDto } from './dtos/PaymentReceivedStateResponse.dto';
import { PaymentReceivedHtmlContentResponseDto } from './dtos/PaymentReceivedHtmlResponse.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import {
BulkDeleteDto,
@@ -50,6 +51,7 @@ import { PaymentReceiveAction } from './types/PaymentReceived.types';
@ApiExtraModels(PaymentReceivedResponseDto)
@ApiExtraModels(PaginatedResponseDto)
@ApiExtraModels(PaymentReceivedStateResponseDto)
@ApiExtraModels(PaymentReceivedHtmlContentResponseDto)
@ApiExtraModels(ValidateBulkDeleteResponseDto)
@ApiCommonHeaders()
@UseGuards(AuthorizationGuard, PermissionGuard)
@@ -236,8 +238,17 @@ export class PaymentReceivesController {
status: 200,
description:
'The payment received details have been successfully retrieved.',
schema: {
$ref: getSchemaPath(PaymentReceivedResponseDto),
content: {
'application/json': {
schema: {
$ref: getSchemaPath(PaymentReceivedResponseDto),
},
},
'application/json+html': {
schema: {
$ref: getSchemaPath(PaymentReceivedHtmlContentResponseDto),
},
},
},
})
public async getPaymentReceive(
@@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class PaymentReceivedHtmlContentResponseDto {
@ApiProperty({ description: 'The HTML content of the payment received', example: '<html>...</html>' })
htmlContent: string;
}
@@ -34,6 +34,7 @@ import { SaleEstimateResponseDto } from './dtos/SaleEstimateResponse.dto';
import { GetSaleEstimatesQueryDto } from './dtos/GetSaleEstimatesQuery.dto';
import { PaginatedResponseDto } from '@/common/dtos/PaginatedResults.dto';
import { SaleEstiamteStateResponseDto } from './dtos/SaleEstimateStateResponse.dto';
import { SaleEstimateHtmlContentResponseDto } from './dtos/SaleEstimateHtmlResponse.dto';
import { ApiCommonHeaders } from '@/common/decorators/ApiCommonHeaders';
import {
BulkDeleteDto,
@@ -50,6 +51,7 @@ import { SaleEstimateAction } from './types/SaleEstimates.types';
@ApiExtraModels(SaleEstimateResponseDto)
@ApiExtraModels(PaginatedResponseDto)
@ApiExtraModels(SaleEstiamteStateResponseDto)
@ApiExtraModels(SaleEstimateHtmlContentResponseDto)
@ApiCommonHeaders()
@ApiExtraModels(ValidateBulkDeleteResponseDto)
@UseGuards(AuthorizationGuard, PermissionGuard)
@@ -322,8 +324,17 @@ export class SaleEstimatesController {
@ApiResponse({
status: 200,
description: 'The sale estimate details have been successfully retrieved.',
schema: {
$ref: getSchemaPath(SaleEstimateResponseDto),
content: {
'application/json': {
schema: {
$ref: getSchemaPath(SaleEstimateResponseDto),
},
},
'application/json+html': {
schema: {
$ref: getSchemaPath(SaleEstimateHtmlContentResponseDto),
},
},
},
})
@ApiParam({
@@ -0,0 +1,6 @@
import { ApiProperty } from '@nestjs/swagger';
export class SaleEstimateHtmlContentResponseDto {
@ApiProperty({ description: 'The HTML content of the estimate', example: '<html>...</html>' })
htmlContent: string;
}
@@ -0,0 +1,155 @@
import { ApiProperty } from '@nestjs/swagger';
export class AddressItemDto {
@ApiProperty({ description: 'The email label', example: 'John Doe' })
label: string;
@ApiProperty({ description: 'The email address', example: 'john@example.com' })
mail: string;
@ApiProperty({ description: 'Whether this is the primary email', example: true, required: false })
primary?: boolean;
}
export class SaleReceiptMailEntryDto {
@ApiProperty({ description: 'The item name', example: 'Product A' })
name: string;
@ApiProperty({ description: 'The quantity', example: 2 })
quantity: number;
@ApiProperty({ description: 'The formatted quantity', example: '2.00' })
quantityFormatted: string;
@ApiProperty({ description: 'The rate/price', example: 100 })
rate: number;
@ApiProperty({ description: 'The formatted rate', example: '$100.00' })
rateFormatted: string;
@ApiProperty({ description: 'The total amount', example: 200 })
total: number;
@ApiProperty({ description: 'The formatted total', example: '$200.00' })
totalFormatted: string;
}
export class SaleReceiptMailResponseDto {
@ApiProperty({ description: 'Whether to attach the receipt PDF', example: true })
attachReceipt: boolean;
@ApiProperty({ description: 'The closed date', example: '2024-01-15T00:00:00Z' })
closedAtDate: string;
@ApiProperty({ description: 'The formatted closed date', example: 'Jan 15, 2024' })
closedAtDateFormatted: string;
@ApiProperty({ description: 'The company name', example: 'Acme Corp' })
companyName: string;
@ApiProperty({ description: 'The customer name', example: 'John Doe' })
customerName: string;
@ApiProperty({ description: 'Format arguments for the message', type: 'object' })
formatArgs: Record<string, unknown>;
@ApiProperty({ description: 'From email addresses', type: [String], example: ['noreply@example.com'] })
from: string[];
@ApiProperty({ description: 'From email options', type: [AddressItemDto] })
fromOptions: AddressItemDto[];
@ApiProperty({ description: 'The email message body', example: 'Please find your receipt attached.' })
message: string;
@ApiProperty({ description: 'The receipt date', example: '2024-01-15T00:00:00Z' })
receiptDate: string;
@ApiProperty({ description: 'The formatted receipt date', example: 'Jan 15, 2024' })
receiptDateFormatted: string;
@ApiProperty({ description: 'The email subject', example: 'Your Receipt from Acme Corp' })
subject: string;
@ApiProperty({ description: 'The subtotal amount', example: 200 })
subtotal: number;
@ApiProperty({ description: 'The formatted subtotal', example: '$200.00' })
subtotalFormatted: string;
@ApiProperty({ description: 'To email addresses', type: [String], example: ['customer@example.com'] })
to: string[];
@ApiProperty({ description: 'To email options', type: [AddressItemDto] })
toOptions: AddressItemDto[];
@ApiProperty({ description: 'The discount amount', example: 20 })
discountAmount: number;
@ApiProperty({ description: 'The formatted discount amount', example: '$20.00' })
discountAmountFormatted: string;
@ApiProperty({ description: 'The discount label', example: 'Discount (10%)' })
discountLabel: string;
@ApiProperty({ description: 'The discount percentage', example: 10, nullable: true })
discountPercentage: number | null;
@ApiProperty({ description: 'The formatted discount percentage', example: '10%' })
discountPercentageFormatted: string;
@ApiProperty({ description: 'The adjustment amount', example: 0 })
adjustment: number;
@ApiProperty({ description: 'The formatted adjustment', example: '$0.00' })
adjustmentFormatted: string;
@ApiProperty({ description: 'The total amount', example: 180 })
total: number;
@ApiProperty({ description: 'The formatted total', example: '$180.00' })
totalFormatted: string;
@ApiProperty({ description: 'The company logo URI', example: 'https://example.com/logo.png', nullable: true })
companyLogoUri?: string | null;
@ApiProperty({ description: 'The primary color', example: '#0066cc', nullable: true })
primaryColor?: string | null;
@ApiProperty({ description: 'The receipt entries', type: [SaleReceiptMailEntryDto] })
entries: SaleReceiptMailEntryDto[];
@ApiProperty({ description: 'The receipt number', example: 'SR-2024-001' })
receiptNumber: string;
}
export class SaleReceiptSendMailBodyDto {
@ApiProperty({ description: 'Whether to attach the receipt PDF', example: true, required: false })
attachReceipt?: boolean;
@ApiProperty({ description: 'From email address', example: 'noreply@example.com', required: false })
from?: string;
@ApiProperty({ description: 'To email addresses', type: [String], example: ['customer@example.com'], required: false })
to?: string[];
@ApiProperty({ description: 'CC email addresses', type: [String], example: [], required: false })
cc?: string[];
@ApiProperty({ description: 'BCC email addresses', type: [String], example: [], required: false })
bcc?: string[];
@ApiProperty({ description: 'The email subject', example: 'Your Receipt', required: false })
subject?: string;
@ApiProperty({ description: 'The email message body', example: 'Please find your receipt attached.', required: false })
message?: string;
@ApiProperty({ description: 'Format arguments', type: 'object', required: false })
formatArgs?: Record<string, unknown>;
}
export class SaleReceiptHtmlContentResponseDto {
@ApiProperty({ description: 'The HTML content of the receipt', example: '<html>...</html>' })
htmlContent: string;
}
+1 -1
View File
@@ -29,7 +29,7 @@
"@testing-library/react": "^9.4.0",
"@testing-library/user-event": "^7.2.1",
"@tiptap/core": "2.1.13",
"@tiptap/extension-color": "latest",
"@tiptap/extension-color": "2.1.13",
"@tiptap/extension-list-item": "2.1.13",
"@tiptap/extension-text-style": "2.1.13",
"@tiptap/pm": "2.1.13",
@@ -29,7 +29,6 @@ import {
AccountTransactionsList
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { accountsKeys } from './query-keys';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
@@ -164,14 +163,11 @@ export function useBulkDeleteAccounts(
export function useValidateBulkDeleteAccounts(
props?: UseMutationOptions<ValidateBulkDeleteResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteAccounts(fetcher, ids).then((res: ValidateBulkDeleteResponse) =>
transformToCamelCase(res as unknown as Record<string, unknown>) as ValidateBulkDeleteResponse
),
mutationFn: (ids: number[]) => validateBulkDeleteAccounts(fetcher, ids),
});
}
@@ -8,7 +8,6 @@ import {
fetchBankingAccountSummary,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../../useRequest';
import { transformToCamelCase } from '@/utils';
import { bankingKeys } from '../query-keys';
/** @deprecated Use AutofillCategorizeTransactionResponse from @bigcapital/sdk-ts */
@@ -18,16 +17,11 @@ export function useGetBankAccountSummaryMeta(
bankAccountId: number,
options?: UseQueryOptions<BankingAccountSummaryResponse, Error>
): UseQueryResult<BankingAccountSummaryResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: bankingKeys.summaryMeta(bankAccountId),
queryFn: () =>
fetchBankingAccountSummary(fetcher, bankAccountId).then(
(data) =>
transformToCamelCase(data as unknown as Record<string, unknown>) as BankingAccountSummaryResponse
),
queryFn: () => fetchBankingAccountSummary(fetcher, bankAccountId),
});
}
@@ -35,15 +29,10 @@ export function useGetAutofillCategorizeTransaction(
uncategorizedTransactionIds: number[],
options?: UseQueryOptions<AutofillCategorizeTransactionResponse, Error>
): UseQueryResult<AutofillCategorizeTransactionResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: bankingKeys.autofillCategorize(uncategorizedTransactionIds),
queryFn: () =>
fetchAutofillCategorizeTransaction(fetcher, uncategorizedTransactionIds).then(
(data) =>
transformToCamelCase(data as unknown as Record<string, unknown>) as AutofillCategorizeTransactionResponse
),
queryFn: () => fetchAutofillCategorizeTransaction(fetcher, uncategorizedTransactionIds),
});
}
@@ -25,22 +25,19 @@ import {
unmatchMatchedTransaction,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../../useRequest';
import { transformToCamelCase } from '@/utils';
import { bankingKeys } from '../query-keys';
export function useGetBankTransactionsMatches(
uncategorizedTransactionIds: number[],
options?: UseQueryOptions<MatchedTransactionsResponse, Error>
): UseQueryResult<MatchedTransactionsResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: bankingKeys.transactionMatches(uncategorizedTransactionIds),
queryFn: () =>
fetchMatchedTransactions(fetcher, uncategorizedTransactionIds).then((data) =>
transformToCamelCase(data as unknown as Record<string, unknown>) as MatchedTransactionsResponse
),
fetchMatchedTransactions(fetcher, uncategorizedTransactionIds) as Promise<MatchedTransactionsResponse>,
});
}
@@ -1,22 +1,18 @@
import { useInfiniteQuery, useQuery, UseQueryOptions, UseQueryResult } from '@tanstack/react-query';
import { fetchExcludedBankTransactions, fetchRecognizedTransaction, fetchRecognizedTransactions } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../../useRequest';
import { transformToCamelCase } from '@/utils';
import { bankingKeys } from '../query-keys';
export function useGetRecognizedBankTransaction(
uncategorizedTransactionId: number,
options?: UseQueryOptions<unknown, Error>
): UseQueryResult<unknown, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: bankingKeys.recognizedTransaction(uncategorizedTransactionId),
queryFn: () =>
fetchRecognizedTransaction(fetcher, uncategorizedTransactionId).then(
(data: unknown) => transformToCamelCase(data as unknown as Record<string, unknown>)
),
queryFn: () => fetchRecognizedTransaction(fetcher, uncategorizedTransactionId),
});
}
@@ -36,7 +36,6 @@ import {
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { useRequestPdf } from '../../useRequestPdf';
import { transformToCamelCase } from '@/utils';
import { creditNotesKeys, CreditNotesQueryKeys } from './query-keys';
import { itemsKeys } from '../items/query-keys';
import { customersKeys } from '../customers/query-keys';
@@ -159,14 +158,12 @@ export function useBulkDeleteCreditNotes(
export function useValidateBulkDeleteCreditNotes(
props?: UseMutationOptions<ValidateBulkDeleteCreditNotesResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteCreditNotes(fetcher, { ids, skipUndeletable: false }).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteCreditNotesResponse
),
validateBulkDeleteCreditNotes(fetcher, { ids, skipUndeletable: false }),
});
}
@@ -366,14 +363,11 @@ export interface CreditNoteStateResponse {
export function useGetCreditNoteState(
options?: UseQueryOptions<CreditNoteStateResponse, Error>
): UseQueryResult<CreditNoteStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery<CreditNoteStateResponse, Error>({
...options,
queryKey: ['CREDIT_NOTE_STATE'],
queryFn: () =>
fetchCreditNoteState(fetcher).then((data) =>
transformToCamelCase(data as unknown as Record<string, unknown>) as CreditNoteStateResponse
),
queryFn: () => fetchCreditNoteState(fetcher) as Promise<CreditNoteStateResponse>,
});
}
@@ -23,7 +23,6 @@ import {
editCustomerOpeningBalance,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { customersKeys } from './query-keys';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
@@ -105,14 +104,12 @@ export function useBulkDeleteCustomers(
export function useValidateBulkDeleteCustomers(
props?: UseMutationOptions<ValidateBulkDeleteCustomersResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteCustomers(fetcher, { ids, skipUndeletable: false }).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteCustomersResponse
),
validateBulkDeleteCustomers(fetcher, { ids, skipUndeletable: false }),
});
}
@@ -11,6 +11,7 @@ import type {
SaleEstimatesListResponse,
CreateSaleEstimateBody,
EditSaleEstimateBody,
SaleEstimateHtmlContentResponse,
} from '@bigcapital/sdk-ts';
import {
fetchSaleEstimates,
@@ -28,7 +29,12 @@ import {
fetchSaleEstimateMail,
sendSaleEstimateMail,
fetchSaleEstimatesState,
fetchSaleEstimateHtmlContent,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { estimatesKeys, EstimatesQueryKeys } from './query-keys';
import { itemsKeys } from '../items/query-keys';
import { useRequestPdf } from '../../useRequestPdf';
export type BulkDeleteEstimatesBody = { ids: number[]; skipUndeletable?: boolean };
export type ValidateBulkDeleteEstimatesResponse = {
@@ -37,11 +43,6 @@ export type ValidateBulkDeleteEstimatesResponse = {
deletableIds: number[];
nonDeletableIds: number[];
};
import useApiRequest, { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { estimatesKeys, EstimatesQueryKeys } from './query-keys';
import { itemsKeys } from '../items/query-keys';
import { useRequestPdf } from '../../useRequestPdf';
// Keys that don't have factory methods yet - keeping inline
const SETTING = 'SETTING';
@@ -145,14 +146,11 @@ export function useBulkDeleteEstimates(
export function useValidateBulkDeleteEstimates(
props?: UseMutationOptions<ValidateBulkDeleteEstimatesResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteSaleEstimates(fetcher, ids).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ValidateBulkDeleteEstimatesResponse
),
mutationFn: (ids: number[]) => validateBulkDeleteSaleEstimates(fetcher, ids),
});
}
@@ -305,14 +303,11 @@ export function useSaleEstimateMailState(
estimateId: number,
props?: UseQueryOptions<SaleEstimateMailStateResponse, Error>
): UseQueryResult<SaleEstimateMailStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: [EstimatesQueryKeys.SALE_ESTIMATE_MAIL_OPTIONS, estimateId],
queryFn: () =>
fetchSaleEstimateMail(fetcher, estimateId).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as SaleEstimateMailStateResponse
),
queryFn: () => fetchSaleEstimateMail(fetcher, estimateId) as Promise<SaleEstimateMailStateResponse>,
});
}
@@ -323,42 +318,27 @@ export interface ISaleEstimatesStateResponse {
export function useGetSaleEstimatesState(
options?: UseQueryOptions<ISaleEstimatesStateResponse, Error>
): UseQueryResult<ISaleEstimatesStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: ['SALE_ESTIMATE_STATE'],
queryFn: () =>
fetchSaleEstimatesState(fetcher).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ISaleEstimatesStateResponse
),
queryFn: () => fetchSaleEstimatesState(fetcher) as Promise<ISaleEstimatesStateResponse>,
});
}
interface GetEstimateHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the sale estimate html content.
* Uses custom Accept header; kept on apiRequest until SDK supports per-request headers.
*/
export const useGetSaleEstimateHtml = (
estimateId: number,
options?: UseQueryOptions<GetEstimateHtmlResponse>
): UseQueryResult<GetEstimateHtmlResponse> => {
const apiRequest = useApiRequest();
options?: UseQueryOptions<SaleEstimateHtmlContentResponse>
): UseQueryResult<SaleEstimateHtmlContentResponse> => {
const fetcher = useApiFetcher();
return useQuery({
...options,
queryKey: ['SALE_ESTIMATE_HTML', estimateId],
queryFn: (): Promise<GetEstimateHtmlResponse> =>
apiRequest
.get(`sale-estimates/${estimateId}`, {
headers: {
Accept: 'application/json+html',
},
})
.then((res) => transformToCamelCase(res.data) as GetEstimateHtmlResponse),
queryFn: () => fetchSaleEstimateHtmlContent(fetcher, estimateId),
});
};
@@ -9,7 +9,7 @@ import type {
CreateExpenseBody,
EditExpenseBody,
Expense,
ExpensesListQuery,
GetExpensesQuery,
ExpensesListResponse,
BulkDeleteExpensesBody,
ValidateBulkDeleteExpensesResponse,
@@ -25,7 +25,6 @@ import {
validateBulkDeleteExpenses,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { expensesKeys } from './query-keys';
import { accountsKeys } from '../accounts/query-keys';
import { customersKeys } from '../customers/query-keys';
@@ -65,9 +64,6 @@ const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>)
queryClient.invalidateQueries({ queryKey: [FINANCIAL_REPORT] });
};
/**
* Creates a new expense.
*/
export function useCreateExpense(
props?: UseMutationOptions<void, Error, CreateExpenseBody>
) {
@@ -84,9 +80,6 @@ export function useCreateExpense(
});
}
/**
* Edits the given expense.
*/
export function useEditExpense(
props?: UseMutationOptions<void, Error, [number, EditExpenseBody]>
) {
@@ -104,9 +97,6 @@ export function useEditExpense(
});
}
/**
* Deletes the given expense.
*/
export function useDeleteExpense(
props?: UseMutationOptions<void, Error, number>
) {
@@ -123,9 +113,6 @@ export function useDeleteExpense(
});
}
/**
* Publishes the given expense.
*/
export function usePublishExpense(
props?: UseMutationOptions<void, Error, number>
) {
@@ -142,9 +129,6 @@ export function usePublishExpense(
});
}
/**
* Bulk deletes expenses.
*/
export function useBulkDeleteExpenses(
props?: UseMutationOptions<void, Error, BulkDeleteExpensesBody>
) {
@@ -164,9 +148,6 @@ export function useBulkDeleteExpenses(
});
}
/**
* Validates bulk delete expenses.
*/
export function useValidateBulkDeleteExpenses(
props?: UseMutationOptions<
ValidateBulkDeleteExpensesResponse,
@@ -174,22 +155,17 @@ export function useValidateBulkDeleteExpenses(
number[]
>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteExpenses(fetcher, { ids }).then((res) =>
transformToCamelCase(res as unknown as Record<string, unknown>) as ValidateBulkDeleteExpensesResponse
),
validateBulkDeleteExpenses(fetcher, { ids, skipUndeletable: false }),
});
}
/**
* Retrieves expenses list.
*/
export function useExpenses(
query?: ExpensesListQuery | null,
query?: GetExpensesQuery | null,
props?: Omit<UseQueryOptions<ExpensesListResponse>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
@@ -197,14 +173,10 @@ export function useExpenses(
return useQuery({
...props,
queryKey: expensesKeys.list(query ?? undefined),
queryFn: async () =>
fetchExpenses(fetcher, query ?? {}),
queryFn: () => fetchExpenses(fetcher, query ?? {}),
});
}
/**
* Retrieves the expense details.
*/
export function useExpense(
id: number | null | undefined,
props?: Omit<UseQueryOptions<Expense>, 'queryKey' | 'queryFn'>
@@ -219,9 +191,6 @@ export function useExpense(
});
}
/**
* Refreshes the expenses list.
*/
export function useRefreshExpenses() {
const queryClient = useQueryClient();
@@ -8,7 +8,6 @@ import {
} from '@tanstack/react-query';
import useApiRequest from '../../useRequest';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { downloadFile } from '../../useDownloadFile';
import { importKeys } from './query-keys';
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
@@ -61,13 +60,12 @@ export function useImportFilePreview(
importId: string,
props?: UseQueryOptions<ImportPreviewResponse, Error, unknown>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: importKeys.preview(importId),
queryFn: () => fetchImportPreview(fetcher, importId),
select: (data) => transformToCamelCase(data),
enabled: !!importId,
});
}
@@ -76,13 +74,12 @@ export function useImportFileMeta(
importId: string,
props?: UseQueryOptions<ImportFileMetaResponse, Error, unknown>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: importKeys.fileMeta(importId),
queryFn: () => fetchImportFileMeta(fetcher, importId),
select: (data) => transformToCamelCase(data),
enabled: !!importId,
});
}
@@ -2,7 +2,6 @@ import { useMutation, useQuery, UseMutationOptions, UseQueryOptions } from '@tan
import type { AcceptInviteBody } from '@bigcapital/sdk-ts';
import { acceptInvite, fetchInviteCheck, resendInvite } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { inviteKeys } from './query-keys';
/**
@@ -26,13 +25,12 @@ export function useInviteMetaByToken(
token: string | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: inviteKeys.meta(token),
queryFn: () => fetchInviteCheck(fetcher, token!),
enabled: !!token,
select: (data) => transformToCamelCase(data as Record<string, unknown>),
});
}
@@ -67,9 +67,6 @@ function commonInvalidateQueries(queryClient: ReturnType<typeof useQueryClient>)
queryClient.invalidateQueries({ queryKey: organizationKeys.mutateAbilities() });
}
/**
* Creates a new sale invoice.
*/
export function useCreateInvoice(
props?: UseMutationOptions<void, Error, CreateSaleInvoiceBody>
) {
@@ -80,19 +77,14 @@ export function useCreateInvoice(
...props,
mutationFn: (values: CreateSaleInvoiceBody) => createSaleInvoice(fetcher, values),
onSuccess: (_data, values) => {
const customerId = (values as { customer_id?: number }).customer_id;
if (customerId != null) {
queryClient.invalidateQueries({ queryKey: customersKeys.detail(customerId) });
}
const customerId = values.customerId as unknown as number;
queryClient.invalidateQueries({ queryKey: customersKeys.detail(customerId) });
queryClient.invalidateQueries({ queryKey: estimatesKeys.all() });
commonInvalidateQueries(queryClient);
},
});
}
/**
* Edits the given sale invoice.
*/
export function useEditInvoice(
props?: UseMutationOptions<void, Error, [number, EditSaleInvoiceBody]>
) {
@@ -104,19 +96,14 @@ export function useEditInvoice(
mutationFn: ([id, values]: [number, EditSaleInvoiceBody]) =>
editSaleInvoice(fetcher, id, values),
onSuccess: (_data, [id, values]) => {
const customerId = values.customerId as unknown as number;
queryClient.invalidateQueries({ queryKey: invoicesKeys.detail(id) });
const customerId = (values as { customer_id?: number }).customer_id;
if (customerId != null) {
queryClient.invalidateQueries({ queryKey: customersKeys.detail(customerId) });
}
queryClient.invalidateQueries({ queryKey: customersKeys.detail(customerId) });
commonInvalidateQueries(queryClient);
},
});
}
/**
* Deletes the given sale invoice.
*/
export function useDeleteInvoice(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
@@ -132,9 +119,6 @@ export function useDeleteInvoice(props?: UseMutationOptions<void, Error, number>
});
}
/**
* Deletes multiple sale invoices in bulk.
*/
export function useBulkDeleteInvoices(
props?: UseMutationOptions<
void,
@@ -158,10 +142,8 @@ export function useBulkDeleteInvoices(
});
}
export type ValidateBulkDeleteInvoicesResponse = ValidateBulkDeleteSaleInvoicesResponse;
export function useValidateBulkDeleteInvoices(
props?: UseMutationOptions<ValidateBulkDeleteInvoicesResponse, Error, number[]>
props?: UseMutationOptions<ValidateBulkDeleteSaleInvoicesResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
@@ -171,9 +153,6 @@ export function useValidateBulkDeleteInvoices(
});
}
/**
* Retrieve sale invoices list with pagination meta.
*/
export function useInvoices(
query?: GetSaleInvoicesQuery,
props?: UseQueryOptions<SaleInvoicesListResponse, Error>
@@ -187,9 +166,6 @@ export function useInvoices(
});
}
/**
* Marks the sale invoice as delivered.
*/
export function useDeliverInvoice(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
@@ -204,18 +180,13 @@ export function useDeliverInvoice(props?: UseMutationOptions<void, Error, number
});
}
/**
* Retrieve the sale invoice details.
*/
export function useInvoice(
invoiceId: number | null | undefined,
props?: UseQueryOptions<SaleInvoice, Error>,
requestProps?: Record<string, unknown>
) {
const fetcher = useApiFetcher();
return useQuery({
...requestProps,
...props,
queryKey: invoicesKeys.detail(invoiceId),
queryFn: () => fetchSaleInvoice(fetcher, invoiceId as number),
@@ -232,32 +203,19 @@ export function usePdfInvoice(invoiceId: number) {
});
}
interface GetInvoiceHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the invoice html content.
*/
export function useInvoiceHtml(
invoiceId: number,
options?: UseQueryOptions<GetInvoiceHtmlResponse, Error>
options?: UseQueryOptions<SaleInvoiceHtmlContentResponse, Error>
): UseQueryResult<GetInvoiceHtmlResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: ['SALE_INVOICE_HTML', invoiceId],
queryFn: () =>
fetchSaleInvoiceHtml(fetcher, invoiceId).then((data: { htmlContent: string }) =>
transformToCamelCase(data) as GetInvoiceHtmlResponse
),
queryFn: () => fetchSaleInvoiceHtml(fetcher, invoiceId),
});
}
/**
* Retrieve due (receivable) invoices of the given customer id.
*/
export function useDueInvoices(
customerId: number | null | undefined,
props?: UseQueryOptions<unknown, Error>
@@ -446,15 +404,12 @@ export function useSaleInvoiceMailState(
invoiceId: number,
options?: UseQueryOptions<GetSaleInvoiceDefaultOptionsResponse, Error>
): UseQueryResult<GetSaleInvoiceDefaultOptionsResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: [InvoicesQueryKeys.SALE_INVOICE_DEFAULT_OPTIONS, invoiceId],
queryFn: () =>
fetchSaleInvoiceMailState(fetcher, invoiceId).then((data: unknown) =>
transformToCamelCase(data) as GetSaleInvoiceDefaultOptionsResponse
),
queryFn: () => fetchSaleInvoiceMailState(fetcher, invoiceId) as Promise<GetSaleInvoiceDefaultOptionsResponse>,
});
}
@@ -464,14 +419,14 @@ export type GetSaleInvoiceStateResponse = SaleInvoiceStateResponse;
export function useGetSaleInvoiceState(
options?: UseQueryOptions<GetSaleInvoiceStateResponse, Error>
): UseQueryResult<GetSaleInvoiceStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: ['SALE_INVOICE_STATE'],
queryFn: () =>
fetchSaleInvoiceState(fetcher).then((data: GetSaleInvoiceStateResponse & { data?: unknown }) =>
transformToCamelCase(data?.data ?? data) as GetSaleInvoiceStateResponse
(data?.data ?? data) as GetSaleInvoiceStateResponse
),
});
}
@@ -35,7 +35,6 @@ import type {
GetInventoryItemsCostResponse,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { itemsKeys } from './query-keys';
import { itemsCategoriesKeys } from '../items-categories/query-keys';
@@ -112,14 +111,12 @@ export function useBulkDeleteItems(
export function useValidateBulkDeleteItems(
props?: UseMutationOptions<ValidateBulkDeleteItemsResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteItems(fetcher, { ids, skipUndeletable: false } as BulkDeleteItemsBody).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteItemsResponse
),
validateBulkDeleteItems(fetcher, { ids, skipUndeletable: false } as BulkDeleteItemsBody),
});
}
@@ -1,5 +1,3 @@
// @ts-nocheck
import { transformToCamelCase } from '@/utils';
import { useQuery, UseQueryOptions } from '@tanstack/react-query';
import { fetchOrganizationBuildJob } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
@@ -9,12 +7,12 @@ import { jobsKeys } from './query-keys';
* Retrieve the job metadata.
*/
export function useJob(jobId: string | number | null | undefined, props: Omit<UseQueryOptions, 'queryKey' | 'queryFn'> = {}) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: jobsKeys.detail(jobId),
queryFn: () =>
fetchOrganizationBuildJob(fetcher, jobId).then((data) => transformToCamelCase(data)),
// @ts-expect-error - jobId is checked by enabled option
queryFn: () => fetchOrganizationBuildJob(fetcher, jobId),
enabled: jobId != null,
});
}
@@ -25,7 +25,6 @@ import {
validateBulkDeleteManualJournals,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { manualJournalsKeys, MANUAL_JOURNAL } from './query-keys';
import { accountsKeys } from '../accounts/query-keys';
import { customersKeys } from '../customers/query-keys';
@@ -139,14 +138,11 @@ export function useValidateBulkDeleteManualJournals(
number[]
>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteManualJournals(fetcher, { ids }).then((res) =>
transformToCamelCase(res as unknown as Record<string, unknown>) as ValidateBulkDeleteManualJournalsResponse
),
mutationFn: (ids: number[]) => validateBulkDeleteManualJournals(fetcher, { ids }),
});
}
@@ -7,7 +7,6 @@ import {
useQuery,
} from '@tanstack/react-query';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import type {
GetInvoicePaymentLinkResponse,
CreateStripeCheckoutSessionResponse,
@@ -71,14 +70,11 @@ export function useGetInvoicePaymentLink(
linkId: string,
options?: UseQueryOptions<GetInvoicePaymentLinkResponse, Error>,
): UseQueryResult<GetInvoicePaymentLinkResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery<GetInvoicePaymentLinkResponse, Error>({
queryKey: paymentLinkKeys.invoice(linkId),
queryFn: () =>
fetchGetInvoicePaymentLink(fetcher, linkId).then((data) =>
transformToCamelCase(data) as GetInvoicePaymentLinkResponse,
),
queryFn: () => fetchGetInvoicePaymentLink(fetcher, linkId),
enabled: !!linkId,
...options,
});
@@ -101,13 +97,11 @@ export const useCreateStripeCheckoutSession = (
Error,
CreateCheckoutSessionValues
> => {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
mutationFn: (values: CreateCheckoutSessionValues) =>
fetchCreateStripeCheckoutSession(fetcher, values.linkId).then((data) =>
transformToCamelCase(data) as CreateStripeCheckoutSessionResponse,
),
fetchCreateStripeCheckoutSession(fetcher, values.linkId),
...options,
});
};
@@ -12,6 +12,10 @@ import type {
PaymentReceived,
CreatePaymentReceivedBody,
EditPaymentReceivedBody,
BulkDeletePaymentsReceivedBody,
ValidateBulkDeletePaymentsReceivedResponse,
PaymentReceivedStateResponse,
PaymentReceivedHtmlContentResponse,
} from '@bigcapital/sdk-ts';
import {
fetchPaymentsReceived,
@@ -25,15 +29,9 @@ import {
fetchPaymentReceiveMail,
sendPaymentReceiveMail,
fetchPaymentReceivedState,
fetchPaymentReceiveHtmlContent,
} from '@bigcapital/sdk-ts';
export type BulkDeletePaymentsReceivedBody = { ids: number[]; skipUndeletable?: boolean };
export type ValidateBulkDeletePaymentsReceivedResponse = {
deletableCount: number;
nonDeletableCount: number;
deletableIds: number[];
nonDeletableIds: number[];
};
import useApiRequest, { useApiFetcher } from '../../useRequest';
import { useRequestQuery } from '../../useQueryRequest';
import { saveInvoke, transformToCamelCase } from '@/utils';
@@ -75,7 +73,7 @@ export function usePaymentReceives(
return useQuery({
...props,
queryKey: paymentReceivesKeys.list(query),
queryFn: () => fetchPaymentsReceived(fetcher, query),
queryFn: () => fetchPaymentsReceived(fetcher),
});
}
@@ -149,14 +147,11 @@ export function useBulkDeletePaymentReceives(
export function useValidateBulkDeletePaymentReceives(
props?: UseMutationOptions<ValidateBulkDeletePaymentsReceivedResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeletePaymentsReceived(fetcher, ids).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ValidateBulkDeletePaymentsReceivedResponse
),
mutationFn: (ids: number[]) => validateBulkDeletePaymentsReceived(fetcher, ids),
});
}
@@ -298,56 +293,40 @@ export function usePaymentReceivedMailState(
paymentReceiveId: number,
props?: UseQueryOptions<GetPaymentReceivedMailStateResponse, Error>
): UseQueryResult<GetPaymentReceivedMailStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: [PaymentReceivesQueryKeys.PAYMENT_RECEIVE_MAIL_OPTIONS, paymentReceiveId],
queryFn: () =>
fetchPaymentReceiveMail(fetcher, paymentReceiveId).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as GetPaymentReceivedMailStateResponse
),
fetchPaymentReceiveMail(fetcher, paymentReceiveId) as Promise<GetPaymentReceivedMailStateResponse>,
});
}
export interface PaymentReceivedStateResponse {
defaultTemplateId: number;
}
export function usePaymentReceivedState(
options?: UseQueryOptions<PaymentReceivedStateResponse, Error>
): UseQueryResult<PaymentReceivedStateResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: ['PAYMENT_RECEIVED_STATE'],
queryFn: () =>
fetchPaymentReceivedState(fetcher).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as PaymentReceivedStateResponse
),
queryFn: () => fetchPaymentReceivedState(fetcher),
});
}
interface PaymentReceivedHtmlResponse {
htmlContent: string;
}
/** HTML content uses custom Accept header; kept on apiRequest. */
/**
* Retrieves the payment received HTML content.
*/
export function useGetPaymentReceiveHtml(
paymentReceivedId: number,
options?: UseQueryOptions<PaymentReceivedHtmlResponse, Error>
): UseQueryResult<PaymentReceivedHtmlResponse, Error> {
const apiRequest = useApiRequest();
options?: UseQueryOptions<PaymentReceivedHtmlContentResponse, Error>
): UseQueryResult<PaymentReceivedHtmlContentResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
...options,
queryKey: ['PAYMENT_RECEIVED_HTML', paymentReceivedId],
queryFn: (): Promise<PaymentReceivedHtmlResponse> =>
apiRequest
.get(`/payments-received/${paymentReceivedId}`, {
headers: { Accept: 'application/json+html' },
})
.then((res) => transformToCamelCase(res.data) as PaymentReceivedHtmlResponse),
queryFn: () => fetchPaymentReceiveHtmlContent(fetcher, paymentReceivedId),
});
}
@@ -20,7 +20,6 @@ import {
type UpdatePaymentMethodResponse,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { paymentServicesKeys } from './query-keys';
// # Get payment services.
@@ -31,13 +30,13 @@ import { paymentServicesKeys } from './query-keys';
export const useGetPaymentServices = (
options?: UseQueryOptions<GetPaymentServicesResponse, Error>,
): UseQueryResult<GetPaymentServicesResponse, Error> => {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery<GetPaymentServicesResponse, Error>({
queryKey: paymentServicesKeys.list(),
queryFn: () =>
fetchGetPaymentServices(fetcher).then((res) =>
transformToCamelCase(res?.payment_services) as GetPaymentServicesResponse,
res?.payment_services as GetPaymentServicesResponse,
),
...options,
});
@@ -51,14 +50,12 @@ export const useGetPaymentServices = (
export const useGetPaymentServicesState = (
options?: UseQueryOptions<GetPaymentServicesStateResponse, Error>,
): UseQueryResult<GetPaymentServicesStateResponse, Error> => {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery<GetPaymentServicesStateResponse, Error>({
queryKey: paymentServicesKeys.state(),
queryFn: () =>
fetchGetPaymentServicesState(fetcher).then((data) =>
transformToCamelCase(data) as GetPaymentServicesStateResponse,
),
fetchGetPaymentServicesState(fetcher) as Promise<GetPaymentServicesStateResponse>,
...options,
});
};
@@ -116,13 +113,13 @@ export const useGetPaymentMethod = (
paymentMethodId: number,
options?: Omit<UseQueryOptions<GetPaymentServiceResponse, Error>, 'queryKey' | 'queryFn'>,
): UseQueryResult<GetPaymentServiceResponse, Error> => {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery<GetPaymentServiceResponse, Error>({
queryKey: paymentServicesKeys.detail(paymentMethodId),
queryFn: () =>
fetchGetPaymentService(fetcher, paymentMethodId).then((res) =>
transformToCamelCase(res?.data) as GetPaymentServiceResponse,
res?.data as GetPaymentServiceResponse,
),
enabled: !!paymentMethodId,
...options,
@@ -13,6 +13,11 @@ import type {
EditSaleReceiptBody,
ValidateBulkDeleteReceiptsResponse,
SaleReceiptStateResponse,
SaleReceiptMailResponse,
SaleReceiptSendMailBody,
SaleReceiptHtmlContentResponse,
GetSaleReceiptsQuery,
BulkDeleteReceiptsBody,
} from '@bigcapital/sdk-ts';
import {
fetchSaleReceipts,
@@ -26,9 +31,9 @@ import {
fetchSaleReceiptMail,
sendSaleReceiptMail,
fetchSaleReceiptState,
fetchSaleReceiptHtmlContent,
} from '@bigcapital/sdk-ts';
import useApiRequest, { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { useRequestPdf } from '../../useRequestPdf';
import { useRequestQuery } from '../../useQueryRequest';
import { receiptsKeys, ReceiptsQueryKeys } from './query-keys';
@@ -58,9 +63,6 @@ function commonInvalidateQueries(queryClient: ReturnType<typeof useQueryClient>)
queryClient.invalidateQueries({ queryKey: [ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
}
/**
* Creates a new sale receipt.
*/
export function useCreateReceipt(
props?: UseMutationOptions<void, Error, CreateSaleReceiptBody>
) {
@@ -74,9 +76,6 @@ export function useCreateReceipt(
});
}
/**
* Edits the given sale receipt.
*/
export function useEditReceipt(
props?: UseMutationOptions<void, Error, [number, EditSaleReceiptBody]>
) {
@@ -94,9 +93,6 @@ export function useEditReceipt(
});
}
/**
* Deletes the given sale receipt.
*/
export function useDeleteReceipt(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
@@ -111,22 +107,15 @@ export function useDeleteReceipt(props?: UseMutationOptions<void, Error, number>
});
}
/**
* Deletes multiple receipts in bulk.
*/
export function useBulkDeleteReceipts(
props?: UseMutationOptions<
void,
Error,
{ ids: number[]; skipUndeletable?: boolean }
>
props?: UseMutationOptions<void, Error, BulkDeleteReceiptsBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
...props,
mutationFn: ({ ids, skipUndeletable = false }: { ids: number[]; skipUndeletable?: boolean }) =>
mutationFn: ({ ids, skipUndeletable = false }: BulkDeleteReceiptsBody) =>
bulkDeleteSaleReceipts(fetcher, { ids, skipUndeletable }),
onSuccess: () => commonInvalidateQueries(queryClient),
});
@@ -143,9 +132,6 @@ export function useValidateBulkDeleteReceipts(
});
}
/**
* Closes the given sale receipt.
*/
export function useCloseReceipt(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
@@ -160,11 +146,8 @@ export function useCloseReceipt(props?: UseMutationOptions<void, Error, number>)
});
}
/**
* Retrieve sale receipts list with pagination meta.
*/
export function useReceipts(
query?: Record<string, unknown>,
query?: GetSaleReceiptsQuery,
props?: UseQueryOptions<SaleReceiptsListResponse, Error>
) {
const fetcher = useApiFetcher();
@@ -176,9 +159,6 @@ export function useReceipts(
});
}
/**
* Retrieve sale receipt detail.
*/
export function useReceipt(
id: number | null | undefined,
props?: UseQueryOptions<SaleReceipt, Error>
@@ -193,9 +173,6 @@ export function useReceipt(
});
}
/**
* Retrieve the receipt pdf document data.
*/
export function usePdfReceipt(receiptId: number) {
return useRequestPdf({ url: `sale-receipts/${receiptId}` });
}
@@ -242,121 +219,60 @@ export function useReceiptSMSDetail(
...requestProps,
},
{
select: (res: { data: unknown }) => res.data,
defaultData: {},
...props,
}
);
}
/**
* Sends the sale receipt mail.
*/
export function useSendSaleReceiptMail(
props?: UseMutationOptions<void, Error, [number, Record<string, unknown>]>
props?: UseMutationOptions<void, Error, [number, SaleReceiptSendMailBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
...props,
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
mutationFn: ([id, values]: [number, SaleReceiptSendMailBody]) =>
sendSaleReceiptMail(fetcher, id, values),
onSuccess: () => commonInvalidateQueries(queryClient),
});
}
export interface GetSaleReceiptMailStateResponse {
attachReceipt: boolean;
closedAtDate: string;
closedAtDateFormatted: string;
companyName: string;
customerName: string;
formatArgs: Record<string, unknown>;
from: string[];
fromOptions: Array<{ mail: string; label: string; primary: boolean }>;
message: string;
receiptDate: string;
receiptDateFormatted: string;
subject: string;
subtotal: number;
subtotalFormatted: string;
to: string[];
toOptions: Array<{ mail: string; label: string; primary: boolean }>;
discountAmount: number;
discountAmountFormatted: string;
discountLabel: string;
discountPercentage: number | null;
discountPercentageFormatted: string;
adjustment: number;
adjustmentFormatted: string;
total: number;
totalFormatted: string;
companyLogoUri?: string | null;
primaryColor?: string | null;
entries: Array<{
name: string;
quantity: number;
quantityFormatted: string;
rate: number;
rateFormatted: string;
total: number;
totalFormatted: string;
}>;
receiptNumber: string;
}
export function useSaleReceiptMailState(
receiptId: number,
props?: UseQueryOptions<GetSaleReceiptMailStateResponse, Error>
): UseQueryResult<GetSaleReceiptMailStateResponse, Error> {
const fetcher = useApiFetcher();
props?: UseQueryOptions<SaleReceiptMailResponse, Error>
): UseQueryResult<SaleReceiptMailResponse, Error> {
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...props,
queryKey: [ReceiptsQueryKeys.SALE_RECEIPT_MAIL_OPTIONS, receiptId],
queryFn: () =>
fetchSaleReceiptMail(fetcher, receiptId).then((data) =>
transformToCamelCase(data) as GetSaleReceiptMailStateResponse
),
queryFn: () => fetchSaleReceiptMail(fetcher, receiptId),
});
}
export type IGetReceiptStateResponse = SaleReceiptStateResponse;
export function useGetReceiptState(
options?: UseQueryOptions<IGetReceiptStateResponse, Error>
): UseQueryResult<IGetReceiptStateResponse, Error> {
const fetcher = useApiFetcher();
options?: UseQueryOptions<SaleReceiptStateResponse, Error>
): UseQueryResult<SaleReceiptStateResponse, Error> {
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
...options,
queryKey: ['SALE_RECEIPT_STATE'],
queryFn: () => fetchSaleReceiptState(fetcher).then((data) => transformToCamelCase(data) as IGetReceiptStateResponse),
queryFn: () => fetchSaleReceiptState(fetcher),
});
}
interface GetReceiptHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the sale receipt html content (custom Accept header; not in SDK).
*/
export function useGetSaleReceiptHtml(
receiptId: number,
options?: UseQueryOptions<GetReceiptHtmlResponse, Error>
): UseQueryResult<GetReceiptHtmlResponse, Error> {
const apiRequest = useApiRequest();
options?: UseQueryOptions<SaleReceiptHtmlContentResponse, Error>
): UseQueryResult<SaleReceiptHtmlContentResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
...options,
queryKey: ['SALE_RECEIPT_HTML', receiptId],
queryFn: () =>
apiRequest
.get(`sale-receipts/${receiptId}`, {
headers: { Accept: 'application/json+html' },
})
.then((res) => transformToCamelCase(res.data) as GetReceiptHtmlResponse),
queryFn: () => fetchSaleReceiptHtmlContent(fetcher, receiptId),
});
}
@@ -100,6 +100,5 @@ export function useRoles(
...props,
queryKey: [...rolesKeys.all(), query],
queryFn: () => fetchRoles(fetcher),
select: (data) => (Array.isArray(data) ? data : (data as { data?: unknown })?.data ?? data),
});
}
@@ -7,12 +7,14 @@ import {
useQuery,
} from '@tanstack/react-query';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import type {
GetStripeConnectLinkResponse,
CreateStripeAccountLinkResponse,
CreateStripeAccountSessionResponse,
CreateStripeAccountResponse,
CreateStripeAccountLinkBody,
CreateStripeAccountSessionBody,
ExchangeStripeOAuthBody,
} from '@bigcapital/sdk-ts';
import {
fetchGetStripeConnectLink,
@@ -25,60 +27,43 @@ import { stripeIntegrationKeys } from './query-keys';
// Create Stripe Account Link
// ------------------------------------
interface StripeAccountLinkResponse {
clientSecret: {
created: number;
expiresAt: number;
object: string;
url: string;
};
}
interface StripeAccountLinkValues {
stripeAccountId: string;
}
export const useCreateStripeAccountLink = (
options?: UseMutationOptions<
StripeAccountLinkResponse,
CreateStripeAccountLinkResponse,
Error,
StripeAccountLinkValues
CreateStripeAccountLinkBody
>,
): UseMutationResult<
StripeAccountLinkResponse,
CreateStripeAccountLinkResponse,
Error,
StripeAccountLinkValues
CreateStripeAccountLinkBody
> => {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
mutationFn: (values: StripeAccountLinkValues) =>
mutationFn: (values: CreateStripeAccountLinkBody) =>
fetchCreateStripeAccountLink(fetcher, {
stripeAccountId: values.stripeAccountId,
}).then((data) => transformToCamelCase(data) as StripeAccountLinkResponse),
}),
...options,
});
};
// Create Stripe Account Session
// ------------------------------------
interface AccountSessionValues {
connectedAccountId?: string;
}
export const useCreateStripeAccountSession = (
options?: UseMutationOptions<
CreateStripeAccountSessionResponse,
Error,
AccountSessionValues
CreateStripeAccountSessionBody
>,
): UseMutationResult<CreateStripeAccountSessionResponse, Error, AccountSessionValues> => {
): UseMutationResult<CreateStripeAccountSessionResponse, Error, CreateStripeAccountSessionBody> => {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: AccountSessionValues) =>
mutationFn: (values: CreateStripeAccountSessionBody) =>
fetchCreateStripeAccountSession(fetcher, {
account: values?.connectedAccountId,
account: values?.account,
}),
...options,
});
@@ -86,20 +71,17 @@ export const useCreateStripeAccountSession = (
// Create Stripe Account
// ------------------------------------
interface CreateStripeAccountValues {}
export const useCreateStripeAccount = (
options?: UseMutationOptions<
CreateStripeAccountResponse,
Error,
CreateStripeAccountValues
void
>,
) => {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (_values: CreateStripeAccountValues) =>
fetchCreateStripeAccount(fetcher),
mutationFn: () => fetchCreateStripeAccount(fetcher),
...options,
});
};
@@ -120,10 +102,6 @@ export const useGetStripeAccountLink = (
// Stripe Account OAuth Callback
// ------------------------------------
interface StripeAccountCallbackMutationValues {
code: string;
}
interface StripeAccountCallbackMutationResponse {
success: boolean;
}
@@ -132,17 +110,17 @@ export const useSetStripeAccountCallback = (
options?: UseMutationOptions<
StripeAccountCallbackMutationResponse,
Error,
StripeAccountCallbackMutationValues
ExchangeStripeOAuthBody
>,
): UseMutationResult<
StripeAccountCallbackMutationResponse,
Error,
StripeAccountCallbackMutationValues
ExchangeStripeOAuthBody
> => {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: StripeAccountCallbackMutationValues) =>
mutationFn: (values: ExchangeStripeOAuthBody) =>
fetchExchangeStripeOAuth(fetcher, { code: values.code }).then(
() => ({ success: true }) as StripeAccountCallbackMutationResponse,
),
@@ -8,7 +8,6 @@ import {
UseQueryResult,
} from '@tanstack/react-query';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import type {
SubscriptionsListResponse,
ChangeSubscriptionPlanBody,
@@ -91,12 +90,11 @@ export function useGetSubscriptions(
GetSubscriptionsResponse
>
): UseQueryResult<GetSubscriptionsResponse, Error> {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useQuery({
queryKey: subscriptionKeys.list(),
queryFn: () => fetchSubscriptions(fetcher),
select: (data) => transformToCamelCase(data) as GetSubscriptionsResponse,
...options,
});
}
@@ -35,7 +35,6 @@ export function useTaxRates(
...props,
queryKey: taxRatesKeys.all(),
queryFn: () => fetchTaxRates(fetcher),
select: (data) => ((data as { data?: unknown })?.data ?? data) as unknown[],
});
}
@@ -33,7 +33,6 @@ import {
deleteAppliedBillToVendorCredit,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { vendorCreditsKeys, VendorCreditsQueryKeys } from './query-keys';
import { vendorsKeys } from '../vendors/query-keys';
import { itemsKeys } from '../items/query-keys';
@@ -143,14 +142,12 @@ export function useValidateBulkDeleteVendorCredits(
number[]
>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteVendorCredits(fetcher, { ids } as BulkDeleteVendorCreditsBody).then(
(data: Record<string, unknown>) => transformToCamelCase(data) as ValidateBulkDeleteVendorCreditsResponse
),
validateBulkDeleteVendorCredits(fetcher, { ids } as BulkDeleteVendorCreditsBody),
});
}
+3 -10
View File
@@ -24,7 +24,6 @@ import {
editVendorOpeningBalance,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../../useRequest';
import { transformToCamelCase } from '@/utils';
import { vendorsKeys } from './query-keys';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
@@ -39,11 +38,7 @@ export function useVendors(
return useQuery({
...props,
queryKey: vendorsKeys.list(query),
queryFn: () =>
(fetchVendors as (f: ReturnType<typeof useApiFetcher>, q?: Record<string, unknown>) => Promise<VendorsListResponse>)(
fetcher,
query
),
queryFn: () => fetchVendors(fetcher, query),
});
}
@@ -102,14 +97,12 @@ export function useBulkDeleteVendors(
export function useValidateBulkDeleteVendors(
props?: UseMutationOptions<ValidateBulkDeleteVendorsResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
const fetcher = useApiFetcher({ enableCamelCaseTransform: true });
return useMutation({
...props,
mutationFn: (ids: number[]) =>
validateBulkDeleteVendors(fetcher, { ids, skipUndeletable: false } as BulkDeleteVendorsBody).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteVendorsResponse
),
validateBulkDeleteVendors(fetcher, { ids, skipUndeletable: false } as BulkDeleteVendorsBody),
});
}
@@ -32,9 +32,6 @@ const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>)
queryClient.invalidateQueries({ queryKey: [DASHBOARD_META] });
};
/**
* Create a new warehouse.
*/
export function useCreateWarehouse(
props?: UseMutationOptions<void, Error, CreateWarehouseBody>
) {
@@ -49,9 +46,6 @@ export function useCreateWarehouse(
});
}
/**
* Edits the given warehouse.
*/
export function useEditWarehouse(
props?: UseMutationOptions<void, Error, [number, EditWarehouseBody]>
) {
@@ -69,9 +63,6 @@ export function useEditWarehouse(
});
}
/**
* Deletes the given warehouse.
*/
export function useDeleteWarehouse(
props?: UseMutationOptions<void, Error, number>
) {
@@ -88,9 +79,6 @@ export function useDeleteWarehouse(
});
}
/**
* Retrieve warehouses list.
*/
export function useWarehouses(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<WarehousesListResponse>, 'queryKey' | 'queryFn'>
@@ -103,9 +91,6 @@ export function useWarehouses(
});
}
/**
* Retrieve the warehouse details.
*/
export function useWarehouse(
id: number | string | null | undefined,
props?: Omit<UseQueryOptions<Warehouse>, 'queryKey' | 'queryFn'>,
@@ -121,9 +106,6 @@ export function useWarehouse(
});
}
/**
* Activate the given warehouse.
*/
export function useActivateWarehouses(
props?: UseMutationOptions<void, Error, number>
) {
@@ -137,9 +119,6 @@ export function useActivateWarehouses(
});
}
/**
* Mark the given warehouse as primary.
*/
export function useMarkWarehouseAsPrimary(
props?: UseMutationOptions<void, Error, number>
) {
+6 -3
View File
@@ -124,8 +124,11 @@ export default function useApiRequest() {
/**
* Returns an ApiFetcher configured with baseUrl and auth headers for use with sdk-ts fetch functions.
* Use this in query hooks that call fetchAccounts, fetchCreditNotes, etc.
*
* @param options - Optional configuration
* @param options.enableCamelCaseTransform - If true, automatically transforms response data from snake_case to camelCase
*/
export function useApiFetcher() {
export function useApiFetcher(options?: { enableCamelCaseTransform?: boolean }) {
const token = useAuthToken();
const organizationId = useAuthOrganizationId();
const currentLocale = getCookie('locale');
@@ -146,9 +149,9 @@ export function useApiFetcher() {
return createApiFetcher({
baseUrl: '',
init: { headers },
disableCamelCaseTransform: true,
disableCamelCaseTransform: !options?.enableCamelCaseTransform,
});
}, [token, organizationId]);
}, [token, organizationId, currentLocale, options?.enableCamelCaseTransform]);
}
/**
+267 -287
View File
File diff suppressed because it is too large Load Diff
+36
View File
@@ -5087,6 +5087,11 @@
"schema": {
"$ref": "#/components/schemas/PaymentReceivedResponseDto"
}
},
"application/json+html": {
"schema": {
"$ref": "#/components/schemas/PaymentReceivedHtmlContentResponseDto"
}
}
}
}
@@ -8275,6 +8280,11 @@
"schema": {
"$ref": "#/components/schemas/SaleEstimateResponseDto"
}
},
"application/json+html": {
"schema": {
"$ref": "#/components/schemas/SaleEstimateHtmlContentResponseDto"
}
}
}
}
@@ -26889,6 +26899,19 @@
"active"
]
},
"PaymentReceivedHtmlContentResponseDto": {
"type": "object",
"properties": {
"htmlContent": {
"type": "string",
"description": "The HTML content of the payment received",
"example": "<html>...</html>"
}
},
"required": [
"htmlContent"
]
},
"PaymentReceivedStateResponseDto": {
"type": "object",
"properties": {
@@ -29590,6 +29613,19 @@
"ids"
]
},
"SaleEstimateHtmlContentResponseDto": {
"type": "object",
"properties": {
"htmlContent": {
"type": "string",
"description": "The HTML content of the estimate",
"example": "<html>...</html>"
}
},
"required": [
"htmlContent"
]
},
"SaleEstiamteStateResponseDto": {
"type": "object",
"properties": {
+14 -7
View File
@@ -19,11 +19,16 @@ export interface CreateApiFetcherConfig {
* Set disableCamelCaseTransform: true to disable this behavior.
*/
export function createApiFetcher(config?: CreateApiFetcherConfig): ApiFetcher {
const parsedConfig = {
baseUrl: '',
disableCamelCaseTransform: true,
...config,
};
const fetcher = Fetcher.for<paths>();
fetcher.configure({
baseUrl: config?.baseUrl ?? '',
init: config?.init,
use: config?.disableCamelCaseTransform ? [] : [createCamelCaseMiddleware()],
baseUrl: parsedConfig.baseUrl,
init: parsedConfig?.init,
use: parsedConfig.disableCamelCaseTransform ? [] : [createCamelCaseMiddleware()],
});
return fetcher;
}
@@ -43,7 +48,8 @@ export async function rawRequest<T = unknown>(
fetcher: ApiFetcher,
method: string,
path: string,
body?: Record<string, unknown>
body?: Record<string, unknown>,
headers?: Record<string, string>
): Promise<T> {
// Access the fetcher's internal configuration
const fetcherConfig = (fetcher as unknown as { config?: { baseUrl: string; init?: RequestInit } }).config;
@@ -51,19 +57,20 @@ export async function rawRequest<T = unknown>(
const init = fetcherConfig?.init ?? {};
const url = `${baseUrl}${path}`;
const headers: Record<string, string> = {
const mergedHeaders: Record<string, string> = {
'Accept': 'application/json',
...(init.headers as Record<string, string> || {}),
...(headers || {}),
};
const requestInit: RequestInit = {
...init,
method,
headers,
headers: mergedHeaders,
};
if (body && (method === 'POST' || method === 'PUT' || method === 'PATCH')) {
headers['Content-Type'] = 'application/json';
mergedHeaders['Content-Type'] = 'application/json';
requestInit.body = JSON.stringify(body);
}
+20 -2
View File
@@ -1,4 +1,5 @@
import type { ApiFetcher } from './fetch-utils';
import { rawRequest } from './fetch-utils';
import { paths } from './schema';
import { OpForPath, OpRequestBody, OpResponseBody } from './utils';
@@ -16,6 +17,8 @@ export type PaymentsReceivedListResponse = OpResponseBody<OpForPath<typeof PAYME
export type PaymentReceived = OpResponseBody<OpForPath<typeof PAYMENTS_RECEIVED_ROUTES.BY_ID, 'get'>>;
export type CreatePaymentReceivedBody = OpRequestBody<OpForPath<typeof PAYMENTS_RECEIVED_ROUTES.LIST, 'post'>>;
export type EditPaymentReceivedBody = OpRequestBody<OpForPath<typeof PAYMENTS_RECEIVED_ROUTES.BY_ID, 'put'>>;
export type PaymentReceivedStateResponse = OpResponseBody<OpForPath<typeof PAYMENTS_RECEIVED_ROUTES.STATE, 'get'>>;
export type PaymentReceivedHtmlContentResponse = { htmlContent: string };
export async function fetchPaymentsReceived(fetcher: ApiFetcher): Promise<PaymentsReceivedListResponse> {
const get = fetcher.path(PAYMENTS_RECEIVED_ROUTES.LIST).method('get').create();
@@ -104,8 +107,23 @@ export async function sendPaymentReceiveMail(
return data;
}
export async function fetchPaymentReceivedState(fetcher: ApiFetcher): Promise<unknown> {
export async function fetchPaymentReceivedState(
fetcher: ApiFetcher,
): Promise<PaymentReceivedStateResponse> {
const get = fetcher.path(PAYMENTS_RECEIVED_ROUTES.STATE).method('get').create();
const { data } = await get({});
return data;
return data as PaymentReceivedStateResponse;
}
export async function fetchPaymentReceiveHtmlContent(
fetcher: ApiFetcher,
id: number
): Promise<PaymentReceivedHtmlContentResponse> {
return rawRequest<PaymentReceivedHtmlContentResponse>(
fetcher,
'GET',
`/api/payments-received/${id}`,
undefined,
{ Accept: 'application/json+html' }
);
}
+15
View File
@@ -1,4 +1,5 @@
import type { ApiFetcher } from './fetch-utils';
import { rawRequest } from './fetch-utils';
import { paths } from './schema';
import { OpForPath, OpQueryParams, OpRequestBody, OpResponseBody } from './utils';
@@ -21,6 +22,7 @@ export type SaleEstimate = OpResponseBody<OpForPath<typeof SALE_ESTIMATES_ROUTES
export type CreateSaleEstimateBody = OpRequestBody<OpForPath<typeof SALE_ESTIMATES_ROUTES.LIST, 'post'>>;
export type EditSaleEstimateBody = OpRequestBody<OpForPath<typeof SALE_ESTIMATES_ROUTES.BY_ID, 'put'>>;
export type GetSaleEstimatesQuery = OpQueryParams<OpForPath<typeof SALE_ESTIMATES_ROUTES.LIST, 'get'>>;
export type SaleEstimateHtmlContentResponse = { htmlContent: string };
export async function fetchSaleEstimates(
fetcher: ApiFetcher,
@@ -137,3 +139,16 @@ export async function fetchSaleEstimatesState(fetcher: ApiFetcher): Promise<unkn
const { data } = await get({});
return data;
}
export async function fetchSaleEstimateHtmlContent(
fetcher: ApiFetcher,
id: number
): Promise<SaleEstimateHtmlContentResponse> {
return rawRequest<SaleEstimateHtmlContentResponse>(
fetcher,
'GET',
`/api/sale-estimates/${id}`,
undefined,
{ Accept: 'application/json+html' }
);
}
+4 -3
View File
@@ -26,6 +26,7 @@ export type BulkDeleteSaleInvoicesBody = OpRequestBody<OpForPath<typeof SALE_INV
export type ValidateBulkDeleteSaleInvoicesResponse = OpResponseBody<OpForPath<typeof SALE_INVOICES_ROUTES.VALIDATE_BULK_DELETE, 'post'>>;
export type SaleInvoiceStateResponse = OpResponseBody<OpForPath<typeof SALE_INVOICES_ROUTES.STATE, 'get'>>;
export type GetSaleInvoicesQuery = OpQueryParams<OpForPath<typeof SALE_INVOICES_ROUTES.LIST, 'get'>>;
export type SaleInvoiceHtmlContentResponse = OpResponseBody<OpForPath<typeof SALE_INVOICES_ROUTES.HTML, 'get'>>;
export async function fetchSaleInvoices(
fetcher: ApiFetcher,
@@ -151,10 +152,10 @@ export async function fetchInvoicePayments(
export async function fetchSaleInvoiceHtml(
fetcher: ApiFetcher,
id: number
): Promise<{ htmlContent: string }> {
): Promise<SaleInvoiceHtmlContentResponse> {
const get = fetcher.path(SALE_INVOICES_ROUTES.HTML).method('get').create();
const { data } = await (get as (params: { id: number }) => Promise<{ data: { htmlContent: string } }>)({ id });
return data as { htmlContent: string };
const { data } = await get({ id });
return data;
}
export async function generateSaleInvoiceSharableLink(
+22 -3
View File
@@ -1,4 +1,5 @@
import type { ApiFetcher } from './fetch-utils';
import { rawRequest } from './fetch-utils';
import { paths } from './schema';
import { OpForPath, OpQueryParams, OpRequestBody, OpResponseBody } from './utils';
@@ -20,6 +21,11 @@ export type BulkDeleteReceiptsBody = OpRequestBody<OpForPath<typeof SALE_RECEIPT
export type ValidateBulkDeleteReceiptsResponse = OpResponseBody<OpForPath<typeof SALE_RECEIPTS_ROUTES.VALIDATE_BULK_DELETE, 'post'>>;
export type SaleReceiptStateResponse = OpResponseBody<OpForPath<typeof SALE_RECEIPTS_ROUTES.STATE, 'get'>>;
export type GetSaleReceiptsQuery = OpQueryParams<OpForPath<typeof SALE_RECEIPTS_ROUTES.LIST, 'get'>>;
export type SaleReceiptMailResponse = OpResponseBody<OpForPath<typeof SALE_RECEIPTS_ROUTES.MAIL, 'get'>>;
export type SaleReceiptSendMailBody = OpRequestBody<OpForPath<typeof SALE_RECEIPTS_ROUTES.MAIL, 'post'>>;
export type SaleReceiptHtmlContentResponse = {
htmlContent: string;
};
export async function fetchSaleReceipts(
fetcher: ApiFetcher,
@@ -85,16 +91,16 @@ export async function closeSaleReceipt(fetcher: ApiFetcher, id: number): Promise
export async function fetchSaleReceiptMail(
fetcher: ApiFetcher,
id: number
): Promise<unknown> {
): Promise<SaleReceiptMailResponse> {
const get = fetcher.path(SALE_RECEIPTS_ROUTES.MAIL).method('get').create();
const { data } = await get({ id });
return data;
return data as SaleReceiptMailResponse;
}
export async function sendSaleReceiptMail(
fetcher: ApiFetcher,
id: number,
body?: Record<string, unknown>
body?: SaleReceiptSendMailBody
): Promise<void> {
const post = fetcher.path(SALE_RECEIPTS_ROUTES.MAIL).method('post').create();
await post({ id, ...(body ?? {}) } as never);
@@ -107,3 +113,16 @@ export async function fetchSaleReceiptState(
const { data } = await (get as (params?: object) => Promise<{ data: SaleReceiptStateResponse }>)({});
return data;
}
export async function fetchSaleReceiptHtmlContent(
fetcher: ApiFetcher,
id: number
): Promise<SaleReceiptHtmlContentResponse> {
return rawRequest<SaleReceiptHtmlContentResponse>(
fetcher,
'GET',
`/api/sale-receipts/${id}`,
undefined,
{ Accept: 'application/json+html' }
);
}
+16
View File
@@ -6886,6 +6886,13 @@ export interface components {
*/
active: boolean;
};
PaymentReceivedHtmlContentResponseDto: {
/**
* @description The HTML content of the payment received
* @example <html>...</html>
*/
htmlContent: string;
};
PaymentReceivedStateResponseDto: {
/**
* @description The ID of the default PDF template for payment received
@@ -8631,6 +8638,13 @@ export interface components {
*/
skipUndeletable: boolean;
};
SaleEstimateHtmlContentResponseDto: {
/**
* @description The HTML content of the estimate
* @example <html>...</html>
*/
htmlContent: string;
};
SaleEstiamteStateResponseDto: {
/**
* @description The ID of the default PDF template for sale estimates
@@ -17169,6 +17183,7 @@ export interface operations {
};
content: {
"application/json": components["schemas"]["PaymentReceivedResponseDto"];
"application/json+html": components["schemas"]["PaymentReceivedHtmlContentResponseDto"];
};
};
};
@@ -18906,6 +18921,7 @@ export interface operations {
};
content: {
"application/json": components["schemas"]["SaleEstimateResponseDto"];
"application/json+html": components["schemas"]["SaleEstimateHtmlContentResponseDto"];
};
};
};