@grupolapa/desarrollos-sdk 0.1.0 → 0.3.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.
@@ -1,6 +1,7 @@
1
- import { clampToRange, getDefaultDownPaymentPctForScheme, getResolvedSchemeForUnit, isInstallmentScheme, } from "./payment-schemes.js";
1
+ import { clampToRange, getDefaultDownPaymentPctForScheme, getResolvedSchemeForUnit, isUondrBundleFlexiblePlanEligible, getUondrResolvedSchemeForUnit, isUondrFlexiblePaymentScheme, isUondrLocalCategory, isInstallmentScheme, } from "./payment-schemes.js";
2
2
  import { clampUondrCashbackDownPaymentPct } from "./social-quote.js";
3
3
  import { clampInstallmentDownPaymentPct, clampInstallmentMonthlyPct, INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT, INSTALLMENT_DEFAULT_MONTHLY_PCT, } from "./installment-allocation.js";
4
+ import { CASHBACK_PAYMENT_OPTION_DIRECT, UONDR_CASHBACK_DIRECT_DOWN_PAYMENT_PCT, normalizeCashbackPaymentOptionId, } from "./cashback-payment-options.js";
4
5
  function parseNumberParam(value, fallback) {
5
6
  if (value === null) {
6
7
  return fallback;
@@ -65,6 +66,21 @@ function pickNumericParam(...values) {
65
66
  function isCategory(value) {
66
67
  return typeof value === "string" && value.trim().length > 0;
67
68
  }
69
+ function parseUnitIdsParam(value, units) {
70
+ if (!value) {
71
+ return [];
72
+ }
73
+ const knownUnitsById = new Map(units.map((unit) => [unit.id, unit]));
74
+ const parsedUnits = [];
75
+ for (const rawUnitId of value.split(",")) {
76
+ const unitId = rawUnitId.trim();
77
+ const unit = knownUnitsById.get(unitId);
78
+ if (unit && !parsedUnits.some((item) => item.id === unit.id)) {
79
+ parsedUnits.push(unit);
80
+ }
81
+ }
82
+ return parsedUnits;
83
+ }
68
84
  export function normalizeQuoteUrlState(search, units, rules, paymentSchemes) {
69
85
  const requestedUnitId = pickStringParam(search.unitId, search.unit);
70
86
  const requestedCategoryParam = getStringParam(search.category);
@@ -94,6 +110,7 @@ export function normalizeQuoteUrlState(search, units, rules, paymentSchemes) {
94
110
  paymentSchemes.find((scheme) => scheme.active) ??
95
111
  null);
96
112
  const defaultDownPaymentPct = getDefaultDownPaymentPctForScheme(resolvedScheme, rules);
113
+ const cashbackPaymentOption = normalizeCashbackPaymentOptionId(pickStringParam(search.cashbackPaymentOption, search.cashbackPlan, search.cashbackOption));
97
114
  return {
98
115
  category: resolvedCategory,
99
116
  unitId: selectedUnit?.id ?? "",
@@ -102,6 +119,7 @@ export function normalizeQuoteUrlState(search, units, rules, paymentSchemes) {
102
119
  downPaymentPct: resolvedScheme?.type === "cashback"
103
120
  ? clampToRange(parseNumberParam(pickNumericParam(search.downPaymentPct, search.enganche), defaultDownPaymentPct), resolvedScheme.downPaymentRange)
104
121
  : defaultDownPaymentPct,
122
+ cashbackPaymentOption,
105
123
  installmentDownPaymentPct: (() => {
106
124
  const value = clampInstallmentDownPaymentPct(parseNumberParam(pickNumericParam(search.installmentDownPaymentPct, search.iEng), INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT));
107
125
  return value;
@@ -125,19 +143,35 @@ export function normalizeSocialQuoteUrlState(search, units, rules, paymentScheme
125
143
  downPaymentPct: resolvedScheme && isInstallmentScheme(resolvedScheme)
126
144
  ? resolvedScheme.downPaymentPct
127
145
  : getDefaultDownPaymentPctForScheme(resolvedScheme, rules),
146
+ cashbackPaymentOption: CASHBACK_PAYMENT_OPTION_DIRECT,
128
147
  includeIva: false,
129
148
  };
130
149
  }
131
- export function normalizeUondrQuoteUrlState(search, units, rules, paymentSchemes) {
150
+ export function normalizeUondrQuoteUrlState(search, units, rules, paymentSchemes, siteCategories = []) {
132
151
  const state = normalizeQuoteUrlState(search, units, rules, paymentSchemes);
133
152
  const selectedUnit = units.find((unit) => unit.id === state.unitId) ?? null;
153
+ const bundleUnits = parseUnitIdsParam(getStringParam(search.units), units);
154
+ const includeLocalFlexiblePlan = (parseBooleanParam(search.bundle, false) || bundleUnits.length > 0) &&
155
+ isUondrBundleFlexiblePlanEligible(bundleUnits, siteCategories);
156
+ const isLocalCategory = isUondrLocalCategory(state.category, siteCategories);
157
+ const isAllowedUondrScheme = (scheme) => scheme.active &&
158
+ (!isLocalCategory ||
159
+ includeLocalFlexiblePlan ||
160
+ !isUondrFlexiblePaymentScheme(scheme));
134
161
  const resolvedScheme = selectedUnit
135
- ? getResolvedSchemeForUnit(selectedUnit, paymentSchemes, state.scheme)
136
- : (paymentSchemes.find((scheme) => scheme.id === state.scheme && scheme.active) ?? null);
162
+ ? getUondrResolvedSchemeForUnit(selectedUnit, paymentSchemes, state.scheme, siteCategories, { includeLocalFlexiblePlan })
163
+ : (paymentSchemes.find((scheme) => scheme.id === state.scheme && isAllowedUondrScheme(scheme)) ??
164
+ paymentSchemes.find((scheme) => scheme.id === rules.defaults.schemeId && isAllowedUondrScheme(scheme)) ??
165
+ paymentSchemes.find(isAllowedUondrScheme) ??
166
+ null);
137
167
  return {
138
168
  ...state,
169
+ scheme: resolvedScheme?.id ?? state.scheme,
139
170
  postDeliveryYears: rules.defaults.postDeliveryYears,
140
- downPaymentPct: clampUondrCashbackDownPaymentPct(resolvedScheme, state.downPaymentPct),
171
+ downPaymentPct: resolvedScheme?.type === "cashback"
172
+ ? clampUondrCashbackDownPaymentPct(resolvedScheme, parseNumberParam(pickNumericParam(search.downPaymentPct, search.enganche), UONDR_CASHBACK_DIRECT_DOWN_PAYMENT_PCT))
173
+ : state.downPaymentPct,
174
+ cashbackPaymentOption: normalizeCashbackPaymentOptionId(state.cashbackPaymentOption),
141
175
  includeIva: false,
142
176
  };
143
177
  }
@@ -150,6 +184,7 @@ export function buildQuoteSearch(state) {
150
184
  params.set("scheme", state.scheme);
151
185
  params.set("years", String(state.postDeliveryYears));
152
186
  params.set("enganche", String(state.downPaymentPct));
187
+ params.set("cashbackPlan", normalizeCashbackPaymentOptionId(state.cashbackPaymentOption));
153
188
  params.set("iEng", String(state.installmentDownPaymentPct));
154
189
  params.set("iMens", String(state.installmentMonthlyPct));
155
190
  params.set("iva", state.includeIva ? "1" : "0");
package/dist/quote.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./bundle-payment-schedule.calc.js";
2
2
  export * from "./calculate-quote.js";
3
+ export * from "./cashback-payment-options.js";
3
4
  export * from "./corporate-actions.js";
4
5
  export * from "./corporate-rent.js";
5
6
  export * from "./delivery-date.js";
package/dist/quote.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./bundle-payment-schedule.calc.js";
2
2
  export * from "./calculate-quote.js";
3
+ export * from "./cashback-payment-options.js";
3
4
  export * from "./corporate-actions.js";
4
5
  export * from "./corporate-rent.js";
5
6
  export * from "./delivery-date.js";
@@ -1,4 +1,7 @@
1
- import type { AppContent, InventoryCategory, QuoteUrlState } from "./types.js";
1
+ import type { AppContent, CashbackPaymentOptionId, InventoryCategory, QuoteUrlState } from "./types.js";
2
+ export type CotizadorSelectionOptions = {
3
+ includeLocalFlexiblePlan?: boolean;
4
+ };
2
5
  export type CotizadorSurface = "default" | "social" | "uondr" | "a-uondr" | "ud" | "entrada";
3
6
  export type CotizadorSelectionState = QuoteUrlState;
4
7
  export type CotizadorSelectionAction = {
@@ -7,28 +10,40 @@ export type CotizadorSelectionAction = {
7
10
  } | {
8
11
  type: "selectCategory";
9
12
  category: InventoryCategory;
13
+ options?: CotizadorSelectionOptions;
10
14
  } | {
11
15
  type: "selectUnit";
12
16
  unitId: string;
17
+ options?: CotizadorSelectionOptions;
13
18
  } | {
14
19
  type: "selectScheme";
15
20
  schemeId: string;
21
+ options?: CotizadorSelectionOptions;
16
22
  } | {
17
23
  type: "setPostDeliveryYears";
18
24
  value: number;
25
+ options?: CotizadorSelectionOptions;
19
26
  } | {
20
27
  type: "setDownPaymentPct";
21
28
  value: number;
29
+ options?: CotizadorSelectionOptions;
30
+ } | {
31
+ type: "setCashbackPaymentOption";
32
+ value: CashbackPaymentOptionId;
33
+ options?: CotizadorSelectionOptions;
22
34
  } | {
23
35
  type: "setInstallmentDownPaymentPct";
24
36
  value: number;
37
+ options?: CotizadorSelectionOptions;
25
38
  } | {
26
39
  type: "setInstallmentMonthlyPct";
27
40
  value: number;
41
+ options?: CotizadorSelectionOptions;
28
42
  } | {
29
43
  type: "setIncludeIva";
30
44
  value: boolean;
45
+ options?: CotizadorSelectionOptions;
31
46
  };
32
- export declare function normalizeSelectionState(requestedState: CotizadorSelectionState, content: AppContent, surface: CotizadorSurface): CotizadorSelectionState;
47
+ export declare function normalizeSelectionState(requestedState: CotizadorSelectionState, content: AppContent, surface: CotizadorSurface, options?: CotizadorSelectionOptions): CotizadorSelectionState;
33
48
  export declare function createInitialSelectionState(content: AppContent, surface: CotizadorSurface): QuoteUrlState;
34
49
  export declare function reduceSelectionState(state: CotizadorSelectionState, action: CotizadorSelectionAction, content: AppContent, surface: CotizadorSurface): QuoteUrlState;
@@ -1,5 +1,6 @@
1
- import { clampToRange, getDefaultDownPaymentPctForScheme, getPaymentSchemeById, getResolvedSchemeForUnit, } from "./payment-schemes.js";
1
+ import { clampToRange, getDefaultDownPaymentPctForScheme, getPaymentSchemeById, getResolvedSchemeForUnit, getUondrResolvedSchemeForUnit, isUondrFlexiblePaymentScheme, isUondrLocalCategory, } from "./payment-schemes.js";
2
2
  import { clampUondrCashbackDownPaymentPct, getSocialDefaultDownPaymentPct, SOCIAL_INCLUDE_IVA, } from "./social-quote.js";
3
+ import { CASHBACK_PAYMENT_OPTION_DIRECT, UONDR_CASHBACK_DIRECT_DOWN_PAYMENT_PCT, normalizeCashbackPaymentOptionId, } from "./cashback-payment-options.js";
3
4
  import { clampInstallmentDownPaymentPct, clampInstallmentMonthlyPct, INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT, INSTALLMENT_DEFAULT_MONTHLY_PCT, } from "./installment-allocation.js";
4
5
  function isNonEmptyString(value) {
5
6
  return typeof value === "string" && value.trim().length > 0;
@@ -30,22 +31,39 @@ function getDefaultUnitForCategory(units, defaultUnitId, category) {
30
31
  units.find((unit) => unit.category === category) ??
31
32
  null);
32
33
  }
33
- function getFallbackScheme(content, requestedSchemeId, category) {
34
+ function getFallbackScheme(content, requestedSchemeId, category, surface, options) {
34
35
  const defaultUnitForCategory = getDefaultUnitForCategory(content.inventory, content.financeRules.defaults.unitId, category);
35
36
  if (defaultUnitForCategory) {
37
+ if (surface === "uondr" || surface === "a-uondr") {
38
+ return getUondrResolvedSchemeForUnit(defaultUnitForCategory, content.paymentSchemes, requestedSchemeId, content.siteContent.categories, {
39
+ includeLocalFlexiblePlan: options.includeLocalFlexiblePlan,
40
+ });
41
+ }
36
42
  return getResolvedSchemeForUnit(defaultUnitForCategory, content.paymentSchemes, requestedSchemeId);
37
43
  }
44
+ const disallowUondrFlexibleScheme = (surface === "uondr" || surface === "a-uondr") &&
45
+ isUondrLocalCategory(category, content.siteContent.categories) &&
46
+ !options.includeLocalFlexiblePlan;
38
47
  const defaultScheme = getPaymentSchemeById(content.paymentSchemes, content.financeRules.defaults.schemeId);
39
- return (content.paymentSchemes.find((scheme) => scheme.id === requestedSchemeId && scheme.active) ??
40
- (defaultScheme?.active ? defaultScheme : null) ??
41
- content.paymentSchemes.find((scheme) => scheme.active) ??
48
+ const isAllowedFallbackScheme = (scheme) => scheme.active &&
49
+ (!disallowUondrFlexibleScheme || !isUondrFlexiblePaymentScheme(scheme));
50
+ return (content.paymentSchemes.find((scheme) => scheme.id === requestedSchemeId && isAllowedFallbackScheme(scheme)) ??
51
+ (defaultScheme && isAllowedFallbackScheme(defaultScheme)
52
+ ? defaultScheme
53
+ : null) ??
54
+ content.paymentSchemes.find(isAllowedFallbackScheme) ??
42
55
  null);
43
56
  }
44
- function resolveScheme(content, unit, requestedSchemeId, category) {
57
+ function resolveScheme(content, unit, requestedSchemeId, category, surface, options) {
45
58
  if (unit) {
59
+ if (surface === "uondr" || surface === "a-uondr") {
60
+ return getUondrResolvedSchemeForUnit(unit, content.paymentSchemes, requestedSchemeId, content.siteContent.categories, {
61
+ includeLocalFlexiblePlan: options.includeLocalFlexiblePlan,
62
+ });
63
+ }
46
64
  return getResolvedSchemeForUnit(unit, content.paymentSchemes, requestedSchemeId);
47
65
  }
48
- return getFallbackScheme(content, requestedSchemeId, category);
66
+ return getFallbackScheme(content, requestedSchemeId, category, surface, options);
49
67
  }
50
68
  function getResolvedDownPaymentPct(surface, requestedState, scheme, content) {
51
69
  if (scheme?.type === "cashback" &&
@@ -60,7 +78,7 @@ function getResolvedDownPaymentPct(surface, requestedState, scheme, content) {
60
78
  }
61
79
  return getDefaultDownPaymentPctForScheme(scheme, content.financeRules);
62
80
  }
63
- export function normalizeSelectionState(requestedState, content, surface) {
81
+ export function normalizeSelectionState(requestedState, content, surface, options = {}) {
64
82
  const availableCategories = getAvailableCategories(content);
65
83
  const requestedUnit = getUnitById(content.inventory, requestedState.unitId);
66
84
  const resolvedCategory = availableCategories.includes(requestedState.category)
@@ -69,7 +87,7 @@ export function normalizeSelectionState(requestedState, content, surface) {
69
87
  const resolvedUnit = requestedUnit && requestedUnit.category === resolvedCategory
70
88
  ? requestedUnit
71
89
  : null;
72
- const resolvedScheme = resolveScheme(content, resolvedUnit, requestedState.scheme, resolvedCategory);
90
+ const resolvedScheme = resolveScheme(content, resolvedUnit, requestedState.scheme, resolvedCategory, surface, options);
73
91
  const installmentDownPaymentPct = clampInstallmentDownPaymentPct(requestedState.installmentDownPaymentPct ??
74
92
  INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT);
75
93
  const installmentMonthlyPct = clampInstallmentMonthlyPct(requestedState.installmentMonthlyPct ?? INSTALLMENT_DEFAULT_MONTHLY_PCT, installmentDownPaymentPct);
@@ -81,6 +99,9 @@ export function normalizeSelectionState(requestedState, content, surface) {
81
99
  ? clampToRange(requestedState.postDeliveryYears, content.financeRules.ranges.postDeliveryYears)
82
100
  : content.financeRules.defaults.postDeliveryYears,
83
101
  downPaymentPct: getResolvedDownPaymentPct(surface, requestedState, resolvedScheme, content),
102
+ cashbackPaymentOption: resolvedScheme?.type === "cashback"
103
+ ? normalizeCashbackPaymentOptionId(requestedState.cashbackPaymentOption)
104
+ : CASHBACK_PAYMENT_OPTION_DIRECT,
84
105
  installmentDownPaymentPct,
85
106
  installmentMonthlyPct,
86
107
  includeIva: surface === "default" ? requestedState.includeIva : SOCIAL_INCLUDE_IVA,
@@ -92,7 +113,10 @@ export function createInitialSelectionState(content, surface) {
92
113
  unitId: content.financeRules.defaults.unitId,
93
114
  scheme: content.financeRules.defaults.schemeId,
94
115
  postDeliveryYears: content.financeRules.defaults.postDeliveryYears,
95
- downPaymentPct: content.financeRules.defaults.downPaymentPct,
116
+ downPaymentPct: surface === "uondr" || surface === "a-uondr"
117
+ ? UONDR_CASHBACK_DIRECT_DOWN_PAYMENT_PCT
118
+ : content.financeRules.defaults.downPaymentPct,
119
+ cashbackPaymentOption: CASHBACK_PAYMENT_OPTION_DIRECT,
96
120
  installmentDownPaymentPct: INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT,
97
121
  installmentMonthlyPct: INSTALLMENT_DEFAULT_MONTHLY_PCT,
98
122
  includeIva: false,
@@ -109,7 +133,7 @@ export function reduceSelectionState(state, action, content, surface) {
109
133
  ...state,
110
134
  category: action.category,
111
135
  unitId: nextUnitId,
112
- }, content, surface);
136
+ }, content, surface, action.options);
113
137
  }
114
138
  case "selectUnit": {
115
139
  const selectedUnit = getUnitById(content.inventory, action.unitId);
@@ -120,37 +144,42 @@ export function reduceSelectionState(state, action, content, surface) {
120
144
  ...state,
121
145
  category: selectedUnit.category,
122
146
  unitId: selectedUnit.id,
123
- }, content, surface);
147
+ }, content, surface, action.options);
124
148
  }
125
149
  case "selectScheme":
126
150
  return normalizeSelectionState({
127
151
  ...state,
128
152
  scheme: action.schemeId,
129
- }, content, surface);
153
+ }, content, surface, action.options);
130
154
  case "setPostDeliveryYears":
131
155
  return normalizeSelectionState({
132
156
  ...state,
133
157
  postDeliveryYears: action.value,
134
- }, content, surface);
158
+ }, content, surface, action.options);
135
159
  case "setDownPaymentPct":
136
160
  return normalizeSelectionState({
137
161
  ...state,
138
162
  downPaymentPct: action.value,
139
- }, content, surface);
163
+ }, content, surface, action.options);
164
+ case "setCashbackPaymentOption":
165
+ return normalizeSelectionState({
166
+ ...state,
167
+ cashbackPaymentOption: action.value,
168
+ }, content, surface, action.options);
140
169
  case "setInstallmentDownPaymentPct":
141
170
  return normalizeSelectionState({
142
171
  ...state,
143
172
  installmentDownPaymentPct: action.value,
144
- }, content, surface);
173
+ }, content, surface, action.options);
145
174
  case "setInstallmentMonthlyPct":
146
175
  return normalizeSelectionState({
147
176
  ...state,
148
177
  installmentMonthlyPct: action.value,
149
- }, content, surface);
178
+ }, content, surface, action.options);
150
179
  case "setIncludeIva":
151
180
  return normalizeSelectionState({
152
181
  ...state,
153
182
  includeIva: action.value,
154
- }, content, surface);
183
+ }, content, surface, action.options);
155
184
  }
