Facturas de cliente

This commit is contained in:
David Arranz 2025-09-11 17:14:51 +02:00
parent cec3eba428
commit edecf0121b
12 changed files with 87 additions and 23 deletions

View File

@ -8,6 +8,24 @@
"description": "IVA general. Tipo estándar nacional.", "description": "IVA general. Tipo estándar nacional.",
"aeat_code": "01" "aeat_code": "01"
}, },
{
"name": "IVA 18%",
"code": "iva_18",
"value": 1800,
"scale": 2,
"group": "IVA",
"description": "IVA general. Tipo estándar nacional hasta finales de 2011",
"aeat_code": null
},
{
"name": "IVA 16%",
"code": "iva_16",
"value": 1600,
"scale": 2,
"group": "IVA",
"description": "IVA general. Tipo estándar nacional hasta finales de 2009.",
"aeat_code": null
},
{ {
"name": "IVA 10%", "name": "IVA 10%",
"code": "iva_10", "code": "iva_10",

View File

@ -3,7 +3,7 @@ import { MoneyDTO } from "../../../common";
export const formatMoney = (value: MoneyDTO) => { export const formatMoney = (value: MoneyDTO) => {
const money = DineroFactory({ const money = DineroFactory({
amount: Number(value.amount), amount: Number(value.value),
currency: value.currency_code as Currency, currency: value.currency_code as Currency,
precision: Number(value.scale), precision: Number(value.scale),
}); });

View File

@ -29,6 +29,9 @@ export class ListCustomerInvoicesAssembler {
...recipientDTO, ...recipientDTO,
}, },
language_code: invoice.languageCode.code,
currency_code: invoice.currencyCode.code,
taxes: invoice.taxes, taxes: invoice.taxes,
subtotal_amount: invoice.subtotalAmount.toObjectString(), subtotal_amount: invoice.subtotalAmount.toObjectString(),

View File

@ -27,6 +27,7 @@ export class InvoiceAmount extends MoneyValue {
return { return {
value: String(this.value), value: String(this.value),
scale: String(this.scale), scale: String(this.scale),
currency_code: this.currencyCode,
}; };
} }

View File

@ -1,4 +1,5 @@
import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api"; import { ExpressController, authGuard, forbidQueryFieldGuard, tenantGuard } from "@erp/core/api";
import { Criteria } from "@repo/rdx-criteria/server";
import { ListCustomerInvoicesUseCase } from "../../../application"; import { ListCustomerInvoicesUseCase } from "../../../application";
export class ListCustomerInvoicesController extends ExpressController { export class ListCustomerInvoicesController extends ExpressController {
@ -8,9 +9,20 @@ export class ListCustomerInvoicesController extends ExpressController {
this.useGuards(authGuard(), tenantGuard(), forbidQueryFieldGuard("companyId")); this.useGuards(authGuard(), tenantGuard(), forbidQueryFieldGuard("companyId"));
} }
private _xxxx() {
if (this.criteria.hasOrder()) {
return this.criteria;
}
const { filters, pageSize, pageNumber } = this.criteria.toPrimitives();
return Criteria.fromPrimitives(filters, "invoice_date", "DESC", pageSize, pageNumber);
}
protected async executeImpl() { protected async executeImpl() {
const companyId = this.getTenantId()!; // garantizado por tenantGuard const companyId = this.getTenantId()!; // garantizado por tenantGuard
const result = await this.useCase.execute({ criteria: this.criteria, companyId });
const criteria = this._xxxx();
const result = await this.useCase.execute({ criteria, companyId });
return result.match( return result.match(
(data) => (data) =>

View File

@ -214,12 +214,12 @@ export class CustomerInvoiceRepository
}, },
]; ];
const raws = await CustomerInvoiceModel.findAll({ const { rows, count } = await CustomerInvoiceModel.findAndCountAll({
...query, ...query,
transaction, transaction,
}); });
return mapper.mapToDTOCollection(raws, raws.length); return mapper.mapToDTOCollection(rows, count);
} catch (err: unknown) { } catch (err: unknown) {
return Result.fail(translateSequelizeError(err)); return Result.fail(translateSequelizeError(err));
} }

View File

@ -17,13 +17,12 @@ export const GetCustomerInvoiceByIdResponseSchema = z.object({
language_code: z.string(), language_code: z.string(),
currency_code: z.string(), currency_code: z.string(),
taxes: z.string(),
subtotal_amount: AmountSchema, subtotal_amount: AmountSchema,
discount_percentage: PercentageSchema, discount_percentage: PercentageSchema,
discount_amount: AmountSchema, discount_amount: AmountSchema,
taxable_amount: AmountSchema, taxable_amount: AmountSchema,
taxes: z.string(),
total_amount: AmountSchema, total_amount: AmountSchema,
items: z.array( items: z.array(

View File

@ -1,4 +1,4 @@
export * from "./create-customer-invoice.response.dto"; export * from "./create-customer-invoice.response.dto";
export * from "./customer-invoices-list.response.dto";
export * from "./get-customer-invoice-by-id.response.dto"; export * from "./get-customer-invoice-by-id.response.dto";
export * from "./list-customer-invoices.response.dto";
export * from "./update-customer-invoice-by-id.response.dto"; export * from "./update-customer-invoice-by-id.response.dto";

View File

@ -1,7 +1,7 @@
import { AmountSchema, MetadataSchema, createListViewResponseSchema } from "@erp/core"; import { AmountSchema, MetadataSchema, createListViewResponseSchema } from "@erp/core";
import * as z from "zod/v4"; import * as z from "zod/v4";
export const CustomerInvoiceListResponseSchema = createListViewResponseSchema( export const ListCustomerInvoiceResponseSchema = createListViewResponseSchema(
z.object({ z.object({
id: z.uuid(), id: z.uuid(),
company_id: z.uuid(), company_id: z.uuid(),
@ -14,6 +14,9 @@ export const CustomerInvoiceListResponseSchema = createListViewResponseSchema(
invoice_date: z.string(), invoice_date: z.string(),
operation_date: z.string(), operation_date: z.string(),
language_code: z.string(),
currency_code: z.string(),
recipient: { recipient: {
tin: z.string(), tin: z.string(),
name: z.string(), name: z.string(),
@ -37,4 +40,4 @@ export const CustomerInvoiceListResponseSchema = createListViewResponseSchema(
}) })
); );
export type CustomerInvoiceListResponseDTO = z.infer<typeof CustomerInvoiceListResponseSchema>; export type CustomerInvoiceListResponseDTO = z.infer<typeof ListCustomerInvoiceResponseSchema>;

View File

@ -15,10 +15,10 @@
"description": "List all customer invoices", "description": "List all customer invoices",
"grid_columns": { "grid_columns": {
"invoice_number": "Inv. number", "invoice_number": "Inv. number",
"invoice_series": "Serie", "series": "Serie",
"invoice_status": "Status", "status": "Status",
"invoice_date": "Date", "invoice_date": "Date",
"total_price": "Total price" "total_amount": "Total price"
} }
}, },
"create": { "create": {

View File

@ -23,16 +23,16 @@ export const CustomerInvoicesListGrid = () => {
// Column Definitions: Defines & controls grid columns. // Column Definitions: Defines & controls grid columns.
const [colDefs] = useState<ColDef[]>([ const [colDefs] = useState<ColDef[]>([
{ {
field: "invoice_status", field: "status",
filter: true, filter: true,
headerName: t("pages.list.grid_columns.invoice_status"), headerName: t("pages.list.grid_columns.status"),
cellRenderer: (params: ValueFormatterParams) => { cellRenderer: (params: ValueFormatterParams) => {
return <CustomerInvoiceStatusBadge status={params.value} />; return <CustomerInvoiceStatusBadge status={params.value} />;
}, },
}, },
{ field: "invoice_number", headerName: t("pages.list.grid_columns.invoice_number") }, { field: "invoice_number", headerName: t("pages.list.grid_columns.invoice_number") },
{ field: "invoice_series", headerName: t("pages.list.grid_columns.invoice_series") }, { field: "series", headerName: t("pages.list.grid_columns.series") },
{ {
field: "invoice_date", field: "invoice_date",
@ -41,9 +41,32 @@ export const CustomerInvoicesListGrid = () => {
return formatDate(params.value); return formatDate(params.value);
}, },
}, },
{ field: "recipient.tin" },
{ field: "recipient.name" },
{ field: "recipient.city" },
{ field: "recipient.province" },
{ field: "recipient.postal_code" },
{ {
field: "total_price", field: "taxable_amount",
headerName: t("pages.list.grid_columns.total_price"), headerName: t("pages.list.grid_columns.taxable_amount"),
valueFormatter: (params: ValueFormatterParams) => {
const rawValue: MoneyDTO = params.value;
return formatMoney(rawValue);
},
},
{
field: "taxes_amount",
headerName: t("pages.list.grid_columns.taxable_amount"),
valueFormatter: (params: ValueFormatterParams) => {
const rawValue: MoneyDTO = params.value;
return formatMoney(rawValue);
},
},
{
field: "total_amount",
headerName: t("pages.list.grid_columns.total_amount"),
valueFormatter: (params: ValueFormatterParams) => { valueFormatter: (params: ValueFormatterParams) => {
const rawValue: MoneyDTO = params.value; const rawValue: MoneyDTO = params.value;
return formatMoney(rawValue); return formatMoney(rawValue);
@ -54,11 +77,11 @@ export const CustomerInvoicesListGrid = () => {
const gridOptions: GridOptions = { const gridOptions: GridOptions = {
columnDefs: colDefs, columnDefs: colDefs,
defaultColDef: { defaultColDef: {
editable: true, editable: false,
flex: 1, flex: 1,
minWidth: 100, minWidth: 100,
filter: false, filter: true,
sortable: false, sortable: true,
resizable: true, resizable: true,
}, },
pagination: true, pagination: true,

View File

@ -35,12 +35,17 @@ export class Criteria extends BaseCriteria {
); );
} }
toJSON(): Record<string, any> { toPrimitives() {
return { return {
filters: this.filters.toPrimitives(), filters: this.filters.toPrimitives(),
//order: this.order. orderBy: this.order.orderBy.value,
orderType: this.order.orderType.value,
pageSize: this.pageSize, pageSize: this.pageSize,
pageNumber: this.pageNumber, pageNumber: this.pageNumber,
}; };
} }
toJSON() {
return this.toPrimitives();
}
} }