feat: Assign default PDF template automatically

This commit is contained in:
Ahmed Bouhuolia
2024-10-02 18:18:57 +02:00
parent cbc60b3c73
commit b23112bc92
30 changed files with 501 additions and 46 deletions

View File

@@ -17,10 +17,19 @@ import {
useBranches,
useSettingsCreditNotes,
useInvoice,
useGetCreditNoteState,
CreditNoteStateResponse,
} from '@/hooks/query';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
const CreditNoteFormContext = React.createContext();
interface CreditNoteFormProviderValue {
creditNoteState: CreditNoteStateResponse;
isCreditNoteStateLoading: boolean;
}
const CreditNoteFormContext = React.createContext<CreditNoteFormProviderValue>(
{} as CreditNoteFormProviderValue,
);
/**
* Credit note data provider.
@@ -78,6 +87,10 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
useGetPdfTemplates({ resource: 'PaymentReceive' });
// Fetches the credit note state.
const { data: creditNoteState, isLoading: isCreditNoteStateLoading } =
useGetCreditNoteState();
// Handle fetching settings.
useSettingsCreditNotes();
@@ -124,6 +137,10 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
// Branding templates.
brandingTemplates,
isBrandingTemplatesLoading,
// Credit note state
creditNoteState,
isCreditNoteStateLoading,
};
const isLoading =
@@ -140,6 +157,7 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
);
}
const useCreditNoteFormContext = () => React.useContext(CreditNoteFormContext);
const useCreditNoteFormContext = () =>
React.useContext<CreditNoteFormProviderValue>(CreditNoteFormContext);
export { CreditNoteFormProvider, useCreditNoteFormContext };

View File

@@ -58,6 +58,7 @@ function EstimateForm({
submitPayload,
createEstimateMutate,
editEstimateMutate,
saleEstimateState,
} = useEstimateFormContext();
const estimateNumber = transactionNumber(
@@ -79,6 +80,7 @@ function EstimateForm({
currency_code: base_currency,
terms_conditions: defaultTo(estimateTermsConditions, ''),
note: defaultTo(estimateCustomerNotes, ''),
pdf_template_id: saleEstimateState?.defaultTemplateId,
}),
};

View File

@@ -11,6 +11,8 @@ import {
useSettingsEstimates,
useCreateEstimate,
useEditEstimate,
useGetSaleEstimatesState,
ISaleEstimatesStateResponse,
} from '@/hooks/query';
import { useProjects } from '@/containers/Projects/hooks';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
@@ -18,7 +20,12 @@ import { Features } from '@/constants';
import { useFeatureCan } from '@/hooks/state';
import { ITEMS_FILTER_ROLES } from './utils';
const EstimateFormContext = createContext();
interface EstimateFormProviderValues {
saleEstimateState: ISaleEstimatesStateResponse;
isSaleEstimateStateLoading: boolean;
}
const EstimateFormContext = createContext({} as EstimateFormProviderValues);
/**
* Estimate form provider.
@@ -76,6 +83,10 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
useGetPdfTemplates({ resource: 'SaleEstimate' });
// Fetches the sale estimate state.
const { data: saleEstimateState, isLoading: isSaleEstimateStateLoading } =
useGetSaleEstimatesState();
// Handle fetch settings.
useSettingsEstimates();
@@ -118,15 +129,21 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
createEstimateMutate,
editEstimateMutate,
// Branding templates
brandingTemplates,
isBrandingTemplatesLoading,
// Estimate state
saleEstimateState,
isSaleEstimateStateLoading,
};
const isLoading =
isCustomersLoading ||
isItemsLoading ||
isEstimateLoading ||
isBrandingTemplatesLoading;
isBrandingTemplatesLoading ||
isSaleEstimateStateLoading;
return (
<DashboardInsider loading={isLoading} name={'estimate-form'}>
@@ -135,6 +152,7 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
);
}
const useEstimateFormContext = () => useContext(EstimateFormContext);
const useEstimateFormContext = () =>
useContext<EstimateFormProviderValues>(EstimateFormContext);
export { EstimateFormProvider, useEstimateFormContext };

View File

@@ -61,6 +61,7 @@ function InvoiceForm({
createInvoiceMutate,
editInvoiceMutate,
submitPayload,
saleInvoiceState
} = useInvoiceFormContext();
// Invoice number.
@@ -83,6 +84,7 @@ function InvoiceForm({
currency_code: base_currency,
invoice_message: defaultTo(invoiceCustomerNotes, ''),
terms_conditions: defaultTo(invoiceTermsConditions, ''),
pdf_template_id: saleInvoiceState?.defaultTemplateId,
...newInvoice,
}),
};

View File

@@ -16,13 +16,22 @@ import {
useEditInvoice,
useSettingsInvoices,
useEstimate,
useGetSaleInvoiceState,
GetSaleInvoiceStateResponse,
} from '@/hooks/query';
import { useProjects } from '@/containers/Projects/hooks';
import { useTaxRates } from '@/hooks/query/taxRates';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
import { useGetPaymentServices } from '@/hooks/query/payment-services';
const InvoiceFormContext = createContext();
interface InvoiceFormContextValue {
saleInvoiceState: GetSaleInvoiceStateResponse | null;
isInvoiceStateLoading: boolean;
}
const InvoiceFormContext = createContext<InvoiceFormContextValue>(
{} as InvoiceFormContextValue,
);
/**
* Accounts chart data provider.
@@ -100,6 +109,9 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
isSuccess: isBranchesSuccess,
} = useBranches({}, { enabled: isBranchFeatureCan });
const { data: saleInvoiceState, isLoading: isInvoiceStateLoading } =
useGetSaleInvoiceState();
// Handle fetching settings.
const { isLoading: isSettingsLoading } = useSettingsInvoices();
@@ -154,6 +166,10 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
// Payment Services
paymentServices,
isPaymentServicesLoading,
// Invoice state
saleInvoiceState,
isInvoiceStateLoading,
};
return (
@@ -172,6 +188,7 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
);
}
const useInvoiceFormContext = () => React.useContext(InvoiceFormContext);
const useInvoiceFormContext = () =>
React.useContext<InvoiceFormContextValue>(InvoiceFormContext);
export { InvoiceFormProvider, useInvoiceFormContext };

View File

@@ -69,6 +69,7 @@ function PaymentReceiveForm({
editPaymentReceiveMutate,
createPaymentReceiveMutate,
isExcessConfirmed,
paymentReceivedState,
} = usePaymentReceiveFormContext();
// Payment receive number.
@@ -77,29 +78,21 @@ function PaymentReceiveForm({
paymentReceiveNextNumber,
);
// Form initial values.
const initialValues = useMemo(
() => ({
...(!isEmpty(paymentReceiveEditPage)
? transformToEditForm(paymentReceiveEditPage, paymentEntriesEditPage)
: {
...defaultPaymentReceive,
// If the auto-increment mode is enabled, take the next payment
// number from the settings.
...(paymentReceiveAutoIncrement && {
payment_receive_no: nextPaymentNumber,
}),
deposit_account_id: defaultTo(preferredDepositAccount, ''),
currency_code: base_currency,
const initialValues = {
...(!isEmpty(paymentReceiveEditPage)
? transformToEditForm(paymentReceiveEditPage, paymentEntriesEditPage)
: {
...defaultPaymentReceive,
// If the auto-increment mode is enabled, take the next payment
// number from the settings.
...(paymentReceiveAutoIncrement && {
payment_receive_no: nextPaymentNumber,
}),
}),
[
paymentReceiveEditPage,
nextPaymentNumber,
paymentEntriesEditPage,
paymentReceiveAutoIncrement,
preferredDepositAccount,
],
);
deposit_account_id: defaultTo(preferredDepositAccount, ''),
currency_code: base_currency,
pdf_template_id: paymentReceivedState.defaultTemplateId,
}),
};
// Handle form submit.
const handleSubmitForm = (
values,

View File

@@ -12,11 +12,21 @@ import {
useBranches,
useCreatePaymentReceive,
useEditPaymentReceive,
usePaymentReceivedState,
PaymentReceivedStateResponse,
} from '@/hooks/query';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
interface PaymentReceivedFormContextValue {
isPaymentReceivedStateLoading: boolean;
paymentReceivedState: PaymentReceivedStateResponse;
}
// Payment receive form context.
const PaymentReceiveFormContext = createContext();
const PaymentReceiveFormContext =
createContext<PaymentReceivedFormContextValue>(
{} as PaymentReceivedFormContextValue,
);
/**
* Payment receive form provider.
@@ -70,6 +80,12 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
useGetPdfTemplates({ resource: 'PaymentReceive' });
// Fetches the payment received initial state.
const {
data: paymentReceivedState,
isLoading: isPaymentReceivedStateLoading,
} = usePaymentReceivedState();
// Detarmines whether the new mode.
const isNewMode = !paymentReceiveId;
@@ -111,6 +127,10 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
// Branding templates
brandingTemplates,
isBrandingTemplatesLoading,
// Payment received state
isPaymentReceivedStateLoading,
paymentReceivedState,
};
const isLoading =
@@ -127,6 +147,6 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
}
const usePaymentReceiveFormContext = () =>
useContext(PaymentReceiveFormContext);
useContext<PaymentReceivedFormContextValue>(PaymentReceiveFormContext);
export { PaymentReceiveFormProvider, usePaymentReceiveFormContext };

View File

@@ -63,6 +63,7 @@ function ReceiptForm({
createReceiptMutate,
submitPayload,
isNewMode,
saleReceiptState,
} = useReceiptFormContext();
// The next receipt number.
@@ -84,6 +85,7 @@ function ReceiptForm({
currency_code: base_currency,
receipt_message: receiptMessage,
terms_conditions: receiptTermsConditions,
pdf_template_id: saleReceiptState?.pdfTemplateId,
}),
};
// Handle the form submit.

View File

@@ -13,11 +13,20 @@ import {
useItems,
useCreateReceipt,
useEditReceipt,
useGetReceiptState,
IGetReceiptStateResponse,
} from '@/hooks/query';
import { useProjects } from '@/containers/Projects/hooks';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
const ReceiptFormContext = createContext();
const ReceiptFormContext = createContext<ReceiptFormProviderValue>(
{} as ReceiptFormProviderValue,
);
interface ReceiptFormProviderValue {
isSaleReceiptStateLoading: boolean;
saleReceiptState: IGetReceiptStateResponse;
}
/**
* Receipt form provider.
@@ -96,6 +105,10 @@ function ReceiptFormProvider({ receiptId, ...props }) {
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
useGetPdfTemplates({ resource: 'SaleReceipt' });
// Fetches the sale receipt state.
const { data: saleReceiptState, isLoading: isSaleReceiptStateLoading } =
useGetReceiptState();
// Fetch receipt settings.
const { isLoading: isSettingLoading } = useSettingsReceipts();
@@ -137,6 +150,10 @@ function ReceiptFormProvider({ receiptId, ...props }) {
// Branding templates
brandingTemplates,
isBrandingTemplatesLoading,
// State
isSaleReceiptStateLoading,
saleReceiptState,
};
const isLoading =
isReceiptLoading ||
@@ -144,7 +161,8 @@ function ReceiptFormProvider({ receiptId, ...props }) {
isCustomersLoading ||
isItemsLoading ||
isSettingLoading ||
isBrandingTemplatesLoading;
isBrandingTemplatesLoading ||
isSaleReceiptStateLoading;
return (
<DashboardInsider loading={isLoading} name={'receipt-form'}>
@@ -153,6 +171,7 @@ function ReceiptFormProvider({ receiptId, ...props }) {
);
}
const useReceiptFormContext = () => React.useContext(ReceiptFormContext);
const useReceiptFormContext = () =>
React.useContext<ReceiptFormProviderValue>(ReceiptFormContext);
export { ReceiptFormProvider, useReceiptFormContext };

View File

@@ -1,7 +1,7 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination } from '@/utils';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
@@ -356,3 +356,21 @@ export function useRefundCreditTransaction(id, props, requestProps) {
export function usePdfCreditNote(creditNoteId) {
return useRequestPdf({ url: `sales/credit_notes/${creditNoteId}` });
}
export interface CreditNoteStateResponse {
defaultTemplateId: number;
}
export function useGetCreditNoteState(
options?: UseQueryOptions<CreditNoteStateResponse, Error>,
): UseQueryResult<CreditNoteStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<CreditNoteStateResponse, Error>(
['CREDIT_NOTE_STATE'],
() =>
apiRequest
.get('/sales/credit_notes/state')
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
}

View File

@@ -2,7 +2,7 @@
import { useQueryClient, useMutation } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import { transformPagination } from '@/utils';
import { transformPagination, transformToCamelCase } from '@/utils';
import t from './types';
import { useRequestPdf } from '../useRequestPdf';
@@ -270,3 +270,22 @@ export function useSaleEstimateDefaultOptions(estimateId, props) {
},
);
}
export interface ISaleEstimatesStateResponse {
defaultTemplateId: number;
}
export function useGetSaleEstimatesState(
options?: UseQueryOptions<ISaleEstimatesStateResponse, Error>,
): UseQueryResult<ISaleEstimatesStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<ISaleEstimatesStateResponse, Error>(
['SALE_ESTIMATES_STATE'],
() =>
apiRequest
.get('/sales/estimates/state')
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
}

View File

@@ -1,7 +1,7 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useQueryClient, useMutation, useQuery } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination } from '@/utils';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
@@ -341,3 +341,22 @@ export function useSaleInvoiceDefaultOptions(invoiceId, props) {
},
);
}
export interface GetSaleInvoiceStateResponse {
defaultTemplateId: number;
}
export function useGetSaleInvoiceState(
options?: UseQueryOptions<GetSaleInvoiceStateResponse, Error>,
): UseQueryResult<GetSaleInvoiceStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<GetSaleInvoiceStateResponse, Error>(
['SALE_INVOICE_STATE'],
() =>
apiRequest
.get(`/sales/invoices/state`)
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
}

View File

@@ -1,11 +1,17 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import {
useMutation,
useQueryClient,
QueryClient,
UseQueryOptions,
UseQueryResult,
useQuery,
} from 'react-query';
import useApiRequest from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, saveInvoke } from '@/utils';
import t from './types';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
// Common invalidate queries.
const commonInvalidateQueries = (client) => {
@@ -269,3 +275,31 @@ export function usePaymentReceiveDefaultOptions(paymentReceiveId, props) {
},
);
}
export interface PaymentReceivedStateResponse {
defaultTemplateId: number;
}
/**
* Retrieves the payment receive state.
* @param {Record<string, any>} query - Query parameters for the request.
* @param {UseQueryOptions<PaymentReceivedStateResponse, Error>} options - Optional query options.
* @returns {UseQueryResult<PaymentReceivedStateResponse, Error>} The query result.
*/
export function usePaymentReceivedState(
query: Record<string, any>,
options?: UseQueryOptions<PaymentReceivedStateResponse, Error>,
): UseQueryResult<PaymentReceivedStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<PaymentReceivedStateResponse, Error>(
[t.PAYMENT_RECEIVE_STATE, query],
() =>
apiRequest
.get('/sales/payment_receives/state', { params: query })
.then((res) => res.data),
{
...options,
},
);
}

View File

@@ -1,5 +1,11 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import {
useQueryClient,
useMutation,
UseQueryResult,
UseQueryOptions,
useQuery,
} from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import { transformPagination } from '@/utils';
@@ -244,3 +250,22 @@ export function useSaleReceiptDefaultOptions(invoiceId, props) {
},
);
}
export interface IGetReceiptStateResponse {
pdfTemplateId: number;
}
export function useGetReceiptState(
options?: UseQueryOptions<IGetReceiptStateResponse, Error>,
): UseQueryResult<IGetReceiptStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<IGetReceiptStateResponse, Error>(
['SALE_RECEIPT_STATE'],
() =>
apiRequest
.get(`/sales/receipts/state`)
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
}