stackin-python-sdk 0.5.0__tar.gz → 0.7.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stackin-python-sdk
3
- Version: 0.5.0
3
+ Version: 0.7.0
4
4
  Summary: Python SDK for issuing, consulting and cancelling electronic invoices.
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stackin-python-sdk"
3
- version = "0.5.0"
3
+ version = "0.7.0"
4
4
  authors = [
5
5
  { name = "Fernando Celmer", email = "email@fernandocelmer.com" },
6
6
  ]
@@ -45,7 +45,7 @@ Changelog = "https://github.com/stackin-io/stackin-python-sdk/releases"
45
45
 
46
46
  [tool.poetry]
47
47
  name = "stackin-python-sdk"
48
- version = "0.5.0"
48
+ version = "0.7.0"
49
49
  description = "Python SDK for issuing, consulting and cancelling electronic invoices."
50
50
  authors = ["Fernando Celmer <email@fernandocelmer.com>"]
51
51
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  """Invoice __init__ module."""
2
2
 
3
- __version__ = "0.5.0"
3
+ __version__ = "0.7.0"
4
4
  __description__ = (
5
5
  "Python SDK for issuing, consulting and cancelling electronic invoices."
6
6
  )
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
+ from typing import Any
6
7
 
7
8
  import requests
8
9
 
@@ -140,15 +141,25 @@ class Invoice:
140
141
  *,
141
142
  document_type: DocumentType,
142
143
  reason: str,
144
+ idempotency_key: str | None = None,
143
145
  ) -> dict:
144
- """Cancels a fiscal document by its access key."""
146
+ """Cancels a fiscal document by its access key.
147
+
148
+ Repeating the same idempotency_key with the same body replays
149
+ the first answer instead of cancelling twice. Cancelling is
150
+ irreversible and has a legal window, so a blind retry on a
151
+ dropped connection is the case this exists for.
152
+ """
145
153
  payload = {
146
154
  "document_type": document_type.value,
147
155
  "reason": reason,
148
156
  }
149
157
 
150
158
  return self._request(
151
- "POST", f"/invoices/{access_key}/cancel", json=payload
159
+ "POST",
160
+ f"/invoices/{access_key}/cancel",
161
+ json=payload,
162
+ idempotency_key=idempotency_key,
152
163
  )
153
164
 
154
165
  def invalidate(
@@ -275,6 +286,14 @@ class Invoice:
275
286
 
276
287
  return self._request("GET", "/invoices", params=params)
277
288
 
289
+ def submissions(self, invoice_id: str) -> list:
290
+ """Every attempt made for one invoice, and what came back.
291
+
292
+ consult() gives the status; this gives the reason. Takes the
293
+ invoice_id because a rejected document has no access key.
294
+ """
295
+ return self._request("GET", f"/invoices/{invoice_id}/submissions")
296
+
278
297
  def manifest(
279
298
  self,
280
299
  access_key: str,
@@ -326,7 +345,7 @@ class Invoice:
326
345
  json: dict | None = None,
327
346
  params: dict | None = None,
328
347
  idempotency_key: str | None = None,
329
- ) -> dict:
348
+ ) -> Any:
330
349
  response = self._send(
331
350
  method,
332
351
  path,
@@ -338,7 +357,9 @@ class Invoice:
338
357
  body = response.json() if response.content else {}
339
358
  except ValueError:
340
359
  body = {}
341
- return body.get("result", body)
360
+ if isinstance(body, dict):
361
+ return body.get("result", body)
362
+ return body
342
363
 
343
364
  def _send(
344
365
  self,