v0.6.6
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
parent
9961383a9f
commit
4f331ceb14
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-server",
|
"name": "@erp/factuges-server",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "tsup src/index.ts --config tsup.config.ts",
|
"build": "tsup src/index.ts --config tsup.config.ts",
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges-web",
|
"name": "@erp/factuges-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --host --clearScreen false",
|
"dev": "vite --host --clearScreen false",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/auth",
|
"name": "@erp/auth",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/core",
|
"name": "@erp/core",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -118,7 +118,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retenc. 35%",
|
"name": "Retenc. 35%",
|
||||||
"code": "retencion_35",
|
"code": "retention_35",
|
||||||
"value": "3500",
|
"value": "3500",
|
||||||
"scale": "2",
|
"scale": "2",
|
||||||
"group": "retention",
|
"group": "retention",
|
||||||
@ -127,7 +127,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retenc. 19%",
|
"name": "Retenc. 19%",
|
||||||
"code": "retencion_19",
|
"code": "retention_19",
|
||||||
"value": "1900",
|
"value": "1900",
|
||||||
"scale": "2",
|
"scale": "2",
|
||||||
"group": "retention",
|
"group": "retention",
|
||||||
@ -136,7 +136,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retenc. 15%",
|
"name": "Retenc. 15%",
|
||||||
"code": "retencion_15",
|
"code": "retention_15",
|
||||||
"value": "1500",
|
"value": "1500",
|
||||||
"scale": "2",
|
"scale": "2",
|
||||||
"group": "retention",
|
"group": "retention",
|
||||||
@ -145,7 +145,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retenc. 7%",
|
"name": "Retenc. 7%",
|
||||||
"code": "retencion_7",
|
"code": "retention_7",
|
||||||
"value": "700",
|
"value": "700",
|
||||||
"scale": "2",
|
"scale": "2",
|
||||||
"group": "retention",
|
"group": "retention",
|
||||||
@ -154,7 +154,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Retenc. 2%",
|
"name": "Retenc. 2%",
|
||||||
"code": "retencion_2",
|
"code": "retention_2",
|
||||||
"value": "200",
|
"value": "200",
|
||||||
"scale": "2",
|
"scale": "2",
|
||||||
"group": "retention",
|
"group": "retention",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customer-invoices",
|
"name": "@erp/customer-invoices",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -188,7 +188,8 @@ export class UpdateProformaInputMapper implements IUpdateProformaInputMapper {
|
|||||||
|
|
||||||
return Result.ok(proformaPatchProps);
|
return Result.ok(proformaPatchProps);
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
return Result.fail(new DomainError("Proforma props mapping failed", { cause: err }));
|
console.error(err);
|
||||||
|
return Result.fail(new DomainError("Proforma props mapping failed (update)", { cause: err }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,8 +24,7 @@ import { prepareIssueProformaTarget } from "../../../issue-proforma/utils";
|
|||||||
import type { ProformaListRow } from "../../../shared";
|
import type { ProformaListRow } from "../../../shared";
|
||||||
import { useListProformasPageController } from "../../controllers";
|
import { useListProformasPageController } from "../../controllers";
|
||||||
import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks";
|
import { ProformaSummaryPanel, ProformasGrid, useProformasGridColumns } from "../blocks";
|
||||||
|
import { ProformaStatusBadge } from "../components";
|
||||||
import { OrdersTable } from "./orders-table";
|
|
||||||
|
|
||||||
export const ListProformasPage = () => {
|
export const ListProformasPage = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -86,7 +85,30 @@ export const ListProformasPage = () => {
|
|||||||
pageSize={listCtrl.pageSize}
|
pageSize={listCtrl.pageSize}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<OrdersTable />
|
{/* Explicación técnica */}
|
||||||
|
<div className="mt-8 rounded border border-border bg-card p-3 sm:p-4 text-xs sm:text-sm text-muted-foreground space-y-2">
|
||||||
|
<p className="font-semibold text-foreground">Estado de proforma</p>
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>
|
||||||
|
<ProformaStatusBadge status="draft" />
|
||||||
|
<strong className="text-foreground">Borrador:</strong> Un{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">div</code> absoluto con{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">pointer-events: none</code> y{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">linear-gradient</code> se superpone
|
||||||
|
encima del scroll.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-foreground">Columna sticky:</strong> La celda de acciones usa{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">sticky right-0 z-20</code>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong className="text-foreground">Responsive:</strong> Columnas ocultas en móviles (
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">hidden sm:</code>,{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">hidden md:</code>,{" "}
|
||||||
|
<code className="rounded bg-muted px-1 text-xs">hidden lg:</code>).
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -43,7 +43,7 @@ export const GetProformaByIdAdapter = {
|
|||||||
recipient: mapRecipient(dto),
|
recipient: mapRecipient(dto),
|
||||||
taxes: dto.taxes.map(mapTaxSummary),
|
taxes: dto.taxes.map(mapTaxSummary),
|
||||||
|
|
||||||
paymentMethod: dto.payment_method?.id,
|
paymentMethodId: dto.payment_method?.id ?? null,
|
||||||
|
|
||||||
subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount),
|
subtotalAmount: MoneyDTOHelper.toNumber(dto.subtotal_amount),
|
||||||
|
|
||||||
@ -85,24 +85,20 @@ const mapItem = (dto: GetProformaByIdResponseDTO["items"][number]): ProformaItem
|
|||||||
|
|
||||||
taxableAmount: MoneyDTOHelper.toNumber(dto.taxable_amount),
|
taxableAmount: MoneyDTOHelper.toNumber(dto.taxable_amount),
|
||||||
|
|
||||||
ivaCode: dto.iva_code,
|
taxCode: dto.iva_code,
|
||||||
ivaPercentage: PercentageDTOHelper.toNumber(dto.iva_percentage),
|
taxPercentage: PercentageDTOHelper.toNumericNulleable(dto.iva_percentage),
|
||||||
ivaAmount: MoneyDTOHelper.toNumber(dto.iva_amount),
|
taxAmount: MoneyDTOHelper.toNumber(dto.iva_amount),
|
||||||
|
|
||||||
recCode: dto.rec_code,
|
recCode: dto.rec_code,
|
||||||
recPercentage: PercentageDTOHelper.toNumber(dto.rec_percentage),
|
recPercentage: PercentageDTOHelper.toNumericNulleable(dto.rec_percentage),
|
||||||
recAmount: MoneyDTOHelper.toNumber(dto.rec_amount),
|
recAmount: MoneyDTOHelper.toNumber(dto.rec_amount),
|
||||||
|
|
||||||
retentionCode: dto.retention_code,
|
retentionCode: dto.retention_code,
|
||||||
retentionPercentage: PercentageDTOHelper.toNumber(dto.retention_percentage),
|
retentionPercentage: PercentageDTOHelper.toNumericNulleable(dto.retention_percentage),
|
||||||
retentionAmount: MoneyDTOHelper.toNumber(dto.retention_amount),
|
retentionAmount: MoneyDTOHelper.toNumber(dto.retention_amount),
|
||||||
|
|
||||||
taxesAmount: MoneyDTOHelper.toNumber(dto.taxes_amount),
|
taxesAmount: MoneyDTOHelper.toNumber(dto.taxes_amount),
|
||||||
totalAmount: MoneyDTOHelper.toNumber(dto.total_amount),
|
totalAmount: MoneyDTOHelper.toNumber(dto.total_amount),
|
||||||
|
|
||||||
// Nota: el DTO de detalle actual no incluye `taxes` por línea.
|
|
||||||
// Dejamos fallback explícito para no inventar parseos.
|
|
||||||
taxes: "",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return item;
|
return item;
|
||||||
|
|||||||
@ -1,3 +1,2 @@
|
|||||||
export * from "./payment-method-options.constants";
|
export * from "./payment-method-options.constants";
|
||||||
export * from "./retentions-options.constants";
|
export * from "./proforma-fiscal-options.constants";
|
||||||
export * from "./taxes-options.constants";
|
|
||||||
|
|||||||
@ -0,0 +1,90 @@
|
|||||||
|
export type ProformaTaxPercentageOption = 21 | 10 | 4 | 0;
|
||||||
|
export type ProformaRecPercentageOption = 5.2 | 1.4 | 0.5 | 0;
|
||||||
|
export type ProformaRetentionPercentageOption = 15 | 7;
|
||||||
|
|
||||||
|
export interface ProformaSelectOption<TValue extends string = string> {
|
||||||
|
value: TValue;
|
||||||
|
label: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProformaTaxDefinition {
|
||||||
|
taxCode: string;
|
||||||
|
taxPercentage: ProformaTaxPercentageOption;
|
||||||
|
taxLabel: string;
|
||||||
|
recCode: string;
|
||||||
|
recPercentage: ProformaRecPercentageOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ProformaRetentionDefinition {
|
||||||
|
retentionCode: string;
|
||||||
|
retentionPercentage: ProformaRetentionPercentageOption;
|
||||||
|
retentionLabel: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const PROFORMA_TAX_DEFINITIONS: Record<ProformaTaxPercentageOption, ProformaTaxDefinition> =
|
||||||
|
{
|
||||||
|
21: {
|
||||||
|
taxCode: "iva_21",
|
||||||
|
taxPercentage: 21,
|
||||||
|
taxLabel: "General",
|
||||||
|
recCode: "rec_5_2",
|
||||||
|
recPercentage: 5.2,
|
||||||
|
},
|
||||||
|
10: {
|
||||||
|
taxCode: "iva_10",
|
||||||
|
taxPercentage: 10,
|
||||||
|
taxLabel: "Reducido",
|
||||||
|
recCode: "rec_1_4",
|
||||||
|
recPercentage: 1.4,
|
||||||
|
},
|
||||||
|
4: {
|
||||||
|
taxCode: "iva_4",
|
||||||
|
taxPercentage: 4,
|
||||||
|
taxLabel: "Superreducido",
|
||||||
|
recCode: "rec_0_5",
|
||||||
|
recPercentage: 0.5,
|
||||||
|
},
|
||||||
|
0: {
|
||||||
|
taxCode: "iva_0",
|
||||||
|
taxPercentage: 0,
|
||||||
|
taxLabel: "Exento",
|
||||||
|
recCode: "rec_0",
|
||||||
|
recPercentage: 0,
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const PROFORMA_RETENTION_DEFINITIONS: Record<
|
||||||
|
ProformaRetentionPercentageOption,
|
||||||
|
ProformaRetentionDefinition
|
||||||
|
> = {
|
||||||
|
15: {
|
||||||
|
retentionCode: "retention_15",
|
||||||
|
retentionPercentage: 15,
|
||||||
|
retentionLabel: "General",
|
||||||
|
},
|
||||||
|
7: {
|
||||||
|
retentionCode: "retention_7",
|
||||||
|
retentionPercentage: 7,
|
||||||
|
retentionLabel: "Inicio actividad",
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const PROFORMA_TAX_OPTIONS: ProformaSelectOption<`${ProformaTaxPercentageOption}`>[] = [
|
||||||
|
{ value: "0", label: "0%" },
|
||||||
|
{ value: "4", label: "4%" },
|
||||||
|
{ value: "10", label: "10%" },
|
||||||
|
{ value: "21", label: "21%" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROFORMA_REC_OPTIONS: ProformaSelectOption<`${ProformaRecPercentageOption}`>[] = [
|
||||||
|
{ value: "0", label: "0%" },
|
||||||
|
{ value: "0.5", label: "0,5%" },
|
||||||
|
{ value: "1.4", label: "1,4%" },
|
||||||
|
{ value: "5.2", label: "5,2%" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const PROFORMA_RETENTION_OPTIONS: ProformaSelectOption<`${ProformaRetentionPercentageOption}`>[] =
|
||||||
|
[
|
||||||
|
{ value: "15", label: "15%" },
|
||||||
|
{ value: "7", label: "7%" },
|
||||||
|
];
|
||||||
@ -1,25 +0,0 @@
|
|||||||
export type RetentionPercentageOption = 15 | 7;
|
|
||||||
|
|
||||||
export interface ProformaRetentionsDefinition {
|
|
||||||
retentionPercentage: RetentionPercentageOption;
|
|
||||||
retentionLabel: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PROFORMA_RETENTION_DEFINITIONS: Record<
|
|
||||||
RetentionPercentageOption,
|
|
||||||
ProformaRetentionsDefinition
|
|
||||||
> = {
|
|
||||||
15: {
|
|
||||||
retentionPercentage: 15,
|
|
||||||
retentionLabel: "General",
|
|
||||||
},
|
|
||||||
7: {
|
|
||||||
retentionPercentage: 7,
|
|
||||||
retentionLabel: "Reducido",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const PROFORMA_RETENTION_OPTIONS = [
|
|
||||||
{ value: "15", label: "15%" },
|
|
||||||
{ value: "7", label: "7%" },
|
|
||||||
];
|
|
||||||
@ -1,37 +0,0 @@
|
|||||||
export type TaxPercentageOption = 21 | 10 | 4 | 0;
|
|
||||||
|
|
||||||
export interface ProformaTaxesDefinition {
|
|
||||||
taxPercentage: TaxPercentageOption;
|
|
||||||
taxLabel: string;
|
|
||||||
recPercentage: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const PROFORMA_TAX_DEFINITIONS: Record<TaxPercentageOption, ProformaTaxesDefinition> = {
|
|
||||||
21: {
|
|
||||||
taxPercentage: 21,
|
|
||||||
taxLabel: "General",
|
|
||||||
recPercentage: 5.2,
|
|
||||||
},
|
|
||||||
10: {
|
|
||||||
taxPercentage: 10,
|
|
||||||
taxLabel: "Reducido",
|
|
||||||
recPercentage: 1.4,
|
|
||||||
},
|
|
||||||
4: {
|
|
||||||
taxPercentage: 4,
|
|
||||||
taxLabel: "Superreducido",
|
|
||||||
recPercentage: 0.5,
|
|
||||||
},
|
|
||||||
0: {
|
|
||||||
taxPercentage: 0,
|
|
||||||
taxLabel: "Exento",
|
|
||||||
recPercentage: 0,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const PROFORMA_TAX_OPTIONS = [
|
|
||||||
{ value: "0", label: "0%" },
|
|
||||||
{ value: "4", label: "4%" },
|
|
||||||
{ value: "10", label: "10%" },
|
|
||||||
{ value: "21", label: "21%" },
|
|
||||||
];
|
|
||||||
@ -24,21 +24,19 @@ export interface ProformaItem {
|
|||||||
|
|
||||||
taxableAmount: number;
|
taxableAmount: number;
|
||||||
|
|
||||||
ivaCode: string;
|
taxCode: string | null;
|
||||||
ivaPercentage: number;
|
taxPercentage: number | null;
|
||||||
ivaAmount: number;
|
taxAmount: number;
|
||||||
|
|
||||||
recCode: string | null;
|
recCode: string | null;
|
||||||
recPercentage: number;
|
recPercentage: number | null;
|
||||||
recAmount: number;
|
recAmount: number;
|
||||||
|
|
||||||
retentionCode: string | null;
|
retentionCode: string | null;
|
||||||
retentionPercentage: number;
|
retentionPercentage: number | null;
|
||||||
retentionAmount: number;
|
retentionAmount: number;
|
||||||
|
|
||||||
taxesAmount: number;
|
taxesAmount: number;
|
||||||
|
|
||||||
totalAmount: number;
|
totalAmount: number;
|
||||||
|
|
||||||
taxes: string;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,8 +7,8 @@
|
|||||||
export interface ProformaTaxSummary {
|
export interface ProformaTaxSummary {
|
||||||
taxableAmount: number;
|
taxableAmount: number;
|
||||||
|
|
||||||
ivaCode: string;
|
ivaCode: string | null;
|
||||||
ivaPercentage: number;
|
ivaPercentage: number | null;
|
||||||
ivaAmount: number;
|
ivaAmount: number;
|
||||||
|
|
||||||
recCode: string | null;
|
recCode: string | null;
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export interface Proforma {
|
|||||||
|
|
||||||
taxes: ProformaTaxSummary[];
|
taxes: ProformaTaxSummary[];
|
||||||
|
|
||||||
paymentMethod?: string;
|
paymentMethodId: string | null;
|
||||||
|
|
||||||
subtotalAmount: number;
|
subtotalAmount: number;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
import { PROFORMA_TAX_DEFINITIONS, type TaxPercentageOption } from "../constants";
|
|
||||||
|
|
||||||
export const getProformaRecPercentage = (taxPercentage: TaxPercentageOption): number => {
|
|
||||||
return PROFORMA_TAX_DEFINITIONS[taxPercentage].recPercentage;
|
|
||||||
};
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
import { PROFORMA_RETENTION_OPTIONS } from "../constants";
|
|
||||||
|
|
||||||
export const getProformaRetentionOptions = () => PROFORMA_RETENTION_OPTIONS;
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
import { PROFORMA_TAX_OPTIONS } from "../constants";
|
|
||||||
|
|
||||||
export const getProformaTaxOptions = () => PROFORMA_TAX_OPTIONS;
|
|
||||||
@ -1,3 +1 @@
|
|||||||
export * from "./get-proforma-rec-percentage";
|
export * from "./proforma-fiscal-options.utils";
|
||||||
export * from "./get-proforma-retention-options";
|
|
||||||
export * from "./get-proforma-tax-options";
|
|
||||||
|
|||||||
@ -0,0 +1,96 @@
|
|||||||
|
import { PercentageHelper, isNullishOrEmpty } from "@repo/rdx-utils";
|
||||||
|
|
||||||
|
import {
|
||||||
|
PROFORMA_REC_OPTIONS,
|
||||||
|
PROFORMA_RETENTION_DEFINITIONS,
|
||||||
|
PROFORMA_RETENTION_OPTIONS,
|
||||||
|
PROFORMA_TAX_DEFINITIONS,
|
||||||
|
PROFORMA_TAX_OPTIONS,
|
||||||
|
type ProformaRecPercentageOption,
|
||||||
|
type ProformaRetentionPercentageOption,
|
||||||
|
type ProformaTaxPercentageOption,
|
||||||
|
} from "../constants";
|
||||||
|
|
||||||
|
export const parseProformaTaxPercentage = (
|
||||||
|
value: number | string | null | undefined
|
||||||
|
): ProformaTaxPercentageOption | null => {
|
||||||
|
if (isNullishOrEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numericValue = Number(value);
|
||||||
|
const normalizedValue = PercentageHelper.normalizePercentage(numericValue);
|
||||||
|
|
||||||
|
if (normalizedValue in PROFORMA_TAX_DEFINITIONS) {
|
||||||
|
return normalizedValue as ProformaTaxPercentageOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const parseProformaRetentionPercentage = (
|
||||||
|
value: number | string | null | undefined
|
||||||
|
): ProformaRetentionPercentageOption | null => {
|
||||||
|
if (isNullishOrEmpty(value)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numericValue = Number(value);
|
||||||
|
const normalizedValue = PercentageHelper.normalizePercentage(numericValue);
|
||||||
|
|
||||||
|
if (normalizedValue in PROFORMA_RETENTION_DEFINITIONS) {
|
||||||
|
return normalizedValue as ProformaRetentionPercentageOption;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProformaTaxCode = (
|
||||||
|
taxPercentage: number | string | null | undefined
|
||||||
|
): string | null => {
|
||||||
|
const parsedTaxPercentage = parseProformaTaxPercentage(taxPercentage);
|
||||||
|
|
||||||
|
if (parsedTaxPercentage === null) return null;
|
||||||
|
|
||||||
|
return PROFORMA_TAX_DEFINITIONS[parsedTaxPercentage].taxCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProformaRecPercentage = (
|
||||||
|
taxPercentage: ProformaTaxPercentageOption | null | undefined
|
||||||
|
): ProformaRecPercentageOption | null => {
|
||||||
|
if (taxPercentage === null || taxPercentage === undefined) return null;
|
||||||
|
|
||||||
|
return PROFORMA_TAX_DEFINITIONS[taxPercentage].recPercentage;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProformaRecCode = (
|
||||||
|
recPercentage: number | string | null | undefined
|
||||||
|
): string | null => {
|
||||||
|
if (recPercentage === null || recPercentage === undefined || recPercentage === "") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const numericValue = Number(recPercentage);
|
||||||
|
|
||||||
|
const definition = Object.values(PROFORMA_TAX_DEFINITIONS).find(
|
||||||
|
(taxDefinition) => taxDefinition.recPercentage === numericValue
|
||||||
|
);
|
||||||
|
|
||||||
|
return definition?.recCode ?? null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProformaRetentionCode = (
|
||||||
|
retentionPercentage: number | string | null | undefined
|
||||||
|
): string | null => {
|
||||||
|
const parsedRetentionPercentage = parseProformaRetentionPercentage(retentionPercentage);
|
||||||
|
|
||||||
|
if (parsedRetentionPercentage === null) return null;
|
||||||
|
|
||||||
|
return PROFORMA_RETENTION_DEFINITIONS[parsedRetentionPercentage].retentionCode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProformaTaxOptions = () => PROFORMA_TAX_OPTIONS;
|
||||||
|
|
||||||
|
export const getProformaRecOptions = () => PROFORMA_REC_OPTIONS;
|
||||||
|
|
||||||
|
export const getProformaRetentionOptions = () => PROFORMA_RETENTION_OPTIONS;
|
||||||
@ -23,7 +23,7 @@ export const mapProformaItemsToProformaItemsUpdateForm = (
|
|||||||
|
|
||||||
itemDiscountPercentage: item.itemDiscountPercentage ?? null,
|
itemDiscountPercentage: item.itemDiscountPercentage ?? null,
|
||||||
|
|
||||||
taxPercentage: item.ivaPercentage ?? null,
|
taxPercentage: item.taxPercentage ?? null,
|
||||||
recPercentage: item.recPercentage ?? null,
|
recPercentage: item.recPercentage ?? null,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,34 +1,24 @@
|
|||||||
import { PercentageHelper } from "@repo/rdx-utils";
|
import type { Proforma } from "../../shared";
|
||||||
|
|
||||||
import type { Proforma, ProformaItem } from "../../shared";
|
|
||||||
import type { ProformaTaxMode, ProformaUpdateForm } from "../entities";
|
import type { ProformaTaxMode, ProformaUpdateForm } from "../entities";
|
||||||
import { buildProformaUpdateDefault } from "../utils";
|
import { buildProformaUpdateDefault } from "../utils";
|
||||||
|
|
||||||
import { mapProformaItemsToProformaItemsUpdateForm } from "./map-proforma-items-to-proforma-items-update-form.adapter";
|
import { mapProformaItemsToProformaItemsUpdateForm } from "./map-proforma-items-to-proforma-items-update-form.adapter";
|
||||||
|
|
||||||
|
interface FiscalDefaults {
|
||||||
|
taxMode: ProformaTaxMode;
|
||||||
|
|
||||||
|
defaultTaxPercentage: number | null;
|
||||||
|
defaultRecPercentage: number | null;
|
||||||
|
defaultRetentionPercentage: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapea una proforma a un formulario de actualización de proforma.
|
* Mapea una proforma a un formulario de actualización de proforma.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpdateForm => {
|
export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpdateForm => {
|
||||||
const proformaDefaults = buildProformaUpdateDefault();
|
const proformaDefaults = buildProformaUpdateDefault();
|
||||||
|
const fiscalDefaults = resolveFiscalDefaults(proforma, proformaDefaults);
|
||||||
const taxMode = inferProformaTaxMode(proforma.items);
|
|
||||||
|
|
||||||
const defaultTaxSummary = proforma.taxes[0];
|
|
||||||
const firstTaxableItem = getFirstTaxableItem(proforma.items);
|
|
||||||
|
|
||||||
const defaultTaxPercentage =
|
|
||||||
defaultTaxSummary?.ivaPercentage ??
|
|
||||||
firstTaxableItem?.ivaPercentage ??
|
|
||||||
proformaDefaults.defaultTaxPercentage;
|
|
||||||
|
|
||||||
const defaultRecPercentage =
|
|
||||||
defaultTaxSummary?.recPercentage ?? firstTaxableItem?.recPercentage ?? null;
|
|
||||||
|
|
||||||
const defaultRetentionPercentage =
|
|
||||||
defaultTaxSummary?.retentionPercentage ?? firstTaxableItem?.retentionPercentage ?? null;
|
|
||||||
|
|
||||||
console.log({ defaultTaxPercentage, defaultRecPercentage, defaultRetentionPercentage, taxMode });
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
series: proforma.series ?? proformaDefaults.series,
|
series: proforma.series ?? proformaDefaults.series,
|
||||||
@ -48,55 +38,56 @@ export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpd
|
|||||||
globalDiscountPercentage:
|
globalDiscountPercentage:
|
||||||
proforma.globalDiscountPercentage ?? proformaDefaults.globalDiscountPercentage,
|
proforma.globalDiscountPercentage ?? proformaDefaults.globalDiscountPercentage,
|
||||||
|
|
||||||
taxMode,
|
taxMode: fiscalDefaults.taxMode,
|
||||||
taxRegimeCode: proformaDefaults.taxRegimeCode,
|
taxRegimeCode: "01", //taxRegimeCode: proforma.taxRegimeCode ?? proformaDefaults.taxRegimeCode, // TODO: implementar en API
|
||||||
|
|
||||||
hasTaxPercentage: PercentageHelper.hasPositivePercentage(defaultTaxPercentage),
|
hasTaxPercentage: fiscalDefaults.defaultTaxPercentage !== null,
|
||||||
defaultTaxPercentage: defaultTaxPercentage,
|
taxPercentage: fiscalDefaults.defaultTaxPercentage,
|
||||||
|
|
||||||
hasRecPercentage: PercentageHelper.hasPositivePercentage(defaultRecPercentage),
|
hasRecPercentage: fiscalDefaults.defaultRecPercentage !== null,
|
||||||
defaultRecPercentage: defaultRecPercentage,
|
recPercentage: fiscalDefaults.defaultRecPercentage,
|
||||||
|
|
||||||
hasRetentionPercentage: PercentageHelper.hasPositivePercentage(defaultRetentionPercentage),
|
hasRetentionPercentage: fiscalDefaults.defaultRetentionPercentage !== null,
|
||||||
defaultRetentionPercentage: defaultRetentionPercentage,
|
retentionPercentage: fiscalDefaults.defaultRetentionPercentage,
|
||||||
|
|
||||||
paymentMethodId: proforma.paymentMethod ?? proformaDefaults.paymentMethodId,
|
paymentMethodId: proforma.paymentMethodId ?? proformaDefaults.paymentMethodId,
|
||||||
|
|
||||||
items: proforma.items.map(mapProformaItemsToProformaItemsUpdateForm),
|
items: proforma.items.map(mapProformaItemsToProformaItemsUpdateForm),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFirstTaxableItem = (items: ProformaItem[]): ProformaItem | undefined => {
|
const resolveFiscalDefaults = (
|
||||||
return items.find((item) => item.isValued) ?? items[0];
|
proforma: Proforma,
|
||||||
};
|
proformaDefaults: ProformaUpdateForm
|
||||||
|
): FiscalDefaults => {
|
||||||
|
// Caso habitual: una sola combinación de impuestos
|
||||||
|
if (proforma.taxes.length === 1) {
|
||||||
|
const taxSummary = proforma.taxes[0];
|
||||||
|
|
||||||
const inferProformaTaxMode = (items: ProformaItem[]): ProformaTaxMode => {
|
return {
|
||||||
const comparableItems = items.filter((item) => item.isValued);
|
taxMode: "single",
|
||||||
|
defaultTaxPercentage: taxSummary.ivaCode === null ? null : taxSummary.ivaPercentage,
|
||||||
if (comparableItems.length === 0) {
|
defaultRecPercentage: taxSummary.recCode === null ? null : taxSummary.recPercentage,
|
||||||
return "single";
|
defaultRetentionPercentage:
|
||||||
|
taxSummary.retentionCode === null ? null : taxSummary.retentionPercentage,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const sourceItems = comparableItems;
|
// Caso excepcional: proforma sin impuestos
|
||||||
|
if (proforma.taxes.length === 0) {
|
||||||
|
return {
|
||||||
|
taxMode: "single",
|
||||||
|
defaultTaxPercentage: proformaDefaults.taxPercentage,
|
||||||
|
defaultRecPercentage: proformaDefaults.recPercentage,
|
||||||
|
defaultRetentionPercentage: proformaDefaults.retentionPercentage,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const ivaPercentages = uniquePercentageValues(sourceItems.map((item) => item.ivaPercentage));
|
// Proforma con varias combinaciones de impuestos
|
||||||
const recPercentages = uniquePercentageValues(sourceItems.map((item) => item.recPercentage));
|
return {
|
||||||
const retentionPercentages = uniquePercentageValues(
|
taxMode: "perLine",
|
||||||
sourceItems.map((item) => item.retentionPercentage)
|
defaultTaxPercentage: proformaDefaults.taxPercentage,
|
||||||
);
|
defaultRecPercentage: proformaDefaults.recPercentage,
|
||||||
|
defaultRetentionPercentage: proformaDefaults.retentionPercentage,
|
||||||
const hasSingleTaxSetup =
|
};
|
||||||
ivaPercentages.length <= 1 && recPercentages.length <= 1 && retentionPercentages.length <= 1;
|
|
||||||
|
|
||||||
return hasSingleTaxSetup ? "single" : "perLine";
|
|
||||||
};
|
|
||||||
|
|
||||||
const uniquePercentageValues = (values: Array<number | null | undefined>): number[] => {
|
|
||||||
return Array.from(
|
|
||||||
new Set(
|
|
||||||
values
|
|
||||||
.filter((value): value is number => value !== null && value !== undefined)
|
|
||||||
.map((value) => PercentageHelper.normalizePercentage(value))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@ -156,12 +156,8 @@ export const useUpdateProformaController = (
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("Parche de actualización construido:", patchData);
|
|
||||||
|
|
||||||
const params = buildUpdateProformaByIdParams(proformaId, patchData, formData);
|
const params = buildUpdateProformaByIdParams(proformaId, patchData, formData);
|
||||||
|
|
||||||
console.log("Enviando actualización con params:", params);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Enviamos cambios al servidor
|
// Enviamos cambios al servidor
|
||||||
const updated = await mutateAsync(params);
|
const updated = await mutateAsync(params);
|
||||||
@ -224,7 +220,7 @@ export const useUpdateProformaController = (
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
(errors: FieldErrors<ProformaUpdateForm>) => {
|
(errors: FieldErrors<ProformaUpdateForm>) => {
|
||||||
console.log(errors);
|
console.error(errors);
|
||||||
focusFirstInputFormError(form);
|
focusFirstInputFormError(form);
|
||||||
|
|
||||||
showWarningToast(
|
showWarningToast(
|
||||||
|
|||||||
@ -2,8 +2,8 @@ import { useCallback, useEffect, useRef } from "react";
|
|||||||
import { type UseFormReturn, useWatch } from "react-hook-form";
|
import { type UseFormReturn, useWatch } from "react-hook-form";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
type RetentionPercentageOption,
|
type ProformaRetentionPercentageOption,
|
||||||
type TaxPercentageOption,
|
type ProformaTaxPercentageOption,
|
||||||
getProformaRecPercentage,
|
getProformaRecPercentage,
|
||||||
} from "../../shared";
|
} from "../../shared";
|
||||||
import type { ProformaTaxMode, ProformaUpdateForm } from "../entities";
|
import type { ProformaTaxMode, ProformaUpdateForm } from "../entities";
|
||||||
@ -16,13 +16,13 @@ export interface UseUpdateProformaTaxControllerResult {
|
|||||||
taxMode: ProformaTaxMode;
|
taxMode: ProformaTaxMode;
|
||||||
|
|
||||||
hasTaxPercentage: boolean;
|
hasTaxPercentage: boolean;
|
||||||
defaultTaxPercentage: number | null;
|
taxPercentage: number | null;
|
||||||
|
|
||||||
hasRecPercentage: boolean;
|
hasRecPercentage: boolean;
|
||||||
defaultRecPercentage: number | null;
|
recPercentage: number | null;
|
||||||
|
|
||||||
hasRetentionPercentage: boolean;
|
hasRetentionPercentage: boolean;
|
||||||
defaultRetentionPercentage: number | null;
|
retentionPercentage: number | null;
|
||||||
|
|
||||||
usesSingleTax: boolean;
|
usesSingleTax: boolean;
|
||||||
usesPerLineTax: boolean;
|
usesPerLineTax: boolean;
|
||||||
@ -30,20 +30,20 @@ export interface UseUpdateProformaTaxControllerResult {
|
|||||||
enablePerLineTaxes: () => void;
|
enablePerLineTaxes: () => void;
|
||||||
disablePerLineTaxes: () => void;
|
disablePerLineTaxes: () => void;
|
||||||
|
|
||||||
updateDefaultTaxPercentage: (newTaxPercentage: RetentionPercentageOption) => void;
|
updateTaxPercentage: (newTaxPercentage: ProformaTaxPercentageOption) => void;
|
||||||
updateDefaultRecPercentage: (enabled: boolean) => void;
|
updateRecPercentage: (enabled: boolean) => void;
|
||||||
updateDefaultRetentionPercentage: (enabled: boolean) => void;
|
updateRetentionPercentage: (newRetentionPercentage: ProformaRetentionPercentageOption) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolveRecPercentage = (
|
const resolveRecPercentage = (
|
||||||
enabled: boolean,
|
enabled: boolean,
|
||||||
taxPercentage: RetentionPercentageOption | null
|
taxPercentage: ProformaTaxPercentageOption | null
|
||||||
): number | null => {
|
): number | null => {
|
||||||
if (!enabled || taxPercentage === null) {
|
if (!enabled || taxPercentage === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return getProformaRecPercentage(taxPercentage as TaxPercentageOption);
|
return getProformaRecPercentage(taxPercentage as ProformaTaxPercentageOption);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUpdateProformaTaxController = ({
|
export const useUpdateProformaTaxController = ({
|
||||||
@ -54,14 +54,13 @@ export const useUpdateProformaTaxController = ({
|
|||||||
const taxMode = useWatch({ control, name: "taxMode" });
|
const taxMode = useWatch({ control, name: "taxMode" });
|
||||||
|
|
||||||
const hasTaxPercentage = useWatch({ control, name: "hasTaxPercentage" }) ?? false;
|
const hasTaxPercentage = useWatch({ control, name: "hasTaxPercentage" }) ?? false;
|
||||||
const defaultTaxPercentage = useWatch({ control, name: "defaultTaxPercentage" }) ?? null;
|
const taxPercentage = useWatch({ control, name: "taxPercentage" }) ?? null;
|
||||||
|
|
||||||
const hasRecPercentage = useWatch({ control, name: "hasRecPercentage" }) ?? false;
|
const hasRecPercentage = useWatch({ control, name: "hasRecPercentage" }) ?? false;
|
||||||
const defaultRecPercentage = useWatch({ control, name: "defaultRecPercentage" }) ?? null;
|
const recPercentage = useWatch({ control, name: "recPercentage" }) ?? null;
|
||||||
|
|
||||||
const hasRetentionPercentage = useWatch({ control, name: "hasRetentionPercentage" }) ?? false;
|
const hasRetentionPercentage = useWatch({ control, name: "hasRetentionPercentage" }) ?? false;
|
||||||
const defaultRetentionPercentage =
|
const retentionPercentage = useWatch({ control, name: "retentionPercentage" }) ?? null;
|
||||||
useWatch({ control, name: "defaultRetentionPercentage" }) ?? null;
|
|
||||||
|
|
||||||
const hasMountedRef = useRef(false);
|
const hasMountedRef = useRef(false);
|
||||||
|
|
||||||
@ -72,14 +71,14 @@ export const useUpdateProformaTaxController = ({
|
|||||||
|
|
||||||
const nextRecPercentage = resolveRecPercentage(
|
const nextRecPercentage = resolveRecPercentage(
|
||||||
hasRecPercentage,
|
hasRecPercentage,
|
||||||
defaultTaxPercentage as RetentionPercentageOption | null
|
taxPercentage as ProformaTaxPercentageOption | null
|
||||||
);
|
);
|
||||||
|
|
||||||
const shouldMarkDirty = hasMountedRef.current;
|
const shouldMarkDirty = hasMountedRef.current;
|
||||||
|
|
||||||
currentItems.forEach((item, index) => {
|
currentItems.forEach((item, index) => {
|
||||||
if (item.taxPercentage !== defaultTaxPercentage) {
|
if (item.taxPercentage !== taxPercentage) {
|
||||||
setValue(`items.${index}.taxPercentage`, defaultTaxPercentage, {
|
setValue(`items.${index}.taxPercentage`, taxPercentage, {
|
||||||
shouldDirty: shouldMarkDirty,
|
shouldDirty: shouldMarkDirty,
|
||||||
shouldTouch: false,
|
shouldTouch: false,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
@ -96,7 +95,7 @@ export const useUpdateProformaTaxController = ({
|
|||||||
});
|
});
|
||||||
|
|
||||||
hasMountedRef.current = true;
|
hasMountedRef.current = true;
|
||||||
}, [defaultTaxPercentage, getValues, hasRecPercentage, setValue, taxMode]);
|
}, [taxPercentage, getValues, hasRecPercentage, setValue, taxMode]);
|
||||||
|
|
||||||
const enablePerLineTaxes = useCallback(() => {
|
const enablePerLineTaxes = useCallback(() => {
|
||||||
setValue("taxMode", "perLine", {
|
setValue("taxMode", "perLine", {
|
||||||
@ -114,20 +113,25 @@ export const useUpdateProformaTaxController = ({
|
|||||||
});
|
});
|
||||||
}, [setValue]);
|
}, [setValue]);
|
||||||
|
|
||||||
const updateDefaultTaxPercentage = useCallback(
|
const updateTaxPercentage = useCallback(
|
||||||
(newTaxPercentage: RetentionPercentageOption): void => {
|
(newTaxPercentage: ProformaTaxPercentageOption): void => {
|
||||||
setValue("defaultTaxPercentage", newTaxPercentage, {
|
setValue("taxPercentage", newTaxPercentage, {
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldTouch: true,
|
shouldTouch: true,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setValue("hasTaxPercentage", true, {
|
||||||
|
shouldDirty: true,
|
||||||
|
shouldValidate: true,
|
||||||
|
});
|
||||||
|
|
||||||
const isRecPercentageEnabled = getValues("hasRecPercentage");
|
const isRecPercentageEnabled = getValues("hasRecPercentage");
|
||||||
|
|
||||||
if (isRecPercentageEnabled) {
|
if (isRecPercentageEnabled) {
|
||||||
setValue(
|
setValue(
|
||||||
"defaultRecPercentage",
|
"recPercentage",
|
||||||
getProformaRecPercentage(newTaxPercentage as TaxPercentageOption),
|
getProformaRecPercentage(newTaxPercentage as ProformaTaxPercentageOption),
|
||||||
{
|
{
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
@ -138,7 +142,7 @@ export const useUpdateProformaTaxController = ({
|
|||||||
[getValues, setValue]
|
[getValues, setValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateDefaultRecPercentage = useCallback(
|
const updateRecPercentage = useCallback(
|
||||||
(enabled: boolean): void => {
|
(enabled: boolean): void => {
|
||||||
setValue("hasRecPercentage", enabled, {
|
setValue("hasRecPercentage", enabled, {
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
@ -146,9 +150,9 @@ export const useUpdateProformaTaxController = ({
|
|||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const taxPercentage = getValues("defaultTaxPercentage") as RetentionPercentageOption | null;
|
const taxPercentage = getValues("taxPercentage") as ProformaTaxPercentageOption | null;
|
||||||
|
|
||||||
setValue("defaultRecPercentage", resolveRecPercentage(enabled, taxPercentage), {
|
setValue("recPercentage", resolveRecPercentage(enabled, taxPercentage), {
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
});
|
});
|
||||||
@ -156,13 +160,18 @@ export const useUpdateProformaTaxController = ({
|
|||||||
[getValues, setValue]
|
[getValues, setValue]
|
||||||
);
|
);
|
||||||
|
|
||||||
const updateDefaultRetentionPercentage = useCallback(
|
const updateRetentionPercentage = useCallback(
|
||||||
(enabled: boolean): void => {
|
(newRetentionPercentage: ProformaRetentionPercentageOption): void => {
|
||||||
setValue("hasRetentionPercentage", enabled, {
|
setValue("retentionPercentage", newRetentionPercentage, {
|
||||||
shouldDirty: true,
|
shouldDirty: true,
|
||||||
shouldTouch: true,
|
shouldTouch: true,
|
||||||
shouldValidate: true,
|
shouldValidate: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
setValue("hasRetentionPercentage", true, {
|
||||||
|
shouldDirty: true,
|
||||||
|
shouldValidate: true,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
[setValue]
|
[setValue]
|
||||||
);
|
);
|
||||||
@ -171,13 +180,13 @@ export const useUpdateProformaTaxController = ({
|
|||||||
taxMode,
|
taxMode,
|
||||||
|
|
||||||
hasTaxPercentage,
|
hasTaxPercentage,
|
||||||
defaultTaxPercentage,
|
taxPercentage,
|
||||||
|
|
||||||
hasRecPercentage,
|
hasRecPercentage,
|
||||||
defaultRecPercentage,
|
recPercentage,
|
||||||
|
|
||||||
hasRetentionPercentage,
|
hasRetentionPercentage,
|
||||||
defaultRetentionPercentage,
|
retentionPercentage,
|
||||||
|
|
||||||
usesSingleTax: taxMode === "single",
|
usesSingleTax: taxMode === "single",
|
||||||
usesPerLineTax: taxMode === "perLine",
|
usesPerLineTax: taxMode === "perLine",
|
||||||
@ -185,8 +194,8 @@ export const useUpdateProformaTaxController = ({
|
|||||||
enablePerLineTaxes,
|
enablePerLineTaxes,
|
||||||
disablePerLineTaxes,
|
disablePerLineTaxes,
|
||||||
|
|
||||||
updateDefaultTaxPercentage,
|
updateTaxPercentage,
|
||||||
updateDefaultRecPercentage,
|
updateRecPercentage,
|
||||||
updateDefaultRetentionPercentage,
|
updateRetentionPercentage,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@ -21,7 +21,7 @@ export const useUpdateProformaTotalsController = ({
|
|||||||
const items = useWatch({ control, name: "items" });
|
const items = useWatch({ control, name: "items" });
|
||||||
|
|
||||||
const hasRetentionPercentage = useWatch({ control, name: "hasRetentionPercentage" });
|
const hasRetentionPercentage = useWatch({ control, name: "hasRetentionPercentage" });
|
||||||
const retentionPercentage = useWatch({ control, name: "defaultRetentionPercentage" });
|
const retentionPercentage = useWatch({ control, name: "retentionPercentage" });
|
||||||
|
|
||||||
const totals = useMemo(() => {
|
const totals = useMemo(() => {
|
||||||
return calculateProformaTotals({
|
return calculateProformaTotals({
|
||||||
|
|||||||
@ -5,4 +5,3 @@ export * from "./proforma-item-update-patch.entity";
|
|||||||
export * from "./proforma-update-form.entity";
|
export * from "./proforma-update-form.entity";
|
||||||
export * from "./proforma-update-form.schema";
|
export * from "./proforma-update-form.schema";
|
||||||
export * from "./proforma-update-patch.entity";
|
export * from "./proforma-update-patch.entity";
|
||||||
export * from "./proforma-update-totals.entity";
|
|
||||||
|
|||||||
@ -38,13 +38,13 @@ export interface ProformaUpdateForm {
|
|||||||
taxRegimeCode: string | null;
|
taxRegimeCode: string | null;
|
||||||
|
|
||||||
hasTaxPercentage: boolean;
|
hasTaxPercentage: boolean;
|
||||||
defaultTaxPercentage: number | null;
|
taxPercentage: number | null;
|
||||||
|
|
||||||
hasRecPercentage: boolean;
|
hasRecPercentage: boolean;
|
||||||
defaultRecPercentage: number | null;
|
recPercentage: number | null;
|
||||||
|
|
||||||
hasRetentionPercentage: boolean;
|
hasRetentionPercentage: boolean;
|
||||||
defaultRetentionPercentage: number | null;
|
retentionPercentage: number | null;
|
||||||
|
|
||||||
paymentMethodId: string | null;
|
paymentMethodId: string | null;
|
||||||
|
|
||||||
|
|||||||
@ -39,13 +39,13 @@ export const ProformaUpdateFormSchema = z
|
|||||||
taxRegimeCode: z.string(),
|
taxRegimeCode: z.string(),
|
||||||
|
|
||||||
hasTaxPercentage: z.boolean(),
|
hasTaxPercentage: z.boolean(),
|
||||||
defaultTaxPercentage: z.number().nullable(),
|
taxPercentage: z.number().nullable(),
|
||||||
|
|
||||||
hasRecPercentage: z.boolean(),
|
hasRecPercentage: z.boolean(),
|
||||||
defaultRecPercentage: z.number().nullable(),
|
recPercentage: z.number().nullable(),
|
||||||
|
|
||||||
hasRetentionPercentage: z.boolean(),
|
hasRetentionPercentage: z.boolean(),
|
||||||
defaultRetentionPercentage: z.number().nullable(),
|
retentionPercentage: z.number().nullable(),
|
||||||
|
|
||||||
paymentMethodId: z.string().nullable(),
|
paymentMethodId: z.string().nullable(),
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ export const ProformaUpdateFormSchema = z
|
|||||||
(formValues) => {
|
(formValues) => {
|
||||||
if (
|
if (
|
||||||
formValues.hasRetentionPercentage &&
|
formValues.hasRetentionPercentage &&
|
||||||
!PercentageHelper.hasPositivePercentage(formValues.defaultRetentionPercentage)
|
!PercentageHelper.hasPositivePercentage(formValues.retentionPercentage)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,13 +29,13 @@ export type ProformaUpdatePatch = {
|
|||||||
taxRegimeCode?: string | null;
|
taxRegimeCode?: string | null;
|
||||||
|
|
||||||
hasTaxPercentage?: boolean;
|
hasTaxPercentage?: boolean;
|
||||||
defaultTaxPercentage?: number | null;
|
taxPercentage?: number | null;
|
||||||
|
|
||||||
hasRecPercentage?: boolean;
|
hasRecPercentage?: boolean;
|
||||||
defaultRecPercentage?: number | null;
|
recPercentage?: number | null;
|
||||||
|
|
||||||
hasRetentionPercentage?: boolean;
|
hasRetentionPercentage?: boolean;
|
||||||
defaultRetentionPercentage?: number | null;
|
retentionPercentage?: number | null;
|
||||||
|
|
||||||
paymentMethodId?: string | null;
|
paymentMethodId?: string | null;
|
||||||
|
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
import type { ProformaHeaderTotals } from "./proforma-calculation.entity";
|
|
||||||
|
|
||||||
export interface ProformaTaxBreakdownLine {
|
|
||||||
taxableBase: number;
|
|
||||||
ivaPercentage: number;
|
|
||||||
ivaAmount: number;
|
|
||||||
recPercentage: number | null;
|
|
||||||
recAmount: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ProformaTotals extends ProformaHeaderTotals {
|
|
||||||
recPercentage: number | null;
|
|
||||||
recAmount: number;
|
|
||||||
|
|
||||||
retentionPercentage: number | null;
|
|
||||||
retentionAmount: number;
|
|
||||||
}
|
|
||||||
@ -113,8 +113,8 @@ export const ProformaLineEditor = ({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "itemDiscountPercentage",
|
id: "itemDiscountPercentage",
|
||||||
header: t("form_fields.items.discount_percentage.label", "% Dto"),
|
header: t("form_fields.items.discount_percentage.label", "Dto (%)"),
|
||||||
headClassName: "w-[100px] text-right",
|
headClassName: "w-[100px] text-left",
|
||||||
cell: ({ index }) => (
|
cell: ({ index }) => (
|
||||||
<PercentageField
|
<PercentageField
|
||||||
inputClassName="border-none"
|
inputClassName="border-none"
|
||||||
@ -129,8 +129,8 @@ export const ProformaLineEditor = ({
|
|||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
id: "taxPercentage",
|
id: "taxPercentage",
|
||||||
header: t("form_fields.items.tax_percentage.label", "IVA"),
|
header: t("form_fields.items.tax_percentage.label", "IVA (%)"),
|
||||||
headClassName: "w-[110px] text-right",
|
headClassName: "w-[110px] text-left",
|
||||||
cell: ({ index }) => (
|
cell: ({ index }) => (
|
||||||
<SelectField
|
<SelectField
|
||||||
deserialize={(value) => (value === null || value === "" ? null : Number(value))}
|
deserialize={(value) => (value === null || value === "" ? null : Number(value))}
|
||||||
|
|||||||
@ -15,7 +15,6 @@ import type {
|
|||||||
} from "../../controllers";
|
} from "../../controllers";
|
||||||
import { ProformaTotalsSummary } from "../blocks";
|
import { ProformaTotalsSummary } from "../blocks";
|
||||||
|
|
||||||
import { ProformaTaxesCard } from "./proforma-taxes-card";
|
|
||||||
import { ProformaUpdateHeaderEditor } from "./proforma-update-header-editor";
|
import { ProformaUpdateHeaderEditor } from "./proforma-update-header-editor";
|
||||||
import { ProformaUpdateItemsEditor } from "./proforma-update-items-editor";
|
import { ProformaUpdateItemsEditor } from "./proforma-update-items-editor";
|
||||||
import { ProformaUpdateTaxEditor } from "./proforma-update-tax-editor";
|
import { ProformaUpdateTaxEditor } from "./proforma-update-tax-editor";
|
||||||
@ -95,10 +94,6 @@ export const ProformaUpdateEditorForm = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-1">
|
|
||||||
<ProformaTaxesCard />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col-reverse gap-3 border-t pt-4 sm:flex-row sm:justify-end">
|
<div className="flex flex-col-reverse gap-3 border-t pt-4 sm:flex-row sm:justify-end">
|
||||||
<Button disabled={isSubmitting} onClick={onReset} type="button" variant="outline">
|
<Button disabled={isSubmitting} onClick={onReset} type="button" variant="outline">
|
||||||
{t("common.reset", "Restablecer")}
|
{t("common.reset", "Restablecer")}
|
||||||
|
|||||||
@ -23,7 +23,12 @@ import { cn } from "@repo/shadcn-ui/lib/utils";
|
|||||||
import { ReceiptTextIcon } from "lucide-react";
|
import { ReceiptTextIcon } from "lucide-react";
|
||||||
|
|
||||||
import { useTranslation } from "../../../../i18n";
|
import { useTranslation } from "../../../../i18n";
|
||||||
import { getProformaRetentionOptions, getProformaTaxOptions } from "../../../shared";
|
import {
|
||||||
|
getProformaRetentionOptions,
|
||||||
|
getProformaTaxOptions,
|
||||||
|
parseProformaRetentionPercentage,
|
||||||
|
parseProformaTaxPercentage,
|
||||||
|
} from "../../../shared";
|
||||||
import type { UseUpdateProformaTaxControllerResult } from "../../controllers";
|
import type { UseUpdateProformaTaxControllerResult } from "../../controllers";
|
||||||
|
|
||||||
interface ProformaUpdateTaxEditorProps {
|
interface ProformaUpdateTaxEditorProps {
|
||||||
@ -167,7 +172,13 @@ export const ProformaUpdateTaxEditor = ({
|
|||||||
inputClassName="bg-background"
|
inputClassName="bg-background"
|
||||||
items={getProformaTaxOptions()}
|
items={getProformaTaxOptions()}
|
||||||
label={t("form_fields.proformas.default_tax_percentage.label", "IVA por defecto")}
|
label={t("form_fields.proformas.default_tax_percentage.label", "IVA por defecto")}
|
||||||
name="defaultTaxPercentage"
|
name="taxPercentage"
|
||||||
|
onChange={(value) => {
|
||||||
|
const parsed = parseProformaTaxPercentage(value as number | null);
|
||||||
|
if (parsed !== null) {
|
||||||
|
taxCtrl.updateTaxPercentage(parsed);
|
||||||
|
}
|
||||||
|
}}
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"form_fields.proformas.default_tax_percentage.placeholder",
|
"form_fields.proformas.default_tax_percentage.placeholder",
|
||||||
"Selecciona IVA"
|
"Selecciona IVA"
|
||||||
@ -198,13 +209,13 @@ export const ProformaUpdateTaxEditor = ({
|
|||||||
|
|
||||||
{taxCtrl.hasRecPercentage ? (
|
{taxCtrl.hasRecPercentage ? (
|
||||||
<span className="text-sm text-muted-foreground">
|
<span className="text-sm text-muted-foreground">
|
||||||
{PercentageHelper.formatPercent(taxCtrl.defaultRecPercentage ?? 0)}
|
{PercentageHelper.formatPercent(taxCtrl.recPercentage ?? 0)}
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
name="hasRecPercentage"
|
name="hasRecPercentage"
|
||||||
onCheckedChange={taxCtrl.updateDefaultRecPercentage}
|
onCheckedChange={taxCtrl.updateRecPercentage}
|
||||||
readOnly={readOnly}
|
readOnly={readOnly}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
@ -223,7 +234,13 @@ export const ProformaUpdateTaxEditor = ({
|
|||||||
inputClassName="bg-background"
|
inputClassName="bg-background"
|
||||||
items={getProformaRetentionOptions()}
|
items={getProformaRetentionOptions()}
|
||||||
label={t("form_fields.proformas.retention_percentage.label", "Retención")}
|
label={t("form_fields.proformas.retention_percentage.label", "Retención")}
|
||||||
name="defaultRetentionPercentage"
|
name="retentionPercentage"
|
||||||
|
onChange={(value) => {
|
||||||
|
const parsed = parseProformaRetentionPercentage(value as number | null);
|
||||||
|
if (parsed !== null) {
|
||||||
|
taxCtrl.updateRetentionPercentage(parsed);
|
||||||
|
}
|
||||||
|
}}
|
||||||
placeholder={t(
|
placeholder={t(
|
||||||
"form_fields.proformas.default_tax_percentage.placeholder",
|
"form_fields.proformas.default_tax_percentage.placeholder",
|
||||||
"Selecciona IVA"
|
"Selecciona IVA"
|
||||||
|
|||||||
@ -22,13 +22,13 @@ export const buildProformaUpdateDefault = (): ProformaUpdateForm => {
|
|||||||
taxRegimeCode: "01",
|
taxRegimeCode: "01",
|
||||||
|
|
||||||
hasTaxPercentage: true,
|
hasTaxPercentage: true,
|
||||||
defaultTaxPercentage: 21,
|
taxPercentage: 21,
|
||||||
|
|
||||||
hasRecPercentage: false,
|
hasRecPercentage: false,
|
||||||
defaultRecPercentage: null,
|
recPercentage: null,
|
||||||
|
|
||||||
hasRetentionPercentage: false,
|
hasRetentionPercentage: false,
|
||||||
defaultRetentionPercentage: 15,
|
retentionPercentage: 15,
|
||||||
|
|
||||||
paymentMethodId: null,
|
paymentMethodId: null,
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,17 @@ import { MoneyDTOHelper, PercentageDTOHelper, QuantityDTOHelper } from "@erp/cor
|
|||||||
import { toNullable } from "@repo/rdx-ddd";
|
import { toNullable } from "@repo/rdx-ddd";
|
||||||
import { ObjectHelper } from "@repo/rdx-utils";
|
import { ObjectHelper } from "@repo/rdx-utils";
|
||||||
|
|
||||||
|
import { getProformaRecCode, getProformaRetentionCode, getProformaTaxCode } from "../../shared";
|
||||||
import type { UpdateProformaByIdParams } from "../../shared/api";
|
import type { UpdateProformaByIdParams } from "../../shared/api";
|
||||||
import type {
|
import type { ProformaItemUpdateForm, ProformaUpdateForm, ProformaUpdatePatch } from "../entities";
|
||||||
ProformaItemUpdateForm,
|
|
||||||
ProformaItemUpdatePatch,
|
interface ProformaItemUpdateDTOContext {
|
||||||
ProformaUpdateForm,
|
currencyCode: string;
|
||||||
ProformaUpdatePatch,
|
taxMode: ProformaUpdateForm["taxMode"];
|
||||||
} from "../entities";
|
ivaCode: string | null;
|
||||||
|
recCode: string | null;
|
||||||
|
retentionCode: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convierte el patch del formulario de actualización de proforma
|
* Convierte el patch del formulario de actualización de proforma
|
||||||
@ -85,9 +89,8 @@ export const buildUpdateProformaByIdParams = (
|
|||||||
|
|
||||||
// Si se han tocado los detalles, se envían todos
|
// Si se han tocado los detalles, se envían todos
|
||||||
if (shouldReplaceItems(patch)) {
|
if (shouldReplaceItems(patch)) {
|
||||||
data.items = formData.items.map((item, index) =>
|
const context = buildProformaItemUpdateDTOContext(formData);
|
||||||
toProformaItemUpdateDTO(item, index, formData)
|
data.items = formData.items.map((item, index) => toProformaItemUpdateDTO(item, index, context));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -97,41 +100,40 @@ export const buildUpdateProformaByIdParams = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const toProformaItemUpdateDTO = (
|
const toProformaItemUpdateDTO = (
|
||||||
item: ProformaItemUpdatePatch,
|
item: ProformaItemUpdateForm,
|
||||||
index: number,
|
index: number,
|
||||||
formData: ProformaUpdateForm
|
context: ProformaItemUpdateDTOContext
|
||||||
): NonNullable<UpdateProformaByIdParams["data"]["items"]>[number] => {
|
): NonNullable<UpdateProformaByIdParams["data"]["items"]>[number] => {
|
||||||
const currencyCode = formData.currencyCode;
|
|
||||||
|
|
||||||
const quantity =
|
|
||||||
item.quantity === null ? null : QuantityDTOHelper.fromNumberNulleable(item.quantity, 2);
|
|
||||||
|
|
||||||
const unit_amount =
|
|
||||||
item.unitAmount === null
|
|
||||||
? null
|
|
||||||
: MoneyDTOHelper.fromNumberNulleable(item.unitAmount, currencyCode, 4);
|
|
||||||
|
|
||||||
const ivaPercentage = resolveLineIvaPercentage(item, formData);
|
|
||||||
const recPercentage = resolveLineRecPercentage(item, formData);
|
|
||||||
const retentionPercentage = resolveLineRetentionPercentage(formData);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
position: index,
|
position: index,
|
||||||
|
|
||||||
description: item.description,
|
description: item.description,
|
||||||
|
|
||||||
quantity,
|
quantity: toNullable(item.quantity, (value) => QuantityDTOHelper.fromNumberNulleable(value, 2)),
|
||||||
unit_amount,
|
|
||||||
|
unit_amount: toNullable(item.unitAmount, (value) =>
|
||||||
|
MoneyDTOHelper.fromNumberNulleable(value, context.currencyCode, 4)
|
||||||
|
),
|
||||||
|
|
||||||
item_discount_percentage: toNullable(item.itemDiscountPercentage, (value) =>
|
item_discount_percentage: toNullable(item.itemDiscountPercentage, (value) =>
|
||||||
PercentageDTOHelper.fromNumber(value, 2)
|
PercentageDTOHelper.fromNumber(value, 2)
|
||||||
),
|
),
|
||||||
|
|
||||||
iva_percentage: toNullable(ivaPercentage, (value) => PercentageDTOHelper.fromNumber(value, 2)),
|
iva_code: resolveItemIvaCode(item, context),
|
||||||
rec_percentage: toNullable(recPercentage, (value) => PercentageDTOHelper.fromNumber(value, 2)),
|
rec_code: resolveItemRecCode(item, context),
|
||||||
retention_percentage: toNullable(retentionPercentage, (value) =>
|
retention_code: context.retentionCode,
|
||||||
PercentageDTOHelper.fromNumber(value, 2)
|
};
|
||||||
),
|
};
|
||||||
|
|
||||||
|
const buildProformaItemUpdateDTOContext = (
|
||||||
|
formData: ProformaUpdateForm
|
||||||
|
): ProformaItemUpdateDTOContext => {
|
||||||
|
return {
|
||||||
|
currencyCode: formData.currencyCode,
|
||||||
|
taxMode: formData.taxMode,
|
||||||
|
ivaCode: formData.taxMode === "single" ? resolveSingleIvaCode(formData) : null,
|
||||||
|
recCode: formData.taxMode === "single" ? resolveSingleRecCode(formData) : null,
|
||||||
|
retentionCode: resolveRetentionCode(formData),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -140,38 +142,56 @@ const shouldReplaceItems = (patch: ProformaUpdatePatch): boolean => {
|
|||||||
ObjectHelper.hasOwn(patch, "items") ||
|
ObjectHelper.hasOwn(patch, "items") ||
|
||||||
ObjectHelper.hasOwn(patch, "taxMode") ||
|
ObjectHelper.hasOwn(patch, "taxMode") ||
|
||||||
ObjectHelper.hasOwn(patch, "hasTaxPercentage") ||
|
ObjectHelper.hasOwn(patch, "hasTaxPercentage") ||
|
||||||
ObjectHelper.hasOwn(patch, "defaultTaxPercentage") ||
|
ObjectHelper.hasOwn(patch, "taxPercentage") ||
|
||||||
ObjectHelper.hasOwn(patch, "hasRecPercentage") ||
|
ObjectHelper.hasOwn(patch, "hasRecPercentage") ||
|
||||||
ObjectHelper.hasOwn(patch, "defaultRecPercentage")
|
ObjectHelper.hasOwn(patch, "recPercentage") ||
|
||||||
|
ObjectHelper.hasOwn(patch, "hasRetentionPercentage") ||
|
||||||
|
ObjectHelper.hasOwn(patch, "retentionPercentage")
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveLineIvaPercentage = (
|
const resolveSingleIvaCode = (formData: ProformaUpdateForm): string | null => {
|
||||||
item: ProformaItemUpdateForm,
|
if (!formData.hasTaxPercentage) {
|
||||||
formData: ProformaUpdateForm
|
return null;
|
||||||
): number | null => {
|
|
||||||
if (formData.taxMode === "single") {
|
|
||||||
return formData.hasTaxPercentage ? formData.defaultTaxPercentage : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.taxPercentage;
|
return getProformaTaxCode(formData.taxPercentage);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveLineRecPercentage = (
|
const resolveSingleRecCode = (formData: ProformaUpdateForm): string | null => {
|
||||||
item: ProformaItemUpdateForm,
|
if (!formData.hasRecPercentage) {
|
||||||
formData: ProformaUpdateForm
|
return null;
|
||||||
): number | null => {
|
|
||||||
if (formData.taxMode === "single") {
|
|
||||||
return formData.hasRecPercentage ? formData.defaultRecPercentage : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.recPercentage;
|
return getProformaRecCode(formData.recPercentage);
|
||||||
};
|
};
|
||||||
|
|
||||||
const resolveLineRetentionPercentage = (formData: ProformaUpdateForm): number | null => {
|
const resolveRetentionCode = (formData: ProformaUpdateForm): string | null => {
|
||||||
return formData.hasRetentionPercentage ? formData.defaultRetentionPercentage : null;
|
if (!formData.hasRetentionPercentage) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProformaRetentionCode(formData.retentionPercentage);
|
||||||
};
|
};
|
||||||
|
|
||||||
const toPercentageDTOOrNull = (value: number | null) => {
|
const resolveItemIvaCode = (
|
||||||
return value === null ? null : PercentageDTOHelper.fromNumber(value, 2);
|
item: ProformaItemUpdateForm,
|
||||||
|
context: ProformaItemUpdateDTOContext
|
||||||
|
): string | null => {
|
||||||
|
if (context.taxMode === "single") {
|
||||||
|
return context.ivaCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProformaTaxCode(item.taxPercentage);
|
||||||
|
};
|
||||||
|
|
||||||
|
const resolveItemRecCode = (
|
||||||
|
item: ProformaItemUpdateForm,
|
||||||
|
context: ProformaItemUpdateDTOContext
|
||||||
|
): string | null => {
|
||||||
|
if (context.taxMode === "single") {
|
||||||
|
return context.recCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
return getProformaRecCode(item.recPercentage);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -5,21 +5,15 @@ import { calculateProformaTotalsFromLines } from "./calculations";
|
|||||||
|
|
||||||
export interface CalculateProformaTotalsParams {
|
export interface CalculateProformaTotalsParams {
|
||||||
globalDiscountPercentage: ProformaUpdateForm["globalDiscountPercentage"];
|
globalDiscountPercentage: ProformaUpdateForm["globalDiscountPercentage"];
|
||||||
|
|
||||||
items: ProformaItemUpdateForm[];
|
items: ProformaItemUpdateForm[];
|
||||||
|
|
||||||
hasRetentionPercentage: boolean;
|
hasRetentionPercentage: boolean;
|
||||||
|
|
||||||
retentionPercentage: number | null;
|
retentionPercentage: number | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const calculateProformaTotals = ({
|
export const calculateProformaTotals = ({
|
||||||
globalDiscountPercentage,
|
globalDiscountPercentage,
|
||||||
|
|
||||||
items,
|
items,
|
||||||
|
|
||||||
hasRetentionPercentage,
|
hasRetentionPercentage,
|
||||||
|
|
||||||
retentionPercentage,
|
retentionPercentage,
|
||||||
}: CalculateProformaTotalsParams): ProformaTotals => {
|
}: CalculateProformaTotalsParams): ProformaTotals => {
|
||||||
const lines = mapProformaItemFormToProformaLineInputs(items, {
|
const lines = mapProformaItemFormToProformaLineInputs(items, {
|
||||||
@ -28,9 +22,7 @@ export const calculateProformaTotals = ({
|
|||||||
|
|
||||||
return calculateProformaTotalsFromLines({
|
return calculateProformaTotalsFromLines({
|
||||||
lines,
|
lines,
|
||||||
|
|
||||||
globalDiscountPercentage,
|
globalDiscountPercentage,
|
||||||
|
|
||||||
retentionPercentage: hasRetentionPercentage ? retentionPercentage : null,
|
retentionPercentage: hasRetentionPercentage ? retentionPercentage : null,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/customers",
|
"name": "@erp/customers",
|
||||||
"description": "Customers",
|
"description": "Customers",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/factuges",
|
"name": "@erp/factuges",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/supplier-invoices",
|
"name": "@erp/supplier-invoices",
|
||||||
"description": "Supplier invoices",
|
"description": "Supplier invoices",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@erp/suppliers",
|
"name": "@erp/suppliers",
|
||||||
"description": "Suppliers",
|
"description": "Suppliers",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "uecko-erp-2025",
|
"name": "uecko-erp-2025",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"apps/*",
|
"apps/*",
|
||||||
"modules/*",
|
"modules/*",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-criteria",
|
"name": "@repo/rdx-criteria",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-ddd",
|
"name": "@repo/rdx-ddd",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-logger",
|
"name": "@repo/rdx-logger",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-ui",
|
"name": "@repo/rdx-ui",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
@ -36,6 +36,7 @@ type SelectFieldProps<TFormValues extends FieldValues> = {
|
|||||||
|
|
||||||
orientation?: "vertical" | "horizontal" | "responsive";
|
orientation?: "vertical" | "horizontal" | "responsive";
|
||||||
|
|
||||||
|
onChange?: (value: unknown) => void;
|
||||||
serialize?: (value: unknown) => string;
|
serialize?: (value: unknown) => string;
|
||||||
deserialize?: (value: SelectFieldValue) => unknown;
|
deserialize?: (value: SelectFieldValue) => unknown;
|
||||||
|
|
||||||
@ -59,6 +60,7 @@ export function SelectField<TFormValues extends FieldValues>({
|
|||||||
|
|
||||||
orientation = "vertical",
|
orientation = "vertical",
|
||||||
|
|
||||||
|
onChange,
|
||||||
serialize,
|
serialize,
|
||||||
deserialize,
|
deserialize,
|
||||||
|
|
||||||
@ -102,7 +104,11 @@ export function SelectField<TFormValues extends FieldValues>({
|
|||||||
|
|
||||||
<Select
|
<Select
|
||||||
disabled={isDisabled}
|
disabled={isDisabled}
|
||||||
onValueChange={(value) => field.onChange(deserializeValue(value))}
|
onValueChange={(value) =>
|
||||||
|
onChange &&
|
||||||
|
onChange(deserializeValue(value)) &&
|
||||||
|
field.onChange(deserializeValue(value))
|
||||||
|
}
|
||||||
value={fieldValue}
|
value={fieldValue}
|
||||||
>
|
>
|
||||||
<SelectTrigger
|
<SelectTrigger
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@repo/rdx-utils",
|
"name": "@repo/rdx-utils",
|
||||||
"version": "0.6.5",
|
"version": "0.6.6",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user