cetustek 0.1.0__tar.gz → 0.2.0__tar.gz

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.

Potentially problematic release.


This version of cetustek might be problematic. Click here for more details.

@@ -0,0 +1,12 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(pip install:*)",
5
+ "Bash(python -m build:*)",
6
+ "Bash(pytest:*)",
7
+ "Bash(python -m py_compile:*)",
8
+ "Bash(python:*)",
9
+ "Bash(RENT_ID=89011917 SITE_CODE=ball888 API_PASSWORD=CACBFF1E1 pytest:*)"
10
+ ]
11
+ }
12
+ }
@@ -0,0 +1,315 @@
1
+ Metadata-Version: 2.4
2
+ Name: cetustek
3
+ Version: 0.2.0
4
+ Summary: Python SDK for Cetustek Taiwan e-invoice API
5
+ Project-URL: Homepage, https://github.com/vincelee888/cetustek
6
+ Project-URL: Repository, https://github.com/vincelee888/cetustek
7
+ Project-URL: Issues, https://github.com/vincelee888/cetustek/issues
8
+ Author: Vince Lee
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: cetustek,e-invoice,einvoice,invoice,taiwan
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Topic :: Office/Business :: Financial
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.9
25
+ Requires-Dist: requests>=2.25.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
28
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
29
+ Description-Content-Type: text/markdown
30
+
31
+ # Cetustek
32
+
33
+ Python SDK for [Cetustek](https://www.cetustek.com.tw/) Taiwan e-invoice API.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install cetustek
39
+ ```
40
+
41
+ ## Quick Start
42
+
43
+ ```python
44
+ from cetustek import Cetustek, CreateInvoiceInput, InvoiceItem
45
+
46
+ # Initialize the client
47
+ client = Cetustek(
48
+ endpoint="https://invoice.cetustek.com.tw/InvoiceMultiWeb/InvoiceAPI",
49
+ rent_id="YOUR_RENT_ID",
50
+ site_code="YOUR_SITE_CODE",
51
+ api_password="YOUR_API_PASSWORD",
52
+ )
53
+
54
+ # Create an invoice
55
+ result = client.createInvoice(CreateInvoiceInput(
56
+ order_id="12345678",
57
+ order_date="2026/01/15",
58
+ buyer_identifier="12345678",
59
+ buyer_name="Company Name",
60
+ donate_mark="0",
61
+ invoice_type="07",
62
+ tax_type="1",
63
+ pay_way="1",
64
+ items=[
65
+ InvoiceItem(
66
+ production_code="PROD001",
67
+ description="Product",
68
+ quantity=1,
69
+ unit_price=1000,
70
+ )
71
+ ],
72
+ ))
73
+
74
+ # Access response as dataclass
75
+ print(f"Invoice Number: {result.invoice_number}")
76
+ print(f"Random Code: {result.random_code}")
77
+ print(f"Invoice Year: {result.invoice_year}")
78
+ ```
79
+
80
+ ## API Reference
81
+
82
+ ### Cetustek Client
83
+
84
+ ```python
85
+ from cetustek import Cetustek
86
+
87
+ client = Cetustek(
88
+ endpoint="https://invoice.cetustek.com.tw/InvoiceMultiWeb/InvoiceAPI",
89
+ rent_id="YOUR_RENT_ID",
90
+ site_code="YOUR_SITE_CODE",
91
+ api_password="YOUR_API_PASSWORD",
92
+ )
93
+ ```
94
+
95
+ | Parameter | Description |
96
+ |-----------|-------------|
97
+ | `endpoint` | Cetustek API endpoint URL |
98
+ | `rent_id` | Your Cetustek rent ID (統一編號) |
99
+ | `site_code` | Your site code |
100
+ | `api_password` | Your API password |
101
+
102
+ ### Create Invoice
103
+
104
+ Create a new e-invoice. Returns `CreateInvoiceResponse`.
105
+
106
+ ```python
107
+ from cetustek import CreateInvoiceInput, InvoiceItem, CetustekAPIError
108
+
109
+ invoice_input = CreateInvoiceInput(
110
+ order_id="12345678", # Unique order ID
111
+ order_date="2026/01/15", # Format: yyyy/MM/dd
112
+ donate_mark="0", # 0: No donation, 1: Donate, 2: Donate to specific org
113
+ invoice_type="07", # 07: B2B, 08: B2C
114
+ tax_type="1", # 1: Taxable, 2: Zero-rated, 3: Tax-free, 9: Mixed
115
+ pay_way="1", # Payment method code
116
+ items=[
117
+ InvoiceItem(
118
+ production_code="PROD001",
119
+ description="Product description",
120
+ quantity=1,
121
+ unit_price=1000,
122
+ unit="件", # Optional: unit name
123
+ )
124
+ ],
125
+ # Optional fields
126
+ buyer_identifier="12345678", # Buyer's tax ID (統一編號)
127
+ buyer_name="Company Name",
128
+ buyer_address="Address",
129
+ buyer_email="email@example.com",
130
+ tax_rate=0.05, # Default: 0.05 (5%)
131
+ carrier_type="3J0002", # Carrier type code
132
+ carrier_id1="/ABC1234", # Carrier ID
133
+ carrier_id2="/ABC1234", # Carrier ID confirmation
134
+ npoban="12345", # NPO code for donation
135
+ remark="備註", # Remark
136
+ )
137
+
138
+ try:
139
+ result = client.createInvoice(invoice_input)
140
+ print(f"Invoice Number: {result.invoice_number}") # e.g., "WP20260002"
141
+ print(f"Random Code: {result.random_code}") # e.g., "6827"
142
+ print(f"Invoice Year: {result.invoice_year}") # e.g., "2026"
143
+ except CetustekAPIError as e:
144
+ print(f"Error: {e.code} - {e.message}")
145
+ ```
146
+
147
+ ### Query Invoice
148
+
149
+ Query an existing invoice by number and year. Returns `QueryInvoiceResponse`.
150
+
151
+ ```python
152
+ from cetustek import QueryInvoiceInput
153
+
154
+ query_input = QueryInvoiceInput(
155
+ invoice_number="AA12345678", # 10-character invoice number
156
+ invoice_year="2026", # 4-digit year
157
+ )
158
+
159
+ result = client.queryInvoice(query_input)
160
+
161
+ # Access invoice details
162
+ print(f"Invoice Number: {result.invoice_number}")
163
+ print(f"Order ID: {result.order_id}")
164
+ print(f"Random Code: {result.random_code}")
165
+ print(f"Buyer Name: {result.buyer_name}")
166
+ print(f"Seller Name: {result.seller_name}")
167
+ print(f"Total Amount: {result.total_amount}")
168
+ print(f"Invoice Status: {result.invoice_status}")
169
+
170
+ # Access raw XML for additional parsing
171
+ print(result.raw_xml)
172
+ ```
173
+
174
+ ### Cancel Invoice
175
+
176
+ Cancel (void) an existing invoice. Returns `CancelInvoiceResponse`.
177
+
178
+ ```python
179
+ from cetustek import CancelInvoiceInput
180
+
181
+ cancel_input = CancelInvoiceInput(
182
+ invoice_number="AA12345678",
183
+ invoice_year="2026",
184
+ remark="Cancellation reason",
185
+ return_tax_document_number=None, # Optional: tax document number
186
+ )
187
+
188
+ # Standard cancellation (with validation)
189
+ result = client.cancelInvoice(cancel_input)
190
+
191
+ # Skip validation checks
192
+ result = client.cancelInvoice(cancel_input, no_check=True)
193
+
194
+ if result.success:
195
+ print("Invoice cancelled successfully")
196
+ else:
197
+ print(f"Failed with code: {result.code}")
198
+ ```
199
+
200
+ ## Response Models
201
+
202
+ ### CreateInvoiceResponse
203
+
204
+ | Field | Type | Description |
205
+ |-------|------|-------------|
206
+ | `invoice_number` | str | 10-character invoice number (e.g., "WP20260002") |
207
+ | `random_code` | str | 4-digit random code (e.g., "6827") |
208
+ | `invoice_year` | str | Year extracted from invoice number (property) |
209
+
210
+ ### QueryInvoiceResponse
211
+
212
+ | Field | Type | Description |
213
+ |-------|------|-------------|
214
+ | `invoice_number` | str | Invoice number |
215
+ | `invoice_date` | str | Invoice date |
216
+ | `invoice_time` | str | Invoice time |
217
+ | `order_id` | str | Order ID |
218
+ | `random_code` | str | Random code |
219
+ | `buyer_identifier` | str | Buyer tax ID |
220
+ | `buyer_name` | str | Buyer name |
221
+ | `seller_identifier` | str | Seller tax ID |
222
+ | `seller_name` | str | Seller name |
223
+ | `invoice_status` | str | Invoice status |
224
+ | `donate_mark` | str | Donation mark |
225
+ | `carrier_type` | str | Carrier type |
226
+ | `carrier_id` | str | Carrier ID |
227
+ | `npoban` | str | NPO code |
228
+ | `tax_type` | str | Tax type |
229
+ | `sales_amount` | float | Sales amount |
230
+ | `tax_amount` | float | Tax amount |
231
+ | `total_amount` | float | Total amount |
232
+ | `raw_xml` | str | Original XML response |
233
+
234
+ ### CancelInvoiceResponse
235
+
236
+ | Field | Type | Description |
237
+ |-------|------|-------------|
238
+ | `success` | bool | Whether cancellation succeeded |
239
+ | `code` | str | Response code ("C0" for success) |
240
+ | `message` | str | Error message (if failed) |
241
+
242
+ ## Input Models
243
+
244
+ ### InvoiceItem
245
+
246
+ | Field | Type | Required | Description |
247
+ |-------|------|----------|-------------|
248
+ | `production_code` | str | Yes | Product code |
249
+ | `description` | str | Yes | Product description |
250
+ | `quantity` | float | Yes | Quantity |
251
+ | `unit_price` | float | Yes | Unit price |
252
+ | `unit` | str | No | Unit name (e.g., "件", "個") |
253
+
254
+ ### CreateInvoiceInput
255
+
256
+ | Field | Type | Required | Description |
257
+ |-------|------|----------|-------------|
258
+ | `order_id` | str | Yes | Unique order ID |
259
+ | `order_date` | str | Yes | Order date (yyyy/MM/dd) |
260
+ | `donate_mark` | str | Yes | Donation mark: 0/1/2 |
261
+ | `invoice_type` | str | Yes | Invoice type: 07 (B2B) / 08 (B2C) |
262
+ | `pay_way` | str | Yes | Payment method code |
263
+ | `tax_type` | str | Yes | Tax type: 1/2/3/4/5/9 |
264
+ | `items` | List[InvoiceItem] | Yes | Invoice items |
265
+ | `buyer_identifier` | str | No | Buyer tax ID |
266
+ | `buyer_name` | str | No | Buyer name |
267
+ | `buyer_address` | str | No | Buyer address |
268
+ | `buyer_email` | str | No | Buyer email |
269
+ | `tax_rate` | float | No | Tax rate (default: 0.05) |
270
+ | `carrier_type` | str | No | Carrier type code |
271
+ | `carrier_id1` | str | No | Carrier ID |
272
+ | `carrier_id2` | str | No | Carrier ID confirmation |
273
+ | `npoban` | str | No | NPO code for donation |
274
+ | `remark` | str | No | Remark |
275
+
276
+ ## Exception Handling
277
+
278
+ ```python
279
+ from cetustek import CetustekError, CetustekAPIError
280
+
281
+ try:
282
+ result = client.createInvoice(invoice_input)
283
+ except CetustekAPIError as e:
284
+ # API returned an error response
285
+ print(f"API Error Code: {e.code}")
286
+ print(f"API Error Message: {e.message}")
287
+ except CetustekError as e:
288
+ # General SDK error (e.g., invalid response format)
289
+ print(f"SDK Error: {e}")
290
+ except Exception as e:
291
+ # Network or other errors
292
+ print(f"Error: {e}")
293
+ ```
294
+
295
+ ## Example
296
+
297
+ See [example.py](example.py) for a complete working example.
298
+
299
+ ## Development
300
+
301
+ ```bash
302
+ # Clone the repository
303
+ git clone https://github.com/vincelee888/cetustek.git
304
+ cd cetustek
305
+
306
+ # Install in development mode
307
+ pip install -e ".[dev]"
308
+
309
+ # Run tests
310
+ pytest
311
+ ```
312
+
313
+ ## License
314
+
315
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,285 @@
1
+ # Cetustek
2
+
3
+ Python SDK for [Cetustek](https://www.cetustek.com.tw/) Taiwan e-invoice API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install cetustek
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```python
14
+ from cetustek import Cetustek, CreateInvoiceInput, InvoiceItem
15
+
16
+ # Initialize the client
17
+ client = Cetustek(
18
+ endpoint="https://invoice.cetustek.com.tw/InvoiceMultiWeb/InvoiceAPI",
19
+ rent_id="YOUR_RENT_ID",
20
+ site_code="YOUR_SITE_CODE",
21
+ api_password="YOUR_API_PASSWORD",
22
+ )
23
+
24
+ # Create an invoice
25
+ result = client.createInvoice(CreateInvoiceInput(
26
+ order_id="12345678",
27
+ order_date="2026/01/15",
28
+ buyer_identifier="12345678",
29
+ buyer_name="Company Name",
30
+ donate_mark="0",
31
+ invoice_type="07",
32
+ tax_type="1",
33
+ pay_way="1",
34
+ items=[
35
+ InvoiceItem(
36
+ production_code="PROD001",
37
+ description="Product",
38
+ quantity=1,
39
+ unit_price=1000,
40
+ )
41
+ ],
42
+ ))
43
+
44
+ # Access response as dataclass
45
+ print(f"Invoice Number: {result.invoice_number}")
46
+ print(f"Random Code: {result.random_code}")
47
+ print(f"Invoice Year: {result.invoice_year}")
48
+ ```
49
+
50
+ ## API Reference
51
+
52
+ ### Cetustek Client
53
+
54
+ ```python
55
+ from cetustek import Cetustek
56
+
57
+ client = Cetustek(
58
+ endpoint="https://invoice.cetustek.com.tw/InvoiceMultiWeb/InvoiceAPI",
59
+ rent_id="YOUR_RENT_ID",
60
+ site_code="YOUR_SITE_CODE",
61
+ api_password="YOUR_API_PASSWORD",
62
+ )
63
+ ```
64
+
65
+ | Parameter | Description |
66
+ |-----------|-------------|
67
+ | `endpoint` | Cetustek API endpoint URL |
68
+ | `rent_id` | Your Cetustek rent ID (統一編號) |
69
+ | `site_code` | Your site code |
70
+ | `api_password` | Your API password |
71
+
72
+ ### Create Invoice
73
+
74
+ Create a new e-invoice. Returns `CreateInvoiceResponse`.
75
+
76
+ ```python
77
+ from cetustek import CreateInvoiceInput, InvoiceItem, CetustekAPIError
78
+
79
+ invoice_input = CreateInvoiceInput(
80
+ order_id="12345678", # Unique order ID
81
+ order_date="2026/01/15", # Format: yyyy/MM/dd
82
+ donate_mark="0", # 0: No donation, 1: Donate, 2: Donate to specific org
83
+ invoice_type="07", # 07: B2B, 08: B2C
84
+ tax_type="1", # 1: Taxable, 2: Zero-rated, 3: Tax-free, 9: Mixed
85
+ pay_way="1", # Payment method code
86
+ items=[
87
+ InvoiceItem(
88
+ production_code="PROD001",
89
+ description="Product description",
90
+ quantity=1,
91
+ unit_price=1000,
92
+ unit="件", # Optional: unit name
93
+ )
94
+ ],
95
+ # Optional fields
96
+ buyer_identifier="12345678", # Buyer's tax ID (統一編號)
97
+ buyer_name="Company Name",
98
+ buyer_address="Address",
99
+ buyer_email="email@example.com",
100
+ tax_rate=0.05, # Default: 0.05 (5%)
101
+ carrier_type="3J0002", # Carrier type code
102
+ carrier_id1="/ABC1234", # Carrier ID
103
+ carrier_id2="/ABC1234", # Carrier ID confirmation
104
+ npoban="12345", # NPO code for donation
105
+ remark="備註", # Remark
106
+ )
107
+
108
+ try:
109
+ result = client.createInvoice(invoice_input)
110
+ print(f"Invoice Number: {result.invoice_number}") # e.g., "WP20260002"
111
+ print(f"Random Code: {result.random_code}") # e.g., "6827"
112
+ print(f"Invoice Year: {result.invoice_year}") # e.g., "2026"
113
+ except CetustekAPIError as e:
114
+ print(f"Error: {e.code} - {e.message}")
115
+ ```
116
+
117
+ ### Query Invoice
118
+
119
+ Query an existing invoice by number and year. Returns `QueryInvoiceResponse`.
120
+
121
+ ```python
122
+ from cetustek import QueryInvoiceInput
123
+
124
+ query_input = QueryInvoiceInput(
125
+ invoice_number="AA12345678", # 10-character invoice number
126
+ invoice_year="2026", # 4-digit year
127
+ )
128
+
129
+ result = client.queryInvoice(query_input)
130
+
131
+ # Access invoice details
132
+ print(f"Invoice Number: {result.invoice_number}")
133
+ print(f"Order ID: {result.order_id}")
134
+ print(f"Random Code: {result.random_code}")
135
+ print(f"Buyer Name: {result.buyer_name}")
136
+ print(f"Seller Name: {result.seller_name}")
137
+ print(f"Total Amount: {result.total_amount}")
138
+ print(f"Invoice Status: {result.invoice_status}")
139
+
140
+ # Access raw XML for additional parsing
141
+ print(result.raw_xml)
142
+ ```
143
+
144
+ ### Cancel Invoice
145
+
146
+ Cancel (void) an existing invoice. Returns `CancelInvoiceResponse`.
147
+
148
+ ```python
149
+ from cetustek import CancelInvoiceInput
150
+
151
+ cancel_input = CancelInvoiceInput(
152
+ invoice_number="AA12345678",
153
+ invoice_year="2026",
154
+ remark="Cancellation reason",
155
+ return_tax_document_number=None, # Optional: tax document number
156
+ )
157
+
158
+ # Standard cancellation (with validation)
159
+ result = client.cancelInvoice(cancel_input)
160
+
161
+ # Skip validation checks
162
+ result = client.cancelInvoice(cancel_input, no_check=True)
163
+
164
+ if result.success:
165
+ print("Invoice cancelled successfully")
166
+ else:
167
+ print(f"Failed with code: {result.code}")
168
+ ```
169
+
170
+ ## Response Models
171
+
172
+ ### CreateInvoiceResponse
173
+
174
+ | Field | Type | Description |
175
+ |-------|------|-------------|
176
+ | `invoice_number` | str | 10-character invoice number (e.g., "WP20260002") |
177
+ | `random_code` | str | 4-digit random code (e.g., "6827") |
178
+ | `invoice_year` | str | Year extracted from invoice number (property) |
179
+
180
+ ### QueryInvoiceResponse
181
+
182
+ | Field | Type | Description |
183
+ |-------|------|-------------|
184
+ | `invoice_number` | str | Invoice number |
185
+ | `invoice_date` | str | Invoice date |
186
+ | `invoice_time` | str | Invoice time |
187
+ | `order_id` | str | Order ID |
188
+ | `random_code` | str | Random code |
189
+ | `buyer_identifier` | str | Buyer tax ID |
190
+ | `buyer_name` | str | Buyer name |
191
+ | `seller_identifier` | str | Seller tax ID |
192
+ | `seller_name` | str | Seller name |
193
+ | `invoice_status` | str | Invoice status |
194
+ | `donate_mark` | str | Donation mark |
195
+ | `carrier_type` | str | Carrier type |
196
+ | `carrier_id` | str | Carrier ID |
197
+ | `npoban` | str | NPO code |
198
+ | `tax_type` | str | Tax type |
199
+ | `sales_amount` | float | Sales amount |
200
+ | `tax_amount` | float | Tax amount |
201
+ | `total_amount` | float | Total amount |
202
+ | `raw_xml` | str | Original XML response |
203
+
204
+ ### CancelInvoiceResponse
205
+
206
+ | Field | Type | Description |
207
+ |-------|------|-------------|
208
+ | `success` | bool | Whether cancellation succeeded |
209
+ | `code` | str | Response code ("C0" for success) |
210
+ | `message` | str | Error message (if failed) |
211
+
212
+ ## Input Models
213
+
214
+ ### InvoiceItem
215
+
216
+ | Field | Type | Required | Description |
217
+ |-------|------|----------|-------------|
218
+ | `production_code` | str | Yes | Product code |
219
+ | `description` | str | Yes | Product description |
220
+ | `quantity` | float | Yes | Quantity |
221
+ | `unit_price` | float | Yes | Unit price |
222
+ | `unit` | str | No | Unit name (e.g., "件", "個") |
223
+
224
+ ### CreateInvoiceInput
225
+
226
+ | Field | Type | Required | Description |
227
+ |-------|------|----------|-------------|
228
+ | `order_id` | str | Yes | Unique order ID |
229
+ | `order_date` | str | Yes | Order date (yyyy/MM/dd) |
230
+ | `donate_mark` | str | Yes | Donation mark: 0/1/2 |
231
+ | `invoice_type` | str | Yes | Invoice type: 07 (B2B) / 08 (B2C) |
232
+ | `pay_way` | str | Yes | Payment method code |
233
+ | `tax_type` | str | Yes | Tax type: 1/2/3/4/5/9 |
234
+ | `items` | List[InvoiceItem] | Yes | Invoice items |
235
+ | `buyer_identifier` | str | No | Buyer tax ID |
236
+ | `buyer_name` | str | No | Buyer name |
237
+ | `buyer_address` | str | No | Buyer address |
238
+ | `buyer_email` | str | No | Buyer email |
239
+ | `tax_rate` | float | No | Tax rate (default: 0.05) |
240
+ | `carrier_type` | str | No | Carrier type code |
241
+ | `carrier_id1` | str | No | Carrier ID |
242
+ | `carrier_id2` | str | No | Carrier ID confirmation |
243
+ | `npoban` | str | No | NPO code for donation |
244
+ | `remark` | str | No | Remark |
245
+
246
+ ## Exception Handling
247
+
248
+ ```python
249
+ from cetustek import CetustekError, CetustekAPIError
250
+
251
+ try:
252
+ result = client.createInvoice(invoice_input)
253
+ except CetustekAPIError as e:
254
+ # API returned an error response
255
+ print(f"API Error Code: {e.code}")
256
+ print(f"API Error Message: {e.message}")
257
+ except CetustekError as e:
258
+ # General SDK error (e.g., invalid response format)
259
+ print(f"SDK Error: {e}")
260
+ except Exception as e:
261
+ # Network or other errors
262
+ print(f"Error: {e}")
263
+ ```
264
+
265
+ ## Example
266
+
267
+ See [example.py](example.py) for a complete working example.
268
+
269
+ ## Development
270
+
271
+ ```bash
272
+ # Clone the repository
273
+ git clone https://github.com/vincelee888/cetustek.git
274
+ cd cetustek
275
+
276
+ # Install in development mode
277
+ pip install -e ".[dev]"
278
+
279
+ # Run tests
280
+ pytest
281
+ ```
282
+
283
+ ## License
284
+
285
+ MIT License - see [LICENSE](LICENSE) for details.