Repaso de clientes
This commit is contained in:
parent
6f11d0cebd
commit
04184ebf1d
@ -4,4 +4,4 @@ import {
|
||||
} from "./get-customer-by-id.response.dto";
|
||||
|
||||
export const CreateCustomerResponseSchema = GetCustomerByIdResponseSchema;
|
||||
export type CustomerCreationResponseDTO = GetCustomerByIdResponseDTO;
|
||||
export type CreateCustomerResponseDTO = GetCustomerByIdResponseDTO;
|
||||
|
||||
@ -48,11 +48,11 @@ export const useCustomerCreateController = (options?: UseCustomerCreateControlle
|
||||
|
||||
const submitHandler = form.handleSubmit(
|
||||
async (formData) => {
|
||||
const inputPayload: CreateCustomerParams = buildCreateCustomerParams(formData);
|
||||
const params: CreateCustomerParams = buildCreateCustomerParams(formData);
|
||||
|
||||
try {
|
||||
// Enviamos cambios al servidor
|
||||
const created = await mutateAsync(inputPayload); // payload es CustomerCreatePayload
|
||||
const created = await mutateAsync(params); // payload es CustomerCreatePayload
|
||||
|
||||
if (options?.successToasts !== false) {
|
||||
showSuccessToast(
|
||||
@ -69,7 +69,7 @@ export const useCustomerCreateController = (options?: UseCustomerCreateControlle
|
||||
showErrorToast(t("pages.create.error.title"), normalizedError.message);
|
||||
}
|
||||
|
||||
options?.onError?.(normalizedError, inputPayload);
|
||||
options?.onError?.(normalizedError, params);
|
||||
}
|
||||
},
|
||||
(errors: FieldErrors<CustomerCreateForm>) => {
|
||||
|
||||
@ -21,38 +21,42 @@ import type { CustomerCreateForm } from "../entities";
|
||||
*/
|
||||
|
||||
export const buildCreateCustomerParams = (formData: CustomerCreateForm): CreateCustomerParams => {
|
||||
// La API de creación de cliente requiere un ID único para el nuevo cliente
|
||||
const id = UniqueID.generateNewID().toString();
|
||||
|
||||
return {
|
||||
// Generamos un ID único para el nuevo cliente.
|
||||
// La API de creación de cliente requiere un ID,
|
||||
id: UniqueID.generateNewID().toString(),
|
||||
id,
|
||||
|
||||
reference: formData.reference,
|
||||
is_company: formData.isCompany ? "1" : "0",
|
||||
name: formData.name,
|
||||
trade_name: formData.tradeName,
|
||||
tin: formData.tin,
|
||||
default_taxes: formData.defaultTaxes,
|
||||
data: {
|
||||
id,
|
||||
reference: formData.reference,
|
||||
is_company: formData.isCompany ? "1" : "0",
|
||||
name: formData.name,
|
||||
trade_name: formData.tradeName,
|
||||
tin: formData.tin,
|
||||
default_taxes: formData.defaultTaxes,
|
||||
|
||||
street: formData.street,
|
||||
street2: formData.street2,
|
||||
city: formData.city,
|
||||
province: formData.province,
|
||||
postal_code: formData.postalCode,
|
||||
country: formData.country,
|
||||
street: formData.street,
|
||||
street2: formData.street2,
|
||||
city: formData.city,
|
||||
province: formData.province,
|
||||
postal_code: formData.postalCode,
|
||||
country: formData.country,
|
||||
|
||||
email_primary: formData.primaryEmail,
|
||||
email_secondary: formData.secondaryEmail,
|
||||
phone_primary: formData.primaryPhone,
|
||||
phone_secondary: formData.secondaryPhone,
|
||||
mobile_primary: formData.primaryMobile,
|
||||
mobile_secondary: formData.secondaryMobile,
|
||||
email_primary: formData.primaryEmail,
|
||||
email_secondary: formData.secondaryEmail,
|
||||
phone_primary: formData.primaryPhone,
|
||||
phone_secondary: formData.secondaryPhone,
|
||||
mobile_primary: formData.primaryMobile,
|
||||
mobile_secondary: formData.secondaryMobile,
|
||||
|
||||
fax: formData.fax,
|
||||
website: formData.website,
|
||||
fax: formData.fax,
|
||||
website: formData.website,
|
||||
|
||||
legal_record: formData.legalRecord,
|
||||
legal_record: formData.legalRecord,
|
||||
|
||||
language_code: formData.languageCode,
|
||||
currency_code: formData.currencyCode,
|
||||
language_code: formData.languageCode,
|
||||
currency_code: formData.currencyCode,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import type { CustomerCreationResponseDTO } from "@erp/customers/common";
|
||||
import type { CreateCustomerResponseDTO } from "@erp/customers/common";
|
||||
|
||||
import type { GetCustomerByIdResult, UpdateCustomerByIdResult } from "../api";
|
||||
import type { Customer } from "../entities";
|
||||
@ -18,7 +18,7 @@ import type { Customer } from "../entities";
|
||||
|
||||
export const GetCustomerByIdAdapter = {
|
||||
fromDTO(
|
||||
dto: GetCustomerByIdResult | CustomerCreationResponseDTO | UpdateCustomerByIdResult,
|
||||
dto: GetCustomerByIdResult | CreateCustomerResponseDTO | UpdateCustomerByIdResult,
|
||||
context?: unknown
|
||||
): Customer {
|
||||
const taxesAdapter = (taxes: string) =>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import type { IDataSource } from "@erp/core/client";
|
||||
|
||||
import type { CreateCustomerRequestDTO, CustomerCreationResponseDTO } from "../../../common";
|
||||
import type { CreateCustomerRequestDTO, CreateCustomerResponseDTO } from "../../../common";
|
||||
|
||||
/**
|
||||
* Crea un nuevo cliente en el sistema utilizando la fuente de datos proporcionada.
|
||||
@ -11,12 +11,22 @@ import type { CreateCustomerRequestDTO, CustomerCreationResponseDTO } from "../.
|
||||
* @throws Error si el ID del cliente no es proporcionado o si la creación falla.
|
||||
*/
|
||||
|
||||
export type CreateCustomerParams = CreateCustomerRequestDTO;
|
||||
export interface CreateCustomerParams {
|
||||
id: string;
|
||||
data: CreateCustomerRequestDTO;
|
||||
}
|
||||
|
||||
export type CreateCustomerResult = CustomerCreationResponseDTO;
|
||||
export type CreateCustomerResult = CreateCustomerResponseDTO;
|
||||
|
||||
export function createCustomer(dataSource: IDataSource, params: CreateCustomerParams) {
|
||||
const { id } = params;
|
||||
const { id, data } = params;
|
||||
|
||||
if (!id) throw new Error("customerId is required");
|
||||
return dataSource.createOne<CreateCustomerRequestDTO, CreateCustomerResult>("customers", params);
|
||||
|
||||
if (id !== data.id) throw new Error("customerId in params must match id in data");
|
||||
|
||||
return dataSource.createOne<CreateCustomerRequestDTO, CreateCustomerResponseDTO>(
|
||||
"customers",
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
@ -5,23 +5,22 @@ import type { IDataSource } from "@erp/core/client";
|
||||
*
|
||||
* @param dataSource - La fuente de datos para interactuar con la API.
|
||||
* @param params - Los parámetros necesarios para eliminar el cliente.
|
||||
* @param signal - Un AbortSignal para cancelar la solicitud si es necesario.
|
||||
* @returns Una promesa que se resuelve cuando el cliente ha sido eliminado exitosamente.
|
||||
* @throws Error si el ID del cliente no es proporcionado o si la eliminación falla.
|
||||
*/
|
||||
|
||||
export type DeleteCustomerByIdParams = {
|
||||
export interface DeleteCustomerByIdParams {
|
||||
id: string;
|
||||
};
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export type DeleteCustomerByIdResult = void;
|
||||
|
||||
export function deleteCustomerById(
|
||||
dataSource: IDataSource,
|
||||
params: DeleteCustomerByIdParams,
|
||||
signal?: AbortSignal
|
||||
params: DeleteCustomerByIdParams
|
||||
): Promise<DeleteCustomerByIdResult> {
|
||||
const { id } = params;
|
||||
const { id, signal } = params;
|
||||
if (!id) throw new Error("customerId is required");
|
||||
return dataSource.deleteOne<DeleteCustomerByIdResult>("customers", id, {
|
||||
signal,
|
||||
|
||||
@ -7,23 +7,19 @@ import type { GetCustomerByIdResponseDTO } from "../../../common";
|
||||
*
|
||||
* @param dataSource - La fuente de datos para interactuar con la API.
|
||||
* @param params - Los parámetros necesarios para obtener el cliente, incluyendo su ID.
|
||||
* @param signal - Un AbortSignal para cancelar la solicitud si es necesario.
|
||||
* @returns Una promesa que resuelve con los detalles del cliente solicitado.
|
||||
* @throws Error si el ID del cliente no es proporcionado o si la recuperación falla.
|
||||
*/
|
||||
|
||||
export type GetCustomerByIdParams = {
|
||||
export interface GetCustomerByIdParams {
|
||||
id: string;
|
||||
};
|
||||
signal?: AbortSignal;
|
||||
}
|
||||
|
||||
export type GetCustomerByIdResult = GetCustomerByIdResponseDTO;
|
||||
|
||||
export function getCustomerById(
|
||||
dataSource: IDataSource,
|
||||
params: GetCustomerByIdParams,
|
||||
signal?: AbortSignal
|
||||
) {
|
||||
const { id } = params;
|
||||
export function getCustomerById(dataSource: IDataSource, params: GetCustomerByIdParams) {
|
||||
const { id, signal } = params;
|
||||
if (!id) throw new Error("customerId is required");
|
||||
return dataSource.getOne<GetCustomerByIdResult>("customers", id, { signal });
|
||||
return dataSource.getOne<GetCustomerByIdResponseDTO>("customers", id, { signal });
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
export * from "./create-customer.api";
|
||||
export * from "./delete-customer-by-id.api";
|
||||
export * from "./get-customer-by-id.api";
|
||||
export * from "./get-list-customers-by-criteria.api";
|
||||
export * from "./list-customers-by-criteria.api";
|
||||
export * from "./update-customer-by-id.api";
|
||||
|
||||
@ -9,24 +9,23 @@ import type { ListCustomersResponseDTO } from "../../../common";
|
||||
*
|
||||
* @param dataSource - La fuente de datos para interactuar con la API.
|
||||
* @param params - Los parámetros necesarios para listar los clientes, incluyendo los criterios de búsqueda.
|
||||
* @param signal - Un AbortSignal para cancelar la solicitud si es necesario.
|
||||
* @returns Una promesa que resuelve con una lista de clientes que cumplen con los criterios especificados.
|
||||
* @throws Error si la recuperación de la lista de clientes falla.
|
||||
*/
|
||||
|
||||
export type ListCustomersByCriteriaParams = {
|
||||
criteria: CriteriaDTO;
|
||||
criteria?: CriteriaDTO;
|
||||
signal?: AbortSignal;
|
||||
};
|
||||
|
||||
export type ListCustomersResult = ListCustomersResponseDTO;
|
||||
|
||||
export function getListCustomersByCriteria(
|
||||
dataSource: IDataSource,
|
||||
params: ListCustomersByCriteriaParams,
|
||||
signal?: AbortSignal
|
||||
params: ListCustomersByCriteriaParams
|
||||
): Promise<ListCustomersResult> {
|
||||
const { criteria } = params;
|
||||
return dataSource.getList<ListCustomersResult>("customers", {
|
||||
const { criteria, signal } = params || { criteria: undefined, signal: undefined };
|
||||
return dataSource.getList<ListCustomersResponseDTO>("customers", {
|
||||
signal,
|
||||
...criteria,
|
||||
});
|
||||
@ -25,7 +25,7 @@ export function updateCustomerById(
|
||||
const { id, data } = params;
|
||||
|
||||
if (!id) throw new Error("customerId is required");
|
||||
return dataSource.updateOne<UpdateCustomerByIdRequestDTO, UpdateCustomerByIdResult>(
|
||||
return dataSource.updateOne<UpdateCustomerByIdRequestDTO, UpdateCustomerByIdResponseDTO>(
|
||||
"customers",
|
||||
id,
|
||||
data
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useDataSource } from "@erp/core/hooks";
|
||||
import { UniqueID, ValidationErrorCollection } from "@repo/rdx-ddd";
|
||||
import { ValidationErrorCollection } from "@repo/rdx-ddd";
|
||||
import { type DefaultError, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { CreateCustomerRequestSchema } from "../../../common";
|
||||
@ -25,15 +25,12 @@ export const useCustomerCreateMutation = () => {
|
||||
mutationKey: CUSTOMER_CREATE_KEY,
|
||||
|
||||
mutationFn: async (payload) => {
|
||||
const id = UniqueID.generateNewID().toString();
|
||||
const payloadWithId: CreateCustomerParams = { ...payload, id };
|
||||
|
||||
const result = schema.safeParse(payloadWithId);
|
||||
const result = schema.safeParse(payload);
|
||||
if (!result.success) {
|
||||
throw new ValidationErrorCollection("Validation failed", toValidationErrors(result.error));
|
||||
}
|
||||
|
||||
const dto: CreateCustomerResult = await createCustomer(dataSource, payloadWithId);
|
||||
const dto: CreateCustomerResult = await createCustomer(dataSource, payload);
|
||||
return GetCustomerByIdAdapter.fromDTO(dto);
|
||||
},
|
||||
|
||||
|
||||
@ -1,11 +1,7 @@
|
||||
import { useDataSource } from "@erp/core/hooks";
|
||||
import { type DefaultError, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import {
|
||||
type DeleteCustomerByIdParams,
|
||||
type DeleteCustomerByIdResult,
|
||||
deleteCustomerById,
|
||||
} from "../api";
|
||||
import { type DeleteCustomerByIdParams, deleteCustomerById } from "../api";
|
||||
|
||||
import {
|
||||
type DeleteCustomerCacheContext,
|
||||
@ -22,33 +18,31 @@ export const useCustomerDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dataSource = useDataSource();
|
||||
|
||||
return useMutation<
|
||||
DeleteCustomerByIdResult,
|
||||
DefaultError,
|
||||
DeleteCustomerByIdParams,
|
||||
DeleteCustomerContext
|
||||
>({
|
||||
mutationKey: CUSTOMER_DELETE_KEY,
|
||||
mutationFn: async ({ id }) => {
|
||||
if (!id) {
|
||||
throw new Error("customerId is required");
|
||||
}
|
||||
return useMutation<{ id: string }, DefaultError, DeleteCustomerByIdParams, DeleteCustomerContext>(
|
||||
{
|
||||
mutationKey: CUSTOMER_DELETE_KEY,
|
||||
mutationFn: async ({ id, signal }) => {
|
||||
if (!id) {
|
||||
throw new Error("customerId is required");
|
||||
}
|
||||
|
||||
await deleteCustomerById(dataSource, { id }, new AbortController().signal);
|
||||
},
|
||||
onMutate: async ({ id }) => {
|
||||
return prepareDeleteCustomerOptimisticUpdate(queryClient, id);
|
||||
},
|
||||
await deleteCustomerById(dataSource, { id, signal });
|
||||
return { id };
|
||||
},
|
||||
onMutate: async ({ id }) => {
|
||||
return prepareDeleteCustomerOptimisticUpdate(queryClient, id);
|
||||
},
|
||||
|
||||
onError: (_error, _variables, context) => {
|
||||
rollbackDeleteCustomerOptimisticUpdate(queryClient, context);
|
||||
},
|
||||
onError: (_error, _variables, context) => {
|
||||
rollbackDeleteCustomerOptimisticUpdate(queryClient, context);
|
||||
},
|
||||
|
||||
onSuccess: (_, variables) => {
|
||||
finalizeDeletedCustomerCaches(queryClient, variables.id);
|
||||
},
|
||||
onSettled: async () => {
|
||||
await invalidateCustomerListQueries(queryClient);
|
||||
},
|
||||
});
|
||||
onSuccess: ({ id }) => {
|
||||
finalizeDeletedCustomerCaches(queryClient, id);
|
||||
},
|
||||
onSettled: async () => {
|
||||
await invalidateCustomerListQueries(queryClient);
|
||||
},
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@ -98,8 +98,8 @@ export const useCustomerUpdateController = (
|
||||
}
|
||||
|
||||
const previousData = customerData;
|
||||
const patchData = buildCustomerUpdatePatch(formData, dirtyFields);
|
||||
|
||||
const patchData = buildCustomerUpdatePatch(formData, dirtyFields);
|
||||
const params: UpdateCustomerByIdParams = buildUpdateCustomerByIdParams(customerId, patchData);
|
||||
|
||||
try {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user