@ph-itdev/ph-warehouse-toolkit 0.1.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.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +117 -0
  3. package/dist/address.cjs +83 -0
  4. package/dist/address.cjs.map +1 -0
  5. package/dist/address.d.cts +24 -0
  6. package/dist/address.d.ts +24 -0
  7. package/dist/address.js +52 -0
  8. package/dist/address.js.map +1 -0
  9. package/dist/barcode.cjs +57 -0
  10. package/dist/barcode.cjs.map +1 -0
  11. package/dist/barcode.d.cts +5 -0
  12. package/dist/barcode.d.ts +5 -0
  13. package/dist/barcode.js +28 -0
  14. package/dist/barcode.js.map +1 -0
  15. package/dist/compliance.cjs +61 -0
  16. package/dist/compliance.cjs.map +1 -0
  17. package/dist/compliance.d.cts +26 -0
  18. package/dist/compliance.d.ts +26 -0
  19. package/dist/compliance.js +33 -0
  20. package/dist/compliance.js.map +1 -0
  21. package/dist/currency.cjs +91 -0
  22. package/dist/currency.cjs.map +1 -0
  23. package/dist/currency.d.cts +20 -0
  24. package/dist/currency.d.ts +20 -0
  25. package/dist/currency.js +57 -0
  26. package/dist/currency.js.map +1 -0
  27. package/dist/documents.cjs +59 -0
  28. package/dist/documents.cjs.map +1 -0
  29. package/dist/documents.d.cts +10 -0
  30. package/dist/documents.d.ts +10 -0
  31. package/dist/documents.js +30 -0
  32. package/dist/documents.js.map +1 -0
  33. package/dist/holidays.cjs +125 -0
  34. package/dist/holidays.cjs.map +1 -0
  35. package/dist/holidays.d.cts +14 -0
  36. package/dist/holidays.d.ts +14 -0
  37. package/dist/holidays.js +95 -0
  38. package/dist/holidays.js.map +1 -0
  39. package/dist/index.cjs +409 -0
  40. package/dist/index.cjs.map +1 -0
  41. package/dist/index.d.cts +8 -0
  42. package/dist/index.d.ts +8 -0
  43. package/dist/index.js +345 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/inventory.cjs +73 -0
  46. package/dist/inventory.cjs.map +1 -0
  47. package/dist/inventory.d.cts +28 -0
  48. package/dist/inventory.d.ts +28 -0
  49. package/dist/inventory.js +40 -0
  50. package/dist/inventory.js.map +1 -0
  51. package/dist/validation.cjs +54 -0
  52. package/dist/validation.cjs.map +1 -0
  53. package/dist/validation.d.cts +6 -0
  54. package/dist/validation.d.ts +6 -0
  55. package/dist/validation.js +24 -0
  56. package/dist/validation.js.map +1 -0
  57. package/package.json +74 -0