156
185
  }
@@ -1,8 +1,8 @@
1
- import type { FinanceRules, InventoryUnit, PaymentSchemeDefinition, QuoteInput, QuoteUrlState } from "./types.js";
1
+ import type { CashbackPaymentOptionId, FinanceRules, InventoryUnit, PaymentSchemeDefinition, QuoteInput, QuoteUrlState } from "./types.js";
2
2
  export declare const SOCIAL_INCLUDE_IVA = false;
3
- export declare const UONDR_CASHBACK_MIN_DOWN_PAYMENT_PCT = 60;
4
3
  export declare function isSameQuoteState(left: QuoteUrlState, right: QuoteUrlState): boolean;
5
4
  export declare function getSocialDefaultDownPaymentPct(scheme: PaymentSchemeDefinition | null, financeRules: FinanceRules): number;
6
5
  export declare function getSocialQuoteInput(unit: InventoryUnit, scheme: PaymentSchemeDefinition, financeRules: FinanceRules): QuoteInput;
7
6
  export declare function getSocialQuoteInputWithCashbackDownPayment(unit: InventoryUnit, scheme: PaymentSchemeDefinition, financeRules: FinanceRules, downPaymentPct: number): QuoteInput;
7
+ export declare function getSocialQuoteInputWithCashbackPaymentOption(unit: InventoryUnit, scheme: PaymentSchemeDefinition, financeRules: FinanceRules, optionId: CashbackPaymentOptionId | undefined, downPaymentPct?: number): QuoteInput;
8
8
  export declare function clampUondrCashbackDownPaymentPct(scheme: PaymentSchemeDefinition | null, downPaymentPct: number): number;
