@zentring/zinvoice 0.1.0 → 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.
- package/README.md +43 -4
- package/dist/index.cjs +149 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +85 -4
- package/dist/index.d.ts +85 -4
- package/dist/index.js +149 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -193,8 +193,7 @@ if (client.supports(Capability.CARRIER)) {
|
|
|
193
193
|
}
|
|
194
194
|
|
|
195
195
|
if (client.supports(Capability.EXCHANGE)) {
|
|
196
|
-
//
|
|
197
|
-
await client.invoices.exchange(...);
|
|
196
|
+
// 支援 B2B 發票交換
|
|
198
197
|
}
|
|
199
198
|
|
|
200
199
|
// 取得所有支援的能力
|
|
@@ -213,7 +212,7 @@ console.log(capabilities);
|
|
|
213
212
|
| `DONATION` | 捐贈 | ✓ |
|
|
214
213
|
| `ALLOWANCE` | 折讓 | ✓ |
|
|
215
214
|
| `VOID` | 作廢 | ✓ |
|
|
216
|
-
| `EXCHANGE` |
|
|
215
|
+
| `EXCHANGE` | B2B 交換 | ✓ |
|
|
217
216
|
| `PRINT` | 列印格式 | ✓ |
|
|
218
217
|
|
|
219
218
|
## 錯誤處理
|
|
@@ -246,11 +245,51 @@ try {
|
|
|
246
245
|
}
|
|
247
246
|
```
|
|
248
247
|
|
|
248
|
+
## 自訂系統商
|
|
249
|
+
|
|
250
|
+
如果您使用的加值中心尚未內建支援,可以自行實作:
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
import { Zinvoice, Capability } from '@zentring/zinvoice';
|
|
254
|
+
|
|
255
|
+
const client = Zinvoice.custom({
|
|
256
|
+
name: '自訂系統商',
|
|
257
|
+
capabilities: [Capability.B2C, Capability.QUERY, Capability.LIST],
|
|
258
|
+
invoices: {
|
|
259
|
+
issue: async (invoice) => {
|
|
260
|
+
// 實作開立發票邏輯
|
|
261
|
+
return {
|
|
262
|
+
invoiceNumber: InvoiceNumber.create('AA12345678'),
|
|
263
|
+
invoiceTime: new Date(),
|
|
264
|
+
randomNumber: '1234',
|
|
265
|
+
barcode: '...',
|
|
266
|
+
qrcodeLeft: '...',
|
|
267
|
+
qrcodeRight: '...',
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
findByNumber: async (number) => { /* ... */ },
|
|
271
|
+
findByOrderId: async (orderId) => { /* ... */ },
|
|
272
|
+
getStatus: async (numbers) => { /* ... */ },
|
|
273
|
+
list: async (query) => { /* ... */ },
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
**重要:** 註冊的 Capability 必須實作對應的方法,否則會拋出 `ValidationError`:
|
|
279
|
+
|
|
280
|
+
| Capability | 必須實作 |
|
|
281
|
+
|------------|----------|
|
|
282
|
+
| `B2C` / `B2B` | `invoices.issue` |
|
|
283
|
+
| `VOID` | `invoices.void` |
|
|
284
|
+
| `QUERY` | `invoices.findByNumber`, `findByOrderId`, `getStatus` |
|
|
285
|
+
| `LIST` | `invoices.list` |
|
|
286
|
+
| `ALLOWANCE` | `allowances.issue`, `void`, `findByNumber`, `findByInvoiceNumber`, `getStatus`, `list` |
|
|
287
|
+
|
|
249
288
|
## 支援的加值中心
|
|
250
289
|
|
|
251
290
|
| Provider | 狀態 | 說明 |
|
|
252
291
|
|----------|:----:|------|
|
|
253
|
-
| `Provider.AMEGO` | ✓ |
|
|
292
|
+
| `Provider.AMEGO` | ✓ | 光貿科技 |
|
|
254
293
|
|
|
255
294
|
## 測試帳號
|
|
256
295
|
|
package/dist/index.cjs
CHANGED
|
@@ -35,7 +35,7 @@ var PROVIDER_CAPABILITIES = {
|
|
|
35
35
|
])
|
|
36
36
|
};
|
|
37
37
|
var PROVIDER_NAMES = {
|
|
38
|
-
["amego" /* AMEGO */]: "\u5149\u8CBF\
|
|
38
|
+
["amego" /* AMEGO */]: "\u5149\u8CBF\u79D1\u6280"
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
// src/errors/index.ts
|
|
@@ -2654,17 +2654,100 @@ var AmegoAllowanceService = class {
|
|
|
2654
2654
|
}
|
|
2655
2655
|
};
|
|
2656
2656
|
|
|
2657
|
+
// src/CustomProvider.ts
|
|
2658
|
+
var CAPABILITY_REQUIREMENTS = {
|
|
2659
|
+
["b2c" /* B2C */]: { invoices: ["issue"] },
|
|
2660
|
+
["b2b" /* B2B */]: { invoices: ["issue"] },
|
|
2661
|
+
["carrier" /* CARRIER */]: {},
|
|
2662
|
+
// Part of issue, no separate handler
|
|
2663
|
+
["donation" /* DONATION */]: {},
|
|
2664
|
+
// Part of issue, no separate handler
|
|
2665
|
+
["void" /* VOID */]: { invoices: ["void"] },
|
|
2666
|
+
["query" /* QUERY */]: { invoices: ["findByNumber", "findByOrderId", "getStatus"] },
|
|
2667
|
+
["list" /* LIST */]: { invoices: ["list"] },
|
|
2668
|
+
["allowance" /* ALLOWANCE */]: { allowances: ["issue", "void", "findByNumber", "findByInvoiceNumber", "getStatus", "list"] },
|
|
2669
|
+
["exchange" /* EXCHANGE */]: {},
|
|
2670
|
+
// TODO: Add exchange handlers when implemented
|
|
2671
|
+
["print" /* PRINT */]: {}
|
|
2672
|
+
// Part of issue result, no separate handler
|
|
2673
|
+
};
|
|
2674
|
+
function validateCustomProviderConfig(config) {
|
|
2675
|
+
const missingHandlers = [];
|
|
2676
|
+
for (const capability of config.capabilities) {
|
|
2677
|
+
const requirements = CAPABILITY_REQUIREMENTS[capability];
|
|
2678
|
+
if (requirements.invoices) {
|
|
2679
|
+
for (const handler of requirements.invoices) {
|
|
2680
|
+
if (!config.invoices?.[handler]) {
|
|
2681
|
+
missingHandlers.push(`invoices.${handler} (required for ${capability})`);
|
|
2682
|
+
}
|
|
2683
|
+
}
|
|
2684
|
+
}
|
|
2685
|
+
if (requirements.allowances) {
|
|
2686
|
+
for (const handler of requirements.allowances) {
|
|
2687
|
+
if (!config.allowances?.[handler]) {
|
|
2688
|
+
missingHandlers.push(`allowances.${handler} (required for ${capability})`);
|
|
2689
|
+
}
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
if (missingHandlers.length > 0) {
|
|
2694
|
+
throw new ValidationError(
|
|
2695
|
+
"customProvider",
|
|
2696
|
+
`Missing required handlers for registered capabilities:
|
|
2697
|
+
- ${missingHandlers.join("\n - ")}`
|
|
2698
|
+
);
|
|
2699
|
+
}
|
|
2700
|
+
}
|
|
2701
|
+
function createCustomInvoiceService(providerName, capabilities, handlers = {}) {
|
|
2702
|
+
const notImplemented = (method, capability) => {
|
|
2703
|
+
return async () => {
|
|
2704
|
+
if (!capabilities.has(capability)) {
|
|
2705
|
+
throw new UnsupportedCapabilityError(capability, providerName);
|
|
2706
|
+
}
|
|
2707
|
+
throw new Error(`${providerName}: ${method} is not implemented`);
|
|
2708
|
+
};
|
|
2709
|
+
};
|
|
2710
|
+
return {
|
|
2711
|
+
issue: handlers.issue ?? notImplemented("issue", "b2c" /* B2C */),
|
|
2712
|
+
void: handlers.void ?? notImplemented("void", "void" /* VOID */),
|
|
2713
|
+
findByNumber: handlers.findByNumber ?? notImplemented("findByNumber", "query" /* QUERY */),
|
|
2714
|
+
findByOrderId: handlers.findByOrderId ?? notImplemented("findByOrderId", "query" /* QUERY */),
|
|
2715
|
+
getStatus: handlers.getStatus ?? notImplemented("getStatus", "query" /* QUERY */),
|
|
2716
|
+
list: handlers.list ?? notImplemented("list", "list" /* LIST */)
|
|
2717
|
+
};
|
|
2718
|
+
}
|
|
2719
|
+
function createCustomAllowanceService(providerName, capabilities, handlers = {}) {
|
|
2720
|
+
const notImplemented = (method) => {
|
|
2721
|
+
return async () => {
|
|
2722
|
+
if (!capabilities.has("allowance" /* ALLOWANCE */)) {
|
|
2723
|
+
throw new UnsupportedCapabilityError("allowance" /* ALLOWANCE */, providerName);
|
|
2724
|
+
}
|
|
2725
|
+
throw new Error(`${providerName}: ${method} is not implemented`);
|
|
2726
|
+
};
|
|
2727
|
+
};
|
|
2728
|
+
return {
|
|
2729
|
+
issue: handlers.issue ?? notImplemented("issue"),
|
|
2730
|
+
void: handlers.void ?? notImplemented("void"),
|
|
2731
|
+
findByNumber: handlers.findByNumber ?? notImplemented("findByNumber"),
|
|
2732
|
+
findByInvoiceNumber: handlers.findByInvoiceNumber ?? notImplemented("findByInvoiceNumber"),
|
|
2733
|
+
getStatus: handlers.getStatus ?? notImplemented("getStatus"),
|
|
2734
|
+
list: handlers.list ?? notImplemented("list")
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
|
|
2657
2738
|
// src/Zinvoice.ts
|
|
2658
2739
|
var Zinvoice = class _Zinvoice {
|
|
2659
2740
|
_provider;
|
|
2741
|
+
_providerName;
|
|
2660
2742
|
_invoiceService;
|
|
2661
2743
|
_allowanceService;
|
|
2662
2744
|
_capabilities;
|
|
2663
|
-
constructor(provider, invoiceService, allowanceService) {
|
|
2745
|
+
constructor(provider, providerName, capabilities, invoiceService, allowanceService) {
|
|
2664
2746
|
this._provider = provider;
|
|
2747
|
+
this._providerName = providerName;
|
|
2748
|
+
this._capabilities = capabilities;
|
|
2665
2749
|
this._invoiceService = invoiceService;
|
|
2666
2750
|
this._allowanceService = allowanceService;
|
|
2667
|
-
this._capabilities = PROVIDER_CAPABILITIES[provider];
|
|
2668
2751
|
}
|
|
2669
2752
|
/**
|
|
2670
2753
|
* Create a Zinvoice client
|
|
@@ -2689,7 +2772,60 @@ var Zinvoice = class _Zinvoice {
|
|
|
2689
2772
|
};
|
|
2690
2773
|
const invoiceService = new AmegoInvoiceService(amegoConfig);
|
|
2691
2774
|
const allowanceService = new AmegoAllowanceService(amegoConfig);
|
|
2692
|
-
return new _Zinvoice(
|
|
2775
|
+
return new _Zinvoice(
|
|
2776
|
+
"amego" /* AMEGO */,
|
|
2777
|
+
PROVIDER_NAMES["amego" /* AMEGO */],
|
|
2778
|
+
PROVIDER_CAPABILITIES["amego" /* AMEGO */],
|
|
2779
|
+
invoiceService,
|
|
2780
|
+
allowanceService
|
|
2781
|
+
);
|
|
2782
|
+
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Create a custom Zinvoice client with user-provided handlers
|
|
2785
|
+
*
|
|
2786
|
+
* @example
|
|
2787
|
+
* ```typescript
|
|
2788
|
+
* const client = Zinvoice.custom({
|
|
2789
|
+
* name: '自訂系統商',
|
|
2790
|
+
* capabilities: [Capability.B2C, Capability.QUERY, Capability.LIST],
|
|
2791
|
+
* invoices: {
|
|
2792
|
+
* issue: async (invoice) => {
|
|
2793
|
+
* // 實作開立發票邏輯
|
|
2794
|
+
* return { invoiceNumber, invoiceTime, randomNumber };
|
|
2795
|
+
* },
|
|
2796
|
+
* findByNumber: async (number) => {
|
|
2797
|
+
* // 實作查詢邏輯
|
|
2798
|
+
* return invoice;
|
|
2799
|
+
* },
|
|
2800
|
+
* findByOrderId: async (orderId) => { ... },
|
|
2801
|
+
* getStatus: async (numbers) => { ... },
|
|
2802
|
+
* list: async (query) => { ... },
|
|
2803
|
+
* },
|
|
2804
|
+
* });
|
|
2805
|
+
* ```
|
|
2806
|
+
*
|
|
2807
|
+
* @throws {ValidationError} If required handlers are not implemented for registered capabilities
|
|
2808
|
+
*/
|
|
2809
|
+
static custom(config) {
|
|
2810
|
+
validateCustomProviderConfig(config);
|
|
2811
|
+
const capabilities = new Set(config.capabilities);
|
|
2812
|
+
const invoiceService = createCustomInvoiceService(
|
|
2813
|
+
config.name,
|
|
2814
|
+
capabilities,
|
|
2815
|
+
config.invoices
|
|
2816
|
+
);
|
|
2817
|
+
const allowanceService = createCustomAllowanceService(
|
|
2818
|
+
config.name,
|
|
2819
|
+
capabilities,
|
|
2820
|
+
config.allowances
|
|
2821
|
+
);
|
|
2822
|
+
return new _Zinvoice(
|
|
2823
|
+
"custom",
|
|
2824
|
+
config.name,
|
|
2825
|
+
capabilities,
|
|
2826
|
+
invoiceService,
|
|
2827
|
+
allowanceService
|
|
2828
|
+
);
|
|
2693
2829
|
}
|
|
2694
2830
|
/**
|
|
2695
2831
|
* Get the invoice service
|
|
@@ -2705,6 +2841,7 @@ var Zinvoice = class _Zinvoice {
|
|
|
2705
2841
|
}
|
|
2706
2842
|
/**
|
|
2707
2843
|
* Get the current provider
|
|
2844
|
+
* Returns 'custom' for custom providers
|
|
2708
2845
|
*/
|
|
2709
2846
|
get provider() {
|
|
2710
2847
|
return this._provider;
|
|
@@ -2713,7 +2850,7 @@ var Zinvoice = class _Zinvoice {
|
|
|
2713
2850
|
* Get the provider display name
|
|
2714
2851
|
*/
|
|
2715
2852
|
get providerName() {
|
|
2716
|
-
return
|
|
2853
|
+
return this._providerName;
|
|
2717
2854
|
}
|
|
2718
2855
|
/**
|
|
2719
2856
|
* Check if a capability is supported
|
|
@@ -2732,9 +2869,15 @@ var Zinvoice = class _Zinvoice {
|
|
|
2732
2869
|
*/
|
|
2733
2870
|
requireCapability(capability) {
|
|
2734
2871
|
if (!this.supports(capability)) {
|
|
2735
|
-
throw new UnsupportedCapabilityError(capability, this.
|
|
2872
|
+
throw new UnsupportedCapabilityError(capability, this._providerName);
|
|
2736
2873
|
}
|
|
2737
2874
|
}
|
|
2875
|
+
/**
|
|
2876
|
+
* Check if this is a custom provider
|
|
2877
|
+
*/
|
|
2878
|
+
get isCustom() {
|
|
2879
|
+
return this._provider === "custom";
|
|
2880
|
+
}
|
|
2738
2881
|
};
|
|
2739
2882
|
|
|
2740
2883
|
// src/domain/shared/CarrierCode.ts
|