package/dist/index.js ADDED
@@ -0,0 +1,345 @@
1
+ // src/currency/format.ts
2
+ function formatPeso(amount, options = {}) {
3
+ const { decimals = 2 } = options;
4
+ const sign = amount < 0 ? "-" : "";
5
+ const abs = Math.abs(amount);
6
+ const formatted = abs.toLocaleString("en-PH", {
7
+ minimumFractionDigits: decimals,
8
+ maximumFractionDigits: decimals
9
+ });
10
+ return `${sign}\u20B1${formatted}`;
11
+ }
12
+ function parsePeso(value) {
13
+ const cleaned = value.replace(/[\u20B1,\s]/g, "");
14
+ return Number(cleaned);
15
+ }
16
+ function formatPesoShort(amount) {
17
+ const abs = Math.abs(amount);
18
+ const sign = amount < 0 ? "-" : "";
19
+ if (abs >= 1e6) {
20
+ const millions = abs / 1e6;
21
+ return `${sign}\u20B1${millions % 1 === 0 ? millions.toFixed(0) : millions.toFixed(1)}M`;
22
+ }
23
+ if (abs >= 1e3) {
24
+ const thousands = abs / 1e3;
25
+ return `${sign}\u20B1${thousands % 1 === 0 ? thousands.toFixed(0) : thousands.toFixed(1)}K`;
26
+ }
27
+ return `${sign}\u20B1${abs}`;
28
+ }
29
+
30
+ // src/currency/tax.ts
31
+ var VAT_RATE = 0.12;
32
+ var VAT_FACTOR = 1 + VAT_RATE;
33
+ function calculateVAT(netAmount) {
34
+ return Math.round(netAmount * VAT_RATE * 100) / 100;
35
+ }
36
+ function addVAT(netAmount) {
37
+ return Math.round(netAmount * VAT_FACTOR * 100) / 100;
38
+ }
39
+ function extractVAT(grossAmount) {
40
+ const vatableAmount = Math.round(grossAmount / VAT_FACTOR * 100) / 100;
41
+ const vatAmount = Math.round((grossAmount - vatableAmount) * 100) / 100;
42
+ return { vatableAmount, vatAmount, grossAmount };
43
+ }
44
+ function isVATRegistered(tin) {
45
+ return /^\d{3}-\d{3}-\d{3}-\d{3}$/.test(tin);
46
+ }
47
+
48
+ // src/address/data.ts
49
+ var REGIONS = [
50
+ { code: "NCR", name: "National Capital Region", provinces: ["Metro Manila"] },
51
+ { code: "01", name: "Ilocos Region", provinces: ["Ilocos Norte", "Ilocos Sur", "La Union", "Pangasinan"] },
52
+ { code: "02", name: "Cagayan Valley", provinces: ["Batanes", "Cagayan", "Isabela", "Nueva Vizcaya", "Quirino"] },
53
+ { code: "03", name: "Central Luzon", provinces: ["Aurora", "Bataan", "Bulacan", "Nueva Ecija", "Pampanga", "Tarlac", "Zambales"] },
54
+ { code: "04A", name: "CALABARZON", provinces: ["Batangas", "Cavite", "Laguna", "Quezon", "Rizal"] },
55
+ { code: "04B", name: "MIMAROPA", provinces: ["Marinduque", "Occidental Mindoro", "Oriental Mindoro", "Palawan", "Romblon"] },
56
+ { code: "05", name: "Bicol Region", provinces: ["Albay", "Camarines Norte", "Camarines Sur", "Catanduanes", "Masbate", "Sorsogon"] },
57
+ { code: "06", name: "Western Visayas", provinces: ["Aklan", "Antique", "Capiz", "Guimaras", "Iloilo", "Negros Occidental"] },
58
+ { code: "07", name: "Central Visayas", provinces: ["Bohol", "Cebu", "Negros Oriental", "Siquijor"] },
59
+ { code: "08", name: "Eastern Visayas", provinces: ["Biliran", "Eastern Samar", "Leyte", "Northern Samar", "Samar", "Southern Leyte"] },
60
+ { code: "09", name: "Zamboanga Peninsula", provinces: ["Zamboanga del Norte", "Zamboanga del Sur", "Zamboanga Sibugay"] },
61
+ { code: "10", name: "Northern Mindanao", provinces: ["Bukidnon", "Camiguin", "Lanao del Norte", "Misamis Occidental", "Misamis Oriental"] },
62
+ { code: "11", name: "Davao Region", provinces: ["Davao de Oro", "Davao del Norte", "Davao del Sur", "Davao Occidental", "Davao Oriental"] },
63
+ { code: "12", name: "SOCCSKSARGEN", provinces: ["Cotabato", "Sarangani", "South Cotabato", "Sultan Kudarat"] },
64
+ { code: "13", name: "Caraga", provinces: ["Agusan del Norte", "Agusan del Sur", "Dinagat Islands", "Surigao del Norte", "Surigao del Sur"] },
65
+ { code: "BARMM", name: "Bangsamoro Autonomous Region in Muslim Mindanao", provinces: ["Basilan", "Lanao del Sur", "Maguindanao", "Sulu", "Tawi-Tawi"] },
66
+ { code: "CAR", name: "Cordillera Administrative Region", provinces: ["Abra", "Apayao", "Benguet", "Ifugao", "Kalinga", "Mountain Province"] }
67
+ ];
68
+
69
+ // src/address/lookup.ts
70
+ function getRegions() {
71
+ return [...REGIONS];
72
+ }
73
+ function getRegionByCode(code) {
74
+ return REGIONS.find((r) => r.code === code);
75
+ }
76
+ function getProvinces(regionCode) {
77
+ const region = getRegionByCode(regionCode);
78
+ return region ? [...region.provinces] : [];
79
+ }
80
+ function formatAddress(addr) {
81
+ const parts = [];
82
+ if (addr.unit) parts.push(addr.unit);
83
+ if (addr.floor) parts.push(`Floor ${addr.floor}`);
84
+ if (addr.building) parts.push(addr.building);
85
+ if (addr.street) parts.push(addr.street);
86
+ if (addr.barangay) parts.push(`Brgy. ${addr.barangay}`);
87
+ if (addr.city) parts.push(addr.city);
88
+ if (addr.province) parts.push(addr.province);
89
+ if (addr.zipCode) parts.push(addr.zipCode);
90
+ return parts.join(", ");
91
+ }
92
+
93
+ // src/compliance/index.ts
94
+ function formatTIN(tin) {
95
+ const cleaned = tin.replace(/[^0-9]/g, "");
96
+ if (cleaned.length === 12) {
97
+ return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6, 9)}-${cleaned.slice(9)}`;
98
+ }
99
+ if (cleaned.length === 15) {
100
+ return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6, 9)}-${cleaned.slice(9, 12)}-${cleaned.slice(12)}`;
101
+ }
102
+ return tin;
103
+ }
104
+ function isValidBIRInvoiceNumber(invoiceNo) {
105
+ return /^[A-Z0-9]{2,12}$/.test(invoiceNo.toUpperCase().replace(/[\s-]/g, ""));
106
+ }
107
+ function generateBIRSerial(branchCode, sequence) {
108
+ const prefix = branchCode.slice(0, 2).toUpperCase();
109
+ const seq = String(sequence).padStart(7, "0");
110
+ return `${prefix}${seq}`;
111
+ }
112
+ function calculateInvoiceTotals(amounts, isVATExclusive) {
113
+ const subtotal = amounts.reduce((sum, a) => sum + a, 0);
114
+ const vatRate = 0.12;
115
+ const vatAmount = isVATExclusive ? Math.round(subtotal * vatRate * 100) / 100 : Math.round((subtotal - subtotal / (1 + vatRate)) * 100) / 100;
116
+ const totalAmount = isVATExclusive ? Math.round(subtotal * (1 + vatRate) * 100) / 100 : subtotal;
117
+ return { subtotal, vatAmount, totalAmount };
118
+ }
119
+
120
+ // src/validation/philippine.ts
121
+ function isValidPHPhone(phone) {
122
+ const mobilePattern = /^09\d{9}$/;
123
+ const landlinePattern = /^\(0\d\)\s?\d{3,4}[-]?\d{4}$/;
124
+ return mobilePattern.test(phone.replace(/[\s-]/g, "")) || landlinePattern.test(phone);
125
+ }
126
+ function isValidPHMobile(phone) {
127
+ const cleaned = phone.replace(/[\s-]/g, "");
128
+ return /^09\d{9}$/.test(cleaned);
129
+ }
130
+ function isValidTIN(tin) {
131
+ const cleaned = tin.replace(/-/g, "");
132
+ return /^\d{12}$/.test(cleaned) || /^\d{15}$/.test(cleaned);
133
+ }
134
+ function isValidPHZipCode(zip) {
135
+ return /^\d{4}$/.test(zip);
136
+ }
137
+
138
+ // src/inventory/sku.ts
139
+ function generateSKU({ prefix, category, sequence }, options = {}) {
140
+ const { separator = "-", padding = 6 } = options;
141
+ const padded = String(sequence).padStart(padding, "0");
142
+ return `${prefix}${separator}${category}${separator}${padded}`;
143
+ }
144
+ function parseSKU(sku) {
145
+ const parts = sku.split("-");
146
+ if (parts.length !== 3) return null;
147
+ const seq = parseInt(parts[2], 10);
148
+ if (isNaN(seq)) return null;
149
+ return { prefix: parts[0], category: parts[1], sequence: seq };
150
+ }
151
+ function validateSKUFormat(sku) {
152
+ return parseSKU(sku) !== null;
153
+ }
154
+
155
+ // src/inventory/stock.ts
156
+ function calculateReorderPoint(averageDailyDemand, leadTimeDays, safetyStock = 0) {
157
+ return averageDailyDemand * leadTimeDays + safetyStock;
158
+ }
159
+ function calculateSafetyStock(maxDailyDemand, averageDailyDemand, maxLeadTimeDays, averageLeadTimeDays) {
160
+ return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);
161
+ }
162
+ function calculateEOQ(annualDemand, orderingCost, holdingCostPerUnit) {
163
+ return Math.sqrt(2 * annualDemand * orderingCost / holdingCostPerUnit);
164
+ }
165
+ function calculateStockValue(items) {
166
+ return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);
167
+ }
168
+
169
+ // src/barcode/checksum.ts
170
+ function calculateEAN13CheckDigit(digits12) {
171
+ const cleaned = digits12.replace(/\D/g, "");
172
+ if (cleaned.length !== 12) {
173
+ throw new Error("EAN-13 requires exactly 12 digits (without check digit)");
174
+ }
175
+ let sum = 0;
176
+ for (let i = 0; i < 12; i++) {
177
+ const d = parseInt(cleaned[i], 10);
178
+ sum += i % 2 === 0 ? d : d * 3;
179
+ }
180
+ return (10 - sum % 10) % 10;
181
+ }
182
+ function validateEAN13(ean) {
183
+ const cleaned = ean.replace(/\D/g, "");
184
+ if (cleaned.length !== 13) return false;
185
+ const expectedCheck = calculateEAN13CheckDigit(cleaned.slice(0, 12));
186
+ return parseInt(cleaned[12], 10) === expectedCheck;
187
+ }
188
+ function generateCode128Data(data) {
189
+ return data.trim();
190
+ }
191
+
192
+ // src/documents/numbering.ts
193
+ function formatDate(d) {
194
+ const y = d.getFullYear();
195
+ const m = String(d.getMonth() + 1).padStart(2, "0");
196
+ const day = String(d.getDate()).padStart(2, "0");
197
+ return `${y}${m}${day}`;
198
+ }
199
+ function generateGRNNumber(opts) {
200
+ const dateStr = formatDate(opts.date ?? /* @__PURE__ */ new Date());
201
+ const seq = String(opts.sequence).padStart(4, "0");
202
+ return `GRN-${opts.warehouseCode}-${dateStr}-${seq}`;
203
+ }
204
+ function generateDRNumber(opts) {
205
+ const dateStr = formatDate(opts.date ?? /* @__PURE__ */ new Date());
206
+ const seq = String(opts.sequence).padStart(4, "0");
207
+ return `DR-${opts.warehouseCode}-${dateStr}-${seq}`;
208
+ }
209
+ function generateReferenceNumber(prefix, sequence, date) {
210
+ const seq = String(sequence).padStart(6, "0");
211
+ if (date) {
212
+ return `${prefix}-${formatDate(date)}-${seq}`;
213
+ }
214
+ return `${prefix}-${seq}`;
215
+ }
216
+
217
+ // src/holidays/data.ts
218
+ var FIXED_HOLIDAYS = [
219
+ { month: 1, day: 1, name: "New Year's Day", type: "regular" },
220
+ { month: 2, day: 25, name: "EDSA People Power Revolution", type: "regular" },
221
+ { month: 4, day: 9, name: "Araw ng Kagitingan (Day of Valor)", type: "regular" },
222
+ { month: 5, day: 1, name: "Labor Day", type: "regular" },
223
+ { month: 6, day: 12, name: "Independence Day", type: "regular" },
224
+ { month: 8, day: 21, name: "Ninoy Aquino Day", type: "special_non_working" },
225
+ { month: 8, day: 26, name: "National Heroes Day", type: "regular" },
226
+ { month: 11, day: 1, name: "All Saints' Day", type: "special_non_working" },
227
+ { month: 11, day: 2, name: "All Souls' Day", type: "special_non_working" },
228
+ { month: 11, day: 30, name: "Bonifacio Day", type: "regular" },
229
+ { month: 12, day: 8, name: "Feast of the Immaculate Conception", type: "special_non_working" },
230
+ { month: 12, day: 24, name: "Christmas Eve", type: "special_non_working" },
231
+ { month: 12, day: 25, name: "Christmas Day", type: "regular" },
232
+ { month: 12, day: 30, name: "Rizal Day", type: "regular" },
233
+ { month: 12, day: 31, name: "Last Day of the Year", type: "special_non_working" }
234
+ ];
235
+ function getPhilippineHolidays(year) {
236
+ const holidays = [];
237
+ for (const h of FIXED_HOLIDAYS) {
238
+ holidays.push({
239
+ name: h.name,
240
+ date: `${year}-${String(h.month).padStart(2, "0")}-${String(h.day).padStart(2, "0")}`,
241
+ type: h.type
242
+ });
243
+ }
244
+ const easterDate = getEasterDate(year);
245
+ const goodFriday = new Date(easterDate);
246
+ goodFriday.setDate(easterDate.getDate() - 2);
247
+ const blackSaturday = new Date(easterDate);
248
+ blackSaturday.setDate(easterDate.getDate() - 1);
249
+ holidays.push({
250
+ name: "Maundy Thursday",
251
+ date: formatDateISO(new Date(easterDate.getTime() - 3 * 864e5)),
252
+ type: "regular"
253
+ });
254
+ holidays.push({
255
+ name: "Good Friday",
256
+ date: formatDateISO(goodFriday),
257
+ type: "regular"
258
+ });
259
+ holidays.push({
260
+ name: "Black Saturday",
261
+ date: formatDateISO(blackSaturday),
262
+ type: "special_non_working"
263
+ });
264
+ holidays.push({
265
+ name: "Easter Sunday",
266
+ date: formatDateISO(easterDate),
267
+ type: "regular"
268
+ });
269
+ return holidays;
270
+ }
271
+ function getEasterDate(year) {
272
+ const a = year % 19;
273
+ const b = Math.floor(year / 100);
274
+ const c = year % 100;
275
+ const d = Math.floor(b / 4);
276
+ const e = b % 4;
277
+ const f = Math.floor((b + 8) / 25);
278
+ const g = Math.floor((b - f + 1) / 3);
279
+ const h = (19 * a + b - d - g + 15) % 30;
280
+ const i = Math.floor(c / 4);
281
+ const k = c % 4;
282
+ const l = (32 + 2 * e + 2 * i - h - k) % 7;
283
+ const m = Math.floor((a + 11 * h + 22 * l) / 451);
284
+ const month = Math.floor((h + l - 7 * m + 114) / 31);
285
+ const day = (h + l - 7 * m + 114) % 31 + 1;
286
+ return new Date(year, month - 1, day);
287
+ }
288
+ function formatDateISO(d) {
289
+ return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
290
+ }
291
+ function isHoliday(date) {
292
+ const iso = formatDateISO(date);
293
+ return getPhilippineHolidays(date.getFullYear()).some((h) => h.date === iso);
294
+ }
295
+ function isRegularHoliday(date) {
296
+ const iso = formatDateISO(date);
297
+ return getPhilippineHolidays(date.getFullYear()).some((h) => h.date === iso && h.type === "regular");
298
+ }
299
+ function isWarehouseOpen(date, options = {}) {
300
+ const { closedDays = [0] } = options;
301
+ if (closedDays.includes(date.getDay())) return false;
302
+ if (isHoliday(date)) return false;
303
+ return true;
304
+ }
305
+ export {
306
+ REGIONS,
307
+ VAT_RATE,
308
+ addVAT,
309
+ calculateEAN13CheckDigit,
310
+ calculateEOQ,
311
+ calculateInvoiceTotals,
312
+ calculateReorderPoint,
313
+ calculateSafetyStock,
314
+ calculateStockValue,
315
+ calculateVAT,
316
+ extractVAT,
317
+ formatAddress,
318
+ formatPeso,
319
+ formatPesoShort,
320
+ formatTIN,
321
+ generateBIRSerial,
322
+ generateCode128Data,
323
+ generateDRNumber,
324
+ generateGRNNumber,
325
+ generateReferenceNumber,
326
+ generateSKU,
327
+ getPhilippineHolidays,
328
+ getProvinces,
329
+ getRegionByCode,
330
+ getRegions,
331
+ isHoliday,
332
+ isRegularHoliday,
333
+ isVATRegistered,
334
+ isValidBIRInvoiceNumber,
335
+ isValidPHMobile,
336
+ isValidPHPhone,
337
+ isValidPHZipCode,
338
+ isValidTIN,
339
+ isWarehouseOpen,
340
+ parsePeso,
341
+ parseSKU,
342
+ validateEAN13,
343
+ validateSKUFormat
344
+ };
345
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/currency/format.ts","../src/currency/tax.ts","../src/address/data.ts","../src/address/lookup.ts","../src/compliance/index.ts","../src/validation/philippine.ts","../src/inventory/sku.ts","../src/inventory/stock.ts","../src/barcode/checksum.ts","../src/documents/numbering.ts","../src/holidays/data.ts"],"sourcesContent":["export interface FormatPesoOptions {\n decimals?: number;\n showSign?: boolean;\n}\n\nexport function formatPeso(amount: number, options: FormatPesoOptions = {}): string {\n const { decimals = 2 } = options;\n const sign = amount < 0 ? '-' : '';\n const abs = Math.abs(amount);\n const formatted = abs.toLocaleString('en-PH', {\n minimumFractionDigits: decimals,\n maximumFractionDigits: decimals,\n });\n return `${sign}\\u20B1${formatted}`;\n}\n\nexport function parsePeso(value: string): number {\n const cleaned = value.replace(/[\\u20B1,\\s]/g, '');\n return Number(cleaned);\n}\n\nexport function formatPesoShort(amount: number): string {\n const abs = Math.abs(amount);\n const sign = amount < 0 ? '-' : '';\n if (abs >= 1_000_000) {\n const millions = abs / 1_000_000;\n return `${sign}\\u20B1${millions % 1 === 0 ? millions.toFixed(0) : millions.toFixed(1)}M`;\n }\n if (abs >= 1_000) {\n const thousands = abs / 1_000;\n return `${sign}\\u20B1${thousands % 1 === 0 ? thousands.toFixed(0) : thousands.toFixed(1)}K`;\n }\n return `${sign}\\u20B1${abs}`;\n}\n","export const VAT_RATE = 0.12;\nconst VAT_FACTOR = 1 + VAT_RATE;\n\nexport function calculateVAT(netAmount: number): number {\n return Math.round(netAmount * VAT_RATE * 100) / 100;\n}\n\nexport function addVAT(netAmount: number): number {\n return Math.round(netAmount * VAT_FACTOR * 100) / 100;\n}\n\nexport interface VATBreakdown {\n vatableAmount: number;\n vatAmount: number;\n grossAmount: number;\n}\n\nexport function extractVAT(grossAmount: number): VATBreakdown {\n const vatableAmount = Math.round((grossAmount / VAT_FACTOR) * 100) / 100;\n const vatAmount = Math.round((grossAmount - vatableAmount) * 100) / 100;\n return { vatableAmount, vatAmount, grossAmount };\n}\n\nexport function isVATRegistered(tin: string): boolean {\n return /^\\d{3}-\\d{3}-\\d{3}-\\d{3}$/.test(tin);\n}\n","export interface Region {\n code: string;\n name: string;\n provinces: string[];\n}\n\nexport interface PhilippineAddress {\n region?: string;\n province?: string;\n city?: string;\n barangay?: string;\n zipCode?: string;\n street?: string;\n building?: string;\n floor?: string;\n unit?: string;\n}\n\nexport const REGIONS: Region[] = [\n { code: 'NCR', name: 'National Capital Region', provinces: ['Metro Manila'] },\n { code: '01', name: 'Ilocos Region', provinces: ['Ilocos Norte', 'Ilocos Sur', 'La Union', 'Pangasinan'] },\n { code: '02', name: 'Cagayan Valley', provinces: ['Batanes', 'Cagayan', 'Isabela', 'Nueva Vizcaya', 'Quirino'] },\n { code: '03', name: 'Central Luzon', provinces: ['Aurora', 'Bataan', 'Bulacan', 'Nueva Ecija', 'Pampanga', 'Tarlac', 'Zambales'] },\n { code: '04A', name: 'CALABARZON', provinces: ['Batangas', 'Cavite', 'Laguna', 'Quezon', 'Rizal'] },\n { code: '04B', name: 'MIMAROPA', provinces: ['Marinduque', 'Occidental Mindoro', 'Oriental Mindoro', 'Palawan', 'Romblon'] },\n { code: '05', name: 'Bicol Region', provinces: ['Albay', 'Camarines Norte', 'Camarines Sur', 'Catanduanes', 'Masbate', 'Sorsogon'] },\n { code: '06', name: 'Western Visayas', provinces: ['Aklan', 'Antique', 'Capiz', 'Guimaras', 'Iloilo', 'Negros Occidental'] },\n { code: '07', name: 'Central Visayas', provinces: ['Bohol', 'Cebu', 'Negros Oriental', 'Siquijor'] },\n { code: '08', name: 'Eastern Visayas', provinces: ['Biliran', 'Eastern Samar', 'Leyte', 'Northern Samar', 'Samar', 'Southern Leyte'] },\n { code: '09', name: 'Zamboanga Peninsula', provinces: ['Zamboanga del Norte', 'Zamboanga del Sur', 'Zamboanga Sibugay'] },\n { code: '10', name: 'Northern Mindanao', provinces: ['Bukidnon', 'Camiguin', 'Lanao del Norte', 'Misamis Occidental', 'Misamis Oriental'] },\n { code: '11', name: 'Davao Region', provinces: ['Davao de Oro', 'Davao del Norte', 'Davao del Sur', 'Davao Occidental', 'Davao Oriental'] },\n { code: '12', name: 'SOCCSKSARGEN', provinces: ['Cotabato', 'Sarangani', 'South Cotabato', 'Sultan Kudarat'] },\n { code: '13', name: 'Caraga', provinces: ['Agusan del Norte', 'Agusan del Sur', 'Dinagat Islands', 'Surigao del Norte', 'Surigao del Sur'] },\n { code: 'BARMM', name: 'Bangsamoro Autonomous Region in Muslim Mindanao', provinces: ['Basilan', 'Lanao del Sur', 'Maguindanao', 'Sulu', 'Tawi-Tawi'] },\n { code: 'CAR', name: 'Cordillera Administrative Region', provinces: ['Abra', 'Apayao', 'Benguet', 'Ifugao', 'Kalinga', 'Mountain Province'] },\n];\n","import { REGIONS, type Region, type PhilippineAddress } from './data.js';\n\nexport function getRegions(): Region[] {\n return [...REGIONS];\n}\n\nexport function getRegionByCode(code: string): Region | undefined {\n return REGIONS.find(r => r.code === code);\n}\n\nexport function getProvinces(regionCode: string): string[] {\n const region = getRegionByCode(regionCode);\n return region ? [...region.provinces] : [];\n}\n\nexport function formatAddress(addr: PhilippineAddress): string {\n const parts: string[] = [];\n if (addr.unit) parts.push(addr.unit);\n if (addr.floor) parts.push(`Floor ${addr.floor}`);\n if (addr.building) parts.push(addr.building);\n if (addr.street) parts.push(addr.street);\n if (addr.barangay) parts.push(`Brgy. ${addr.barangay}`);\n if (addr.city) parts.push(addr.city);\n if (addr.province) parts.push(addr.province);\n if (addr.zipCode) parts.push(addr.zipCode);\n return parts.join(', ');\n}\n","/**\n * Philippine BIR Compliance utilities\n * - TIN formatting\n * - VAT registration checks\n * - Invoice numbering per BIR guidelines\n */\n\nexport function formatTIN(tin: string): string {\n const cleaned = tin.replace(/[^0-9]/g, '');\n if (cleaned.length === 12) {\n return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6, 9)}-${cleaned.slice(9)}`;\n }\n if (cleaned.length === 15) {\n return `${cleaned.slice(0, 3)}-${cleaned.slice(3, 6)}-${cleaned.slice(6, 9)}-${cleaned.slice(9, 12)}-${cleaned.slice(12)}`;\n }\n return tin; // return as-is if unexpected format\n}\n\nexport function isValidBIRInvoiceNumber(invoiceNo: string): boolean {\n // BIR serial numbers: 2 letters + 7 digits (e.g., AB1234567) or\n // machine-registered: up to 12 alphanumeric characters\n return /^[A-Z0-9]{2,12}$/.test(invoiceNo.toUpperCase().replace(/[\\s-]/g, ''));\n}\n\nexport function generateBIRSerial(\n branchCode: string,\n sequence: number\n): string {\n const prefix = branchCode.slice(0, 2).toUpperCase();\n const seq = String(sequence).padStart(7, '0');\n return `${prefix}${seq}`;\n}\n\nexport interface InvoiceMetadata {\n invoiceNumber: string;\n date: Date;\n sellerTIN: string;\n sellerName: string;\n buyerName?: string;\n totalAmount: number;\n vatAmount: number;\n isVATExclusive: boolean;\n}\n\nexport function calculateInvoiceTotals(\n amounts: number[],\n isVATExclusive: boolean\n): { subtotal: number; vatAmount: number; totalAmount: number } {\n const subtotal = amounts.reduce((sum, a) => sum + a, 0);\n const vatRate = 0.12;\n const vatAmount = isVATExclusive\n ? Math.round(subtotal * vatRate * 100) / 100\n : Math.round((subtotal - subtotal / (1 + vatRate)) * 100) / 100;\n const totalAmount = isVATExclusive\n ? Math.round(subtotal * (1 + vatRate) * 100) / 100\n : subtotal;\n return { subtotal, vatAmount, totalAmount };\n}\n","export function isValidPHPhone(phone: string): boolean {\n const mobilePattern = /^09\\d{9}$/;\n // Landline: (0X) XXXX-XXXX or 0X-XXXX-XXXX or (0X)XXXX-XXXX\n const landlinePattern = /^\\(0\\d\\)\\s?\\d{3,4}[-]?\\d{4}$/;\n return mobilePattern.test(phone.replace(/[\\s-]/g, '')) || landlinePattern.test(phone);\n}\n\nexport function isValidPHMobile(phone: string): boolean {\n const cleaned = phone.replace(/[\\s-]/g, '');\n return /^09\\d{9}$/.test(cleaned);\n}\n\nexport function isValidTIN(tin: string): boolean {\n const cleaned = tin.replace(/-/g, '');\n // Standard: 12 digits, Branch: 15 digits (12 + 3)\n return /^\\d{12}$/.test(cleaned) || /^\\d{15}$/.test(cleaned);\n}\n\nexport function isValidPHZipCode(zip: string): boolean {\n return /^\\d{4}$/.test(zip);\n}\n","export interface SKUGenerateOptions {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport interface SKUFormatOptions {\n separator?: string;\n padding?: number;\n}\n\nexport function generateSKU(\n { prefix, category, sequence }: SKUGenerateOptions,\n options: SKUFormatOptions = {}\n): string {\n const { separator = '-', padding = 6 } = options;\n const padded = String(sequence).padStart(padding, '0');\n return `${prefix}${separator}${category}${separator}${padded}`;\n}\n\nexport interface ParsedSKU {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport function parseSKU(sku: string): ParsedSKU | null {\n const parts = sku.split('-');\n if (parts.length !== 3) return null;\n const seq = parseInt(parts[2], 10);\n if (isNaN(seq)) return null;\n return { prefix: parts[0], category: parts[1], sequence: seq };\n}\n\nexport function validateSKUFormat(sku: string): boolean {\n return parseSKU(sku) !== null;\n}\n","export function calculateReorderPoint(\n averageDailyDemand: number,\n leadTimeDays: number,\n safetyStock: number = 0\n): number {\n return averageDailyDemand * leadTimeDays + safetyStock;\n}\n\nexport function calculateSafetyStock(\n maxDailyDemand: number,\n averageDailyDemand: number,\n maxLeadTimeDays: number,\n averageLeadTimeDays: number\n): number {\n return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);\n}\n\nexport function calculateEOQ(\n annualDemand: number,\n orderingCost: number,\n holdingCostPerUnit: number\n): number {\n return Math.sqrt((2 * annualDemand * orderingCost) / holdingCostPerUnit);\n}\n\nexport interface StockItem {\n quantity: number;\n unitCost: number;\n}\n\nexport function calculateStockValue(items: StockItem[]): number {\n return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);\n}\n","export function calculateEAN13CheckDigit(digits12: string): number {\n const cleaned = digits12.replace(/\\D/g, '');\n if (cleaned.length !== 12) {\n throw new Error('EAN-13 requires exactly 12 digits (without check digit)');\n }\n let sum = 0;\n for (let i = 0; i < 12; i++) {\n const d = parseInt(cleaned[i], 10);\n sum += i % 2 === 0 ? d : d * 3;\n }\n return (10 - (sum % 10)) % 10;\n}\n\nexport function validateEAN13(ean: string): boolean {\n const cleaned = ean.replace(/\\D/g, '');\n if (cleaned.length !== 13) return false;\n const expectedCheck = calculateEAN13CheckDigit(cleaned.slice(0, 12));\n return parseInt(cleaned[12], 10) === expectedCheck;\n}\n\nexport function generateCode128Data(data: string): string {\n return data.trim();\n}\n","export interface NumberingOptions {\n warehouseCode: string;\n date?: Date;\n sequence: number;\n}\n\nfunction formatDate(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}${m}${day}`;\n}\n\nexport function generateGRNNumber(opts: NumberingOptions): string {\n const dateStr = formatDate(opts.date ?? new Date());\n const seq = String(opts.sequence).padStart(4, '0');\n return `GRN-${opts.warehouseCode}-${dateStr}-${seq}`;\n}\n\nexport function generateDRNumber(opts: NumberingOptions): string {\n const dateStr = formatDate(opts.date ?? new Date());\n const seq = String(opts.sequence).padStart(4, '0');\n return `DR-${opts.warehouseCode}-${dateStr}-${seq}`;\n}\n\nexport function generateReferenceNumber(\n prefix: string,\n sequence: number,\n date?: Date\n): string {\n const seq = String(sequence).padStart(6, '0');\n if (date) {\n return `${prefix}-${formatDate(date)}-${seq}`;\n }\n return `${prefix}-${seq}`;\n}\n","export interface PhilippineHoliday {\n name: string;\n date: string;\n type: 'regular' | 'special_non_working';\n}\n\nconst FIXED_HOLIDAYS: { month: number; day: number; name: string; type: PhilippineHoliday['type'] }[] = [\n { month: 1, day: 1, name: \"New Year's Day\", type: 'regular' },\n { month: 2, day: 25, name: 'EDSA People Power Revolution', type: 'regular' },\n { month: 4, day: 9, name: 'Araw ng Kagitingan (Day of Valor)', type: 'regular' },\n { month: 5, day: 1, name: 'Labor Day', type: 'regular' },\n { month: 6, day: 12, name: 'Independence Day', type: 'regular' },\n { month: 8, day: 21, name: 'Ninoy Aquino Day', type: 'special_non_working' },\n { month: 8, day: 26, name: 'National Heroes Day', type: 'regular' },\n { month: 11, day: 1, name: \"All Saints' Day\", type: 'special_non_working' },\n { month: 11, day: 2, name: \"All Souls' Day\", type: 'special_non_working' },\n { month: 11, day: 30, name: 'Bonifacio Day', type: 'regular' },\n { month: 12, day: 8, name: 'Feast of the Immaculate Conception', type: 'special_non_working' },\n { month: 12, day: 24, name: 'Christmas Eve', type: 'special_non_working' },\n { month: 12, day: 25, name: 'Christmas Day', type: 'regular' },\n { month: 12, day: 30, name: 'Rizal Day', type: 'regular' },\n { month: 12, day: 31, name: 'Last Day of the Year', type: 'special_non_working' },\n];\n\nexport function getPhilippineHolidays(year: number): PhilippineHoliday[] {\n const holidays: PhilippineHoliday[] = [];\n\n for (const h of FIXED_HOLIDAYS) {\n holidays.push({\n name: h.name,\n date: `${year}-${String(h.month).padStart(2, '0')}-${String(h.day).padStart(2, '0')}`,\n type: h.type,\n });\n }\n\n const easterDate = getEasterDate(year);\n const goodFriday = new Date(easterDate);\n goodFriday.setDate(easterDate.getDate() - 2);\n const blackSaturday = new Date(easterDate);\n blackSaturday.setDate(easterDate.getDate() - 1);\n\n holidays.push({\n name: 'Maundy Thursday',\n date: formatDateISO(new Date(easterDate.getTime() - 3 * 86400000)),\n type: 'regular',\n });\n holidays.push({\n name: 'Good Friday',\n date: formatDateISO(goodFriday),\n type: 'regular',\n });\n holidays.push({\n name: 'Black Saturday',\n date: formatDateISO(blackSaturday),\n type: 'special_non_working',\n });\n holidays.push({\n name: 'Easter Sunday',\n date: formatDateISO(easterDate),\n type: 'regular',\n });\n\n return holidays;\n}\n\nfunction getEasterDate(year: number): Date {\n const a = year % 19;\n const b = Math.floor(year / 100);\n const c = year % 100;\n const d = Math.floor(b / 4);\n const e = b % 4;\n const f = Math.floor((b + 8) / 25);\n const g = Math.floor((b - f + 1) / 3);\n const h = (19 * a + b - d - g + 15) % 30;\n const i = Math.floor(c / 4);\n const k = c % 4;\n const l = (32 + 2 * e + 2 * i - h - k) % 7;\n const m = Math.floor((a + 11 * h + 22 * l) / 451);\n const month = Math.floor((h + l - 7 * m + 114) / 31);\n const day = ((h + l - 7 * m + 114) % 31) + 1;\n return new Date(year, month - 1, day);\n}\n\nfunction formatDateISO(d: Date): string {\n return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n}\n\nexport function isHoliday(date: Date): boolean {\n const iso = formatDateISO(date);\n return getPhilippineHolidays(date.getFullYear()).some(h => h.date === iso);\n}\n\nexport function isRegularHoliday(date: Date): boolean {\n const iso = formatDateISO(date);\n return getPhilippineHolidays(date.getFullYear()).some(h => h.date === iso && h.type === 'regular');\n}\n\nexport interface WarehouseOpenOptions {\n closedDays?: number[];\n}\n\nexport function isWarehouseOpen(date: Date, options: WarehouseOpenOptions = {}): boolean {\n const { closedDays = [0] } = options;\n if (closedDays.includes(date.getDay())) return false;\n if (isHoliday(date)) return false;\n return true;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/inventory/index.ts
21
+ var inventory_exports = {};
22
+ __export(inventory_exports, {
23
+ calculateEOQ: () => calculateEOQ,
24
+ calculateReorderPoint: () => calculateReorderPoint,
25
+ calculateSafetyStock: () => calculateSafetyStock,
26
+ calculateStockValue: () => calculateStockValue,
27
+ generateSKU: () => generateSKU,
28
+ parseSKU: () => parseSKU,
29
+ validateSKUFormat: () => validateSKUFormat
30
+ });
31
+ module.exports = __toCommonJS(inventory_exports);
32
+
33
+ // src/inventory/sku.ts
34
+ function generateSKU({ prefix, category, sequence }, options = {}) {
35
+ const { separator = "-", padding = 6 } = options;
36
+ const padded = String(sequence).padStart(padding, "0");
37
+ return `${prefix}${separator}${category}${separator}${padded}`;
38
+ }
39
+ function parseSKU(sku) {
40
+ const parts = sku.split("-");
41
+ if (parts.length !== 3) return null;
42
+ const seq = parseInt(parts[2], 10);
43
+ if (isNaN(seq)) return null;
44
+ return { prefix: parts[0], category: parts[1], sequence: seq };
45
+ }
46
+ function validateSKUFormat(sku) {
47
+ return parseSKU(sku) !== null;
48
+ }
49
+
50
+ // src/inventory/stock.ts
51
+ function calculateReorderPoint(averageDailyDemand, leadTimeDays, safetyStock = 0) {
52
+ return averageDailyDemand * leadTimeDays + safetyStock;
53
+ }
54
+ function calculateSafetyStock(maxDailyDemand, averageDailyDemand, maxLeadTimeDays, averageLeadTimeDays) {
55
+ return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);
56
+ }
57
+ function calculateEOQ(annualDemand, orderingCost, holdingCostPerUnit) {
58
+ return Math.sqrt(2 * annualDemand * orderingCost / holdingCostPerUnit);
59
+ }
60
+ function calculateStockValue(items) {
61
+ return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);
62
+ }
63
+ // Annotate the CommonJS export names for ESM import in node:
64
+ 0 && (module.exports = {
65
+ calculateEOQ,
66
+ calculateReorderPoint,
67
+ calculateSafetyStock,
68
+ calculateStockValue,
69
+ generateSKU,
70
+ parseSKU,
71
+ validateSKUFormat
72
+ });
73
+ //# sourceMappingURL=inventory.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/inventory/index.ts","../src/inventory/sku.ts","../src/inventory/stock.ts"],"sourcesContent":["export { generateSKU, parseSKU, validateSKUFormat } from './sku.js';\nexport type { SKUGenerateOptions, SKUFormatOptions, ParsedSKU } from './sku.js';\nexport { calculateReorderPoint, calculateSafetyStock, calculateEOQ, calculateStockValue } from './stock.js';\nexport type { StockItem } from './stock.js';\n","export interface SKUGenerateOptions {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport interface SKUFormatOptions {\n separator?: string;\n padding?: number;\n}\n\nexport function generateSKU(\n { prefix, category, sequence }: SKUGenerateOptions,\n options: SKUFormatOptions = {}\n): string {\n const { separator = '-', padding = 6 } = options;\n const padded = String(sequence).padStart(padding, '0');\n return `${prefix}${separator}${category}${separator}${padded}`;\n}\n\nexport interface ParsedSKU {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport function parseSKU(sku: string): ParsedSKU | null {\n const parts = sku.split('-');\n if (parts.length !== 3) return null;\n const seq = parseInt(parts[2], 10);\n if (isNaN(seq)) return null;\n return { prefix: parts[0], category: parts[1], sequence: seq };\n}\n\nexport function validateSKUFormat(sku: string): boolean {\n return parseSKU(sku) !== null;\n}\n","export function calculateReorderPoint(\n averageDailyDemand: number,\n leadTimeDays: number,\n safetyStock: number = 0\n): number {\n return averageDailyDemand * leadTimeDays + safetyStock;\n}\n\nexport function calculateSafetyStock(\n maxDailyDemand: number,\n averageDailyDemand: number,\n maxLeadTimeDays: number,\n averageLeadTimeDays: number\n): number {\n return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);\n}\n\nexport function calculateEOQ(\n annualDemand: number,\n orderingCost: number,\n holdingCostPerUnit: number\n): number {\n return Math.sqrt((2 * annualDemand * orderingCost) / holdingCostPerUnit);\n}\n\nexport interface StockItem {\n quantity: number;\n unitCost: number;\n}\n\nexport function calculateStockValue(items: StockItem[]): number {\n return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACWO,SAAS,YACd,EAAE,QAAQ,UAAU,SAAS,GAC7B,UAA4B,CAAC,GACrB;AACR,QAAM,EAAE,YAAY,KAAK,UAAU,EAAE,IAAI;AACzC,QAAM,SAAS,OAAO,QAAQ,EAAE,SAAS,SAAS,GAAG;AACrD,SAAO,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM;AAC9D;AAQO,SAAS,SAAS,KAA+B;AACtD,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,MAAI,MAAM,GAAG,EAAG,QAAO;AACvB,SAAO,EAAE,QAAQ,MAAM,CAAC,GAAG,UAAU,MAAM,CAAC,GAAG,UAAU,IAAI;AAC/D;AAEO,SAAS,kBAAkB,KAAsB;AACtD,SAAO,SAAS,GAAG,MAAM;AAC3B;;;ACpCO,SAAS,sBACd,oBACA,cACA,cAAsB,GACd;AACR,SAAO,qBAAqB,eAAe;AAC7C;AAEO,SAAS,qBACd,gBACA,oBACA,iBACA,qBACQ;AACR,UAAQ,kBAAkB,wBAAwB,iBAAiB;AACrE;AAEO,SAAS,aACd,cACA,cACA,oBACQ;AACR,SAAO,KAAK,KAAM,IAAI,eAAe,eAAgB,kBAAkB;AACzE;AAOO,SAAS,oBAAoB,OAA4B;AAC9D,SAAO,MAAM,OAAO,CAAC,OAAO,SAAS,QAAQ,KAAK,WAAW,KAAK,UAAU,CAAC;AAC/E;","names":[]}
@@ -0,0 +1,28 @@
1
+ interface SKUGenerateOptions {
2
+ prefix: string;
3
+ category: string;
4
+ sequence: number;
5
+ }
6
+ interface SKUFormatOptions {
7
+ separator?: string;
8
+ padding?: number;
9
+ }
10
+ declare function generateSKU({ prefix, category, sequence }: SKUGenerateOptions, options?: SKUFormatOptions): string;
11
+ interface ParsedSKU {
12
+ prefix: string;
13
+ category: string;
14
+ sequence: number;
15
+ }
16
+ declare function parseSKU(sku: string): ParsedSKU | null;
17
+ declare function validateSKUFormat(sku: string): boolean;
18
+
19
+ declare function calculateReorderPoint(averageDailyDemand: number, leadTimeDays: number, safetyStock?: number): number;
20
+ declare function calculateSafetyStock(maxDailyDemand: number, averageDailyDemand: number, maxLeadTimeDays: number, averageLeadTimeDays: number): number;
21
+ declare function calculateEOQ(annualDemand: number, orderingCost: number, holdingCostPerUnit: number): number;
22
+ interface StockItem {
23
+ quantity: number;
24
+ unitCost: number;
25
+ }
26
+ declare function calculateStockValue(items: StockItem[]): number;
27
+
28
+ export { type ParsedSKU, type SKUFormatOptions, type SKUGenerateOptions, type StockItem, calculateEOQ, calculateReorderPoint, calculateSafetyStock, calculateStockValue, generateSKU, parseSKU, validateSKUFormat };
@@ -0,0 +1,28 @@
1
+ interface SKUGenerateOptions {
2
+ prefix: string;
3
+ category: string;
4
+ sequence: number;
5
+ }
6
+ interface SKUFormatOptions {
7
+ separator?: string;
8
+ padding?: number;
9
+ }
10
+ declare function generateSKU({ prefix, category, sequence }: SKUGenerateOptions, options?: SKUFormatOptions): string;
11
+ interface ParsedSKU {
12
+ prefix: string;
13
+ category: string;
14
+ sequence: number;
15
+ }
16
+ declare function parseSKU(sku: string): ParsedSKU | null;
17
+ declare function validateSKUFormat(sku: string): boolean;
18
+
19
+ declare function calculateReorderPoint(averageDailyDemand: number, leadTimeDays: number, safetyStock?: number): number;
20
+ declare function calculateSafetyStock(maxDailyDemand: number, averageDailyDemand: number, maxLeadTimeDays: number, averageLeadTimeDays: number): number;
21
+ declare function calculateEOQ(annualDemand: number, orderingCost: number, holdingCostPerUnit: number): number;
22
+ interface StockItem {
23
+ quantity: number;
24
+ unitCost: number;
25
+ }
26
+ declare function calculateStockValue(items: StockItem[]): number;
27
+
28
+ export { type ParsedSKU, type SKUFormatOptions, type SKUGenerateOptions, type StockItem, calculateEOQ, calculateReorderPoint, calculateSafetyStock, calculateStockValue, generateSKU, parseSKU, validateSKUFormat };
@@ -0,0 +1,40 @@
1
+ // src/inventory/sku.ts
2
+ function generateSKU({ prefix, category, sequence }, options = {}) {
3
+ const { separator = "-", padding = 6 } = options;
4
+ const padded = String(sequence).padStart(padding, "0");
5
+ return `${prefix}${separator}${category}${separator}${padded}`;
6
+ }
7
+ function parseSKU(sku) {
8
+ const parts = sku.split("-");
9
+ if (parts.length !== 3) return null;
10
+ const seq = parseInt(parts[2], 10);
11
+ if (isNaN(seq)) return null;
12
+ return { prefix: parts[0], category: parts[1], sequence: seq };
13
+ }
14
+ function validateSKUFormat(sku) {
15
+ return parseSKU(sku) !== null;
16
+ }
17
+
18
+ // src/inventory/stock.ts
19
+ function calculateReorderPoint(averageDailyDemand, leadTimeDays, safetyStock = 0) {
20
+ return averageDailyDemand * leadTimeDays + safetyStock;
21
+ }
22
+ function calculateSafetyStock(maxDailyDemand, averageDailyDemand, maxLeadTimeDays, averageLeadTimeDays) {
23
+ return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);
24
+ }
25
+ function calculateEOQ(annualDemand, orderingCost, holdingCostPerUnit) {
26
+ return Math.sqrt(2 * annualDemand * orderingCost / holdingCostPerUnit);
27
+ }
28
+ function calculateStockValue(items) {
29
+ return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);
30
+ }
31
+ export {
32
+ calculateEOQ,
33
+ calculateReorderPoint,
34
+ calculateSafetyStock,
35
+ calculateStockValue,
36
+ generateSKU,
37
+ parseSKU,
38
+ validateSKUFormat
39
+ };
40
+ //# sourceMappingURL=inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/inventory/sku.ts","../src/inventory/stock.ts"],"sourcesContent":["export interface SKUGenerateOptions {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport interface SKUFormatOptions {\n separator?: string;\n padding?: number;\n}\n\nexport function generateSKU(\n { prefix, category, sequence }: SKUGenerateOptions,\n options: SKUFormatOptions = {}\n): string {\n const { separator = '-', padding = 6 } = options;\n const padded = String(sequence).padStart(padding, '0');\n return `${prefix}${separator}${category}${separator}${padded}`;\n}\n\nexport interface ParsedSKU {\n prefix: string;\n category: string;\n sequence: number;\n}\n\nexport function parseSKU(sku: string): ParsedSKU | null {\n const parts = sku.split('-');\n if (parts.length !== 3) return null;\n const seq = parseInt(parts[2], 10);\n if (isNaN(seq)) return null;\n return { prefix: parts[0], category: parts[1], sequence: seq };\n}\n\nexport function validateSKUFormat(sku: string): boolean {\n return parseSKU(sku) !== null;\n}\n","export function calculateReorderPoint(\n averageDailyDemand: number,\n leadTimeDays: number,\n safetyStock: number = 0\n): number {\n return averageDailyDemand * leadTimeDays + safetyStock;\n}\n\nexport function calculateSafetyStock(\n maxDailyDemand: number,\n averageDailyDemand: number,\n maxLeadTimeDays: number,\n averageLeadTimeDays: number\n): number {\n return (maxLeadTimeDays - averageLeadTimeDays) * (maxDailyDemand - averageDailyDemand);\n}\n\nexport function calculateEOQ(\n annualDemand: number,\n orderingCost: number,\n holdingCostPerUnit: number\n): number {\n return Math.sqrt((2 * annualDemand * orderingCost) / holdingCostPerUnit);\n}\n\nexport interface StockItem {\n quantity: number;\n unitCost: number;\n}\n\nexport function calculateStockValue(items: StockItem[]): number {\n return items.reduce((total, item) => total + item.quantity * item.unitCost, 0);\n}\n"],"mappings":";AAWO,SAAS,YACd,EAAE,QAAQ,UAAU,SAAS,GAC7B,UAA4B,CAAC,GACrB;AACR,QAAM,EAAE,YAAY,KAAK,UAAU,EAAE,IAAI;AACzC,QAAM,SAAS,OAAO,QAAQ,EAAE,SAAS,SAAS,GAAG;AACrD,SAAO,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM;AAC9D;AAQO,SAAS,SAAS,KAA+B;AACtD,QAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,QAAM,MAAM,SAAS,MAAM,CAAC,GAAG,EAAE;AACjC,MAAI,MAAM,GAAG,EAAG,QAAO;AACvB,SAAO,EAAE,QAAQ,MAAM,CAAC,GAAG,UAAU,MAAM,CAAC,GAAG,UAAU,IAAI;AAC/D;AAEO,SAAS,kBAAkB,KAAsB;AACtD,SAAO,SAAS,GAAG,MAAM;AAC3B;;;ACpCO,SAAS,sBACd,oBACA,cACA,cAAsB,GACd;AACR,SAAO,qBAAqB,eAAe;AAC7C;AAEO,SAAS,qBACd,gBACA,oBACA,iBACA,qBACQ;AACR,UAAQ,kBAAkB,wBAAwB,iBAAiB;AACrE;AAEO,SAAS,aACd,cACA,cACA,oBACQ;AACR,SAAO,KAAK,KAAM,IAAI,eAAe,eAAgB,kBAAkB;AACzE;AAOO,SAAS,oBAAoB,OAA4B;AAC9D,SAAO,MAAM,OAAO,CAAC,OAAO,SAAS,QAAQ,KAAK,WAAW,KAAK,UAAU,CAAC;AAC/E;","names":[]}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/validation/index.ts
21
+ var validation_exports = {};
22
+ __export(validation_exports, {
23
+ isValidPHMobile: () => isValidPHMobile,
24
+ isValidPHPhone: () => isValidPHPhone,
25
+ isValidPHZipCode: () => isValidPHZipCode,
26
+ isValidTIN: () => isValidTIN
27
+ });
28
+ module.exports = __toCommonJS(validation_exports);
29
+
30
+ // src/validation/philippine.ts
31
+ function isValidPHPhone(phone) {
32
+ const mobilePattern = /^09\d{9}$/;
33
+ const landlinePattern = /^\(0\d\)\s?\d{3,4}[-]?\d{4}$/;
34
+ return mobilePattern.test(phone.replace(/[\s-]/g, "")) || landlinePattern.test(phone);
35
+ }
36
+ function isValidPHMobile(phone) {
37
+ const cleaned = phone.replace(/[\s-]/g, "");
38
+ return /^09\d{9}$/.test(cleaned);
39
+ }
40
+ function isValidTIN(tin) {
41
+ const cleaned = tin.replace(/-/g, "");
42
+ return /^\d{12}$/.test(cleaned) || /^\d{15}$/.test(cleaned);
43
+ }
44
+ function isValidPHZipCode(zip) {
45
+ return /^\d{4}$/.test(zip);
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ isValidPHMobile,
50
+ isValidPHPhone,
51
+ isValidPHZipCode,
52
+ isValidTIN
53
+ });
54
+ //# sourceMappingURL=validation.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/validation/index.ts","../src/validation/philippine.ts"],"sourcesContent":["export { isValidPHPhone, isValidPHMobile, isValidTIN, isValidPHZipCode } from './philippine.js';\n","export function isValidPHPhone(phone: string): boolean {\n const mobilePattern = /^09\\d{9}$/;\n // Landline: (0X) XXXX-XXXX or 0X-XXXX-XXXX or (0X)XXXX-XXXX\n const landlinePattern = /^\\(0\\d\\)\\s?\\d{3,4}[-]?\\d{4}$/;\n return mobilePattern.test(phone.replace(/[\\s-]/g, '')) || landlinePattern.test(phone);\n}\n\nexport function isValidPHMobile(phone: string): boolean {\n const cleaned = phone.replace(/[\\s-]/g, '');\n return /^09\\d{9}$/.test(cleaned);\n}\n\nexport function isValidTIN(tin: string): boolean {\n const cleaned = tin.replace(/-/g, '');\n // Standard: 12 digits, Branch: 15 digits (12 + 3)\n return /^\\d{12}$/.test(cleaned) || /^\\d{15}$/.test(cleaned);\n}\n\nexport function isValidPHZipCode(zip: string): boolean {\n return /^\\d{4}$/.test(zip);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,SAAS,eAAe,OAAwB;AACrD,QAAM,gBAAgB;AAEtB,QAAM,kBAAkB;AACxB,SAAO,cAAc,KAAK,MAAM,QAAQ,UAAU,EAAE,CAAC,KAAK,gBAAgB,KAAK,KAAK;AACtF;AAEO,SAAS,gBAAgB,OAAwB;AACtD,QAAM,UAAU,MAAM,QAAQ,UAAU,EAAE;AAC1C,SAAO,YAAY,KAAK,OAAO;AACjC;AAEO,SAAS,WAAW,KAAsB;AAC/C,QAAM,UAAU,IAAI,QAAQ,MAAM,EAAE;AAEpC,SAAO,WAAW,KAAK,OAAO,KAAK,WAAW,KAAK,OAAO;AAC5D;AAEO,SAAS,iBAAiB,KAAsB;AACrD,SAAO,UAAU,KAAK,GAAG;AAC3B;","names":[]}