hvp-shared 6.47.0 → 6.47.1

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.
@@ -128,8 +128,8 @@ export declare function calculateRecommendedPricePVP(params: {
128
128
  unitPurchasePriceBI: number;
129
129
  vatSalePercent: number;
130
130
  }): number | null;
131
- /** Cost-based multiplier for floor price (PHARM, PHARM_FRAC, COST_ML, COST) */
132
- export declare const MIN_PRICE_COST_FACTOR = 0.25;
131
+ /** Cost-based multiplier for floor price (PHARM, PHARM_FRAC, COST_ML, COST) — cost + 25% margin */
132
+ export declare const MIN_PRICE_COST_FACTOR = 1.25;
133
133
  /** Cost-based multiplier for floor price (EXT_COST) */
134
134
  export declare const MIN_PRICE_EXT_COST_FACTOR = 1;
135
135
  /** Fraction of salePricePVP for recommended minimum price (COMP_SVC) */
@@ -218,9 +218,11 @@ function getDefaultPricePolicy(section, saleUnit, conversionFactor) {
218
218
  // =============================================================================
219
219
  // ROUNDING HELPER
220
220
  // =============================================================================
221
- /** Round to nearest multiple of 5 */
221
+ /** Round to nearest multiple of 5 (minimum 5 for positive values) */
222
222
  function roundToNearest5(value) {
223
- return Math.round(value / 5) * 5;
223
+ if (value <= 0)
224
+ return 0;
225
+ return Math.max(5, Math.round(value / 5) * 5);
224
226
  }
225
227
  /**
226
228
  * Calculate the recommended price PVP (con IVA) for a catalog item.
@@ -243,8 +245,8 @@ function calculateRecommendedPricePVP(params) {
243
245
  // =============================================================================
244
246
  // FLOOR PRICE CALCULATION
245
247
  // =============================================================================
246
- /** Cost-based multiplier for floor price (PHARM, PHARM_FRAC, COST_ML, COST) */
247
- exports.MIN_PRICE_COST_FACTOR = 0.25;
248
+ /** Cost-based multiplier for floor price (PHARM, PHARM_FRAC, COST_ML, COST) — cost + 25% margin */
249
+ exports.MIN_PRICE_COST_FACTOR = 1.25;
248
250
  /** Cost-based multiplier for floor price (EXT_COST) */
249
251
  exports.MIN_PRICE_EXT_COST_FACTOR = 1.0;
250
252
  /** Fraction of salePricePVP for recommended minimum price (COMP_SVC) */
@@ -319,17 +319,17 @@ describe('calculateFloorPrices', () => {
319
319
  const defaults = { unitPurchasePriceBI: 100, vatSalePercent: 16, salePricePVP: 500 };
320
320
  describe('cost-based policies (PHARM, PHARM_FRAC, COST_ML, COST)', () => {
321
321
  const costPolicies = [pricing_constants_1.PricePolicy.PHARM, pricing_constants_1.PricePolicy.PHARM_FRAC, pricing_constants_1.PricePolicy.COST_ML, pricing_constants_1.PricePolicy.COST];
322
- it.each(costPolicies)('%s: both = cost × 0.25 × (1+VAT/100), round5', (policy) => {
323
- // $100 * 0.25 * 1.16 = $29 → round5 = $30
322
+ it.each(costPolicies)('%s: both = cost × 1.25 × (1+VAT/100), round5', (policy) => {
323
+ // $100 * 1.25 * 1.16 = $145 → round5 = $145
324
324
  const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: policy });
325
- expect(result.recommendedMinimumPrice).toBe(30);
326
- expect(result.floorPrice).toBe(30);
325
+ expect(result.recommendedMinimumPrice).toBe(145);
326
+ expect(result.floorPrice).toBe(145);
327
327
  });
328
328
  it('should round to nearest 5', () => {
329
- // $80 * 0.25 * 1.16 = $23.20 → round5 = $25
329
+ // $80 * 1.25 * 1.16 = $116 → round5 = $115
330
330
  const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.PHARM, unitPurchasePriceBI: 80 });
331
- expect(result.recommendedMinimumPrice).toBe(25);
332
- expect(result.floorPrice).toBe(25);
331
+ expect(result.recommendedMinimumPrice).toBe(115);
332
+ expect(result.floorPrice).toBe(115);
333
333
  });
334
334
  it('should return null when cost is 0', () => {
335
335
  const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.PHARM, unitPurchasePriceBI: 0 });
@@ -342,14 +342,20 @@ describe('calculateFloorPrices', () => {
342
342
  expect(result.floorPrice).toBeNull();
343
343
  });
344
344
  it('should handle 0% VAT', () => {
345
- // $100 * 0.25 * 1.0 = $25 → $25
345
+ // $100 * 1.25 * 1.0 = $125 → $125
346
346
  const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.COST, vatSalePercent: 0 });
347
- expect(result.recommendedMinimumPrice).toBe(25);
348
- expect(result.floorPrice).toBe(25);
347
+ expect(result.recommendedMinimumPrice).toBe(125);
348
+ expect(result.floorPrice).toBe(125);
349
+ });
350
+ it('should never return less than 5 for positive cost', () => {
351
+ // $1 * 1.25 * 1.0 = $1.25 → round5 = 0, but min is 5
352
+ const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.PHARM, unitPurchasePriceBI: 1, vatSalePercent: 0 });
353
+ expect(result.recommendedMinimumPrice).toBe(5);
354
+ expect(result.floorPrice).toBe(5);
349
355
  });
350
356
  });
351
357
  describe('EXT_COST', () => {
352
- it('both = cost × 1.0 × (1+VAT/100), round5', () => {
358
+ it('both = cost × 1.0 × (1+VAT/100), round5 (at-cost recovery)', () => {
353
359
  // $100 * 1.0 * 1.16 = $116 → round5 = $115
354
360
  const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.EXT_COST });
355
361
  expect(result.recommendedMinimumPrice).toBe(115);
@@ -366,6 +372,12 @@ describe('calculateFloorPrices', () => {
366
372
  expect(result.recommendedMinimumPrice).toBe(230);
367
373
  expect(result.floorPrice).toBe(230);
368
374
  });
375
+ it('should never return less than 5 for positive cost', () => {
376
+ // $2 * 1.0 * 1.0 = $2 → round5 = 0, but min is 5
377
+ const result = (0, pricing_constants_1.calculateFloorPrices)({ ...defaults, pricePolicy: pricing_constants_1.PricePolicy.EXT_COST, unitPurchasePriceBI: 2, vatSalePercent: 0 });
378
+ expect(result.recommendedMinimumPrice).toBe(5);
379
+ expect(result.floorPrice).toBe(5);
380
+ });
369
381
  });
370
382
  describe('COMP_SVC', () => {
371
383
  it('recommendedMinimumPrice = salePricePVP × 0.50, floorPrice = 0', () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hvp-shared",
3
- "version": "6.47.0",
3
+ "version": "6.47.1",
4
4
  "description": "Shared types and utilities for HVP backend and frontend",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",