@@ -1,13 +1,15 @@
1
1
  import { clampToRange, getDefaultDownPaymentPctForScheme, isCashbackScheme, isInstallmentScheme, } from "./payment-schemes.js";
2
2
  import { INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT, INSTALLMENT_DEFAULT_MONTHLY_PCT, } from "./installment-allocation.js";
3
+ import { CASHBACK_PAYMENT_OPTION_DIRECT, getUondrCashbackDirectDownPaymentRange, getUondrCashbackOptionDownPaymentPct, normalizeCashbackPaymentOptionId, } from "./cashback-payment-options.js";
3
4
  export const SOCIAL_INCLUDE_IVA = false;
4
- export const UONDR_CASHBACK_MIN_DOWN_PAYMENT_PCT = 60;
5
5
  export function isSameQuoteState(left, right) {
6
6
  return (left.category === right.category &&
7
7
  left.unitId === right.unitId &&
8
8
  left.scheme === right.scheme &&
9
9
  left.postDeliveryYears === right.postDeliveryYears &&
10
10
  left.downPaymentPct === right.downPaymentPct &&
11
+ normalizeCashbackPaymentOptionId(left.cashbackPaymentOption) ===
12
+ normalizeCashbackPaymentOptionId(right.cashbackPaymentOption) &&
11
13
  left.installmentDownPaymentPct === right.installmentDownPaymentPct &&
12
14
  left.installmentMonthlyPct === right.installmentMonthlyPct &&
13
15
  left.includeIva === right.includeIva);
@@ -25,6 +27,7 @@ export function getSocialQuoteInput(unit, scheme, financeRules) {
25
27
  plusvaliaAnnualPct: financeRules.defaults.plusvaliaAnnualPct,
26
28
  postDeliveryYears: financeRules.defaults.postDeliveryYears,
27
29
  downPaymentPct: getSocialDefaultDownPaymentPct(scheme, financeRules),
30
+ cashbackPaymentOption: CASHBACK_PAYMENT_OPTION_DIRECT,
28
31
  installmentDownPaymentPct: INSTALLMENT_DEFAULT_DOWN_PAYMENT_PCT,
29
32
  installmentMonthlyPct: INSTALLMENT_DEFAULT_MONTHLY_PCT,
30
33
  includeIva: SOCIAL_INCLUDE_IVA,
@@ -40,12 +43,24 @@ export function getSocialQuoteInputWithCashbackDownPayment(unit, scheme, finance
40
43
  downPaymentPct: clampToRange(downPaymentPct, scheme.downPaymentRange),
41
44
  };
42
45
  }
46
+ export function getSocialQuoteInputWithCashbackPaymentOption(unit, scheme, financeRules, optionId, downPaymentPct) {
47
+ const input = getSocialQuoteInput(unit, scheme, financeRules);
48
+ if (!isCashbackScheme(scheme)) {
49
+ return input;
50
+ }
51
+ const cashbackPaymentOption = normalizeCashbackPaymentOptionId(optionId);
52
+ return {
53
+ ...input,
54
+ cashbackPaymentOption,
55
+ downPaymentPct: getUondrCashbackOptionDownPaymentPct(scheme, cashbackPaymentOption, downPaymentPct),
56
+ };
57
+ }
58
+ // The stored enganche always tracks the direct-option range, even while the
59
+ // staged option is selected (staged math fixes its own 30%), so the slider
60
+ // value survives toggling between options and URL round-trips.
43
61
  export function clampUondrCashbackDownPaymentPct(scheme, downPaymentPct) {
44
62
  if (!scheme || !isCashbackScheme(scheme)) {
45
63
  return downPaymentPct;
46
64
  }
47
- return clampToRange(downPaymentPct, {
48
- ...scheme.downPaymentRange,
49
- min: Math.max(scheme.downPaymentRange.min, UONDR_CASHBACK_MIN_DOWN_PAYMENT_PCT),
50
- });
65
+ return clampToRange(downPaymentPct, getUondrCashbackDirectDownPaymentRange(scheme));
51
66
  }
package/dist/types.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type PaymentSchemeType = "cashback" | "installment";
2
+ export type CashbackPaymentOptionId = "direct" | "staged";
2
3
  export type PaymentProvider = "mercado_pago" | "stripe";
3
4
  export type InventoryStatus = "available" | "reserved" | "sold" | "unavailable";
4
5
  export type InventoryStatusLabels = {
@@ -147,6 +148,7 @@ export interface SiteContent {
147
148
  heroEyebrow: string;
148
149
  heroTitle: string;
149
150
  heroDescription: string;
151
+ salesWhatsappPhone?: string;
150
152
  splash: SplashScreenContent;
151
153
  favicon?: UploadedImageAsset;
152
154
  uondrHeaderIcon?: UploadedImageAsset;
@@ -195,6 +197,7 @@ export interface QuoteInput {
195
197
  plusvaliaAnnualPct: number;
196
198
  postDeliveryYears: number;
197
199
  downPaymentPct: number;
200
+ cashbackPaymentOption?: CashbackPaymentOptionId;
198
201
  installmentDownPaymentPct?: number;
199
202
  installmentMonthlyPct?: number;
200
203
  includeIva: boolean;
@@ -279,6 +282,7 @@ export interface QuoteUrlState {
279
282
  scheme: string;
280
283
  postDeliveryYears: number;
281
284
  downPaymentPct: number;
285
+ cashbackPaymentOption?: CashbackPaymentOptionId;
282
286
  installmentDownPaymentPct?: number;
283
287
  installmentMonthlyPct?: number;
284
288
  includeIva: boolean;
@@ -417,6 +421,146 @@ export interface PublicSessionResponse {
417
421
  token: string;
418
422
  tokenType: "Bearer";
419
423
  }
424
+ export type JourneyErrorCode = "origin_denied" | "mapping_not_found" | "configuration_required" | "configuration_invalid" | "quote_expired" | "unit_unavailable" | "hold_conflict" | "payment_conflict" | "rate_limited" | "session_expired";
425
+ export type JourneyStatus = "active" | "payment_pending" | "operation_pending" | "completed" | "paid_conflict" | "expired";
426
+ export type JourneyConfigurationStatus = "required" | "completed" | "invalid" | "superseded";
427
+ export type JourneyQuoteStatus = "active" | "expired" | "superseded" | "consumed";
428
+ export type JourneyHoldStatus = "acquiring" | "active" | "confirmed" | "released" | "expired" | "conflict";
429
+ export type JourneyCheckoutStatus = "not_started" | "pending" | "requires_action" | "paid" | "failed";
430
+ export type JourneyOperationStatus = "not_started" | "pending" | "draft_created";
431
+ export interface JourneyApiErrorBody extends DesarrollosApiErrorBody {
432
+ code: JourneyErrorCode;
433
+ }
434
+ export interface PublicJourneySelection {
435
+ selectedAt: string;
436
+ unit: InventoryUnit;
437
+ }
438
+ export interface PublicJourneyConfiguration {
439
+ completedAt: string | null;
440
+ configurationId: string | null;
441
+ hash: string | null;
442
+ revision: number | null;
443
+ status: JourneyConfigurationStatus;
444
+ }
445
+ export interface PublicJourneyQuote {
446
+ bookingAmountMXN: number;
447
+ configurationAdjustmentMXN: 0;
448
+ createdAt: string;
449
+ currency: "MXN";
450
+ expiresAt: string;
451
+ id: string;
452
+ revision: number;
453
+ status: JourneyQuoteStatus;
454
+ totalPriceMXN: number;
455
+ unitPriceMXN: number;
456
+ }
457
+ export interface PublicJourneyHold {
458
+ expiresAt: string | null;
459
+ id: string;
460
+ status: JourneyHoldStatus;
461
+ unitId: string;
462
+ updatedAt: string;
463
+ }
464
+ export interface PublicJourneyCheckout {
465
+ checkoutUrl: string | null;
466
+ externalReference: string | null;
467
+ provider: PaymentProvider;
468
+ providerStatus: string | null;
469
+ status: JourneyCheckoutStatus;
470
+ updatedAt: string;
471
+ }
472
+ export interface PublicJourneyConflict {
473
+ code: "payment_conflict";
474
+ createdAt: string;
475
+ id: string;
476
+ status: "open" | "resolved";
477
+ }
478
+ export interface PublicJourneyOperation {
479
+ id: string | null;
480
+ status: JourneyOperationStatus;
481
+ updatedAt: string | null;
482
+ }
483
+ export interface PublicJourneyStatus {
484
+ checkout: PublicJourneyCheckout | null;
485
+ configuration: PublicJourneyConfiguration;
486
+ conflict: PublicJourneyConflict | null;
487
+ createdAt: string;
488
+ expiresAt: string;
489
+ hold: PublicJourneyHold | null;
490
+ id: string;
491
+ leadStatus: "required" | "completed";
492
+ operation: PublicJourneyOperation;
493
+ quote: PublicJourneyQuote | null;
494
+ selection: PublicJourneySelection | null;
495
+ status: JourneyStatus;
496
+ updatedAt: string;
497
+ }
498
+ export interface CreateJourneyResponse {
499
+ eligibleUnitIds: string[];
500
+ journey: PublicJourneyStatus;
501
+ journeyToken: string;
502
+ tokenType: "Bearer";
503
+ turnstileSiteKey: string;
504
+ }
505
+ export interface CreateJourneyRequest {
506
+ integrationKey: string;
507
+ journeyToken?: string;
508
+ }
509
+ export interface JourneyRequest {
510
+ journeyId: string;
511
+ journeyToken: string;
512
+ }
513
+ export type GetJourneyRequest = JourneyRequest;
514
+ export type GetJourneyResponse = PublicJourneyStatus;
515
+ export interface UpdateJourneySelectionRequest extends JourneyRequest {
516
+ selection: {
517
+ unitId: string;
518
+ };
519
+ }
520
+ export interface PublicJourneyConfiguratorSession {
521
+ allowedDesignIds: string[];
522
+ embedUrl: string;
523
+ expiresAt: string;
524
+ protocolVersion: "1.0";
525
+ restoreConfiguration: {
526
+ configurationId: string;
527
+ hash: string;
528
+ revision: number;
529
+ } | null;
530
+ sessionId: string;
531
+ }
532
+ export interface CreateJourneyConfiguratorSessionResponse {
533
+ journey: PublicJourneyStatus;
534
+ session: PublicJourneyConfiguratorSession;
535
+ }
536
+ export type CreateJourneyConfiguratorSessionRequest = JourneyRequest;
537
+ export interface CompleteJourneyConfigurationRequest extends JourneyRequest {
538
+ configuration: {
539
+ configurationId: string;
540
+ hash: string;
541
+ revision: number;
542
+ };
543
+ }
544
+ export interface UpdateJourneyLeadRequest extends JourneyRequest {
545
+ lead: {
546
+ email: string;
547
+ name: string;
548
+ phone: string;
549
+ };
550
+ }
551
+ export interface CreateJourneyCheckoutRequest extends JourneyRequest {
552
+ checkout: {
553
+ idempotencyKey: string;
554
+ payment: PublicReservationPaymentRequest;
555
+ turnstileToken: string;
556
+ };
557
+ }
558
+ export type UpdateJourneySelectionResponse = PublicJourneyStatus;
559
+ export type CompleteJourneyConfigurationResponse = PublicJourneyStatus;
560
+ export type CreateJourneyQuoteRequest = JourneyRequest;
561
+ export type CreateJourneyQuoteResponse = PublicJourneyStatus;
562
+ export type UpdateJourneyLeadResponse = PublicJourneyStatus;
563
+ export type CreateJourneyCheckoutResponse = PublicJourneyStatus;
420
564
  export interface PublicReservationItemRequest {
421
565
  productKind?: ReservationProductKind;
422
566
  productLabel?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@grupolapa/desarrollos-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-agnostic TypeScript SDK for Grupo LAPA public desarrollo integrations.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",
@@ -23,6 +23,11 @@
23
23
  "import": "./dist/server.js",
24
24
  "default": "./dist/server.js"
25
25
  },
26
+ "./embed": {
27
+ "types": "./dist/embed-protocol.d.ts",
28
+ "import": "./dist/embed-protocol.js",
29
+ "default": "./dist/embed-protocol.js"
30
+ },
26
31
  "./quote": {
27
32
  "types": "./dist/quote.d.ts",
28
33
  "import": "./dist/quote.js",
@@ -45,7 +50,7 @@
45
50
  },
46
51
  "scripts": {
47
52
  "build": "rm -rf dist && tsc -p tsconfig.build.json && node scripts/add-js-extensions.mjs",
48
- "prepack": "pnpm run build",
53
+ "test": "node --import tsx --test \"src/**/*.test.ts\"",
49
54
  "typecheck": "tsc --noEmit"
50
55
  }
51
- }
56
+ }