Facturas de cliente
This commit is contained in:
parent
60dacc4c32
commit
1c66d20c24
@ -1,6 +1,7 @@
|
|||||||
import { MoneyDTO, MoneyDTOHelper } from "@erp/core/common";
|
import { type MoneyDTO, MoneyDTOHelper } from "@erp/core/common";
|
||||||
import type { Currency } from "dinero.js";
|
import type { Currency } from "dinero.js";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
import { useTranslation } from "../i18n";
|
import { useTranslation } from "../i18n";
|
||||||
|
|
||||||
export type { Currency };
|
export type { Currency };
|
||||||
@ -94,7 +95,7 @@ export function useMoney(overrides?: {
|
|||||||
|
|
||||||
// Formateos
|
// Formateos
|
||||||
const formatCurrency = React.useCallback(
|
const formatCurrency = React.useCallback(
|
||||||
(dto: MoneyDTO, loc?: string) => MoneyDTOHelper.formatDTO(dto, loc ?? locale),
|
(dto: MoneyDTO, loc?: string) => MoneyDTOHelper.format(dto, loc ?? locale),
|
||||||
[locale]
|
[locale]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
|
||||||
@ -1,19 +1,21 @@
|
|||||||
import {
|
import {
|
||||||
|
ValidationErrorCollection,
|
||||||
|
type ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
ValidationErrorCollection,
|
|
||||||
ValidationErrorDetail,
|
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
|
||||||
|
import type { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
||||||
import {
|
import {
|
||||||
CustomerInvoiceItem,
|
CustomerInvoiceItem,
|
||||||
CustomerInvoiceItemDescription,
|
CustomerInvoiceItemDescription,
|
||||||
CustomerInvoiceItemProps,
|
type CustomerInvoiceItemProps,
|
||||||
ItemAmount,
|
ItemAmount,
|
||||||
ItemDiscount,
|
ItemDiscount,
|
||||||
ItemQuantity,
|
ItemQuantity,
|
||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
|
|
||||||
import { hasNoUndefinedFields } from "./has-no-undefined-fields";
|
import { hasNoUndefinedFields } from "./has-no-undefined-fields";
|
||||||
|
|
||||||
export function mapDTOToCustomerInvoiceItemsProps(
|
export function mapDTOToCustomerInvoiceItemsProps(
|
||||||
@ -3,18 +3,20 @@ import {
|
|||||||
UniqueID,
|
UniqueID,
|
||||||
UtcDate,
|
UtcDate,
|
||||||
ValidationErrorCollection,
|
ValidationErrorCollection,
|
||||||
ValidationErrorDetail,
|
type ValidationErrorDetail,
|
||||||
extractOrPushError,
|
extractOrPushError,
|
||||||
maybeFromNullableVO,
|
maybeFromNullableVO,
|
||||||
} from "@repo/rdx-ddd";
|
} from "@repo/rdx-ddd";
|
||||||
import { Result } from "@repo/rdx-utils";
|
import { Result } from "@repo/rdx-utils";
|
||||||
import { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
|
||||||
|
import type { CreateCustomerInvoiceRequestDTO } from "../../../common";
|
||||||
import {
|
import {
|
||||||
CustomerInvoiceNumber,
|
CustomerInvoiceNumber,
|
||||||
CustomerInvoiceProps,
|
type CustomerInvoiceProps,
|
||||||
CustomerInvoiceSerie,
|
CustomerInvoiceSerie,
|
||||||
CustomerInvoiceStatus,
|
CustomerInvoiceStatus,
|
||||||
} from "../../domain";
|
} from "../../domain";
|
||||||
|
|
||||||
import { mapDTOToCustomerInvoiceItemsProps } from "./map-dto-to-customer-invoice-items-props";
|
import { mapDTOToCustomerInvoiceItemsProps } from "./map-dto-to-customer-invoice-items-props";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1,7 +0,0 @@
|
|||||||
import { UtcDate } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export function formatDateDTO(dateString: string) {
|
|
||||||
const result = UtcDate.createFromISO(dateString).data;
|
|
||||||
|
|
||||||
return result.toEuropeanString();
|
|
||||||
}
|
|
||||||
@ -1,25 +0,0 @@
|
|||||||
import { MoneyDTO } from "@erp/core";
|
|
||||||
import { MoneyValue } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export type FormatMoneyOptions = {
|
|
||||||
locale: string;
|
|
||||||
hideZeros?: boolean;
|
|
||||||
newScale?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function formatMoneyDTO(
|
|
||||||
amount: MoneyDTO,
|
|
||||||
{ locale, hideZeros = false, newScale = 2 }: FormatMoneyOptions
|
|
||||||
) {
|
|
||||||
if (hideZeros && (amount.value === "0" || amount.value === "")) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const money = MoneyValue.create({
|
|
||||||
value: Number(amount.value),
|
|
||||||
currency_code: amount.currency_code,
|
|
||||||
scale: Number(amount.scale),
|
|
||||||
}).data;
|
|
||||||
|
|
||||||
return money.convertScale(newScale).format(locale);
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common";
|
|
||||||
|
|
||||||
export function formatPaymentMethodDTO(
|
|
||||||
paymentMethod?: GetIssueInvoiceByIdResponseDTO["payment_method"]
|
|
||||||
) {
|
|
||||||
if (!paymentMethod) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return paymentMethod.payment_description ?? "";
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { PercentageDTO } from "@erp/core";
|
|
||||||
import { Percentage } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export function formatPercentageDTO(Percentage_value: PercentageDTO, locale: string) {
|
|
||||||
if (Percentage_value.value === "0" || Percentage_value.value === "") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = Percentage.create({
|
|
||||||
value: Number(Percentage_value.value),
|
|
||||||
scale: Number(Percentage_value.scale),
|
|
||||||
}).data;
|
|
||||||
|
|
||||||
return value.format(locale);
|
|
||||||
}
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
import { QuantityDTO } from "@erp/core";
|
|
||||||
import { Quantity } from "@repo/rdx-ddd";
|
|
||||||
|
|
||||||
export function formatQuantityDTO(quantity_value: QuantityDTO) {
|
|
||||||
if (quantity_value.value === "0" || quantity_value.value === "") {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const value = Quantity.create({
|
|
||||||
value: Number(quantity_value.value),
|
|
||||||
scale: Number(quantity_value.scale),
|
|
||||||
}).data;
|
|
||||||
|
|
||||||
return value.format();
|
|
||||||
}
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
export * from "./format-date-dto";
|
|
||||||
export * from "./format-money-dto";
|
|
||||||
export * from "./format-payment_method-dto";
|
|
||||||
export * from "./format-percentage-dto";
|
|
||||||
export * from "./format-quantity-dto";
|
|
||||||
//export * from "./map-dto-to-customer-invoice-props";
|
|
||||||
@ -1,9 +1,8 @@
|
|||||||
|
import { MoneyDTOHelper, PercentageDTOHelper, QuantityDTOHelper } from "@erp/core";
|
||||||
import { type IPresenterOutputParams, Presenter } from "@erp/core/api";
|
import { type IPresenterOutputParams, Presenter } from "@erp/core/api";
|
||||||
import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common";
|
import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common";
|
||||||
import type { ArrayElement } from "@repo/rdx-utils";
|
import type { ArrayElement } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import { type FormatMoneyOptions, formatMoneyDTO, formatQuantityDTO } from "../../helpers";
|
|
||||||
|
|
||||||
type CustomerInvoiceItemsDTO = GetIssueInvoiceByIdResponseDTO["items"];
|
type CustomerInvoiceItemsDTO = GetIssueInvoiceByIdResponseDTO["items"];
|
||||||
type CustomerInvoiceItemDTO = ArrayElement<CustomerInvoiceItemsDTO>;
|
type CustomerInvoiceItemDTO = ArrayElement<CustomerInvoiceItemsDTO>;
|
||||||
|
|
||||||
@ -13,24 +12,39 @@ export class CustomerInvoiceItemsReportPersenter extends Presenter<
|
|||||||
> {
|
> {
|
||||||
private _locale!: string;
|
private _locale!: string;
|
||||||
|
|
||||||
private _mapItem(invoiceItem: CustomerInvoiceItemDTO, index: number) {
|
private _mapItem(invoiceItem: CustomerInvoiceItemDTO, _index: number) {
|
||||||
const moneyOptions: FormatMoneyOptions = {
|
const moneyOptions = {
|
||||||
locale: this._locale,
|
|
||||||
hideZeros: true,
|
hideZeros: true,
|
||||||
newScale: 2,
|
minimumFractionDigits: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...invoiceItem,
|
...invoiceItem,
|
||||||
|
|
||||||
quantity: formatQuantityDTO(invoiceItem.quantity),
|
quantity: QuantityDTOHelper.format(invoiceItem.quantity, this._locale, {
|
||||||
unit_amount: formatMoneyDTO(invoiceItem.unit_amount, moneyOptions),
|
minimumFractionDigits: 0,
|
||||||
subtotal_amount: formatMoneyDTO(invoiceItem.subtotal_amount, moneyOptions),
|
}),
|
||||||
// discount_percetage: formatPercentageDTO(invoiceItem.discount_percentage, this._locale),
|
unit_amount: MoneyDTOHelper.format(invoiceItem.unit_amount, this._locale, moneyOptions),
|
||||||
discount_amount: formatMoneyDTO(invoiceItem.discount_amount, moneyOptions),
|
subtotal_amount: MoneyDTOHelper.format(
|
||||||
taxable_amount: formatMoneyDTO(invoiceItem.taxable_amount, moneyOptions),
|
invoiceItem.subtotal_amount,
|
||||||
taxes_amount: formatMoneyDTO(invoiceItem.taxes_amount, moneyOptions),
|
this._locale,
|
||||||
total_amount: formatMoneyDTO(invoiceItem.total_amount, moneyOptions),
|
moneyOptions
|
||||||
|
),
|
||||||
|
discount_percentage: PercentageDTOHelper.format(
|
||||||
|
invoiceItem.discount_percentage,
|
||||||
|
this._locale,
|
||||||
|
{
|
||||||
|
minimumFractionDigits: 0,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
discount_amount: MoneyDTOHelper.format(
|
||||||
|
invoiceItem.discount_amount,
|
||||||
|
this._locale,
|
||||||
|
moneyOptions
|
||||||
|
),
|
||||||
|
taxable_amount: MoneyDTOHelper.format(invoiceItem.taxable_amount, this._locale, moneyOptions),
|
||||||
|
taxes_amount: MoneyDTOHelper.format(invoiceItem.taxes_amount, this._locale, moneyOptions),
|
||||||
|
total_amount: MoneyDTOHelper.format(invoiceItem.total_amount, this._locale, moneyOptions),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import { type JsonTaxCatalogProvider, SpainTaxCatalogProvider } from "@erp/core";
|
import { type JsonTaxCatalogProvider, MoneyDTOHelper, SpainTaxCatalogProvider } from "@erp/core";
|
||||||
import { type IPresenterOutputParams, Presenter } from "@erp/core/api";
|
import { type IPresenterOutputParams, Presenter } from "@erp/core/api";
|
||||||
import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common";
|
import type { GetIssueInvoiceByIdResponseDTO } from "@erp/customer-invoices/common";
|
||||||
import type { ArrayElement } from "@repo/rdx-utils";
|
import type { ArrayElement } from "@repo/rdx-utils";
|
||||||
|
|
||||||
import { type FormatMoneyOptions, formatMoneyDTO } from "../../helpers";
|
|
||||||
|
|
||||||
type CustomerInvoiceTaxesDTO = GetIssueInvoiceByIdResponseDTO["taxes"];
|
type CustomerInvoiceTaxesDTO = GetIssueInvoiceByIdResponseDTO["taxes"];
|
||||||
type CustomerInvoiceTaxDTO = ArrayElement<CustomerInvoiceTaxesDTO>;
|
type CustomerInvoiceTaxDTO = ArrayElement<CustomerInvoiceTaxesDTO>;
|
||||||
|
|
||||||
@ -16,10 +14,9 @@ export class CustomerInvoiceTaxesReportPresenter extends Presenter<
|
|||||||
private _taxCatalog!: JsonTaxCatalogProvider;
|
private _taxCatalog!: JsonTaxCatalogProvider;
|
||||||
|
|
||||||
private _mapTax(taxItem: CustomerInvoiceTaxDTO) {
|
private _mapTax(taxItem: CustomerInvoiceTaxDTO) {
|
||||||
const moneyOptions: FormatMoneyOptions = {
|
const moneyOptions = {
|
||||||
locale: this._locale,
|
|
||||||
hideZeros: true,
|
hideZeros: true,
|
||||||
newScale: 2,
|
minimumFractionDigits: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
const taxCatalogItem = this._taxCatalog.findByCode(taxItem.tax_code);
|
const taxCatalogItem = this._taxCatalog.findByCode(taxItem.tax_code);
|
||||||
@ -27,8 +24,8 @@ export class CustomerInvoiceTaxesReportPresenter extends Presenter<
|
|||||||
return {
|
return {
|
||||||
tax_code: taxItem.tax_code,
|
tax_code: taxItem.tax_code,
|
||||||
tax_name: taxCatalogItem.unwrap().name,
|
tax_name: taxCatalogItem.unwrap().name,
|
||||||
taxable_amount: formatMoneyDTO(taxItem.taxable_amount, moneyOptions),
|
taxable_amount: MoneyDTOHelper.format(taxItem.taxable_amount, this._locale, moneyOptions),
|
||||||
taxes_amount: formatMoneyDTO(taxItem.taxes_amount, moneyOptions),
|
taxes_amount: MoneyDTOHelper.format(taxItem.taxes_amount, this._locale, moneyOptions),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,18 +1,22 @@
|
|||||||
|
import { DateHelper, MoneyDTOHelper, PercentageDTOHelper } from "@erp/core";
|
||||||
import { Presenter } from "@erp/core/api";
|
import { Presenter } from "@erp/core/api";
|
||||||
|
|
||||||
import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto";
|
import type { GetIssueInvoiceByIdResponseDTO } from "../../../../common/dto";
|
||||||
import {
|
|
||||||
type FormatMoneyOptions,
|
|
||||||
formatDateDTO,
|
|
||||||
formatMoneyDTO,
|
|
||||||
formatPercentageDTO,
|
|
||||||
} from "../../helpers";
|
|
||||||
import { formatPaymentMethodDTO } from "../../helpers/format-payment_method-dto";
|
|
||||||
|
|
||||||
export class CustomerInvoiceReportPresenter extends Presenter<
|
export class CustomerInvoiceReportPresenter extends Presenter<
|
||||||
GetIssueInvoiceByIdResponseDTO,
|
GetIssueInvoiceByIdResponseDTO,
|
||||||
unknown
|
unknown
|
||||||
> {
|
> {
|
||||||
|
private _formatPaymentMethodDTO(
|
||||||
|
paymentMethod?: GetIssueInvoiceByIdResponseDTO["payment_method"]
|
||||||
|
) {
|
||||||
|
if (!paymentMethod) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return paymentMethod.payment_description ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
toOutput(invoiceDTO: GetIssueInvoiceByIdResponseDTO) {
|
toOutput(invoiceDTO: GetIssueInvoiceByIdResponseDTO) {
|
||||||
const itemsPresenter = this.presenterRegistry.getPresenter({
|
const itemsPresenter = this.presenterRegistry.getPresenter({
|
||||||
resource: "customer-invoice-items",
|
resource: "customer-invoice-items",
|
||||||
@ -35,10 +39,9 @@ export class CustomerInvoiceReportPresenter extends Presenter<
|
|||||||
locale,
|
locale,
|
||||||
});
|
});
|
||||||
|
|
||||||
const moneyOptions: FormatMoneyOptions = {
|
const moneyOptions = {
|
||||||
locale,
|
|
||||||
hideZeros: true,
|
hideZeros: true,
|
||||||
newScale: 2,
|
minimumFractionDigits: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -46,15 +49,15 @@ export class CustomerInvoiceReportPresenter extends Presenter<
|
|||||||
taxes: taxesDTO,
|
taxes: taxesDTO,
|
||||||
items: itemsDTO,
|
items: itemsDTO,
|
||||||
|
|
||||||
invoice_date: formatDateDTO(invoiceDTO.invoice_date),
|
invoice_date: DateHelper.format(invoiceDTO.invoice_date, locale),
|
||||||
subtotal_amount: formatMoneyDTO(invoiceDTO.subtotal_amount, moneyOptions),
|
subtotal_amount: MoneyDTOHelper.format(invoiceDTO.subtotal_amount, locale, moneyOptions),
|
||||||
discount_percentage: formatPercentageDTO(invoiceDTO.discount_percentage, locale),
|
discount_percentage: PercentageDTOHelper.format(invoiceDTO.discount_percentage, locale),
|
||||||
discount_amount: formatMoneyDTO(invoiceDTO.discount_amount, moneyOptions),
|
discount_amount: MoneyDTOHelper.format(invoiceDTO.discount_amount, locale, moneyOptions),
|
||||||
taxable_amount: formatMoneyDTO(invoiceDTO.taxable_amount, moneyOptions),
|
taxable_amount: MoneyDTOHelper.format(invoiceDTO.taxable_amount, locale, moneyOptions),
|
||||||
taxes_amount: formatMoneyDTO(invoiceDTO.taxes_amount, moneyOptions),
|
taxes_amount: MoneyDTOHelper.format(invoiceDTO.taxes_amount, locale, moneyOptions),
|
||||||
total_amount: formatMoneyDTO(invoiceDTO.total_amount, moneyOptions),
|
total_amount: MoneyDTOHelper.format(invoiceDTO.total_amount, locale, moneyOptions),
|
||||||
|
|
||||||
payment_method: formatPaymentMethodDTO(invoiceDTO.payment_method),
|
payment_method: this._formatPaymentMethodDTO(invoiceDTO.payment_method),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -55,8 +55,9 @@
|
|||||||
|
|
||||||
table th,
|
table th,
|
||||||
table td {
|
table td {
|
||||||
border-top: 1px solid;
|
border-top: 0px solid;
|
||||||
border-left: 1px solid;
|
border-left: 1px solid #000;
|
||||||
|
border-right: 1px solid #000;
|
||||||
border-bottom: 0px solid;
|
border-bottom: 0px solid;
|
||||||
padding: 3px 10px;
|
padding: 3px 10px;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
@ -65,6 +66,11 @@
|
|||||||
|
|
||||||
table th {
|
table th {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
border-top: 1px solid #000;
|
||||||
|
border-bottom: 1px solid #000;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #e7e0df;
|
||||||
|
color: #ff0014;
|
||||||
}
|
}
|
||||||
|
|
||||||
.totals {
|
.totals {
|
||||||
@ -157,12 +163,12 @@
|
|||||||
<!-- Tu tabla -->
|
<!-- Tu tabla -->
|
||||||
<table class="table-header">
|
<table class="table-header">
|
||||||
<thead>
|
<thead>
|
||||||
<tr class="text-left bg-gray-200 text-red-500">
|
<tr>
|
||||||
<th class="py-2">Concepto</th>
|
<th class="py-2">Concepto</th>
|
||||||
<th class="py-2">Cantidad</th>
|
<th class="py-2">Ud.</th>
|
||||||
<th class="py-2">Precio unidad</th>
|
<th class="py-2">Imp.</th>
|
||||||
<th class="py-2">Dto</th>
|
<th class="py-2"> </th>
|
||||||
<th class="py-2">Importe total</th>
|
<th class="py-2">Imp. total</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
@ -172,6 +178,7 @@
|
|||||||
<td>{{description}}</td>
|
<td>{{description}}</td>
|
||||||
<td class="text-right">{{#if quantity}}{{quantity}}{{else}} {{/if}}</td>
|
<td class="text-right">{{#if quantity}}{{quantity}}{{else}} {{/if}}</td>
|
||||||
<td class="text-right">{{#if unit_amount}}{{unit_amount}}{{else}} {{/if}}</td>
|
<td class="text-right">{{#if unit_amount}}{{unit_amount}}{{else}} {{/if}}</td>
|
||||||
|
<td class="text-right">{{#if discount_percentage}}{{discount_percentage}}{{else}} {{/if}}</td>
|
||||||
<td class="text-right">{{#if taxable_amount}}{{taxable_amount}}{{else}} {{/if}}</td>
|
<td class="text-right">{{#if taxable_amount}}{{taxable_amount}}{{else}} {{/if}}</td>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
@ -7,7 +7,9 @@ const InvoicesLayout = lazy(() =>
|
|||||||
import("./components").then((m) => ({ default: m.InvoicesLayout }))
|
import("./components").then((m) => ({ default: m.InvoicesLayout }))
|
||||||
);
|
);
|
||||||
|
|
||||||
const InvoiceListPage = lazy(() => import("./pages").then((m) => ({ default: m.InvoiceListPage })));
|
const ProformaListPage = lazy(() =>
|
||||||
|
import("./pages").then((m) => ({ default: m.InvoiceListPage }))
|
||||||
|
);
|
||||||
|
|
||||||
const CustomerInvoiceAdd = lazy(() =>
|
const CustomerInvoiceAdd = lazy(() =>
|
||||||
import("./pages").then((m) => ({ default: m.CustomerInvoiceCreate }))
|
import("./pages").then((m) => ({ default: m.CustomerInvoiceCreate }))
|
||||||
@ -26,8 +28,8 @@ export const CustomerInvoiceRoutes = (params: ModuleClientParams): RouteObject[]
|
|||||||
</InvoicesLayout>
|
</InvoicesLayout>
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
{ path: "", index: true, element: <ProformasListPage /> }, // index
|
{ path: "", index: true, element: <ProformaListPage /> }, // index
|
||||||
{ path: "list", element: <ProformasListPage /> },
|
{ path: "list", element: <ProformaListPage /> },
|
||||||
{ path: "create", element: <CustomerInvoiceAdd /> },
|
{ path: "create", element: <CustomerInvoiceAdd /> },
|
||||||
{ path: ":id/edit", element: <InvoiceUpdatePage /> },
|
{ path: ":id/edit", element: <InvoiceUpdatePage /> },
|
||||||
],
|
],
|
||||||
@ -40,9 +42,8 @@ export const CustomerInvoiceRoutes = (params: ModuleClientParams): RouteObject[]
|
|||||||
</InvoicesLayout>
|
</InvoicesLayout>
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
{ path: "", index: true, element: <InvoiceListPage /> }, // index
|
//{ path: "", index: true, element: <InvoiceListPage /> }, // index
|
||||||
{ path: "list", element: <InvoiceListPage /> },
|
//{ path: "list", element: <InvoiceListPage /> },
|
||||||
|
|
||||||
//
|
//
|
||||||
/*{ path: "create", element: <CustomerInvoicesList /> },
|
/*{ path: "create", element: <CustomerInvoicesList /> },
|
||||||
{ path: ":id", element: <CustomerInvoicesList /> },
|
{ path: ":id", element: <CustomerInvoicesList /> },
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
export * from "../proformas";
|
||||||
|
|
||||||
export * from "./create";
|
export * from "./create";
|
||||||
export * from "./list";
|
export * from "./list";
|
||||||
export * from "./update";
|
export * from "./update";
|
||||||
|
|||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./use-proformas-query";
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
import { useDataSource } from "@erp/core/hooks";
|
||||||
|
import { type DefaultError, type QueryKey, useQuery } from "@tanstack/react-query";
|
||||||
|
|
||||||
|
export const CUSTOMER_INVOICE_QUERY_KEY = (id: string): QueryKey =>
|
||||||
|
["customer_invoice", id] as const;
|
||||||
|
|
||||||
|
type InvoiceQueryOptions = {
|
||||||
|
enabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useInvoiceQuery = (invoiceId?: string, options?: InvoiceQueryOptions) => {
|
||||||
|
const dataSource = useDataSource();
|
||||||
|
const enabled = (options?.enabled ?? true) && !!invoiceId;
|
||||||
|
|
||||||
|
return useQuery<CustomerInvoice, DefaultError>({
|
||||||
|
queryKey: CUSTOMER_INVOICE_QUERY_KEY(invoiceId ?? "unknown"),
|
||||||
|
queryFn: async (context) => {
|
||||||
|
const { signal } = context;
|
||||||
|
if (!invoiceId) {
|
||||||
|
if (!invoiceId) throw new Error("invoiceId is required");
|
||||||
|
}
|
||||||
|
return await dataSource.getOne<CustomerInvoice>("customer-invoices", invoiceId, {
|
||||||
|
signal,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enabled,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
export function useQuery<
|
||||||
|
TQueryFnData = unknown,
|
||||||
|
TError = unknown,
|
||||||
|
TData = TQueryFnData,
|
||||||
|
TQueryKey extends QueryKey = QueryKey
|
||||||
|
>
|
||||||
|
|
||||||
|
TQueryFnData: the type returned from the queryFn.
|
||||||
|
TError: the type of Errors to expect from the queryFn.
|
||||||
|
TData: the type our data property will eventually have.
|
||||||
|
Only relevant if you use the select option,
|
||||||
|
because then the data property can be different
|
||||||
|
from what the queryFn returns.
|
||||||
|
Otherwise, it will default to whatever the queryFn returns.
|
||||||
|
TQueryKey: the type of our queryKey, only relevant
|
||||||
|
if you use the queryKey that is passed to your queryFn.
|
||||||
|
|
||||||
|
*/
|
||||||
2
modules/customer-invoices/src/web/proformas/index.ts
Normal file
2
modules/customer-invoices/src/web/proformas/index.ts
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
export * from "./hooks";
|
||||||
|
export * from "./pages";
|
||||||
@ -0,0 +1 @@
|
|||||||
|
export * from "./list";
|
||||||
@ -5,10 +5,10 @@ import { Button } from "@repo/shadcn-ui/components";
|
|||||||
import { PlusIcon } from "lucide-react";
|
import { PlusIcon } from "lucide-react";
|
||||||
import { useMemo, useState } from "react";
|
import { useMemo, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useInvoicesQuery } from "../../hooks";
|
|
||||||
import { useTranslation } from "../../i18n";
|
import { useInvoicesQuery } from "../../../hooks";
|
||||||
import { invoiceResumeDtoToFormAdapter } from "../../schemas/invoice-resume-dto.adapter";
|
import { useTranslation } from "../../../i18n";
|
||||||
import { InvoicesListGrid } from "./invoices-list-grid";
|
import { invoiceResumeDtoToFormAdapter } from "../../../schemas";
|
||||||
|
|
||||||
export const ProformaListPage = () => {
|
export const ProformaListPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -61,8 +61,8 @@ export const ProformaListPage = () => {
|
|||||||
return (
|
return (
|
||||||
<AppContent>
|
<AppContent>
|
||||||
<ErrorAlert
|
<ErrorAlert
|
||||||
title={t("pages.list.loadErrorTitle")}
|
|
||||||
message={(error as Error)?.message || "Error al cargar el listado"}
|
message={(error as Error)?.message || "Error al cargar el listado"}
|
||||||
|
title={t("pages.list.loadErrorTitle")}
|
||||||
/>
|
/>
|
||||||
<BackHistoryButton />
|
<BackHistoryButton />
|
||||||
</AppContent>
|
</AppContent>
|
||||||
@ -73,35 +73,35 @@ export const ProformaListPage = () => {
|
|||||||
<>
|
<>
|
||||||
<AppHeader>
|
<AppHeader>
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={t("pages.list.title")}
|
|
||||||
description={t("pages.list.description")}
|
description={t("pages.list.description")}
|
||||||
rightSlot={
|
rightSlot={
|
||||||
<div className='flex items-center space-x-2'>
|
<div className="flex items-center space-x-2">
|
||||||
<Button
|
<Button
|
||||||
|
aria-label={t("pages.create.title")}
|
||||||
|
className="cursor-pointer"
|
||||||
onClick={() => navigate("/customer-invoices/create")}
|
onClick={() => navigate("/customer-invoices/create")}
|
||||||
variant={"default"}
|
variant={"default"}
|
||||||
aria-label={t("pages.create.title")}
|
|
||||||
className='cursor-pointer'
|
|
||||||
>
|
>
|
||||||
<PlusIcon className='mr-2 h-4 w-4' aria-hidden />
|
<PlusIcon aria-hidden className="mr-2 h-4 w-4" />
|
||||||
{t("pages.create.title")}
|
{t("pages.create.title")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
title={t("pages.list.title")}
|
||||||
/>
|
/>
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
<AppContent>
|
<AppContent>
|
||||||
<div className='flex flex-col w-full h-full py-3'>
|
<div className="flex flex-col w-full h-full py-3">
|
||||||
<div className={"flex-1"}>
|
<div className={"flex-1"}>
|
||||||
<InvoicesListGrid
|
<ProformasGrid
|
||||||
invoicesPage={invoicesPageData}
|
data={invoicesPageData}
|
||||||
loading={isLoading}
|
loading={isLoading}
|
||||||
pageIndex={pageIndex}
|
|
||||||
pageSize={pageSize}
|
|
||||||
onPageChange={handlePageChange}
|
onPageChange={handlePageChange}
|
||||||
onPageSizeChange={handlePageSizeChange}
|
onPageSizeChange={handlePageSizeChange}
|
||||||
searchValue={search}
|
|
||||||
onSearchChange={handleSearchChange}
|
onSearchChange={handleSearchChange}
|
||||||
|
pageIndex={pageIndex}
|
||||||
|
pageSize={pageSize}
|
||||||
|
searchValue={search}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { MoneyDTOHelper, PercentageDTOHelper, formatCurrency } from "@erp/core";
|
import { MoneyDTOHelper, PercentageDTOHelper, formatCurrency } from "@erp/core";
|
||||||
import { InvoiceSummaryFormData } from "./invoice-resume.form.schema";
|
|
||||||
import { CustomerInvoiceSummary } from "./invoices.api.schema";
|
import type { InvoiceSummaryFormData } from "./invoice-resume.form.schema";
|
||||||
|
import type { CustomerInvoiceSummary } from "./invoices.api.schema";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convierte el DTO completo de API a datos numéricos para el formulario.
|
* Convierte el DTO completo de API a datos numéricos para el formulario.
|
||||||
|
|||||||
@ -28,6 +28,6 @@
|
|||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"noUncheckedSideEffectImports": true
|
"noUncheckedSideEffectImports": true
|
||||||
},
|
},
|
||||||
"include": ["src"],
|
"include": ["src", "../core/src/common/helpers/date-helper.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,8 +98,6 @@ export class Percentage extends ValueObject<PercentageProps> {
|
|||||||
|
|
||||||
return this.toNumber().toLocaleString(locale, {
|
return this.toNumber().toLocaleString(locale, {
|
||||||
style: "percent",
|
style: "percent",
|
||||||
minimumFractionDigits: scale,
|
|
||||||
maximumSignificantDigits: scale,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user