File size: 3,766 Bytes
ce8f04a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
 * Node built-in test runner for pure eligibility spine display helpers.
 * Mirrors eligibilitySpineModel.ts (kept small + isolated).
 * Run: node --test src/components/company/eligibilitySpineModel.node-test.mjs
 */
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';

const DE_MINIMIS_LIMIT_EUR = 300_000;

const MSP_LABELS = {
  mikro: 'Mikroprzedsiębiorstwo',
  mala: 'Małe przedsiębiorstwo',
  srednia: 'Średnie przedsiębiorstwo',
  duza: 'Duże przedsiębiorstwo',
  unknown: 'Nieustalony',
};

function normalizeNip(raw) {
  return String(raw || '').replace(/\D/g, '');
}

function isValidNip(raw) {
  return normalizeNip(raw).length === 10;
}

function mspLabel(status) {
  const key = String(status || 'unknown').toLowerCase();
  return MSP_LABELS[key] || status || MSP_LABELS.unknown;
}

function deMinimisUsage(dm) {
  const limit =
    dm?.limit_eur != null && !Number.isNaN(Number(dm.limit_eur))
      ? Number(dm.limit_eur)
      : DE_MINIMIS_LIMIT_EUR;
  const used =
    dm?.used_eur === null || dm?.used_eur === undefined || Number.isNaN(Number(dm.used_eur))
      ? null
      : Number(dm.used_eur);
  let remaining =
    dm?.remaining_eur === null ||
    dm?.remaining_eur === undefined ||
    Number.isNaN(Number(dm.remaining_eur))
      ? null
      : Number(dm.remaining_eur);
  if (remaining === null && used !== null) {
    remaining = Math.max(0, limit - used);
  }
  const exhausted =
    Boolean(dm?.exhausted) ||
    (remaining !== null && remaining <= 0) ||
    (used !== null && used >= limit);
  const usagePct =
    used !== null && limit > 0 ? Math.min(100, Math.max(0, (used / limit) * 100)) : 0;
  return { used, limit, remaining, exhausted, usagePct };
}

describe('normalizeNip / isValidNip', () => {
  it('strips dashes and spaces', () => {
    assert.equal(normalizeNip('521-321-45-67'), '5213214567');
    assert.equal(normalizeNip('521 321 45 67'), '5213214567');
  });

  it('strips non-digit junk', () => {
    assert.equal(normalizeNip('NIP: 5213214567'), '5213214567');
  });

  it('validates exact 10 digits', () => {
    assert.equal(isValidNip('5213214567'), true);
    assert.equal(isValidNip('521-321-45-67'), true);
    assert.equal(isValidNip('123'), false);
    assert.equal(isValidNip(''), false);
  });
});

describe('mspLabel', () => {
  it('maps known statuses', () => {
    assert.equal(mspLabel('mikro'), 'Mikroprzedsiębiorstwo');
    assert.equal(mspLabel('duza'), 'Duże przedsiębiorstwo');
    assert.equal(mspLabel('unknown'), 'Nieustalony');
  });

  it('falls back for empty', () => {
    assert.equal(mspLabel(null), 'Nieustalony');
    assert.equal(mspLabel(''), 'Nieustalony');
  });
});

describe('deMinimisUsage', () => {
  it('defaults limit to 300000', () => {
    const u = deMinimisUsage({ used_eur: 50_000 });
    assert.equal(u.limit, 300_000);
    assert.equal(u.used, 50_000);
    assert.equal(u.remaining, 250_000);
    assert.equal(u.exhausted, false);
    assert.ok(u.usagePct > 16 && u.usagePct < 17);
  });

  it('marks exhausted at limit', () => {
    const u = deMinimisUsage({ used_eur: 300_000, limit_eur: 300_000 });
    assert.equal(u.exhausted, true);
    assert.equal(u.remaining, 0);
    assert.equal(u.usagePct, 100);
  });

  it('respects explicit remaining and exhausted flag', () => {
    const u = deMinimisUsage({
      used_eur: 100,
      remaining_eur: 0,
      exhausted: true,
      limit_eur: 300_000,
    });
    assert.equal(u.remaining, 0);
    assert.equal(u.exhausted, true);
  });

  it('handles missing de minimis blob', () => {
    const u = deMinimisUsage(null);
    assert.equal(u.used, null);
    assert.equal(u.limit, 300_000);
    assert.equal(u.remaining, null);
    assert.equal(u.usagePct, 0);
  });
});