Clientes y facturas de cliente
This commit is contained in:
parent
c285c2d897
commit
f72273b069
@ -3,13 +3,13 @@ import { CustomerInvoiceListDTO } from "@erp/customer-invoices/api/infrastructur
|
|||||||
import { Criteria } from "@repo/rdx-criteria/server";
|
import { Criteria } from "@repo/rdx-criteria/server";
|
||||||
import { toEmptyString } from "@repo/rdx-ddd";
|
import { toEmptyString } from "@repo/rdx-ddd";
|
||||||
import { ArrayElement, Collection } from "@repo/rdx-utils";
|
import { ArrayElement, Collection } from "@repo/rdx-utils";
|
||||||
import { CustomerInvoiceListResponseDTO } from "../../../../common/dto";
|
import { ListCustomerInvoicesResponseDTO } from "../../../../common/dto";
|
||||||
|
|
||||||
export class ListCustomerInvoicesPresenter extends Presenter {
|
export class ListCustomerInvoicesPresenter extends Presenter {
|
||||||
protected _mapInvoice(invoice: CustomerInvoiceListDTO) {
|
protected _mapInvoice(invoice: CustomerInvoiceListDTO) {
|
||||||
const recipientDTO = invoice.recipient.toObjectString();
|
const recipientDTO = invoice.recipient.toObjectString();
|
||||||
|
|
||||||
const invoiceDTO: ArrayElement<CustomerInvoiceListResponseDTO["items"]> = {
|
const invoiceDTO: ArrayElement<ListCustomerInvoicesResponseDTO["items"]> = {
|
||||||
id: invoice.id.toString(),
|
id: invoice.id.toString(),
|
||||||
company_id: invoice.companyId.toString(),
|
company_id: invoice.companyId.toString(),
|
||||||
customer_id: invoice.customerId.toString(),
|
customer_id: invoice.customerId.toString(),
|
||||||
@ -48,7 +48,7 @@ export class ListCustomerInvoicesPresenter extends Presenter {
|
|||||||
toOutput(params: {
|
toOutput(params: {
|
||||||
customerInvoices: Collection<CustomerInvoiceListDTO>;
|
customerInvoices: Collection<CustomerInvoiceListDTO>;
|
||||||
criteria: Criteria;
|
criteria: Criteria;
|
||||||
}): CustomerInvoiceListResponseDTO {
|
}): ListCustomerInvoicesResponseDTO {
|
||||||
const { customerInvoices, criteria } = params;
|
const { customerInvoices, criteria } = params;
|
||||||
|
|
||||||
const invoices = customerInvoices.map((invoice) => this._mapInvoice(invoice));
|
const invoices = customerInvoices.map((invoice) => this._mapInvoice(invoice));
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import { Criteria } from "@repo/rdx-criteria/server";
|
|||||||
import { UniqueID } from "@repo/rdx-ddd";
|
import { UniqueID } from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { Transaction } from "sequelize";
|
import { Transaction } from "sequelize";
|
||||||
import { CustomerInvoiceListResponseDTO } from "../../../common/dto";
|
import { ListCustomerInvoicesResponseDTO } from "../../../common/dto";
|
||||||
import { CustomerInvoiceService } from "../../domain";
|
import { CustomerInvoiceService } from "../../domain";
|
||||||
import { ListCustomerInvoicesPresenter } from "../presenters";
|
import { ListCustomerInvoicesPresenter } from "../presenters";
|
||||||
|
|
||||||
@ -21,7 +21,7 @@ export class ListCustomerInvoicesUseCase {
|
|||||||
|
|
||||||
public execute(
|
public execute(
|
||||||
params: ListCustomerInvoicesUseCaseInput
|
params: ListCustomerInvoicesUseCaseInput
|
||||||
): Promise<Result<CustomerInvoiceListResponseDTO, Error>> {
|
): Promise<Result<ListCustomerInvoicesResponseDTO, Error>> {
|
||||||
const { criteria, companyId } = params;
|
const { criteria, companyId } = params;
|
||||||
const presenter = this.presenterRegistry.getPresenter({
|
const presenter = this.presenterRegistry.getPresenter({
|
||||||
resource: "customer-invoice",
|
resource: "customer-invoice",
|
||||||
|
|||||||
@ -101,17 +101,17 @@
|
|||||||
|
|
||||||
<aside class="flex items-start mb-4 w-full">
|
<aside class="flex items-start mb-4 w-full">
|
||||||
<!-- Bloque IZQUIERDO: imagen arriba + texto abajo, alineado a la izquierda -->
|
<!-- Bloque IZQUIERDO: imagen arriba + texto abajo, alineado a la izquierda -->
|
||||||
<div class="flex flex-col items-start text-left">
|
<div class="w-[70%] flex flex-col items-start text-left">
|
||||||
<img src="https://rodax-software.com/images/logo1.jpg" alt="Logo Rodax" class="block h-14 w-auto mb-1" />
|
<img src="https://rodax-software.com/images/logo1.jpg" alt="Logo Rodax" class="block h-14 w-auto mb-1" />
|
||||||
<div class="flex w-full gap-30">
|
<div class="flex w-full gap-9">
|
||||||
<div class="w-[30%] bg-amber-400 p-3 text-sm leading-tight">
|
<div class="p-1 ">
|
||||||
<p><span class="font-semibold">Factura nº:</span> {{reference}}</p>
|
<p><span>Factura nº:</span>xxxxxxxx</p>
|
||||||
<p><span class="font-semibold">Fecha:</span> {{date}}</p>
|
<p><span>Fecha:</span>12/12/2024</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-[70%] bg-amber-700 p-3 text-sm leading-tight text-white">
|
<div class="p-1">
|
||||||
<h2 class="font-semibold uppercase mb-1">{{customer.name}}</h2>
|
<h2 class="font-semibold uppercase mb-1">{{customer.name}}</h2>
|
||||||
<p>AAAA</p>
|
<p>AAAA</p>
|
||||||
<p>BBBBBB</p>
|
<p>BBBBBBsdfsfsdf sfsdf sf sdfs fsdfsd fsdf sdfsd fds </p>
|
||||||
<p>CCCCC</p>
|
<p>CCCCC</p>
|
||||||
<p>DDDDD</p>
|
<p>DDDDD</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { MetadataSchema, MoneySchema, createListViewResponseSchema } from "@erp/core";
|
import { MetadataSchema, MoneySchema, createListViewResponseSchema } from "@erp/core";
|
||||||
import * as z from "zod/v4";
|
import * as z from "zod/v4";
|
||||||
|
|
||||||
export const ListCustomerInvoiceResponseSchema = createListViewResponseSchema(
|
export const ListCustomerInvoicesResponseSchema = createListViewResponseSchema(
|
||||||
z.object({
|
z.object({
|
||||||
id: z.uuid(),
|
id: z.uuid(),
|
||||||
company_id: z.uuid(),
|
company_id: z.uuid(),
|
||||||
@ -40,4 +40,4 @@ export const ListCustomerInvoiceResponseSchema = createListViewResponseSchema(
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
export type CustomerInvoiceListResponseDTO = z.infer<typeof ListCustomerInvoiceResponseSchema>;
|
export type ListCustomerInvoicesResponseDTO = z.infer<typeof ListCustomerInvoicesResponseSchema>;
|
||||||
|
|||||||
@ -1,25 +1,37 @@
|
|||||||
import { useState } from "react";
|
|
||||||
|
|
||||||
import { AG_GRID_LOCALE_ES } from "@ag-grid-community/locale";
|
import { AG_GRID_LOCALE_ES } from "@ag-grid-community/locale";
|
||||||
// Grid
|
import type {
|
||||||
import type { ColDef, GridOptions, ValueFormatterParams } from "ag-grid-community";
|
SizeColumnsToContentStrategy,
|
||||||
import { AllCommunityModule, ModuleRegistry } from "ag-grid-community";
|
SizeColumnsToFitGridStrategy,
|
||||||
|
SizeColumnsToFitProvidedWidthStrategy,
|
||||||
ModuleRegistry.registerModules([AllCommunityModule]);
|
ValueFormatterParams,
|
||||||
|
} from "ag-grid-community";
|
||||||
|
import { AllCommunityModule, ColDef, GridOptions, ModuleRegistry } from "ag-grid-community";
|
||||||
|
import { useMemo, useState } from "react";
|
||||||
|
|
||||||
import { MoneyDTO } from "@erp/core";
|
import { MoneyDTO } from "@erp/core";
|
||||||
import { formatDate, formatMoney } from "@erp/core/client";
|
import { formatDate, formatMoney } from "@erp/core/client";
|
||||||
// Core CSS
|
import { Button } from "@repo/shadcn-ui/components";
|
||||||
import { AgGridReact } from "ag-grid-react";
|
import { AgGridReact } from "ag-grid-react";
|
||||||
import { Link } from "react-router-dom";
|
import { ChevronRightIcon } from "lucide-react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useCustomerInvoicesQuery } from "../hooks";
|
import { useCustomerInvoicesQuery } from "../hooks";
|
||||||
import { useTranslation } from "../i18n";
|
import { useTranslation } from "../i18n";
|
||||||
import { CustomerInvoiceStatusBadge } from "./customer-invoice-status-badge";
|
import { CustomerInvoiceStatusBadge } from "./customer-invoice-status-badge";
|
||||||
|
|
||||||
|
ModuleRegistry.registerModules([AllCommunityModule]);
|
||||||
|
|
||||||
// Create new GridExample component
|
// Create new GridExample component
|
||||||
export const CustomerInvoicesListGrid = () => {
|
export const CustomerInvoicesListGrid = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { data, isLoading, isPending, isError, error } = useCustomerInvoicesQuery({
|
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: customersData,
|
||||||
|
isLoading: isLoadingCustomerInvoices,
|
||||||
|
isError: isLoadError,
|
||||||
|
error: loadError,
|
||||||
|
} = useCustomerInvoicesQuery({
|
||||||
pagination: {
|
pagination: {
|
||||||
pageSize: 999,
|
pageSize: 999,
|
||||||
},
|
},
|
||||||
@ -78,31 +90,56 @@ export const CustomerInvoicesListGrid = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: "id",
|
colId: "actions",
|
||||||
headerName: t("pages.list.grid_columns.total_amount"),
|
headerName: t("pages.list.grid_columns.actions", "Actions"),
|
||||||
cellRenderer: (params: ValueFormatterParams) => {
|
cellRenderer: (params: ValueFormatterParams) => {
|
||||||
return <Link to={params.value}>Hola</Link>;
|
const { data } = params;
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
variant='secondary'
|
||||||
|
size='icon'
|
||||||
|
className='size-8'
|
||||||
|
onClick={() => {
|
||||||
|
navigate(`${data.id}/edit`);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ChevronRightIcon />
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const gridOptions: GridOptions = {
|
const autoSizeStrategy = useMemo<
|
||||||
rowModelType: "clientSide",
|
| SizeColumnsToFitGridStrategy
|
||||||
columnDefs: colDefs,
|
| SizeColumnsToFitProvidedWidthStrategy
|
||||||
defaultColDef: {
|
| SizeColumnsToContentStrategy
|
||||||
editable: false,
|
>(() => {
|
||||||
flex: 1,
|
return {
|
||||||
minWidth: 100,
|
type: "fitGridWidth",
|
||||||
filter: true,
|
defaultMinWidth: 100,
|
||||||
sortable: true,
|
columnLimits: [{ colId: "actions", minWidth: 75, maxWidth: 75 }],
|
||||||
resizable: true,
|
};
|
||||||
},
|
}, []);
|
||||||
pagination: true,
|
|
||||||
paginationPageSize: 15,
|
const gridOptions: GridOptions = useMemo(
|
||||||
paginationPageSizeSelector: [10, 15, 20, 30, 50],
|
() => ({
|
||||||
localeText: AG_GRID_LOCALE_ES,
|
columnDefs: colDefs,
|
||||||
rowSelection: { mode: "multiRow" },
|
autoSizeStrategy: autoSizeStrategy,
|
||||||
};
|
defaultColDef: {
|
||||||
|
editable: false,
|
||||||
|
flex: 1,
|
||||||
|
filter: false,
|
||||||
|
sortable: false,
|
||||||
|
resizable: true,
|
||||||
|
},
|
||||||
|
pagination: true,
|
||||||
|
paginationPageSize: 10,
|
||||||
|
paginationPageSizeSelector: [10, 20, 30, 50],
|
||||||
|
localeText: AG_GRID_LOCALE_ES,
|
||||||
|
}),
|
||||||
|
[autoSizeStrategy, colDefs]
|
||||||
|
);
|
||||||
|
|
||||||
// Container: Defines the grid's theme & dimensions.
|
// Container: Defines the grid's theme & dimensions.
|
||||||
return (
|
return (
|
||||||
@ -113,7 +150,11 @@ export const CustomerInvoicesListGrid = () => {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AgGridReact rowData={data?.items ?? []} loading={isLoading || isPending} {...gridOptions} />
|
<AgGridReact
|
||||||
|
rowData={customersData?.items ?? []}
|
||||||
|
loading={isLoadingCustomerInvoices}
|
||||||
|
{...gridOptions}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,22 +1,22 @@
|
|||||||
import { useDataSource, useQueryKey } from "@erp/core/hooks";
|
import { useDataSource, useQueryKey } from "@erp/core/hooks";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { CustomerInvoiceListResponseDTO } from "../../common/dto";
|
import { ListCustomerInvoicesResponseDTO } from "../../common/dto";
|
||||||
|
|
||||||
// Obtener todas las facturas
|
// Obtener todas las facturas
|
||||||
export const useCustomerInvoicesQuery = (params: any) => {
|
export const useCustomerInvoicesQuery = (params?: any) => {
|
||||||
const dataSource = useDataSource();
|
const dataSource = useDataSource();
|
||||||
const keys = useQueryKey();
|
const keys = useQueryKey();
|
||||||
|
|
||||||
return useQuery<CustomerInvoiceListResponseDTO>({
|
return useQuery<ListCustomerInvoicesResponseDTO>({
|
||||||
queryKey: keys().data().resource("customer-invoices").action("list").params(params).get(),
|
queryKey: keys().data().resource("customer-invoices").action("list").params(params).get(),
|
||||||
queryFn: (context) => {
|
queryFn: async (context) => {
|
||||||
console.log(dataSource.getBaseUrl());
|
|
||||||
console.log(params);
|
|
||||||
const { signal } = context;
|
const { signal } = context;
|
||||||
return dataSource.getList<CustomerInvoiceListResponseDTO>("customer-invoices", {
|
const invoices = await dataSource.getList("customer-invoices", {
|
||||||
signal,
|
signal,
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return invoices as ListCustomerInvoicesResponseDTO;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -110,15 +110,6 @@ export const CustomerEditForm = ({ formId, data, onSubmit, isPending }: Customer
|
|||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<TextField
|
|
||||||
control={form.control}
|
|
||||||
name='tin'
|
|
||||||
required
|
|
||||||
label={t("form_fields.tin.label")}
|
|
||||||
placeholder={t("form_fields.tin.placeholder")}
|
|
||||||
description={t("form_fields.tin.description")}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<TextField
|
<TextField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name='name'
|
name='name'
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user