diff --git a/apps/web/src/layout/app-fullscreen-layout.tsx b/apps/web/src/layout/app-fullscreen-layout.tsx
index 314ead21..81d07584 100644
--- a/apps/web/src/layout/app-fullscreen-layout.tsx
+++ b/apps/web/src/layout/app-fullscreen-layout.tsx
@@ -1,9 +1,11 @@
import { Outlet } from "react-router-dom";
+import { AppMain } from "./app-main";
+
export const AppFullscreenLayout = () => {
return (
-
+
-
+
);
};
diff --git a/modules/core/src/web/components/form/form-actions/page-form-header.tsx b/modules/core/src/web/components/form/form-actions/page-form-header.tsx
index 8d3990e8..6fb4c658 100644
--- a/modules/core/src/web/components/form/form-actions/page-form-header.tsx
+++ b/modules/core/src/web/components/form/form-actions/page-form-header.tsx
@@ -32,7 +32,12 @@ export const PageFormHeader = ({
contentClassName,
}: PageFormHeaderProps) => {
return (
-
+
-
+
{title}
diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-form-to-proforma-line-inpus.ts b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-form-to-proforma-line-inpus.ts
index 72d96598..4692c865 100644
--- a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-form-to-proforma-line-inpus.ts
+++ b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-form-to-proforma-line-inpus.ts
@@ -1,3 +1,5 @@
+import { isNullishOrEmpty } from "@repo/rdx-utils";
+
import type { ProformaItemUpdateForm, ProformaLineInput } from "../entities";
/**
@@ -16,16 +18,19 @@ export const mapProformaItemFormToProformaLineInputs = (
items: ProformaItemUpdateForm[],
params: MapProformaItemFormToProformaLineInputsParams
): ProformaLineInput[] => {
- return items
- .filter((item) => item.isValued)
- .map((item) => ({
- quantity: item.quantity,
- unitAmount: item.unitAmount,
+ return (
+ items
+ // quitar tuplas no valoradas
+ .filter((item) => !(isNullishOrEmpty(item.quantity) || isNullishOrEmpty(item.unitAmount)))
+ .map((item) => ({
+ quantity: item.quantity,
+ unitAmount: item.unitAmount,
- itemDiscountPercentage: item.itemDiscountPercentage,
- globalDiscountPercentage: params.globalDiscountPercentage,
+ itemDiscountPercentage: item.itemDiscountPercentage,
+ globalDiscountPercentage: params.globalDiscountPercentage,
- taxPercentage: item.taxPercentage,
- recPercentage: item.recPercentage,
- }));
+ taxPercentage: item.taxPercentage,
+ recPercentage: item.recPercentage,
+ }))
+ );
};
diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts
index be78eaac..b079c1d7 100644
--- a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts
+++ b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-items-to-proforma-items-update-form.adapter.ts
@@ -14,7 +14,7 @@ export const mapProformaItemsToProformaItemsUpdateForm = (
return {
id: item.id,
position: item.position,
- isValued: item.isValued,
+ //isValued: item.isValued, <- campo calculado en frontend, no se mapea desde la API
description: item.description ?? null,
diff --git a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts
index 37ddbbe5..581e5ece 100644
--- a/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts
+++ b/modules/customer-invoices/src/web/proformas/update/adapters/map-proforma-to-proforma-update-form.adapter.ts
@@ -41,7 +41,8 @@ export const mapProformaToProformaUpdateForm = (proforma: Proforma): ProformaUpd
taxMode: fiscalDefaults.taxMode,
taxRegimeCode: "01", //taxRegimeCode: proforma.taxRegimeCode ?? proformaDefaults.taxRegimeCode, // TODO: implementar en API
- hasTaxPercentage: fiscalDefaults.defaultTaxPercentage !== null,
+ hasTaxPercentage:
+ fiscalDefaults.taxMode === "single" && fiscalDefaults.defaultTaxPercentage !== null,
taxPercentage: fiscalDefaults.defaultTaxPercentage,
hasRecPercentage: fiscalDefaults.defaultRecPercentage !== null,
diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts
index 95007d50..a4f34463 100644
--- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts
+++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-items-controller.ts
@@ -1,3 +1,4 @@
+import { isNullishOrEmpty } from "@repo/rdx-utils";
import * as React from "react";
import {
type FieldArrayWithId,
@@ -16,6 +17,8 @@ import { calculateProformaLinesTotals } from "../utils/calculations/calculate-pr
export interface ProformaItemAmounts {
subtotal: number;
itemDiscountAmount: number;
+ subtotalTaxable: number;
+ taxAmount: number;
total: number;
}
@@ -35,6 +38,8 @@ export interface UseUpdateProformaItemsControllerResult {
hasItems: boolean;
itemCount: number;
+ getItemIsValued: (index: number) => boolean;
+
itemErrors: ProformaItemError[];
getItemError: (index: number) => ProformaItemError | undefined;
getItemErrorMessage: (index: number) => string | undefined;
@@ -96,9 +101,14 @@ export const useUpdateProformaItemsController = ({
const appendItem = React.useCallback(() => {
const nextPosition = getValues("items")?.length ?? 0;
- append(buildProformaItemUpdateDefault(nextPosition), {
- shouldFocus: false,
- });
+ append(
+ buildProformaItemUpdateDefault(nextPosition, {
+ defaultTaxPercentage: getValues("taxPercentage") ?? undefined,
+ }),
+ {
+ shouldFocus: true,
+ }
+ );
}, [append, getValues]);
const removeItem = React.useCallback(
@@ -161,23 +171,6 @@ export const useUpdateProformaItemsController = ({
[getValues, replaceItems]
);
- const getItemAmounts = React.useCallback(
- (index: number): ProformaItemAmounts => {
- const line = mapProformaItemFormToProformaLineInputs([items[index]], {
- globalDiscountPercentage: null,
- })[0];
-
- const amounts = calculateProformaLineTotal(line);
-
- return {
- subtotal: amounts.subtotalBeforeDiscounts,
- itemDiscountAmount: amounts.itemDiscountAmount,
- total: amounts.subtotalBeforeGlobalDiscount,
- };
- },
- [items]
- );
-
const insertItemAt = React.useCallback(
(index: number) => {
const currentItems = getValues("items") ?? [];
@@ -223,6 +216,19 @@ export const useUpdateProformaItemsController = ({
};
}, [items]);
+ const itemsIsValued = React.useMemo(() => {
+ return items.map((item, _) => {
+ return !(isNullishOrEmpty(item.quantity) || isNullishOrEmpty(item.unitAmount));
+ });
+ }, [items]);
+
+ const getItemIsValued = React.useCallback(
+ (index: number): boolean => {
+ return itemsIsValued[index] ?? false;
+ },
+ [itemsIsValued]
+ );
+
const itemErrors = React.useMemo(() => {
if (!Array.isArray(errors.items)) return [];
@@ -241,7 +247,6 @@ export const useUpdateProformaItemsController = ({
const error = itemErrors[index];
return (
- error?.isValued?.message ??
error?.quantity?.message ??
error?.unitAmount?.message ??
error?.description?.message ??
@@ -251,6 +256,25 @@ export const useUpdateProformaItemsController = ({
[itemErrors]
);
+ const getItemAmounts = React.useCallback(
+ (index: number): ProformaItemAmounts => {
+ const line = mapProformaItemFormToProformaLineInputs([items[index]], {
+ globalDiscountPercentage: null,
+ })[0];
+
+ const amounts = calculateProformaLineTotal(line);
+
+ return {
+ subtotal: amounts.subtotalBeforeDiscounts,
+ itemDiscountAmount: amounts.itemDiscountAmount,
+ subtotalTaxable: amounts.subtotalTaxable,
+ taxAmount: amounts.taxAmount,
+ total: amounts.totalAmount,
+ };
+ },
+ [items]
+ );
+
return {
fields,
items,
@@ -258,6 +282,8 @@ export const useUpdateProformaItemsController = ({
hasItems: items.length > 0,
itemCount: items.length,
+ getItemIsValued,
+
itemErrors,
getItemError,
getItemErrorMessage,
diff --git a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-tax-controller.ts b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-tax-controller.ts
index d4484829..9adc9d1d 100644
--- a/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-tax-controller.ts
+++ b/modules/customer-invoices/src/web/proformas/update/controllers/use-update-proforma-tax-controller.ts
@@ -98,6 +98,8 @@ export const useUpdateProformaTaxController = ({
}, [taxPercentage, getValues, hasRecPercentage, setValue, taxMode]);
const enablePerLineTaxes = useCallback(() => {
+ // Activar impuestos por línea
+
setValue("taxMode", "perLine", {
shouldDirty: true,
shouldTouch: true,
@@ -106,6 +108,8 @@ export const useUpdateProformaTaxController = ({
}, [setValue]);
const disablePerLineTaxes = useCallback(() => {
+ // Desactivar impuestos por línea
+
setValue("taxMode", "single", {
shouldDirty: true,
shouldTouch: true,
diff --git a/modules/customer-invoices/src/web/proformas/update/entities/proforma-calculation.entity.ts b/modules/customer-invoices/src/web/proformas/update/entities/proforma-calculation.entity.ts
index eb4d7f67..499eb6d1 100644
--- a/modules/customer-invoices/src/web/proformas/update/entities/proforma-calculation.entity.ts
+++ b/modules/customer-invoices/src/web/proformas/update/entities/proforma-calculation.entity.ts
@@ -15,6 +15,9 @@ export interface ProformaLineTotal {
subtotalBeforeGlobalDiscount: number;
globalDiscountAmount: number;
totalDiscountAmount: number;
+ subtotalTaxable: number;
+ taxAmount: number;
+ totalAmount: number;
}
export interface ProformaTaxBreakdown {
diff --git a/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.entity.ts b/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.entity.ts
index 5e49915c..7766d3ee 100644
--- a/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.entity.ts
+++ b/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.entity.ts
@@ -1,7 +1,7 @@
export interface ProformaItemUpdateForm {
id: string;
position: number;
- isValued: boolean;
+ //isValued: boolean; <- campo calculado en frontend, no se mapea desde la API
description: string | null;
diff --git a/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.schema.ts b/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.schema.ts
index e384da1d..fef5f62b 100644
--- a/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.schema.ts
+++ b/modules/customer-invoices/src/web/proformas/update/entities/proforma-item-update-form.schema.ts
@@ -17,7 +17,7 @@ import { z } from "zod/v4";
export const ProformaItemUpdateFormSchema = z.object({
id: z.string(),
position: z.number(),
- isValued: z.boolean(),
+ //isValued: z.boolean(), <- campo calculado en frontend, no se mapea desde la API
description: z.string().nullable(),
diff --git a/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx b/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx
index b52ca175..0c2a7ddb 100644
--- a/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx
+++ b/modules/customer-invoices/src/web/proformas/update/ui/blocks/line-editor.tsx
@@ -63,6 +63,7 @@ export interface LineEditorProps {
moveDownLabel: string;
removeLabel: string;
+ disabled?: boolean;
className?: string;
}
@@ -96,6 +97,8 @@ export const LineEditor = ({
moveDownLabel,
removeLabel,
+ disabled = false,
+
className,
}: LineEditorProps) => {
return (
@@ -104,12 +107,24 @@ export const LineEditor = ({
{title}
-