feat: implementar soporte para carga de etiquetas de informe multilingüe y eliminar etiquetas obsoletas
This commit is contained in:
parent
ac117c1b18
commit
d6387f6e3e
@ -25,8 +25,7 @@ RUN cd ./server && yarn install
|
|||||||
RUN cd ./server && yarn run build || { echo 'Error during build'; exit 1; }
|
RUN cd ./server && yarn run build || { echo 'Error during build'; exit 1; }
|
||||||
|
|
||||||
# Copiar plantillas
|
# Copiar plantillas
|
||||||
RUN mkdir -p /api/dist/server/src/contexts/sales/infrastructure/express/controllers/quotes/reportQuote/reporter/templates/quote/
|
COPY server/src/contexts/sales/infrastructure/express/controllers/quotes/reportQuote/reporter/templates/quote/ /api/dist/server/src/contexts/sales/infrastructure/express/controllers/quotes/reportQuote/reporter/templates/quote/
|
||||||
COPY server/src/contexts/sales/infrastructure/express/controllers/quotes/reportQuote/reporter/templates/quote/* /api/dist/server/src/contexts/sales/infrastructure/express/controllers/quotes/reportQuote/reporter/templates/quote
|
|
||||||
|
|
||||||
# Copiar logo por defecto
|
# Copiar logo por defecto
|
||||||
RUN mkdir -p /api/dist/uploads/images/
|
RUN mkdir -p /api/dist/uploads/images/
|
||||||
@ -75,4 +74,3 @@ EXPOSE 3001
|
|||||||
|
|
||||||
# Comando para correr la aplicación
|
# Comando para correr la aplicación
|
||||||
CMD node -r ts-node/register/transpile-only -r tsconfig-paths/register ./server/src/index.js
|
CMD node -r ts-node/register/transpile-only -r tsconfig-paths/register ./server/src/index.js
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,53 @@
|
|||||||
|
import { readFileSync } from "fs";
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export const REPORT_LANGUAGES = ["es", "en", "fr"] as const;
|
||||||
|
export type ReportLanguage = (typeof REPORT_LANGUAGES)[number];
|
||||||
|
|
||||||
|
export interface ReportLabels {
|
||||||
|
official_distributor: string;
|
||||||
|
dealer_logo: string;
|
||||||
|
document_title: string;
|
||||||
|
browser_title: string;
|
||||||
|
quote_number: string;
|
||||||
|
date: string;
|
||||||
|
validity: string;
|
||||||
|
salesperson: string;
|
||||||
|
customer_reference: string;
|
||||||
|
page: string;
|
||||||
|
of: string;
|
||||||
|
quantity: string;
|
||||||
|
description: string;
|
||||||
|
unit_price: string;
|
||||||
|
subtotal: string;
|
||||||
|
discount: string;
|
||||||
|
total_amount: string;
|
||||||
|
payment_method: string;
|
||||||
|
notes: string;
|
||||||
|
net_amount: string;
|
||||||
|
discounts: string;
|
||||||
|
percentage_discount: string;
|
||||||
|
taxable_amount: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const resolveReportLanguage = (language: string): ReportLanguage =>
|
||||||
|
REPORT_LANGUAGES.includes(language as ReportLanguage) ? (language as ReportLanguage) : "es";
|
||||||
|
|
||||||
|
const requiredKeys = [
|
||||||
|
"official_distributor", "dealer_logo", "document_title", "browser_title", "quote_number",
|
||||||
|
"date", "validity", "salesperson", "customer_reference", "page", "of", "quantity",
|
||||||
|
"description", "unit_price", "subtotal", "discount", "total_amount", "payment_method",
|
||||||
|
"notes", "net_amount", "discounts", "percentage_discount", "taxable_amount",
|
||||||
|
] satisfies (keyof ReportLabels)[];
|
||||||
|
|
||||||
|
export const loadReportLabels = (language: ReportLanguage): ReportLabels => {
|
||||||
|
const filepath = path.join(__dirname, "./templates/quote/locales", `${language}.json`);
|
||||||
|
const labels = JSON.parse(readFileSync(filepath, "utf8")) as Partial<ReportLabels>;
|
||||||
|
const missingKeys = requiredKeys.filter((key) => !(key in labels));
|
||||||
|
|
||||||
|
if (missingKeys.length) {
|
||||||
|
throw new Error(`Missing report labels for ${language}: ${missingKeys.join(", ")}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels as ReportLabels;
|
||||||
|
};
|
||||||
@ -1,82 +0,0 @@
|
|||||||
export const reportLabels = {
|
|
||||||
es: {
|
|
||||||
official_distributor: "DISTRIBUIDOR OFICIAL",
|
|
||||||
dealer_logo: "Logo distribuidor",
|
|
||||||
document_title: "PRESUPUESTO",
|
|
||||||
browser_title: "Presupuesto",
|
|
||||||
quote_number: "Presupuesto nº:",
|
|
||||||
date: "Fecha:",
|
|
||||||
validity: "Validez:",
|
|
||||||
salesperson: "Vendedor:",
|
|
||||||
customer_reference: "Referencia cliente:",
|
|
||||||
page: "Página",
|
|
||||||
of: "de",
|
|
||||||
quantity: "Cant.",
|
|
||||||
description: "Descripción",
|
|
||||||
unit_price: "Prec. Unitario",
|
|
||||||
subtotal: "Subtotal",
|
|
||||||
discount: "Dto (%)",
|
|
||||||
total_amount: "Importe total",
|
|
||||||
payment_method: "Forma de pago:",
|
|
||||||
notes: "Notas:",
|
|
||||||
net_amount: "Importe neto",
|
|
||||||
discounts: "Descuentos",
|
|
||||||
percentage_discount: "% Descuento",
|
|
||||||
taxable_amount: "Base imponible",
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
official_distributor: "OFFICIAL DISTRIBUTOR",
|
|
||||||
dealer_logo: "Dealer logo",
|
|
||||||
document_title: "QUOTE",
|
|
||||||
browser_title: "Quote",
|
|
||||||
quote_number: "Quote no.:",
|
|
||||||
date: "Date:",
|
|
||||||
validity: "Validity:",
|
|
||||||
salesperson: "Salesperson:",
|
|
||||||
customer_reference: "Customer reference:",
|
|
||||||
page: "Page",
|
|
||||||
of: "of",
|
|
||||||
quantity: "Qty.",
|
|
||||||
description: "Description",
|
|
||||||
unit_price: "Unit price",
|
|
||||||
subtotal: "Subtotal",
|
|
||||||
discount: "Discount (%)",
|
|
||||||
total_amount: "Total amount",
|
|
||||||
payment_method: "Payment method:",
|
|
||||||
notes: "Notes:",
|
|
||||||
net_amount: "Net amount",
|
|
||||||
discounts: "Discounts",
|
|
||||||
percentage_discount: "% Discount",
|
|
||||||
taxable_amount: "Taxable amount",
|
|
||||||
},
|
|
||||||
fr: {
|
|
||||||
official_distributor: "DISTRIBUTEUR OFFICIEL",
|
|
||||||
dealer_logo: "Logo du distributeur",
|
|
||||||
document_title: "DEVIS",
|
|
||||||
browser_title: "Devis",
|
|
||||||
quote_number: "Devis n° :",
|
|
||||||
date: "Date :",
|
|
||||||
validity: "Validité :",
|
|
||||||
salesperson: "Commercial :",
|
|
||||||
customer_reference: "Référence client :",
|
|
||||||
page: "Page",
|
|
||||||
of: "sur",
|
|
||||||
quantity: "Qté",
|
|
||||||
description: "Description",
|
|
||||||
unit_price: "Prix unitaire",
|
|
||||||
subtotal: "Sous-total",
|
|
||||||
discount: "Remise (%)",
|
|
||||||
total_amount: "Montant total",
|
|
||||||
payment_method: "Mode de paiement :",
|
|
||||||
notes: "Notes :",
|
|
||||||
net_amount: "Montant net",
|
|
||||||
discounts: "Remises",
|
|
||||||
percentage_discount: "% de remise",
|
|
||||||
taxable_amount: "Base imposable",
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
export type ReportLanguage = keyof typeof reportLabels;
|
|
||||||
|
|
||||||
export const resolveReportLanguage = (language: string): ReportLanguage =>
|
|
||||||
language === "en" || language === "fr" ? language : "es";
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { ISalesContext } from "@/contexts/sales/infrastructure/Sales.context";
|
import { ISalesContext } from "@/contexts/sales/infrastructure/Sales.context";
|
||||||
import { createQuoteMapper } from "@/contexts/sales/infrastructure/mappers/quote.mapper";
|
import { createQuoteMapper } from "@/contexts/sales/infrastructure/mappers/quote.mapper";
|
||||||
import { resolveReportLanguage } from "./ReportQuote.labels";
|
import { loadReportLabels, resolveReportLanguage } from "./ReportQuote.i18n";
|
||||||
import { ReportQuotePresenter } from "./ReportQuote.reporter";
|
import { ReportQuotePresenter } from "./ReportQuote.reporter";
|
||||||
|
|
||||||
const source = (
|
const source = (
|
||||||
@ -82,4 +82,8 @@ describe("ReportQuotePresenter", () => {
|
|||||||
it("falls back to Spanish labels and language for unsupported quote languages", async () => {
|
it("falls back to Spanish labels and language for unsupported quote languages", async () => {
|
||||||
expect(resolveReportLanguage("zz")).toBe("es");
|
expect(resolveReportLanguage("zz")).toBe("es");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("loads the French labels from the template locale", () => {
|
||||||
|
expect(loadReportLabels("fr").document_title).toBe("DEVIS");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import * as handlebars from "handlebars";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import puppeteer from "puppeteer";
|
import puppeteer from "puppeteer";
|
||||||
import report from "puppeteer-report";
|
import report from "puppeteer-report";
|
||||||
import { reportLabels, resolveReportLanguage } from "./ReportQuote.labels";
|
import { loadReportLabels, resolveReportLanguage } from "./ReportQuote.i18n";
|
||||||
import { Language } from "@shared/contexts";
|
import { Language } from "@shared/contexts";
|
||||||
import { resolveLocalizedQuoteDescriptions } from "@/contexts/sales/application/services";
|
import { resolveLocalizedQuoteDescriptions } from "@/contexts/sales/application/services";
|
||||||
|
|
||||||
@ -82,7 +82,7 @@ const map = async (quote: Quote, context: ISalesContext) => {
|
|||||||
customer_reference: quote.customerReference.toString(),
|
customer_reference: quote.customerReference.toString(),
|
||||||
customer_information: quote.customer.toString(),
|
customer_information: quote.customer.toString(),
|
||||||
lang_code: langCode,
|
lang_code: langCode,
|
||||||
labels: reportLabels[langCode],
|
labels: loadReportLabels(langCode),
|
||||||
currency_code: quote.currency.toString(),
|
currency_code: quote.currency.toString(),
|
||||||
|
|
||||||
payment_method: quote.paymentMethod.toString(),
|
payment_method: quote.paymentMethod.toString(),
|
||||||
|
|||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"official_distributor": "OFFICIAL DISTRIBUTOR", "dealer_logo": "Dealer logo", "document_title": "QUOTE", "browser_title": "Quote", "quote_number": "Quote no.:", "date": "Date:", "validity": "Validity:", "salesperson": "Salesperson:", "customer_reference": "Customer reference:", "page": "Page", "of": "of", "quantity": "Qty.", "description": "Description", "unit_price": "Unit price", "subtotal": "Subtotal", "discount": "Discount (%)", "total_amount": "Total amount", "payment_method": "Payment method:", "notes": "Notes:", "net_amount": "Net amount", "discounts": "Discounts", "percentage_discount": "% Discount", "taxable_amount": "Taxable amount"
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"official_distributor": "DISTRIBUIDOR OFICIAL", "dealer_logo": "Logo distribuidor", "document_title": "PRESUPUESTO", "browser_title": "Presupuesto", "quote_number": "Presupuesto nº:", "date": "Fecha:", "validity": "Validez:", "salesperson": "Vendedor:", "customer_reference": "Referencia cliente:", "page": "Página", "of": "de", "quantity": "Cant.", "description": "Descripción", "unit_price": "Prec. Unitario", "subtotal": "Subtotal", "discount": "Dto (%)", "total_amount": "Importe total", "payment_method": "Forma de pago:", "notes": "Notas:", "net_amount": "Importe neto", "discounts": "Descuentos", "percentage_discount": "% Descuento", "taxable_amount": "Base imponible"
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"official_distributor": "DISTRIBUTEUR OFFICIEL", "dealer_logo": "Logo du distributeur", "document_title": "DEVIS", "browser_title": "Devis", "quote_number": "Devis n° :", "date": "Date :", "validity": "Validité :", "salesperson": "Commercial :", "customer_reference": "Référence client :", "page": "Page", "of": "sur", "quantity": "Qté", "description": "Description", "unit_price": "Prix unitaire", "subtotal": "Sous-total", "discount": "Remise (%)", "total_amount": "Montant total", "payment_method": "Mode de paiement :", "notes": "Notes :", "net_amount": "Montant net", "discounts": "Remises", "percentage_discount": "% de remise", "taxable_amount": "Base imposable"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user