@zauru-sdk/utils 6.12.0 → 6.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,6 +1,8 @@
1
+ export * from "./zauru/api.loaders.js";
1
2
  export * from "./zauru/automatic-number.utils.js";
2
3
  export * from "./zauru/bitacora-edicion-masiva.utils.js";
3
4
  export * from "./zauru/bundles.utils.js";
5
+ export * from "./zauru/catalogs.loader.js";
4
6
  export * from "./zauru/cases.utils.js";
5
7
  export * from "./zauru/consolidated-history.utils.js";
6
8
  export * from "./zauru/costos-items.utils.js";
@@ -0,0 +1,173 @@
1
+ import { createElement } from "react";
2
+ import { redirect } from "@remix-run/node";
3
+ import { config } from "@zauru-sdk/config";
4
+ import { getAgencyInfo, getEmployeeInfo, getHeaders, getOauthUserInfo, getProfileInformation, getReceptionTemplate, getSession, getVariablesByName, } from "@zauru-sdk/services";
5
+ import { createCatalogsLoader, } from "./catalogs.loader.js";
6
+ const missingParamPayload = (description) => ({
7
+ description,
8
+ title: "Ocurrió un error.",
9
+ error: true,
10
+ type: "error",
11
+ });
12
+ const namedErrorPayload = (name, empty, description) => ({
13
+ [name]: empty,
14
+ error: true,
15
+ type: "error",
16
+ title: `Ocurrió un error al obtener la información de ${name}!.`,
17
+ description,
18
+ });
19
+ const sdkProfileHandlers = {
20
+ oauthProfile: ({ session }) => getOauthUserInfo(session.get("code")),
21
+ agencyProfile: ({ headers, session }) => getAgencyInfo(headers, session),
22
+ employeeProfile: ({ headers, session }) => getEmployeeInfo(Number(session.get("employee_id")), headers),
23
+ userProfile: ({ headers }) => getProfileInformation(headers),
24
+ };
25
+ const sdkTemplateHandlers = {
26
+ receptionTemplate: async ({ headers, session, name }) => {
27
+ try {
28
+ const { reception_template_webapp_var } = await getVariablesByName(headers, session, ["reception_template_webapp_var"]);
29
+ headers.Accept = "text/html";
30
+ return getReceptionTemplate(headers, reception_template_webapp_var);
31
+ }
32
+ catch (error) {
33
+ console.error(error);
34
+ return Response.json(namedErrorPayload(name, {}, error?.toString() ?? ""));
35
+ }
36
+ },
37
+ };
38
+ const createNamedResourceLoader = (queryParam, sdkHandlers, extras, emptyOnError, missingDescription) => {
39
+ return async ({ request }) => {
40
+ try {
41
+ const cookie = request.headers.get("Cookie");
42
+ const session = await getSession(cookie);
43
+ if (!session.has("username")) {
44
+ return redirect("/");
45
+ }
46
+ const headers = await getHeaders(cookie, session);
47
+ const url = new URL(request.url);
48
+ const name = url.searchParams.get(queryParam) ?? "";
49
+ if (!name) {
50
+ return Response.json(missingParamPayload(missingDescription));
51
+ }
52
+ const handler = extras?.[name] ?? sdkHandlers[name];
53
+ if (!handler) {
54
+ return Response.json(missingParamPayload(missingDescription));
55
+ }
56
+ const result = await handler({
57
+ request,
58
+ session,
59
+ headers,
60
+ url,
61
+ name,
62
+ });
63
+ if (result instanceof Response) {
64
+ return result;
65
+ }
66
+ if (result.error || !result.data) {
67
+ return Response.json(namedErrorPayload(name, emptyOnError, `${result.userMsg ?? ""}`));
68
+ }
69
+ return { [name]: result.data };
70
+ }
71
+ catch (error) {
72
+ console.error(error);
73
+ const name = new URL(request.url).searchParams.get(queryParam) || queryParam;
74
+ return namedErrorPayload(name, emptyOnError, `${error}`);
75
+ }
76
+ };
77
+ };
78
+ /**
79
+ * Remix loader for `/api/profiles`. Pass extras to add or override profile names.
80
+ */
81
+ export function createProfilesLoader(extras) {
82
+ return createNamedResourceLoader("profile", sdkProfileHandlers, extras, {}, "No se envió ningún parámetro de perfil a buscar");
83
+ }
84
+ /**
85
+ * Remix loader for `/api/session`.
86
+ * Modern query: `name` + `type` (`environment` | `sessionVariable` | session attr).
87
+ * Legacy Remix 1: `attribute` only, read from the session.
88
+ */
89
+ export function createSessionLoader() {
90
+ return async ({ request }) => {
91
+ const cookie = request.headers.get("Cookie");
92
+ const session = await getSession(cookie);
93
+ const headers = await getHeaders(cookie, session);
94
+ if (!session.has("username")) {
95
+ return redirect("/");
96
+ }
97
+ const url = new URL(request.url);
98
+ const name = url.searchParams.get("name") ?? url.searchParams.get("attribute") ?? "";
99
+ const type = url.searchParams.get("type");
100
+ if (!name) {
101
+ return Response.json({
102
+ data: "",
103
+ ...missingParamPayload("No se envió ningún parámetro de name o type a buscar"),
104
+ });
105
+ }
106
+ if (type === "environment") {
107
+ return Response.json({
108
+ data: config[name],
109
+ });
110
+ }
111
+ if (type === "sessionVariable") {
112
+ try {
113
+ const response = await getVariablesByName(headers, session, [name]);
114
+ return Response.json({ data: response[name] });
115
+ }
116
+ catch {
117
+ return Response.json({
118
+ data: "",
119
+ ...missingParamPayload(`No se encontró la variable ${name} en la sesión`),
120
+ });
121
+ }
122
+ }
123
+ return Response.json({
124
+ data: session.get(name),
125
+ });
126
+ };
127
+ }
128
+ /**
129
+ * Remix loader for `/api/templates`. Pass extras to add or override template names.
130
+ */
131
+ export function createTemplatesLoader(extras) {
132
+ return createNamedResourceLoader("object", sdkTemplateHandlers, extras, {}, "No se envió ningún parámetro de templates a buscar");
133
+ }
134
+ const apiResourceLoaders = (extras) => ({
135
+ catalogs: createCatalogsLoader(extras?.catalogs),
136
+ profiles: createProfilesLoader(extras?.profiles),
137
+ session: createSessionLoader(),
138
+ templates: createTemplatesLoader(extras?.templates),
139
+ });
140
+ const apiPathSegment = (request, splat) => {
141
+ if (splat) {
142
+ return splat.split("/").filter(Boolean)[0] ?? "";
143
+ }
144
+ const parts = new URL(request.url).pathname.split("/").filter(Boolean);
145
+ return parts.at(-1) ?? "";
146
+ };
147
+ /**
148
+ * Single Remix splat loader for `/api/catalogs|profiles|session|templates`.
149
+ * App-specific handlers go in `extras` under the matching resource.
150
+ */
151
+ export function createZauruApiLoader(extras) {
152
+ const loaders = apiResourceLoaders(extras);
153
+ return async (args) => {
154
+ const segment = apiPathSegment(args.request, args.params?.["*"]);
155
+ const loader = loaders[segment];
156
+ if (!loader) {
157
+ return Response.json(missingParamPayload("No se envió ningún parámetro de catálogo a buscar"));
158
+ }
159
+ return loader(args);
160
+ };
161
+ }
162
+ export function ProfilesRoute() {
163
+ return createElement("div", { style: { fontFamily: "system-ui, sans-serif", lineHeight: "1.4" } }, "PROFILES LOAD");
164
+ }
165
+ export function SessionRoute() {
166
+ return createElement("div", { style: { fontFamily: "system-ui, sans-serif", lineHeight: "1.4" } }, "SESSION LOAD");
167
+ }
168
+ export function TemplatesRoute() {
169
+ return createElement("div", { style: { fontFamily: "system-ui, sans-serif", lineHeight: "1.4" } }, "TEMPLATES LOAD");
170
+ }
171
+ export function ZauruApiRoute() {
172
+ return createElement("div", { style: { fontFamily: "system-ui, sans-serif", lineHeight: "1.4" } }, "API LOAD");
173
+ }
@@ -0,0 +1,188 @@
1
+ import { createElement } from "react";
2
+ import { redirect } from "@remix-run/node";
3
+ import { get4pinosPoDiscountHistory, get4pinosSolicitudEliminacionPO, get4pinosWeightLimitPerBasket, getAgencies, getAllForms, getAuthorizationUpdateDiscountPO, getBookings, getCaseFormSubmissionsByCaseId, getCases, getCCPorcentajesDeRechazo, getClientCategories, getCurrencies, getEmployees, getFormsByDocumentType, getHeaders, getInvoiceFormSubmissionsByAgencyId, getInvoiceFormSubmissionsByInvoiceId, getInvoicesByAgencyId, getItems, getMotivosRechazo, getMyAgencyLotStocks, getMyCaseFormSubmissions, getPayeeCategories, getPayeeCategoriesByNotesMatch, getPayees, getPaymentMethods, getPaymentTerms, getPrintTemplates, getProviderCategories, getProviders, getSession, getSuggestedPrices, } from "@zauru-sdk/services";
4
+ import { getBitacorasPOMassive } from "./bitacora-edicion-masiva.utils.js";
5
+ import { getBundlesByLabCategory, getBundlesRecipByLabCategory } from "./bundles.utils.js";
6
+ import { getEmployeesByCurrentAgency, getEmployeesByLabAgency } from "./employees.utils.js";
7
+ import { getInvoicesByLabAgency } from "./invoices.utils.js";
8
+ import { getItemServicesByLabCategory, getItemsByLabCategory, getItemsByReceptionCategory, getLabItemCategories, } from "./items.utils.js";
9
+ import { getClientesLaboratorio, TEXT_PAYEE_CATEGORY_NOTES_FOR_PRICE, } from "./payees.utils.js";
10
+ import { getProgramaciones } from "./programaciones.utils.js";
11
+ import { getShipmentsToMyAgency } from "./shipments.utils.js";
12
+ import { getTemplates } from "./templates.utils.js";
13
+ import { getTipoMuestras } from "./tiposMuestra.utils.js";
14
+ import { getReceptionTypes } from "./webapp-tables.utils.js";
15
+ const missingQueryParam = (param) => {
16
+ console.warn({
17
+ description: `No se envió ningún parámetro de ${param} a buscar`,
18
+ title: "Ocurrió un error.",
19
+ error: true,
20
+ type: "error",
21
+ });
22
+ return Response.json({});
23
+ };
24
+ const catalogErrorPayload = (catalog, description) => ({
25
+ [catalog]: [],
26
+ error: true,
27
+ type: "error",
28
+ title: `Ocurrió un error al obtener el catálogo de ${catalog}!.`,
29
+ description,
30
+ });
31
+ const unknownCatalogPayload = {
32
+ description: "No se envió ningún parámetro de catálogo a buscar",
33
+ title: "Ocurrió un error.",
34
+ error: true,
35
+ type: "error",
36
+ };
37
+ const sdkCatalogHandlers = {
38
+ printTemplates: ({ session }) => getPrintTemplates(session),
39
+ paymentMethods: ({ session }) => getPaymentMethods(session),
40
+ invoiceFormSubmissions: ({ session, url }) => {
41
+ const agency_id = url.searchParams.get("agency_id") ?? session.get("agency_id");
42
+ return getInvoiceFormSubmissionsByAgencyId(session, agency_id);
43
+ },
44
+ payees: ({ session }) => getPayees(session),
45
+ items: ({ session }) => getItems(session),
46
+ payeesForLab: ({ session }) => getClientesLaboratorio(session),
47
+ currencies: ({ session }) => getCurrencies(session),
48
+ employees: ({ session }) => getEmployees(session),
49
+ employeesByLab: ({ headers, session }) => getEmployeesByLabAgency(headers, session),
50
+ employeesByCurrentAgency: ({ session }) => getEmployeesByCurrentAgency(session),
51
+ shipmentsToMyAgency: ({ session }) => getShipmentsToMyAgency(session),
52
+ allForms: ({ session, url }) => {
53
+ const withSubmissions = url.searchParams.get("withSubmissions") === "true";
54
+ return getAllForms(session, { withSubmissions });
55
+ },
56
+ invoiceForms: ({ session }) => getFormsByDocumentType(session, "invoice"),
57
+ caseForms: ({ session }) => getFormsByDocumentType(session, "case"),
58
+ paymentTerms: ({ session }) => getPaymentTerms(session),
59
+ invoicesByLab: ({ headers, session }) => getInvoicesByLabAgency(headers, session),
60
+ invoicesByCurrentAgency: ({ session, url }) => {
61
+ const tag_id = url.searchParams.get("tag_id") ?? undefined;
62
+ const invoice_id = url.searchParams.get("invoice_id") ?? undefined;
63
+ return getInvoicesByAgencyId(session, session.get("agency_id"), {
64
+ tag_id,
65
+ invoice_id,
66
+ });
67
+ },
68
+ payeeCategoriesLabPrices: ({ session }) => getPayeeCategoriesByNotesMatch(session, TEXT_PAYEE_CATEGORY_NOTES_FOR_PRICE),
69
+ payeeCategories: ({ session }) => getPayeeCategories(session),
70
+ receptionTypes: ({ headers, session }) => getReceptionTypes(headers, session),
71
+ bitacoraRechazoMasivo: ({ headers, session }) => getBitacorasPOMassive(headers, session),
72
+ cases: ({ session, url }) => {
73
+ const tag_id = url.searchParams.get("tag_id") ?? undefined;
74
+ const assignedToMe = url.searchParams.get("assignedToMe") === "true";
75
+ return getCases(session, {
76
+ tag_id,
77
+ ...(assignedToMe
78
+ ? { responsible_id: Number(session.get("employee_id")) }
79
+ : {}),
80
+ });
81
+ },
82
+ myCases: ({ session }) => getCases(session, {
83
+ responsible_id: Number(session.get("employee_id")),
84
+ }),
85
+ myCaseFormSubmissions: ({ headers, session }) => getMyCaseFormSubmissions(headers, session),
86
+ tiposDeMuestra: ({ headers, session }) => getTipoMuestras(headers, session),
87
+ myAgencyLotStocks: ({ session }) => getMyAgencyLotStocks(session),
88
+ motivosRechazo: ({ headers, session }) => getMotivosRechazo(headers, session),
89
+ ccPorcentajesDeRechazo: ({ headers, session }) => getCCPorcentajesDeRechazo(headers, session),
90
+ programaciones4pinos: ({ headers, session }) => getProgramaciones(headers, session),
91
+ solicitudesEliminacionPO: ({ headers, session }) => get4pinosSolicitudEliminacionPO(headers, session),
92
+ pesoMaximoPorCanasta: ({ headers, session }) => get4pinosWeightLimitPerBasket(headers, session),
93
+ poDiscountHistory: ({ headers, session }) => get4pinosPoDiscountHistory(headers, session),
94
+ authorizationUpdateDiscountPO: ({ headers, session }) => getAuthorizationUpdateDiscountPO(headers, session),
95
+ itemsByReception: ({ headers, session }) => getItemsByReceptionCategory(headers, session),
96
+ itemsByLab: ({ headers, session }) => getItemsByLabCategory(headers, session),
97
+ itemServicesByLab: ({ headers, session }) => getItemServicesByLabCategory(headers, session),
98
+ itemCategoriesForLab: ({ headers, session }) => getLabItemCategories(headers, session),
99
+ bundlesRecipForLab: ({ headers, session }) => getBundlesRecipByLabCategory(headers, session),
100
+ bundlesForLab: ({ headers, session }) => getBundlesByLabCategory(headers, session),
101
+ templates: ({ headers, session }) => getTemplates(headers, session),
102
+ bookings: ({ session, wheres }) => getBookings(session, wheres),
103
+ suggestedPrices: ({ session, url }) => {
104
+ const withItems = url.searchParams.get("withItems") === "true";
105
+ const withItemCategories = url.searchParams.get("withItemCategories") === "true";
106
+ return getSuggestedPrices(session, { withItems, withItemCategories });
107
+ },
108
+ providerCategories: ({ session }) => getProviderCategories(session),
109
+ clientCategories: ({ session }) => getClientCategories(session),
110
+ providers: ({ session }) => getProviders(session),
111
+ agencies: ({ session }) => getAgencies(session),
112
+ invoiceFormSubmissionsByAgencyId: async ({ session, url }) => {
113
+ const agency_id = url.searchParams.get("agency_id");
114
+ if (!agency_id) {
115
+ return missingQueryParam("agency_id");
116
+ }
117
+ return getInvoiceFormSubmissionsByAgencyId(session, agency_id);
118
+ },
119
+ invoiceFormSubmissionsByInvoiceId: async ({ headers, session, url }) => {
120
+ const withFiles = url.searchParams.get("withFiles") === "true";
121
+ const invoiceId = url.searchParams.get("invoiceId");
122
+ if (!invoiceId) {
123
+ return missingQueryParam("invoiceId");
124
+ }
125
+ return getInvoiceFormSubmissionsByInvoiceId(headers, session, invoiceId, withFiles);
126
+ },
127
+ caseFormSubmissionsByCaseId: async ({ headers, session, url }) => {
128
+ const withFiles = url.searchParams.get("withFiles") === "true";
129
+ const caseId = url.searchParams.get("caseId");
130
+ if (!caseId) {
131
+ return missingQueryParam("caseId");
132
+ }
133
+ return getCaseFormSubmissionsByCaseId(headers, session, caseId, withFiles);
134
+ },
135
+ };
136
+ /**
137
+ * Remix loader for `/api/catalogs`. Shared catalog names live in the SDK;
138
+ * pass `extras` to add or override handlers for a single webapp.
139
+ */
140
+ export function createCatalogsLoader(extras) {
141
+ return async ({ request }) => {
142
+ try {
143
+ const cookie = request.headers.get("Cookie");
144
+ const session = await getSession(cookie);
145
+ if (!session.has("username")) {
146
+ return redirect("/");
147
+ }
148
+ const headers = await getHeaders(cookie, session);
149
+ const url = new URL(request.url);
150
+ const catalog = url.searchParams.get("catalog") ?? "";
151
+ const wheres = url.searchParams
152
+ .get("wheres")
153
+ ?.split("&")
154
+ .map((where) => decodeURIComponent(where))
155
+ .filter((where) => where !== "") ?? [];
156
+ if (!catalog) {
157
+ return Response.json(unknownCatalogPayload);
158
+ }
159
+ const handler = extras?.[catalog] ?? sdkCatalogHandlers[catalog];
160
+ if (!handler) {
161
+ return Response.json(unknownCatalogPayload);
162
+ }
163
+ const result = await handler({
164
+ request,
165
+ session,
166
+ headers,
167
+ url,
168
+ catalog,
169
+ wheres,
170
+ });
171
+ if (result instanceof Response) {
172
+ return result;
173
+ }
174
+ if (result.error || !result.data) {
175
+ return Response.json(catalogErrorPayload(catalog, `${result.userMsg ?? ""}`));
176
+ }
177
+ return { [catalog]: result.data };
178
+ }
179
+ catch (error) {
180
+ console.error(error);
181
+ const catalog = new URL(request.url).searchParams.get("catalog") || "catalog";
182
+ return catalogErrorPayload(catalog, `${error}`);
183
+ }
184
+ };
185
+ }
186
+ export function CatalogsRoute() {
187
+ return createElement("div", { style: { fontFamily: "system-ui, sans-serif", lineHeight: "1.4" } }, "CATALOGS LOAD");
188
+ }
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
+ export * from "./zauru/api.loaders.js";
1
2
  export * from "./zauru/automatic-number.utils.js";
