mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-05-31 15:09:00 +00:00
wip
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
||||
import { CreateCustomerDto } from './dtos/CreateCustomer.dto';
|
||||
import { EditCustomerDto } from './dtos/EditCustomer.dto';
|
||||
import { CustomerResponseDto } from './dtos/CustomerResponse.dto';
|
||||
import { CustomersListResponseDto } from './dtos/CustomersListResponse.dto';
|
||||
import { GetCustomersQueryDto } from './dtos/GetCustomersQuery.dto';
|
||||
import {
|
||||
BulkDeleteCustomersDto,
|
||||
@@ -36,6 +37,7 @@ import { CustomerAction } from './types/Customers.types';
|
||||
@Controller('customers')
|
||||
@ApiTags('Customers')
|
||||
@ApiExtraModels(CustomerResponseDto)
|
||||
@ApiExtraModels(CustomersListResponseDto)
|
||||
@ApiExtraModels(ValidateBulkDeleteCustomersResponseDto)
|
||||
@ApiCommonHeaders()
|
||||
@UseGuards(AuthorizationGuard, PermissionGuard)
|
||||
@@ -60,10 +62,7 @@ export class CustomersController {
|
||||
@ApiResponse({
|
||||
status: 200,
|
||||
description: 'The customers have been successfully retrieved.',
|
||||
schema: {
|
||||
type: 'array',
|
||||
items: { $ref: getSchemaPath(CustomerResponseDto) },
|
||||
},
|
||||
schema: { $ref: getSchemaPath(CustomersListResponseDto) },
|
||||
})
|
||||
getCustomers(@Query() filterDTO: GetCustomersQueryDto) {
|
||||
return this.customersApplication.getCustomers(filterDTO);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { CustomerResponseDto } from './CustomerResponse.dto';
|
||||
|
||||
class CustomersPaginationDto {
|
||||
@ApiProperty({ example: 1 })
|
||||
page: number;
|
||||
|
||||
@ApiProperty({ example: 12 })
|
||||
pageSize: number;
|
||||
|
||||
@ApiProperty({ example: 42 })
|
||||
total: number;
|
||||
}
|
||||
|
||||
export class CustomersListResponseDto {
|
||||
@ApiProperty({ type: [CustomerResponseDto] })
|
||||
data: CustomerResponseDto[];
|
||||
|
||||
@ApiProperty({ type: CustomersPaginationDto })
|
||||
pagination: CustomersPaginationDto;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { createContext, useContext } from 'react';
|
||||
import type { Item, Customer } from '@bigcapital/sdk-ts';
|
||||
|
||||
import {
|
||||
useEstimate,
|
||||
@@ -30,11 +31,11 @@ type EstimateFormSubmitPayload = Record<string, unknown>;
|
||||
interface EstimateFormContextValue {
|
||||
estimateId?: number;
|
||||
estimate: UseEstimateResult['data'];
|
||||
items: any;
|
||||
customers: any;
|
||||
items: Item[];
|
||||
customers: Customer[];
|
||||
branches: UseBranchesResult['data'];
|
||||
warehouses: UseWarehousesResult['data'];
|
||||
projects: any;
|
||||
projects: unknown[];
|
||||
isNewMode: boolean;
|
||||
|
||||
isItemsFetching: boolean;
|
||||
@@ -163,11 +164,11 @@ function EstimateFormProvider({
|
||||
const provider: EstimateFormContextValue = {
|
||||
estimateId,
|
||||
estimate,
|
||||
items: (itemsData as any)?.items,
|
||||
customers: (customersData as any)?.customers,
|
||||
items: itemsData?.data ?? [],
|
||||
customers: customersData?.data ?? [],
|
||||
branches,
|
||||
warehouses,
|
||||
projects: (projectsData as any)?.projects,
|
||||
projects: (projectsData as { data?: { projects?: unknown[] } })?.data?.projects ?? [],
|
||||
isNewMode,
|
||||
|
||||
isItemsFetching,
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import { Group, PageFormBigNumber } from '@/components';
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
// @ts-nocheck
|
||||
import React, { createContext, useState } from 'react';
|
||||
import type {
|
||||
SaleInvoice,
|
||||
CreateSaleInvoiceBody,
|
||||
EditSaleInvoiceBody,
|
||||
SaleInvoiceStateResponse,
|
||||
Item,
|
||||
Customer,
|
||||
Warehouse,
|
||||
Branch,
|
||||
TaxRate,
|
||||
PdfTemplateResponse,
|
||||
GetPaymentServicesResponse,
|
||||
} from '@bigcapital/sdk-ts';
|
||||
import { isEmpty, pick } from 'lodash';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
import { Features } from '@/constants';
|
||||
import { useFeatureCan } from '@/hooks/state';
|
||||
import { DashboardInsider } from '@/components/Dashboard';
|
||||
import { transformToEditForm, ITEMS_FILTER_ROLES_QUERY } from './utils';
|
||||
import {
|
||||
useInvoice,
|
||||
@@ -17,28 +28,77 @@ import {
|
||||
useSettingsInvoices,
|
||||
useEstimate,
|
||||
useGetSaleInvoiceState,
|
||||
GetSaleInvoiceStateResponse,
|
||||
} from '@/hooks/query';
|
||||
import { useProjects } from '@/containers/Projects/hooks';
|
||||
import { useTaxRates } from '@/hooks/query/tax-rates';
|
||||
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
|
||||
import { useGetPaymentServices } from '@/hooks/query/payment-services';
|
||||
|
||||
interface InvoiceFormContextValue {
|
||||
saleInvoiceState: GetSaleInvoiceStateResponse | null;
|
||||
isInvoiceStateLoading: boolean;
|
||||
}
|
||||
type InvoiceFormSubmitPayload = {
|
||||
redirect?: boolean;
|
||||
};
|
||||
|
||||
const InvoiceFormContext = createContext<InvoiceFormContextValue>(
|
||||
{} as InvoiceFormContextValue,
|
||||
type InvoiceFormContextValue = {
|
||||
invoice: SaleInvoice | undefined;
|
||||
items: Item[];
|
||||
customers: Customer[];
|
||||
newInvoice: ReturnType<typeof transformToEditForm> | [];
|
||||
estimateId: string | undefined;
|
||||
invoiceId: number | undefined;
|
||||
submitPayload: InvoiceFormSubmitPayload | undefined;
|
||||
branches: Branch[];
|
||||
warehouses: Warehouse[];
|
||||
projects: unknown[];
|
||||
taxRates: TaxRate[];
|
||||
brandingTemplates: PdfTemplateResponse[];
|
||||
paymentServices: GetPaymentServicesResponse | undefined;
|
||||
|
||||
isInvoiceLoading: boolean;
|
||||
isItemsLoading: boolean;
|
||||
isCustomersLoading: boolean;
|
||||
isSettingsLoading: boolean;
|
||||
isWarehouesLoading: boolean;
|
||||
isBranchesLoading: boolean;
|
||||
isFeatureLoading: boolean;
|
||||
isBranchesSuccess: boolean;
|
||||
isWarehousesSuccess: boolean;
|
||||
isTaxRatesLoading: boolean;
|
||||
isBrandingTemplatesLoading: boolean;
|
||||
isInvoiceStateLoading: boolean;
|
||||
isPaymentServicesLoading: boolean;
|
||||
isBootLoading: boolean;
|
||||
isNewMode: boolean;
|
||||
|
||||
createInvoiceMutate: (values: CreateSaleInvoiceBody) => Promise<void>;
|
||||
editInvoiceMutate: (args: [number, EditSaleInvoiceBody]) => Promise<void>;
|
||||
setSubmitPayload: React.Dispatch<
|
||||
React.SetStateAction<InvoiceFormSubmitPayload | undefined>
|
||||
>;
|
||||
|
||||
saleInvoiceState: SaleInvoiceStateResponse | undefined;
|
||||
};
|
||||
|
||||
const InvoiceFormContext = createContext<InvoiceFormContextValue | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
type InvoiceFormProviderProps = {
|
||||
invoiceId?: number;
|
||||
baseCurrency?: string;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accounts chart data provider.
|
||||
* Invoice form data provider.
|
||||
*/
|
||||
function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
function InvoiceFormProvider({
|
||||
invoiceId,
|
||||
baseCurrency,
|
||||
...props
|
||||
}: InvoiceFormProviderProps) {
|
||||
const { state } = useLocation();
|
||||
const estimateId = state?.action;
|
||||
const estimateId = (state as { action?: string })?.action;
|
||||
const estimateIdNum = estimateId ? Number(estimateId) : undefined;
|
||||
|
||||
// Features guard.
|
||||
const { featureCan } = useFeatureCan();
|
||||
@@ -47,9 +107,7 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
const isProjectsFeatureCan = featureCan(Features.Projects);
|
||||
|
||||
// Fetch invoice data.
|
||||
const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId, {
|
||||
enabled: !!invoiceId,
|
||||
});
|
||||
const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId);
|
||||
|
||||
// Fetch tax rates.
|
||||
const { data: taxRates, isLoading: isTaxRatesLoading } = useTaxRates();
|
||||
@@ -62,8 +120,8 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
|
||||
// Fetches the estimate by the given id.
|
||||
const { data: estimate, isLoading: isEstimateLoading } = useEstimate(
|
||||
estimateId,
|
||||
{ enabled: !!estimateId },
|
||||
estimateIdNum,
|
||||
{ enabled: !!estimateIdNum },
|
||||
);
|
||||
|
||||
// Fetches branding templates of invoice.
|
||||
@@ -78,7 +136,7 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
? transformToEditForm({
|
||||
...pick(estimate, ['customer_id', 'currency_code', 'entries']),
|
||||
})
|
||||
: [];
|
||||
: ([] as []);
|
||||
|
||||
// Handle fetching the items table based on the given query.
|
||||
const {
|
||||
@@ -120,7 +178,9 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
const { mutateAsync: editInvoiceMutate } = useEditInvoice();
|
||||
|
||||
// Form submit payload.
|
||||
const [submitPayload, setSubmitPayload] = useState();
|
||||
const [submitPayload, setSubmitPayload] = useState<
|
||||
InvoiceFormSubmitPayload | undefined
|
||||
>();
|
||||
|
||||
// Detarmines whether the form in new mode.
|
||||
const isNewMode = !invoiceId;
|
||||
@@ -140,19 +200,19 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
isSettingsLoading ||
|
||||
isInvoiceStateLoading;
|
||||
|
||||
const provider = {
|
||||
const provider: InvoiceFormContextValue = {
|
||||
invoice,
|
||||
items: itemsData?.items,
|
||||
customers: customersData?.customers,
|
||||
items: itemsData?.data ?? [],
|
||||
customers: customersData?.data ?? [],
|
||||
newInvoice,
|
||||
estimateId,
|
||||
invoiceId,
|
||||
submitPayload,
|
||||
branches,
|
||||
warehouses,
|
||||
projects: projectsData?.projects,
|
||||
taxRates,
|
||||
brandingTemplates,
|
||||
branches: branches ?? [],
|
||||
warehouses: warehouses ?? [],
|
||||
projects: (projectsData as { data?: { projects?: unknown[] } })?.data?.projects ?? [],
|
||||
taxRates: taxRates?.data ?? [],
|
||||
brandingTemplates: brandingTemplates?.templates ?? [],
|
||||
|
||||
isInvoiceLoading,
|
||||
isItemsLoading,
|
||||
@@ -166,16 +226,18 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
isTaxRatesLoading,
|
||||
isBrandingTemplatesLoading,
|
||||
|
||||
createInvoiceMutate,
|
||||
editInvoiceMutate,
|
||||
createInvoiceMutate: createInvoiceMutate as (
|
||||
values: CreateSaleInvoiceBody,
|
||||
) => Promise<void>,
|
||||
editInvoiceMutate: editInvoiceMutate as (
|
||||
args: [number, EditSaleInvoiceBody],
|
||||
) => Promise<void>,
|
||||
setSubmitPayload,
|
||||
isNewMode,
|
||||
|
||||
// Payment Services
|
||||
paymentServices,
|
||||
isPaymentServicesLoading,
|
||||
|
||||
// Invoice state
|
||||
saleInvoiceState,
|
||||
isInvoiceStateLoading,
|
||||
|
||||
@@ -185,7 +247,14 @@ function InvoiceFormProvider({ invoiceId, baseCurrency, ...props }) {
|
||||
return <InvoiceFormContext.Provider value={provider} {...props} />;
|
||||
}
|
||||
|
||||
const useInvoiceFormContext = () =>
|
||||
React.useContext<InvoiceFormContextValue>(InvoiceFormContext);
|
||||
const useInvoiceFormContext = (): InvoiceFormContextValue => {
|
||||
const ctx = React.useContext(InvoiceFormContext);
|
||||
if (!ctx) {
|
||||
throw new Error(
|
||||
'useInvoiceFormContext must be used within an InvoiceFormProvider',
|
||||
);
|
||||
}
|
||||
return ctx;
|
||||
};
|
||||
|
||||
export { InvoiceFormProvider, useInvoiceFormContext };
|
||||
|
||||
@@ -37,11 +37,7 @@ export function useCustomers(
|
||||
return useQuery({
|
||||
...props,
|
||||
queryKey: customersKeys.list(query),
|
||||
queryFn: () =>
|
||||
(fetchCustomers as (f: ReturnType<typeof useApiFetcher>, q?: Record<string, unknown>) => Promise<CustomersListResponse>)(
|
||||
fetcher,
|
||||
query
|
||||
),
|
||||
queryFn: () => fetchCustomers(fetcher, query),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8375,6 +8375,17 @@ export interface components {
|
||||
*/
|
||||
nonDeletableIds: number[];
|
||||
};
|
||||
CustomersListResponseDto: {
|
||||
data: components["schemas"]["CustomerResponseDto"][];
|
||||
pagination: {
|
||||
/** @example 1 */
|
||||
page: number;
|
||||
/** @example 12 */
|
||||
pageSize: number;
|
||||
/** @example 42 */
|
||||
total: number;
|
||||
};
|
||||
};
|
||||
CustomerResponseDto: {
|
||||
/** @example 1500 */
|
||||
balance: number;
|
||||
@@ -19109,7 +19120,7 @@ export interface operations {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["CustomerResponseDto"][];
|
||||
"application/json": components["schemas"]["CustomersListResponseDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user