smartbill-sdk 1.0.0
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.
- checksums.yaml +7 -0
- data/AGENTS.md +211 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE.txt +21 -0
- data/README.md +265 -0
- data/Rakefile +22 -0
- data/Steepfile +6 -0
- data/docs/openapi.json +9741 -0
- data/examples/create_estimate_sync.rb +53 -0
- data/examples/create_invoice_eur_product_in_ron.rb +100 -0
- data/examples/create_invoice_sync.rb +57 -0
- data/examples/create_payment_sync.rb +36 -0
- data/examples/fiscal_receipt_sync.rb +50 -0
- data/examples/invoice_lifecycle_sync.rb +43 -0
- data/examples/list_series_sync.rb +27 -0
- data/examples/send_email_sync.rb +40 -0
- data/examples/taxes_and_stocks_sync.rb +48 -0
- data/lib/smartbill/sdk/api_error.rb +27 -0
- data/lib/smartbill/sdk/auth_error.rb +8 -0
- data/lib/smartbill/sdk/client.rb +68 -0
- data/lib/smartbill/sdk/contracts/base.rb +33 -0
- data/lib/smartbill/sdk/contracts/email_contract.rb +29 -0
- data/lib/smartbill/sdk/contracts/estimate_contract.rb +18 -0
- data/lib/smartbill/sdk/contracts/invoice_contract.rb +29 -0
- data/lib/smartbill/sdk/contracts/invoice_payment_contract.rb +18 -0
- data/lib/smartbill/sdk/contracts/invoice_ref_contract.rb +19 -0
- data/lib/smartbill/sdk/contracts/payment_contract.rb +37 -0
- data/lib/smartbill/sdk/contracts/storno_contract.rb +17 -0
- data/lib/smartbill/sdk/contracts.rb +19 -0
- data/lib/smartbill/sdk/error.rb +8 -0
- data/lib/smartbill/sdk/models/base_response.rb +16 -0
- data/lib/smartbill/sdk/models/client.rb +26 -0
- data/lib/smartbill/sdk/models/discount_type.rb +13 -0
- data/lib/smartbill/sdk/models/document_type.rb +13 -0
- data/lib/smartbill/sdk/models/email_document.rb +23 -0
- data/lib/smartbill/sdk/models/email_response.rb +12 -0
- data/lib/smartbill/sdk/models/email_status.rb +13 -0
- data/lib/smartbill/sdk/models/estimate.rb +32 -0
- data/lib/smartbill/sdk/models/fiscal_receipt_response.rb +16 -0
- data/lib/smartbill/sdk/models/invoice.rb +44 -0
- data/lib/smartbill/sdk/models/invoice_create_response.rb +10 -0
- data/lib/smartbill/sdk/models/invoice_payment.rb +15 -0
- data/lib/smartbill/sdk/models/invoice_ref.rb +24 -0
- data/lib/smartbill/sdk/models/payment.rb +49 -0
- data/lib/smartbill/sdk/models/payment_status_response.rb +19 -0
- data/lib/smartbill/sdk/models/payment_type.rb +22 -0
- data/lib/smartbill/sdk/models/product.rb +38 -0
- data/lib/smartbill/sdk/models/proforma_invoices_response.rb +13 -0
- data/lib/smartbill/sdk/models/series.rb +14 -0
- data/lib/smartbill/sdk/models/series_list_response.rb +14 -0
- data/lib/smartbill/sdk/models/stock_list.rb +13 -0
- data/lib/smartbill/sdk/models/stock_product.rb +15 -0
- data/lib/smartbill/sdk/models/stock_warehouse.rb +13 -0
- data/lib/smartbill/sdk/models/stocks_response.rb +14 -0
- data/lib/smartbill/sdk/models/storno_request.rb +17 -0
- data/lib/smartbill/sdk/models/storno_response.rb +14 -0
- data/lib/smartbill/sdk/models/struct.rb +102 -0
- data/lib/smartbill/sdk/models/tax.rb +14 -0
- data/lib/smartbill/sdk/models/taxes_response.rb +14 -0
- data/lib/smartbill/sdk/models.rb +17 -0
- data/lib/smartbill/sdk/net_http_adapter.rb +62 -0
- data/lib/smartbill/sdk/rate_limit_error.rb +9 -0
- data/lib/smartbill/sdk/response.rb +12 -0
- data/lib/smartbill/sdk/services/base_service.rb +39 -0
- data/lib/smartbill/sdk/services/configuration_service.rb +29 -0
- data/lib/smartbill/sdk/services/email_service.rb +18 -0
- data/lib/smartbill/sdk/services/estimates_service.rb +60 -0
- data/lib/smartbill/sdk/services/invoices_service.rb +69 -0
- data/lib/smartbill/sdk/services/payments_service.rb +50 -0
- data/lib/smartbill/sdk/services/stocks_service.rb +21 -0
- data/lib/smartbill/sdk/services.rb +30 -0
- data/lib/smartbill/sdk/transport/rate_limiter.rb +49 -0
- data/lib/smartbill/sdk/transport/request.rb +17 -0
- data/lib/smartbill/sdk/transport.rb +162 -0
- data/lib/smartbill/sdk/transport_error.rb +8 -0
- data/lib/smartbill/sdk/types.rb +22 -0
- data/lib/smartbill/sdk/validation_error.rb +8 -0
- data/lib/smartbill/sdk/version.rb +7 -0
- data/lib/smartbill/sdk.rb +31 -0
- data/sig/smartbill/sdk.rbs +661 -0
- data/skills/README.md +35 -0
- data/skills/smartbill-email/SKILL.md +120 -0
- data/skills/smartbill-invoices/SKILL.md +178 -0
- data/skills/smartbill-payments/SKILL.md +194 -0
- metadata +214 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
module Smartbill
|
|
2
|
+
module Sdk
|
|
3
|
+
VERSION: String
|
|
4
|
+
|
|
5
|
+
DEFAULT_BASE_URL: String
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# --- Exceptions ---------------------------------------------------------------
|
|
10
|
+
|
|
11
|
+
module Smartbill
|
|
12
|
+
module Sdk
|
|
13
|
+
class Error < StandardError
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class AuthError < Error
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class RateLimitError < Error
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class TransportError < Error
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
class ValidationError < Error
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class APIError < Error
|
|
29
|
+
attr_reader error_text: String
|
|
30
|
+
attr_reader message_field: String?
|
|
31
|
+
attr_reader status_code: Integer?
|
|
32
|
+
|
|
33
|
+
def initialize: (
|
|
34
|
+
?error_text: String,
|
|
35
|
+
?message: String?,
|
|
36
|
+
?status_code: Integer?
|
|
37
|
+
) -> void
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# --- Types --------------------------------------------------------------------
|
|
43
|
+
|
|
44
|
+
module Smartbill
|
|
45
|
+
module Sdk
|
|
46
|
+
module Types
|
|
47
|
+
# A strict String or strict Integer (the SmartBill API returns some
|
|
48
|
+
# fields as either, depending on the endpoint).
|
|
49
|
+
type str_or_int = String | Integer
|
|
50
|
+
|
|
51
|
+
StrOrInt: untyped
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# --- HTTP transport -----------------------------------------------------------
|
|
57
|
+
|
|
58
|
+
module Smartbill
|
|
59
|
+
module Sdk
|
|
60
|
+
# A simple HTTP response value object returned by adapters.
|
|
61
|
+
class Response < ::Struct[untyped]
|
|
62
|
+
def self.new: (status: Integer, body: String?, content_type: String?) -> Response
|
|
63
|
+
def initialize: (status: Integer, body: String?, content_type: String?) -> void
|
|
64
|
+
|
|
65
|
+
attr_accessor status(): Integer
|
|
66
|
+
attr_accessor body(): String?
|
|
67
|
+
attr_accessor content_type(): String?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
module Smartbill
|
|
73
|
+
module Sdk
|
|
74
|
+
module Transport
|
|
75
|
+
DEFAULT_BASE_URL: String
|
|
76
|
+
DEFAULT_TIMEOUT: Float
|
|
77
|
+
|
|
78
|
+
ENVELOPE_KEYS: Array[String]
|
|
79
|
+
ERROR_FIELDS: Array[String]
|
|
80
|
+
|
|
81
|
+
# A request value object built by `build_request` and sent by an adapter.
|
|
82
|
+
class Request < ::Struct[untyped]
|
|
83
|
+
def self.new: (
|
|
84
|
+
http_method: String,
|
|
85
|
+
url: String,
|
|
86
|
+
headers: Hash[String, String],
|
|
87
|
+
query: Hash[String, untyped]?,
|
|
88
|
+
body: String?
|
|
89
|
+
) -> Request
|
|
90
|
+
def initialize: (
|
|
91
|
+
http_method: String,
|
|
92
|
+
url: String,
|
|
93
|
+
headers: Hash[String, String],
|
|
94
|
+
query: Hash[String, untyped]?,
|
|
95
|
+
body: String?
|
|
96
|
+
) -> void
|
|
97
|
+
|
|
98
|
+
attr_accessor http_method(): String
|
|
99
|
+
attr_accessor url(): String
|
|
100
|
+
attr_accessor headers(): Hash[String, String]
|
|
101
|
+
attr_accessor query(): Hash[String, untyped]?
|
|
102
|
+
attr_accessor body(): String?
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def self.build_auth_header: (String username, String token) -> String
|
|
106
|
+
def self.build_auth: (String username, String token) -> String
|
|
107
|
+
|
|
108
|
+
def self.build_request: (
|
|
109
|
+
method: String,
|
|
110
|
+
base_url: String,
|
|
111
|
+
path: String,
|
|
112
|
+
?params: Hash[String, untyped]?,
|
|
113
|
+
?json_body: untyped?,
|
|
114
|
+
?accept: String,
|
|
115
|
+
?content_type: String,
|
|
116
|
+
?auth_header: String?
|
|
117
|
+
) -> Request
|
|
118
|
+
|
|
119
|
+
def self.parse_envelope: (untyped payload) -> untyped
|
|
120
|
+
|
|
121
|
+
def self.extract_error: (untyped envelope) -> [String, String?]
|
|
122
|
+
|
|
123
|
+
def self.handle_response: (Response response, ?binary: bool) -> untyped
|
|
124
|
+
|
|
125
|
+
# Simple token-bucket limiter: `max_calls` per `window_seconds`.
|
|
126
|
+
class RateLimiter
|
|
127
|
+
attr_reader max_calls: Integer
|
|
128
|
+
attr_reader window_seconds: Float
|
|
129
|
+
|
|
130
|
+
def initialize: (?max_calls: Integer, ?window_seconds: Float) -> void
|
|
131
|
+
def acquire: () -> void
|
|
132
|
+
def notify_403: () -> void
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
module Smartbill
|
|
139
|
+
module Sdk
|
|
140
|
+
# Default HTTP adapter backed by stdlib `Net::HTTP`.
|
|
141
|
+
#
|
|
142
|
+
# The SDK talks to the adapter through a single method, `#call`, which
|
|
143
|
+
# receives a `Transport::Request` and returns a `Response`.
|
|
144
|
+
class NetHttpAdapter
|
|
145
|
+
def initialize: (?timeout: Integer | Float) -> void
|
|
146
|
+
def call: (Transport::Request req) -> Response
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# --- Models (dry-struct) ------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
module Smartbill
|
|
154
|
+
module Sdk
|
|
155
|
+
module Models
|
|
156
|
+
INFLECTOR: untyped # Dry::Inflector
|
|
157
|
+
|
|
158
|
+
# Base class for every SmartBill request/response model. A thin adapter
|
|
159
|
+
# over `Dry::Struct` providing snake_case <-> camelCase I/O, type
|
|
160
|
+
# coercion, required-attribute presence (raises `ValidationError`), and
|
|
161
|
+
# permissive parsing (unknown input keys are ignored).
|
|
162
|
+
class Struct
|
|
163
|
+
# Construct a struct, translating `Dry::Struct::Error` (e.g. a missing
|
|
164
|
+
# required attribute) into `ValidationError`.
|
|
165
|
+
def self.new: (?untyped attrs) ?{ () -> void } -> instance
|
|
166
|
+
|
|
167
|
+
# Serialize to a camelCase-keyed Hash matching the SmartBill API,
|
|
168
|
+
# omitting nil values by default. Nested structs and arrays of
|
|
169
|
+
# structs are serialized recursively.
|
|
170
|
+
def to_h: (?exclude_none: bool) -> Hash[String, untyped]
|
|
171
|
+
|
|
172
|
+
def to_json: (*untyped args) -> String
|
|
173
|
+
|
|
174
|
+
# Return a snake_case Symbol-keyed Hash (including nils) reflecting
|
|
175
|
+
# the Ruby attributes, with nested structs recursively converted to
|
|
176
|
+
# hashes. Used as input to the validation contracts.
|
|
177
|
+
def to_attributes: () -> Hash[Symbol, untyped]
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
# Document type for the e-mail endpoint.
|
|
181
|
+
module DocumentType
|
|
182
|
+
INVOICE: String # "factura"
|
|
183
|
+
PROFORMA: String # "proforma"
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Possible values for `type` on payments / incasari.
|
|
187
|
+
module PaymentType
|
|
188
|
+
CHITANTA: String
|
|
189
|
+
BON: String
|
|
190
|
+
CARD: String
|
|
191
|
+
CARD_ONLINE: String
|
|
192
|
+
CEC: String
|
|
193
|
+
BILET_ORDIN: String
|
|
194
|
+
ORDIN_PLATA: String
|
|
195
|
+
MANDAT_POSTAL: String
|
|
196
|
+
EXTRAS_DE_CONT: String
|
|
197
|
+
RAMBURS: String
|
|
198
|
+
ALTA_INCASARE: String
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Discount type: 1 = valoric, 2 = procentual.
|
|
202
|
+
module DiscountType
|
|
203
|
+
VALORIC: Integer # 1
|
|
204
|
+
PROCENTUAL: Integer # 2
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
# Client data (`client` / `clientMin`).
|
|
208
|
+
class Client < Struct
|
|
209
|
+
attr_reader name: String
|
|
210
|
+
attr_reader vat_code: String?
|
|
211
|
+
attr_reader code: String?
|
|
212
|
+
attr_reader address: String?
|
|
213
|
+
attr_reader reg_com: String?
|
|
214
|
+
attr_reader is_tax_payer: bool?
|
|
215
|
+
attr_reader contact: String?
|
|
216
|
+
attr_reader phone: String?
|
|
217
|
+
attr_reader city: String?
|
|
218
|
+
attr_reader county: String?
|
|
219
|
+
attr_reader country: String?
|
|
220
|
+
attr_reader email: String?
|
|
221
|
+
attr_reader bank: String?
|
|
222
|
+
attr_reader iban: String?
|
|
223
|
+
attr_reader save_to_db: bool?
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
# A product or discount line on an invoice / proforma / bon fiscal.
|
|
227
|
+
class Product < Struct
|
|
228
|
+
attr_reader name: String
|
|
229
|
+
attr_reader code: String?
|
|
230
|
+
attr_reader product_description: String?
|
|
231
|
+
attr_reader translated_name: String?
|
|
232
|
+
attr_reader translated_measuring_unit: String?
|
|
233
|
+
attr_reader is_discount: bool?
|
|
234
|
+
attr_reader number_of_items: Integer?
|
|
235
|
+
attr_reader measuring_unit_name: String?
|
|
236
|
+
attr_reader currency: String?
|
|
237
|
+
attr_reader quantity: Float?
|
|
238
|
+
attr_reader price: Float?
|
|
239
|
+
attr_reader is_tax_included: bool?
|
|
240
|
+
attr_reader tax_name: String?
|
|
241
|
+
attr_reader tax_percentage: Float?
|
|
242
|
+
attr_reader exchange_rate: Float?
|
|
243
|
+
attr_reader save_to_db: bool?
|
|
244
|
+
attr_reader warehouse_name: String?
|
|
245
|
+
attr_reader is_service: bool?
|
|
246
|
+
attr_reader discount_type: Integer?
|
|
247
|
+
attr_reader discount_percentage: Float?
|
|
248
|
+
attr_reader discount_value: Float?
|
|
249
|
+
attr_reader discount_tax_value: Float?
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Reference to an existing document (series + number). Accepts both
|
|
253
|
+
# `seriesName` and `series` on input; always emits `seriesName`.
|
|
254
|
+
class InvoiceRef < Struct
|
|
255
|
+
attr_reader series_name: String
|
|
256
|
+
attr_reader number: String
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
# Payment-at-issuance block embedded in an `Invoice`.
|
|
260
|
+
class InvoicePayment < Struct
|
|
261
|
+
attr_reader value: Float
|
|
262
|
+
attr_reader payment_series: String?
|
|
263
|
+
attr_reader type: String
|
|
264
|
+
attr_reader is_cash: bool?
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
# Request body for `POST /invoice` (emitere factura).
|
|
268
|
+
class Invoice < Struct
|
|
269
|
+
attr_reader company_vat_code: String
|
|
270
|
+
attr_reader client: Client?
|
|
271
|
+
attr_reader is_draft: bool?
|
|
272
|
+
attr_reader issue_date: String?
|
|
273
|
+
attr_reader series_name: String?
|
|
274
|
+
attr_reader currency: String?
|
|
275
|
+
attr_reader exchange_rate: Float?
|
|
276
|
+
attr_reader language: String?
|
|
277
|
+
attr_reader precision: Integer?
|
|
278
|
+
attr_reader issuer_cnp: String?
|
|
279
|
+
attr_reader issuer_name: String?
|
|
280
|
+
attr_reader aviz: String?
|
|
281
|
+
attr_reader due_date: String?
|
|
282
|
+
attr_reader mentions: String?
|
|
283
|
+
attr_reader observations: String?
|
|
284
|
+
attr_reader delegate_auto: String?
|
|
285
|
+
attr_reader delegate_identity_card: String?
|
|
286
|
+
attr_reader delegate_name: String?
|
|
287
|
+
attr_reader delivery_date: String?
|
|
288
|
+
attr_reader payment_date: String?
|
|
289
|
+
attr_reader use_stock: bool?
|
|
290
|
+
attr_reader use_estimate_details: bool?
|
|
291
|
+
attr_reader use_payment_tax: bool?
|
|
292
|
+
attr_reader payment_base: Float?
|
|
293
|
+
attr_reader colected_tax: Float?
|
|
294
|
+
attr_reader payment_total: Float?
|
|
295
|
+
attr_reader payment_url: String?
|
|
296
|
+
attr_reader estimate: InvoiceRef?
|
|
297
|
+
attr_reader products: Array[Product]
|
|
298
|
+
attr_reader payment: InvoicePayment?
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# Request body for `POST /invoice/reverse` (stornare factura).
|
|
302
|
+
class StornoRequest < Struct
|
|
303
|
+
attr_reader company_vat_code: String
|
|
304
|
+
attr_reader series_name: String
|
|
305
|
+
attr_reader number: String
|
|
306
|
+
attr_reader issue_date: String?
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# Request body for `POST /estimate` (emitere proforma).
|
|
310
|
+
class Estimate < Struct
|
|
311
|
+
attr_reader company_vat_code: String
|
|
312
|
+
attr_reader client: Client?
|
|
313
|
+
attr_reader is_draft: bool?
|
|
314
|
+
attr_reader issue_date: String?
|
|
315
|
+
attr_reader series_name: String?
|
|
316
|
+
attr_reader currency: String?
|
|
317
|
+
attr_reader exchange_rate: Float?
|
|
318
|
+
attr_reader language: String?
|
|
319
|
+
attr_reader precision: Integer?
|
|
320
|
+
attr_reader issuer_cnp: String?
|
|
321
|
+
attr_reader issuer_name: String?
|
|
322
|
+
attr_reader aviz: String?
|
|
323
|
+
attr_reader due_date: String?
|
|
324
|
+
attr_reader mentions: String?
|
|
325
|
+
attr_reader observations: String?
|
|
326
|
+
attr_reader delegate_name: String?
|
|
327
|
+
attr_reader delegate_identity_card: String?
|
|
328
|
+
attr_reader delegate_auto: String?
|
|
329
|
+
attr_reader payment_url: String?
|
|
330
|
+
attr_reader use_stock: bool?
|
|
331
|
+
attr_reader products: Array[Product]
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
# Request body for `POST /payment`.
|
|
335
|
+
class Payment < Struct
|
|
336
|
+
attr_reader company_vat_code: String
|
|
337
|
+
attr_reader client: Client?
|
|
338
|
+
attr_reader issue_date: String?
|
|
339
|
+
attr_reader currency: String?
|
|
340
|
+
attr_reader language: String?
|
|
341
|
+
attr_reader exchange_rate: Float?
|
|
342
|
+
attr_reader precision: Integer?
|
|
343
|
+
attr_reader issuer_cnp: String?
|
|
344
|
+
attr_reader series_name: String?
|
|
345
|
+
attr_reader number: String?
|
|
346
|
+
attr_reader value: Float?
|
|
347
|
+
attr_reader text: String?
|
|
348
|
+
attr_reader translated_text: String?
|
|
349
|
+
attr_reader is_draft: bool?
|
|
350
|
+
attr_reader type: String?
|
|
351
|
+
attr_reader is_cash: bool?
|
|
352
|
+
attr_reader observation: String?
|
|
353
|
+
attr_reader use_invoice_details: bool?
|
|
354
|
+
attr_reader invoices_list: Array[InvoiceRef]?
|
|
355
|
+
attr_reader return_fiscal_printer_text: bool?
|
|
356
|
+
attr_reader use_stock: bool?
|
|
357
|
+
attr_reader products: Array[Product]?
|
|
358
|
+
attr_reader received_cash: Float?
|
|
359
|
+
attr_reader received_card: Float?
|
|
360
|
+
attr_reader received_tichete_masa: Float?
|
|
361
|
+
attr_reader received_tichete_cadou: Float?
|
|
362
|
+
attr_reader received_ordin_de_plata: Float?
|
|
363
|
+
attr_reader received_cec: Float?
|
|
364
|
+
attr_reader received_credit: Float?
|
|
365
|
+
attr_reader received_cupon: Float?
|
|
366
|
+
attr_reader received_puncte_de_fidelitate: Float?
|
|
367
|
+
attr_reader received_bonuri_valoare_fixa: Float?
|
|
368
|
+
attr_reader received_moneda_alternativa: Float?
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Request body for `POST /document/send`.
|
|
372
|
+
class EmailDocument < Struct
|
|
373
|
+
attr_reader company_vat_code: String
|
|
374
|
+
attr_reader series_name: String
|
|
375
|
+
attr_reader number: String
|
|
376
|
+
attr_reader type: String?
|
|
377
|
+
attr_reader subject: String?
|
|
378
|
+
attr_reader to: String?
|
|
379
|
+
attr_reader cc: String?
|
|
380
|
+
attr_reader bcc: String?
|
|
381
|
+
attr_reader body_text: String?
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# A VAT rate entry from `GET /tax`.
|
|
385
|
+
class Tax < Struct
|
|
386
|
+
attr_reader name: String?
|
|
387
|
+
attr_reader percentage: Float?
|
|
388
|
+
attr_reader id: Types::str_or_int?
|
|
389
|
+
end
|
|
390
|
+
|
|
391
|
+
# A document series entry from `GET /series`.
|
|
392
|
+
class Series < Struct
|
|
393
|
+
attr_reader name: String?
|
|
394
|
+
attr_reader next_number: Types::str_or_int?
|
|
395
|
+
attr_reader type: String?
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
# Parsed response of `GET /tax`.
|
|
399
|
+
class TaxesResponse < Struct
|
|
400
|
+
attr_reader error_text: String?
|
|
401
|
+
attr_reader message: String?
|
|
402
|
+
attr_reader taxes: Array[Tax]
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# Parsed response of `GET /series`.
|
|
406
|
+
class SeriesListResponse < Struct
|
|
407
|
+
attr_reader error_text: String?
|
|
408
|
+
attr_reader message: String?
|
|
409
|
+
attr_reader list: Array[Series]
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# A product entry within a stock list.
|
|
413
|
+
class StockProduct < Struct
|
|
414
|
+
attr_reader measuring_unit: String?
|
|
415
|
+
attr_reader product_code: String?
|
|
416
|
+
attr_reader product_name: String?
|
|
417
|
+
attr_reader quantity: Float?
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
# Warehouse details attached to a stock list entry.
|
|
421
|
+
class StockWarehouse < Struct
|
|
422
|
+
attr_reader warehouse_name: String?
|
|
423
|
+
attr_reader warehouse_type: String?
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
# A `list` entry under the stocks response — products + warehouse.
|
|
427
|
+
class StockList < Struct
|
|
428
|
+
attr_reader products: Array[StockProduct]
|
|
429
|
+
attr_reader warehouse: StockWarehouse?
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
# Parsed response of `GET /stocks`.
|
|
433
|
+
class StocksResponse < Struct
|
|
434
|
+
attr_reader error_text: String?
|
|
435
|
+
attr_reader message: String?
|
|
436
|
+
attr_reader list: Array[StockList]
|
|
437
|
+
end
|
|
438
|
+
|
|
439
|
+
# Common envelope: `errorText`/`message`/`number`/`series`/`url`.
|
|
440
|
+
class BaseResponse < Struct
|
|
441
|
+
attr_reader error_text: String?
|
|
442
|
+
attr_reader message: String?
|
|
443
|
+
attr_reader number: String?
|
|
444
|
+
attr_reader series: String?
|
|
445
|
+
attr_reader url: String?
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
# Response for invoice / proforma creation.
|
|
449
|
+
class InvoiceCreateResponse < BaseResponse
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# Response for `POST /invoice/reverse`.
|
|
453
|
+
class StornoResponse < BaseResponse
|
|
454
|
+
attr_reader document_url: String?
|
|
455
|
+
attr_reader document_id: Types::str_or_int?
|
|
456
|
+
attr_reader document_view_url: String?
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# Response for `GET /invoice/paymentstatus`.
|
|
460
|
+
class PaymentStatusResponse < Struct
|
|
461
|
+
attr_reader error_text: String?
|
|
462
|
+
attr_reader message: String?
|
|
463
|
+
attr_reader number: String?
|
|
464
|
+
attr_reader series: String?
|
|
465
|
+
attr_reader invoice_total_amount: Float?
|
|
466
|
+
attr_reader paid_amount: Float?
|
|
467
|
+
attr_reader unpaid_amount: Float?
|
|
468
|
+
attr_reader paid: bool?
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
# Response for `GET /estimate/invoices`.
|
|
472
|
+
class ProformaInvoicesResponse < BaseResponse
|
|
473
|
+
attr_reader are_invoices_created: bool?
|
|
474
|
+
attr_reader invoices: Array[InvoiceRef]
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
# The `status` block of an `EmailResponse`.
|
|
478
|
+
class EmailStatus < Struct
|
|
479
|
+
attr_reader code: Types::str_or_int?
|
|
480
|
+
attr_reader message: String?
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
# Response for `POST /document/send` (`Response.status`).
|
|
484
|
+
class EmailResponse < Struct
|
|
485
|
+
attr_reader status: EmailStatus?
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
# Response for bon-fiscal endpoints.
|
|
489
|
+
class FiscalReceiptResponse < BaseResponse
|
|
490
|
+
attr_reader id: Types::str_or_int?
|
|
491
|
+
end
|
|
492
|
+
end
|
|
493
|
+
end
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
# --- Validation contracts (dry-validation) ------------------------------------
|
|
497
|
+
|
|
498
|
+
module Smartbill
|
|
499
|
+
module Sdk
|
|
500
|
+
module Contracts
|
|
501
|
+
# Base class for every SmartBill validation contract.
|
|
502
|
+
class Base
|
|
503
|
+
DATE_REGEX: Regexp
|
|
504
|
+
|
|
505
|
+
# Validate `struct` against this contract, raising `ValidationError`
|
|
506
|
+
# with the aggregated error messages on failure. Returns the struct
|
|
507
|
+
# unchanged on success.
|
|
508
|
+
def self.validate!: (Models::Struct struct) -> Models::Struct
|
|
509
|
+
end
|
|
510
|
+
|
|
511
|
+
class InvoiceRefContract < Base
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
class InvoicePaymentContract < Base
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
class InvoiceContract < Base
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
class EstimateContract < Base
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
class PaymentContract < Base
|
|
524
|
+
PAYMENT_TYPES: Array[String]
|
|
525
|
+
end
|
|
526
|
+
|
|
527
|
+
class EmailContract < Base
|
|
528
|
+
DOCUMENT_TYPES: Array[String]
|
|
529
|
+
EMAIL_REGEX: Regexp
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
class StornoContract < Base
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
end
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# --- Services -----------------------------------------------------------------
|
|
539
|
+
|
|
540
|
+
module Smartbill
|
|
541
|
+
module Sdk
|
|
542
|
+
module Services
|
|
543
|
+
# Serialize a model, optionally wrapping it in an envelope.
|
|
544
|
+
def self.dump_model: (Models::Struct model, ?envelope_key: String?) -> untyped
|
|
545
|
+
|
|
546
|
+
# Parse a payload into a model instance.
|
|
547
|
+
def self.parse: (untyped payload, untyped model_class) -> Models::Struct
|
|
548
|
+
|
|
549
|
+
# Base class for all services.
|
|
550
|
+
class BaseService
|
|
551
|
+
def initialize: (Client client) -> void
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
# `/invoice` endpoints.
|
|
555
|
+
class InvoicesService < BaseService
|
|
556
|
+
def create: (Models::Invoice invoice) -> Models::InvoiceCreateResponse
|
|
557
|
+
def delete: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
558
|
+
def reverse: (Models::StornoRequest storno) -> Models::StornoResponse
|
|
559
|
+
def cancel: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
560
|
+
def restore: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
561
|
+
def payment_status: (String cif, String series_name, String number) -> Models::PaymentStatusResponse
|
|
562
|
+
# Returns the raw PDF body as a binary String.
|
|
563
|
+
def pdf: (String cif, String series_name, String number) -> String
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
# `/estimate` endpoints.
|
|
567
|
+
class EstimatesService < BaseService
|
|
568
|
+
def create: (Models::Estimate estimate) -> Models::InvoiceCreateResponse
|
|
569
|
+
def delete: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
570
|
+
def cancel: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
571
|
+
def restore: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
572
|
+
def pdf: (String cif, String series_name, String number) -> String
|
|
573
|
+
def invoices_status: (String cif, String series_name, String number) -> Models::ProformaInvoicesResponse
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
# `/payment` endpoints.
|
|
577
|
+
class PaymentsService < BaseService
|
|
578
|
+
def create: (Models::Payment payment) -> Models::FiscalReceiptResponse
|
|
579
|
+
|
|
580
|
+
# Delete a non-chitanta payment via `DELETE /payment/v2`.
|
|
581
|
+
def delete_other: (
|
|
582
|
+
String cif,
|
|
583
|
+
payment_type: String,
|
|
584
|
+
?payment_date: String?,
|
|
585
|
+
?payment_value: Float?,
|
|
586
|
+
?client_name: String?,
|
|
587
|
+
?client_cif: String?,
|
|
588
|
+
?invoice_series: String?,
|
|
589
|
+
?invoice_number: String?
|
|
590
|
+
) -> Models::BaseResponse
|
|
591
|
+
|
|
592
|
+
def delete_chitanta: (String cif, String series_name, String number) -> Models::BaseResponse
|
|
593
|
+
def fiscal_receipt_text: (String cif, String id) -> Models::FiscalReceiptResponse
|
|
594
|
+
end
|
|
595
|
+
|
|
596
|
+
# `/document/send` endpoint.
|
|
597
|
+
class EmailService < BaseService
|
|
598
|
+
def send: (Models::EmailDocument email) -> Models::EmailResponse
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
# `/tax` and `/series` endpoints. Note: on a `Client`, both
|
|
602
|
+
# `client.taxes` and `client.series` are the same `ConfigurationService`.
|
|
603
|
+
class ConfigurationService < BaseService
|
|
604
|
+
def taxes: (String cif) -> Models::TaxesResponse
|
|
605
|
+
def series: (String cif, ?type: String?) -> Models::SeriesListResponse
|
|
606
|
+
end
|
|
607
|
+
|
|
608
|
+
# `/stocks` endpoint.
|
|
609
|
+
class StocksService < BaseService
|
|
610
|
+
def get: (
|
|
611
|
+
String cif,
|
|
612
|
+
String date,
|
|
613
|
+
?warehouse_name: String?,
|
|
614
|
+
?product_name: String?,
|
|
615
|
+
?product_code: String?
|
|
616
|
+
) -> Models::StocksResponse
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
end
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
# --- Client -------------------------------------------------------------------
|
|
623
|
+
|
|
624
|
+
module Smartbill
|
|
625
|
+
module Sdk
|
|
626
|
+
# Synchronous client for the SmartBill Cloud REST API.
|
|
627
|
+
class Client
|
|
628
|
+
attr_reader username: String
|
|
629
|
+
attr_reader token: String
|
|
630
|
+
attr_reader base_url: String
|
|
631
|
+
attr_reader auth_header: String
|
|
632
|
+
attr_reader invoices: Services::InvoicesService
|
|
633
|
+
attr_reader estimates: Services::EstimatesService
|
|
634
|
+
attr_reader payments: Services::PaymentsService
|
|
635
|
+
attr_reader email: Services::EmailService
|
|
636
|
+
attr_reader taxes: Services::ConfigurationService
|
|
637
|
+
attr_reader series: Services::ConfigurationService
|
|
638
|
+
attr_reader stocks: Services::StocksService
|
|
639
|
+
|
|
640
|
+
def initialize: (
|
|
641
|
+
username: String,
|
|
642
|
+
token: String,
|
|
643
|
+
?base_url: String,
|
|
644
|
+
?timeout: Float,
|
|
645
|
+
?enforce_rate_limit: bool,
|
|
646
|
+
?http: untyped
|
|
647
|
+
) -> void
|
|
648
|
+
|
|
649
|
+
# Send a `Transport::Request` and return the parsed payload.
|
|
650
|
+
# When `binary` is true, the raw body String is returned.
|
|
651
|
+
def execute: (Transport::Request request, ?binary: bool) -> untyped
|
|
652
|
+
|
|
653
|
+
# Close the underlying HTTP adapter. A no-op for the default
|
|
654
|
+
# `Net::HTTP` adapter.
|
|
655
|
+
def close: () -> void
|
|
656
|
+
|
|
657
|
+
# Yield self to a block and ensure `#close` is called afterwards.
|
|
658
|
+
def with_client: () { (Client client) -> untyped } -> untyped
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
end
|
data/skills/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Agent Skills for `smartbill-sdk`
|
|
2
|
+
|
|
3
|
+
These are [pi](https://github.com/earendil-works/pi-coding-agent) skills
|
|
4
|
+
(`SKILL.md` files) that teach coding agents how to use this SDK. An agent
|
|
5
|
+
imports a skill to get concise, copy-pasteable usage guidance for a given
|
|
6
|
+
area of the API.
|
|
7
|
+
|
|
8
|
+
Install the SDK first (`gem install smartbill-sdk` or add it to your
|
|
9
|
+
Gemfile), then use any skill:
|
|
10
|
+
|
|
11
|
+
| Skill | Covers |
|
|
12
|
+
|------------------------|------------------------------------------------------------------------|
|
|
13
|
+
| `smartbill-invoices` | Invoices & proformas/estimates: create, storno, cancel, restore, PDF, payment status |
|
|
14
|
+
| `smartbill-payments` | Payments & fiscal receipts (`bon fiscal`): `POST /payment`, payment types, mixed cash/card, fiscal-printer text, delete |
|
|
15
|
+
| `smartbill-email` | Emailing a document (`POST /document/send`): base64 subject/body, invoice/proforma |
|
|
16
|
+
|
|
17
|
+
## Importing into a pi agent
|
|
18
|
+
|
|
19
|
+
Copy any of these `SKILL.md` files into your agent's skills directory (or
|
|
20
|
+
symlink them), then reference the skill by its `name` in the front matter.
|
|
21
|
+
Each skill is self-contained and points back to the relevant source files,
|
|
22
|
+
models, and runnable `examples/` scripts in this repo for deeper detail.
|
|
23
|
+
|
|
24
|
+
## Layout
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
skills/
|
|
28
|
+
smartbill-invoices/SKILL.md
|
|
29
|
+
smartbill-payments/SKILL.md
|
|
30
|
+
smartbill-email/SKILL.md
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
All skills assume the SDK is installed and that you have a SmartBill
|
|
34
|
+
`username` (login e-mail) and API `token` (SmartBill Cloud → **Contul Meu →
|
|
35
|
+
Integrari → API**).
|