2
3
  export * from "./zauru/bitacora-edicion-masiva.utils.js";
3
4
  export * from "./zauru/bundles.utils.js";
5
+ export * from "./zauru/catalogs.loader.js";
4
6
  export * from "./zauru/cases.utils.js";
5
7
  export * from "./zauru/consolidated-history.utils.js";
6
8
  export * from "./zauru/costos-items.utils.js";
@@ -0,0 +1,41 @@
1
+ import { type ReactElement } from "react";
2
+ import type { LoaderFunction } from "@remix-run/node";
3
+ import { getHeaders, getSession } from "@zauru-sdk/services";
4
+ import type { AxiosUtilsResponse } from "@zauru-sdk/types";
5
+ import { type CatalogHandler } from "./catalogs.loader.js";
6
+ export type ApiHandlerContext = {
7
+ request: Request;
8
+ session: Awaited<ReturnType<typeof getSession>>;
9
+ headers: Awaited<ReturnType<typeof getHeaders>>;
10
+ url: URL;
11
+ name: string;
12
+ };
13
+ export type ApiHandler = (ctx: ApiHandlerContext) => Promise<AxiosUtilsResponse<unknown> | Response>;
14
+ export type ZauruApiLoaderExtras = {
15
+ catalogs?: Record<string, CatalogHandler>;
16
+ profiles?: Record<string, ApiHandler>;
17
+ templates?: Record<string, ApiHandler>;
18
+ };
19
+ /**
20
+ * Remix loader for `/api/profiles`. Pass extras to add or override profile names.
21
+ */
22
+ export declare function createProfilesLoader(extras?: Record<string, ApiHandler>): LoaderFunction;
23
+ /**
24
+ * Remix loader for `/api/session`.
25
+ * Modern query: `name` + `type` (`environment` | `sessionVariable` | session attr).
26
+ * Legacy Remix 1: `attribute` only, read from the session.
27
+ */
28
+ export declare function createSessionLoader(): LoaderFunction;
29
+ /**
30
+ * Remix loader for `/api/templates`. Pass extras to add or override template names.
31
+ */
32
+ export declare function createTemplatesLoader(extras?: Record<string, ApiHandler>): LoaderFunction;
33
+ /**
34
+ * Single Remix splat loader for `/api/catalogs|profiles|session|templates`.
35
+ * App-specific handlers go in `extras` under the matching resource.
36
+ */
37
+ export declare function createZauruApiLoader(extras?: ZauruApiLoaderExtras): LoaderFunction;
38
+ export declare function ProfilesRoute(): ReactElement;
39
+ export declare function SessionRoute(): ReactElement;
40
+ export declare function TemplatesRoute(): ReactElement;
41
+ export declare function ZauruApiRoute(): ReactElement;
@@ -0,0 +1,19 @@
1
+ import { type ReactElement } from "react";
2
+ import type { LoaderFunction, Session } from "@remix-run/node";
3
+ import { getHeaders } from "@zauru-sdk/services";
4
+ import type { AxiosUtilsResponse } from "@zauru-sdk/types";
5
+ export type CatalogLoaderContext = {
6
+ request: Request;
7
+ session: Session;
8
+ headers: Awaited<ReturnType<typeof getHeaders>>;
9
+ url: URL;
10
+ catalog: string;
11
+ wheres: string[];
12
+ };
13
+ export type CatalogHandler = (ctx: CatalogLoaderContext) => Promise<AxiosUtilsResponse<unknown> | Response>;
14
+ /**
15
+ * Remix loader for `/api/catalogs`. Shared catalog names live in the SDK;
16
+ * pass `extras` to add or override handlers for a single webapp.
17
+ */
18
+ export declare function createCatalogsLoader(extras?: Record<string, CatalogHandler>): LoaderFunction;
19
+ export declare function CatalogsRoute(): ReactElement;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zauru-sdk/utils",
3
- "version": "6.12.0",
3
+ "version": "6.14.0",
4
4
  "description": "Utilidades, parseo de request y demás para desarrollo de webapps de Zauru",
5
5
  "main": "./dist/esm/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -20,7 +20,12 @@
20
20
  ],
21
21
  "author": "Oscar Cuéllar",
22
22
  "license": "MIT",
23
+ "peerDependencies": {
24
+ "react": "^18.2.0 || ^19.0.0"
25
+ },
23
26
  "devDependencies": {
27
+ "@types/react": "^18.2.20",
28
+ "react": "^18.2.0",
24
29
  "typescript": "^5.1.6"
25
30
  },
26
31
  "dependencies": {
@@ -32,5 +37,5 @@
32
37
  "@zauru-sdk/types": "^6.16.0",
33
38
  "moment": "^2.30.1"
34
39
  },
35
- "gitHead": "9e840d01a540f2ab49233dda2cb2b0c916ffba0b"
40
+ "gitHead": "b0d95fcc90a6789ba2bf4bdcb0f54070c7583e85"
36
41
  }