OrangeDataPack 0.0.1__py3-none-any.whl
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.
- orangedatapack-0.0.1.dist-info/METADATA +13 -0
- orangedatapack-0.0.1.dist-info/RECORD +15 -0
- orangedatapack-0.0.1.dist-info/WHEEL +4 -0
- orangedatatools/__init__.py +0 -0
- orangedatatools/client.py +133 -0
- orangedatatools/schemas/__init__.py +6 -0
- orangedatatools/schemas/base_args.py +34 -0
- orangedatatools/schemas/client_args.py +18 -0
- orangedatatools/schemas/common.py +230 -0
- orangedatatools/schemas/correction12_args.py +14 -0
- orangedatatools/schemas/correction_args.py +55 -0
- orangedatatools/schemas/fiscal_args.py +27 -0
- orangedatatools/schemas/itemcode_args.py +18 -0
- orangedatatools/utils/__init__.py +0 -0
- orangedatatools/utils/endpoints.py +65 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: OrangeDataPack
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Package for OrangeData API service
|
|
5
|
+
Requires-Dist: cryptography>=50.0.1
|
|
6
|
+
Requires-Dist: phonenumbers>=9.0.40
|
|
7
|
+
Requires-Dist: pydantic>=2.13.5
|
|
8
|
+
Requires-Dist: pydantic-extra-types>=2.11.1
|
|
9
|
+
Requires-Dist: requests>=2.34.2
|
|
10
|
+
Requires-Python: >=3.14.3
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# orange-data
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
orangedatatools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
orangedatatools/client.py,sha256=XVluZy7EjthASBkvHRHzbr5WN4Q3dOf6zhn6UjNjHMM,4495
|
|
3
|
+
orangedatatools/schemas/__init__.py,sha256=t_D-nDZI2aSzdeNC1OojqOOga6YEV4A1TRnREwtf-3c,268
|
|
4
|
+
orangedatatools/schemas/base_args.py,sha256=O9iTvjkxFG_6FcLf6w6cN5gGfdEsT9E1_ZsJLS545vc,871
|
|
5
|
+
orangedatatools/schemas/client_args.py,sha256=VWAIQ_6bTOvFQHnRlVx-d8Pwk5B3EmcMIpoU_Jlu4dk,835
|
|
6
|
+
orangedatatools/schemas/common.py,sha256=Gg25PoHPIprIzUP9IE8do6vnpCVLWdOv0i1iDDXUaJc,8039
|
|
7
|
+
orangedatatools/schemas/correction12_args.py,sha256=_DJgq08bq3IH4pYiqJLEGvjjJNuzNRq9SIZRVAOYs8M,327
|
|
8
|
+
orangedatatools/schemas/correction_args.py,sha256=WnCqNU0u2aBD0azUF0VfM6vNTfUhZzjndI1dIMMvfYw,2456
|
|
9
|
+
orangedatatools/schemas/fiscal_args.py,sha256=Tj-zzHksbPgDVerqerpbgLj20_RNO0AJa0n3M91mjQs,1218
|
|
10
|
+
orangedatatools/schemas/itemcode_args.py,sha256=W7YOsD2TL8Y9VjphzD3r2hR4r4gZf7k_wavQKHMzNW8,562
|
|
11
|
+
orangedatatools/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
+
orangedatatools/utils/endpoints.py,sha256=2PIQn0t3z695_RQT_GuvJzUYd7QZcigiNioD1SiHupM,1466
|
|
13
|
+
orangedatapack-0.0.1.dist-info/WHEEL,sha256=e4_1dyBeezi8ZjfxrZ3bnVOxFDa3ksqVqH0jTHkUZ3k,81
|
|
14
|
+
orangedatapack-0.0.1.dist-info/METADATA,sha256=O2xxVqiOzih6C9YMj2Kz4qZMrdOtbs_Bv8CrXfeaGbg,362
|
|
15
|
+
orangedatapack-0.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import json
|
|
3
|
+
from urllib.parse import urljoin
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
from cryptography.hazmat.primitives import hashes
|
|
7
|
+
from cryptography.hazmat.primitives.asymmetric import padding
|
|
8
|
+
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
|
9
|
+
from pydantic import BaseModel, validate_call
|
|
10
|
+
|
|
11
|
+
from orangedatatools.schemas import (
|
|
12
|
+
Correction12Schema,
|
|
13
|
+
CorrectionSchema,
|
|
14
|
+
DocumentSchema,
|
|
15
|
+
ItemCodeSchema,
|
|
16
|
+
)
|
|
17
|
+
from orangedatatools.schemas.client_args import ClientArgs
|
|
18
|
+
from orangedatatools.utils.endpoints import OrangeEndpoints as ENDS
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class OrangeDataClient:
|
|
22
|
+
@validate_call
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
org_params: ClientArgs,
|
|
26
|
+
api_url: str,
|
|
27
|
+
key_private_path: str,
|
|
28
|
+
client_key_path: str,
|
|
29
|
+
client_cert_path: str,
|
|
30
|
+
):
|
|
31
|
+
"""Initializes the client with the passed parameters.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
org_params (Client Args): Organization parameters.
|
|
35
|
+
api_url (str): The URL of the API for sending requests.
|
|
36
|
+
key_private_path (str): The path to the private key for signing.
|
|
37
|
+
client_key_path (str): The path to the client's private key.
|
|
38
|
+
client_cert_path (str): The path to the client SSL certificate.
|
|
39
|
+
"""
|
|
40
|
+
self.org_params = org_params
|
|
41
|
+
self.api_url = api_url.rstrip("/")
|
|
42
|
+
self.key_private_path = key_private_path
|
|
43
|
+
self.client_key_path = client_key_path
|
|
44
|
+
self.client_cert_path = client_cert_path
|
|
45
|
+
|
|
46
|
+
def __combineData(self, data: BaseModel) -> dict:
|
|
47
|
+
"""Merging organization parameters and receipt data
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
data (BaseModel): Pydantic data schema
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
**self.org_params.model_dump(),
|
|
55
|
+
**data.model_dump(exclude_none=True, mode="json"),
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
def __computeSignature(self, data: bytes) -> base64:
|
|
59
|
+
"""Creating a signature based on a private pem key"""
|
|
60
|
+
|
|
61
|
+
with open(self.key_private_path, "rb") as pem_in:
|
|
62
|
+
pemlines = pem_in.read()
|
|
63
|
+
private_key = load_pem_private_key(pemlines, password=None)
|
|
64
|
+
signature = private_key.sign(data, padding.PKCS1v15(), hashes.SHA256())
|
|
65
|
+
|
|
66
|
+
return base64.b64encode(signature).decode("utf-8")
|
|
67
|
+
|
|
68
|
+
def __signPost(self, params: BaseModel, path: str) -> tuple[str, int]:
|
|
69
|
+
data = self.__combineData(params)
|
|
70
|
+
bytes_data = json.dumps(data, ensure_ascii=False).encode("utf-8")
|
|
71
|
+
sign = self.__computeSignature(bytes_data)
|
|
72
|
+
|
|
73
|
+
headers = {
|
|
74
|
+
"Accept": "application/json",
|
|
75
|
+
"Content-Type": "application/json",
|
|
76
|
+
"X-Signature": sign,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
url_path = urljoin(self.api_url, path)
|
|
80
|
+
|
|
81
|
+
r = requests.post(
|
|
82
|
+
url=url_path,
|
|
83
|
+
headers=headers,
|
|
84
|
+
json=data,
|
|
85
|
+
cert=(self.client_cert_path, self.client_key_path),
|
|
86
|
+
verify=False,
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
return r.text, r.status_code
|
|
90
|
+
|
|
91
|
+
def __Get(self, path: str) -> tuple[str, int]:
|
|
92
|
+
url_path = urljoin(self.api_url, path)
|
|
93
|
+
r = requests.get(url=url_path)
|
|
94
|
+
|
|
95
|
+
return r.text, r.status_code
|
|
96
|
+
|
|
97
|
+
@validate_call
|
|
98
|
+
def create_receipt(self, order_params: DocumentSchema) -> tuple[str, int]:
|
|
99
|
+
return self.__signPost(order_params, ENDS.document())
|
|
100
|
+
|
|
101
|
+
def check_receipt(self, document_id: str) -> tuple[str, int]:
|
|
102
|
+
path = ENDS.document_status(self.org_params.inn, document_id)
|
|
103
|
+
|
|
104
|
+
return self.__Get(path)
|
|
105
|
+
|
|
106
|
+
@validate_call
|
|
107
|
+
def create_correction(self, correction_params: CorrectionSchema) -> tuple[str, int]:
|
|
108
|
+
return self.__signPost(correction_params, ENDS.corrections())
|
|
109
|
+
|
|
110
|
+
def check_correction(self, correction_id: str) -> tuple[str, int]:
|
|
111
|
+
path = ENDS.corrections_status(self.org_params.inn, correction_id)
|
|
112
|
+
|
|
113
|
+
return self.__Get(path)
|
|
114
|
+
|
|
115
|
+
@validate_call
|
|
116
|
+
def create_correction12(
|
|
117
|
+
self, correction_params: Correction12Schema
|
|
118
|
+
) -> tuple[str, int]:
|
|
119
|
+
return self.__signPost(correction_params, ENDS.corrections12())
|
|
120
|
+
|
|
121
|
+
def check_correction12(self, correction_id: str) -> tuple[str, int]:
|
|
122
|
+
path = ENDS.correction12_status(self.org_params.inn, correction_id)
|
|
123
|
+
|
|
124
|
+
return self.__Get(path)
|
|
125
|
+
|
|
126
|
+
@validate_call
|
|
127
|
+
def create_itemcode(self, itemcode_params: ItemCodeSchema) -> tuple[str, int]:
|
|
128
|
+
return self.__signPost(itemcode_params, ENDS.itemcode())
|
|
129
|
+
|
|
130
|
+
def check_itemcode(self, itemcode_id: str) -> tuple[str, int]:
|
|
131
|
+
path = ENDS.itemcode_status(self.org_params.inn, itemcode_id)
|
|
132
|
+
|
|
133
|
+
return self.__Get(path)
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
from .correction12_args import Correction12Schema
|
|
2
|
+
from .correction_args import CorrectionSchema
|
|
3
|
+
from .fiscal_args import DocumentSchema
|
|
4
|
+
from .itemcode_args import ItemCodeSchema
|
|
5
|
+
|
|
6
|
+
__all__ = ["CorrectionSchema", "Correction12Schema", "DocumentSchema", "ItemCodeSchema"]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ReqBodyBase(BaseModel):
|
|
7
|
+
id: str = Field(max_length=64)
|
|
8
|
+
callbackUrl: Optional[str] = Field(default=None, max_length=1024)
|
|
9
|
+
callbackApiKey: Optional[str] = Field(default=None, max_length=3072)
|
|
10
|
+
meta: Optional[str] = Field(default=None, max_length=128)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _IgnoreItemCodeCheckMixin(BaseModel):
|
|
14
|
+
"""Mixin with the common flag ignoreItemCodeCheck."""
|
|
15
|
+
|
|
16
|
+
ignoreItemCodeCheck: Optional[bool] = Field(default=None)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ReqBodyBaseFiscal(ReqBodyBase, _IgnoreItemCodeCheckMixin):
|
|
20
|
+
"""Base schema for fiscal documents."""
|
|
21
|
+
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ReqBodyBaseCorrection(ReqBodyBase):
|
|
26
|
+
"""Base schema for correction receipts."""
|
|
27
|
+
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ReqBodyBaseCorrection12(ReqBodyBase, _IgnoreItemCodeCheckMixin):
|
|
32
|
+
"""Base schema for correction receipts (format 1.2)."""
|
|
33
|
+
|
|
34
|
+
pass
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ClientArgs(BaseModel):
|
|
7
|
+
inn: str = Field(min_length=10, max_length=12)
|
|
8
|
+
group: Optional[str] = Field(
|
|
9
|
+
default=None,
|
|
10
|
+
max_length=32,
|
|
11
|
+
description=(
|
|
12
|
+
"Название ключа, который должен быть использован для проверки подписи. "
|
|
13
|
+
"Для клиентов используется их ИНН, для новых клиентов с 01.02.25 ИНН_ID "
|
|
14
|
+
"(ID - идентификационный номер пользователя в системе). Для партнеров "
|
|
15
|
+
"и платежных агентов код с маской 301****, для вендинга 401****."
|
|
16
|
+
),
|
|
17
|
+
)
|
|
18
|
+
key: str = Field(max_length=32)
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
from typing import Annotated, Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field, PlainSerializer
|
|
6
|
+
from pydantic_extra_types.phone_numbers import PhoneNumber
|
|
7
|
+
|
|
8
|
+
DecimalField = Annotated[
|
|
9
|
+
Decimal,
|
|
10
|
+
PlainSerializer(lambda x: float(x), return_type=float, when_used="json"),
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TaxSystem(IntEnum):
|
|
15
|
+
osn = 0
|
|
16
|
+
usn_income = 1
|
|
17
|
+
usn_profit = 2
|
|
18
|
+
envd = 3
|
|
19
|
+
esn = 4
|
|
20
|
+
patent = 5
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CalcIndicator(IntEnum):
|
|
24
|
+
income = 1
|
|
25
|
+
income_return = 2
|
|
26
|
+
expense = 3
|
|
27
|
+
expense_return = 4
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class VatRate(IntEnum):
|
|
31
|
+
vat_20 = 1
|
|
32
|
+
vat_10 = 2
|
|
33
|
+
vat_20_120 = 3
|
|
34
|
+
vat_10_110 = 4
|
|
35
|
+
vat_0 = 5
|
|
36
|
+
vat_none = 6
|
|
37
|
+
vat_5 = 7
|
|
38
|
+
vat_7 = 8
|
|
39
|
+
vat_5_105 = 9
|
|
40
|
+
vat_7_107 = 10
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class PaymentMethod(IntEnum):
|
|
44
|
+
prepayment_full = 1
|
|
45
|
+
prepayment_partial = 2
|
|
46
|
+
advance = 3
|
|
47
|
+
full_payment = 4
|
|
48
|
+
partial_credit = 5
|
|
49
|
+
credit = 6
|
|
50
|
+
credit_payment = 7
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class SettlementSubject(IntEnum):
|
|
54
|
+
product = 1
|
|
55
|
+
excisable = 2
|
|
56
|
+
work = 3
|
|
57
|
+
service = 4
|
|
58
|
+
gambling_bet = 5
|
|
59
|
+
gambling_win = 6
|
|
60
|
+
lottery_ticket = 7
|
|
61
|
+
lottery_win = 8
|
|
62
|
+
ip_rights = 9
|
|
63
|
+
advance = 10
|
|
64
|
+
agent_fee = 11
|
|
65
|
+
payout = 12
|
|
66
|
+
other_subject = 13
|
|
67
|
+
property_right = 14
|
|
68
|
+
non_op_income = 15
|
|
69
|
+
other_payments = 16
|
|
70
|
+
trading_fee = 17
|
|
71
|
+
tourist_tax = 18
|
|
72
|
+
deposit = 19
|
|
73
|
+
expense = 20
|
|
74
|
+
pension_ip = 21
|
|
75
|
+
pension = 22
|
|
76
|
+
medical_ip = 23
|
|
77
|
+
medical = 24
|
|
78
|
+
social = 25
|
|
79
|
+
casino = 26
|
|
80
|
+
cash_out = 27
|
|
81
|
+
unmarked_atnm = 30
|
|
82
|
+
marked_atm = 31
|
|
83
|
+
tnm = 32
|
|
84
|
+
tm = 33
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class Contact(PhoneNumber):
|
|
88
|
+
phone_format = "E164"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class FractionalQuantityMarkedProductSchema(BaseModel):
|
|
92
|
+
Numerator: Optional[int] = Field(default=None)
|
|
93
|
+
Denominator: Optional[int] = Field(default=None)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class BarcodesCalculationItem(BaseModel):
|
|
97
|
+
ean8: Optional[str] = Field(default=None, max_length=8)
|
|
98
|
+
ean13: Optional[str] = Field(default=None, max_length=13)
|
|
99
|
+
itf14: Optional[str] = Field(default=None, max_length=14)
|
|
100
|
+
gs1: Optional[str] = Field(default=None, max_length=38)
|
|
101
|
+
mi: Optional[str] = Field(default=None, max_length=20)
|
|
102
|
+
egais20: Optional[str] = Field(default=None, max_length=23)
|
|
103
|
+
egais30: Optional[str] = Field(default=None, max_length=14)
|
|
104
|
+
f1: Optional[str] = Field(default=None, max_length=32)
|
|
105
|
+
f2: Optional[str] = Field(default=None, max_length=32)
|
|
106
|
+
f3: Optional[str] = Field(default=None, max_length=32)
|
|
107
|
+
f4: Optional[str] = Field(default=None, max_length=32)
|
|
108
|
+
f5: Optional[str] = Field(default=None, max_length=32)
|
|
109
|
+
f6: Optional[str] = Field(default=None, max_length=32)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class OperationalDetailsSchema(BaseModel):
|
|
113
|
+
date: Optional[str] = Field(default=None)
|
|
114
|
+
id: Optional[int] = Field(default=None, le=255)
|
|
115
|
+
value: Optional[str] = Field(default=None, max_length=64)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class InformationBuyerSchema(BaseModel):
|
|
119
|
+
name: Optional[str] = Field(default=None, max_length=239)
|
|
120
|
+
inn: Optional[str] = Field(default=None, min_length=10, max_length=12)
|
|
121
|
+
birthDate: Optional[str] = Field(default=None, max_length=10)
|
|
122
|
+
citizenship: Optional[str] = Field(default=None, max_length=3)
|
|
123
|
+
identityDocumentCode: Optional[str] = Field(default=None, max_length=2)
|
|
124
|
+
identityDocumentData: Optional[str] = Field(default=None, max_length=64)
|
|
125
|
+
address: Optional[str] = Field(default=None, max_length=239)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class AgentDataSchema(BaseModel):
|
|
129
|
+
paymentTransferOperatorPhoneNumbers: list[str]
|
|
130
|
+
paymentAgentOperation: str = Field(max_length=24)
|
|
131
|
+
paymentAgentPhoneNumbers: list[str]
|
|
132
|
+
paymentOperatorName: str = Field(max_length=64)
|
|
133
|
+
paymentOperatorAddress: str = Field(max_length=243)
|
|
134
|
+
paymentOperatorINN: str = Field(min_length=10, max_length=12)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class SupplierInfoSchema(BaseModel):
|
|
138
|
+
phoneNumbers: list[Contact]
|
|
139
|
+
name: str = Field(max_length=239)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
class AdditionalUserDetailsSchema(BaseModel):
|
|
143
|
+
name: str = Field(max_length=64)
|
|
144
|
+
value: str = Field(max_length=234)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class PaymentSchema(BaseModel):
|
|
148
|
+
type: int = Field(ge=1, le=16)
|
|
149
|
+
amount: DecimalField = Field(decimal_places=2)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class PaymentInfo(BaseModel):
|
|
153
|
+
amount: DecimalField = Field(decimal_places=2)
|
|
154
|
+
type: int = Field(le=255)
|
|
155
|
+
id: str = Field(max_length=256)
|
|
156
|
+
additionalInfo: str = Field(max_length=256)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
class PaymentsInfo(BaseModel):
|
|
160
|
+
payments: list[PaymentInfo]
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ReceiptClosingParametersSchema(BaseModel):
|
|
164
|
+
payments: list[PaymentSchema]
|
|
165
|
+
taxationSystem: TaxSystem
|
|
166
|
+
electronicPaymentsInfo: PaymentsInfo
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
class PostionSchema(BaseModel):
|
|
170
|
+
quantity: DecimalField = Field(decimal_places=6)
|
|
171
|
+
price: DecimalField = Field(decimal_places=2)
|
|
172
|
+
tax: VatRate
|
|
173
|
+
taxSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
174
|
+
text: str = Field(max_length=128)
|
|
175
|
+
paymentMethodType: Optional[PaymentMethod] = Field(
|
|
176
|
+
default=PaymentMethod.full_payment
|
|
177
|
+
)
|
|
178
|
+
paymentSubjectType: Optional[SettlementSubject] = Field(
|
|
179
|
+
default=SettlementSubject.product
|
|
180
|
+
)
|
|
181
|
+
nomenclatureCode: Optional[bytes] = Field(default=None, min_length=8, max_length=32)
|
|
182
|
+
itemCode: Optional[str] = Field(default=None, max_length=233)
|
|
183
|
+
plannedStatus: Optional[int] = Field(default=None, le=256)
|
|
184
|
+
supplierInfo: Optional[SupplierInfoSchema] = Field(default=None)
|
|
185
|
+
supplierINN: Optional[str] = Field(default=None, min_length=10, max_length=12)
|
|
186
|
+
agentType: Optional[int] = Field(default=None, ge=1, le=127)
|
|
187
|
+
agentInfo: Optional[AgentDataSchema] = Field(default=None)
|
|
188
|
+
unitOfMeasurement: Optional[str] = Field(default=None, max_length=16)
|
|
189
|
+
quantityMeasurementUnit: Optional[int] = Field(default=None, le=255)
|
|
190
|
+
additionalAttribute: Optional[str] = Field(default=None, max_length=64)
|
|
191
|
+
manufacturerCountryCode: Optional[str] = Field(default=None, max_length=3)
|
|
192
|
+
customsDeclarationNumber: Optional[str] = Field(default=None, max_length=32)
|
|
193
|
+
excise: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
194
|
+
unitTaxSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
195
|
+
fractionalQuantity: Optional[FractionalQuantityMarkedProductSchema] = Field(
|
|
196
|
+
default=None
|
|
197
|
+
)
|
|
198
|
+
barcodes: Optional[BarcodesCalculationItem] = Field(default=None)
|
|
199
|
+
assignedStatus: Optional[int] = Field(default=None)
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
class BaseContent(BaseModel):
|
|
203
|
+
ffdVersion: Optional[int] = Field(default=2)
|
|
204
|
+
type: CalcIndicator
|
|
205
|
+
positions: list[PostionSchema]
|
|
206
|
+
checkClose: ReceiptClosingParametersSchema
|
|
207
|
+
customerContact: str = Field(max_length=64)
|
|
208
|
+
additionalUserAttribute: Optional[AdditionalUserDetailsSchema] = Field(default=None)
|
|
209
|
+
additionalAttribute: Optional[str] = Field(default=None, max_length=16)
|
|
210
|
+
automatNumber: Optional[str] = Field(default=None, max_length=20)
|
|
211
|
+
settlementAddress: Optional[str] = Field(default=None, max_length=243)
|
|
212
|
+
settlementPlace: Optional[str] = Field(default=None, max_length=243)
|
|
213
|
+
cashier: Optional[str] = Field(default=None, max_length=64)
|
|
214
|
+
cashierINN: Optional[str] = Field(default=None, min_length=12)
|
|
215
|
+
senderEmail: Optional[str] = Field(default=None, max_length=64)
|
|
216
|
+
totalSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
217
|
+
vat1Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
218
|
+
vat2Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
219
|
+
vat3Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
220
|
+
vat4Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
221
|
+
vat5Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
222
|
+
vat6Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
223
|
+
vat7Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
224
|
+
vat8Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
225
|
+
vat9Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
226
|
+
vat10Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
227
|
+
operationalAttribute: Optional[OperationalDetailsSchema] = Field(default=None)
|
|
228
|
+
timeZone: Optional[int] = Field(default=None, ge=1, le=11)
|
|
229
|
+
isInternetStore: Optional[bool] = Field(default=None)
|
|
230
|
+
useTax20: Optional[bool] = Field(default=None)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
from pydantic import Field
|
|
2
|
+
|
|
3
|
+
from .base_args import ReqBodyBaseCorrection12
|
|
4
|
+
from .common import BaseContent
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Correction12SchemaContent(BaseContent):
|
|
8
|
+
correctionType: str
|
|
9
|
+
causeDocumentDate: str
|
|
10
|
+
causeDocumentNumber: str
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Correction12Schema(ReqBodyBaseCorrection12):
|
|
14
|
+
content: Correction12SchemaContent
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from decimal import Decimal
|
|
2
|
+
from enum import IntEnum
|
|
3
|
+
from typing import Optional
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
from .base_args import ReqBodyBaseCorrection
|
|
8
|
+
from .common import DecimalField, TaxSystem
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CorrectionTypes(IntEnum):
|
|
12
|
+
self_selected = 0 # выбрана самостоятельно
|
|
13
|
+
prescribed = 1 # предписана (обязательна)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class CorrectionCalcIndicator(IntEnum):
|
|
17
|
+
"""Calculation indicator for a correction receipt (income/expense only)."""
|
|
18
|
+
|
|
19
|
+
income = 1
|
|
20
|
+
expense = 3
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class CorrectionSchemaContent(BaseModel):
|
|
24
|
+
correctionType: CorrectionTypes
|
|
25
|
+
type: CorrectionCalcIndicator
|
|
26
|
+
causeDocumentDate: str
|
|
27
|
+
causeDocumentNumber: Optional[str] = Field(default=None, max_length=32)
|
|
28
|
+
totalSum: DecimalField = Field(decimal_places=2)
|
|
29
|
+
cashSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
30
|
+
eCashSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
31
|
+
prepaymentSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
32
|
+
postpaymentSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
33
|
+
otherPaymentTypeSum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
34
|
+
tax1Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
35
|
+
tax2Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
36
|
+
tax3Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
37
|
+
tax4Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
38
|
+
tax5Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
39
|
+
tax6Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
40
|
+
tax7Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
41
|
+
tax8Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
42
|
+
tax9Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
43
|
+
tax10Sum: Optional[Decimal] = Field(default=None, decimal_places=2)
|
|
44
|
+
taxationSystem: TaxSystem
|
|
45
|
+
automatNumber: Optional[str] = Field(default=None, max_length=20)
|
|
46
|
+
settlementAddress: Optional[str] = Field(default=None, max_length=243)
|
|
47
|
+
settlementPlace: Optional[str] = Field(default=None, max_length=243)
|
|
48
|
+
customerContact: str = Field(max_length=64)
|
|
49
|
+
senderEmail: Optional[str] = Field(default=None, max_length=64)
|
|
50
|
+
isInternetStore: Optional[bool] = Field(default=None)
|
|
51
|
+
useTax20: Optional[bool] = Field(default=None)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class CorrectionSchema(ReqBodyBaseCorrection):
|
|
55
|
+
content: CorrectionSchemaContent
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import Field
|
|
4
|
+
|
|
5
|
+
from .base_args import ReqBodyBaseFiscal
|
|
6
|
+
from .common import BaseContent, Contact, InformationBuyerSchema
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DocumentSchemaContent(BaseContent):
|
|
10
|
+
agentType: Optional[int] = Field(default=None, le=127)
|
|
11
|
+
paymentTransferOperatorPhoneNumbers: Optional[list[Contact]] = Field(default=None)
|
|
12
|
+
paymentAgentOperation: Optional[str] = Field(default=None, max_length=24)
|
|
13
|
+
paymentAgentPhoneNumbers: Optional[list[Contact]] = Field(default=None)
|
|
14
|
+
paymentOperatorPhoneNumbers: Optional[list[Contact]] = Field(default=None)
|
|
15
|
+
paymentOperatorName: Optional[str] = Field(default=None, max_length=64)
|
|
16
|
+
paymentOperatorAddress: Optional[str] = Field(default=None, max_length=243)
|
|
17
|
+
paymentOperatorINN: Optional[str] = Field(
|
|
18
|
+
default=None, min_length=10, max_length=12
|
|
19
|
+
)
|
|
20
|
+
supplierPhoneNumbers: Optional[list[Contact]] = Field(default=None)
|
|
21
|
+
customer: Optional[str] = Field(default=None, max_length=243)
|
|
22
|
+
customerINN: Optional[str] = Field(default=None, min_length=10, max_length=12)
|
|
23
|
+
customerInfo: Optional[InformationBuyerSchema] = Field(default=None)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class DocumentSchema(ReqBodyBaseFiscal):
|
|
27
|
+
content: DocumentSchemaContent
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
from .base_args import ReqBodyBaseFiscal
|
|
6
|
+
from .common import DecimalField, FractionalQuantityMarkedProductSchema
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ItemCodeSchemaContent(BaseModel):
|
|
10
|
+
plannedStatus: int = Field(le=256)
|
|
11
|
+
itemCode: int = Field(ge=1, le=223)
|
|
12
|
+
quantityMeasurementUnit: Optional[int] = Field(le=255, default=None)
|
|
13
|
+
quantity: Optional[DecimalField]
|
|
14
|
+
fractionalQuantity: Optional[FractionalQuantityMarkedProductSchema]
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ItemCodeSchema(ReqBodyBaseFiscal):
|
|
18
|
+
content: ItemCodeSchemaContent
|
|
File without changes
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
class OrangeEndpoints:
|
|
2
|
+
BASE = "/api/v2"
|
|
3
|
+
|
|
4
|
+
@classmethod
|
|
5
|
+
def check(cls) -> str:
|
|
6
|
+
"""
|
|
7
|
+
GET-method
|
|
8
|
+
"""
|
|
9
|
+
return f"{cls.BASE}/"
|
|
10
|
+
|
|
11
|
+
@classmethod
|
|
12
|
+
def document(cls) -> str:
|
|
13
|
+
"""
|
|
14
|
+
POST-method
|
|
15
|
+
"""
|
|
16
|
+
return f"{cls.BASE}/documents"
|
|
17
|
+
|
|
18
|
+
@classmethod
|
|
19
|
+
def corrections12(cls) -> str:
|
|
20
|
+
"""
|
|
21
|
+
POST-method
|
|
22
|
+
"""
|
|
23
|
+
return f"{cls.BASE}/correction12"
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def itemcode(cls) -> str:
|
|
27
|
+
"""
|
|
28
|
+
POST-method
|
|
29
|
+
"""
|
|
30
|
+
return f"{cls.BASE}/itemcode"
|
|
31
|
+
|
|
32
|
+
@classmethod
|
|
33
|
+
def corrections(cls) -> str:
|
|
34
|
+
"""
|
|
35
|
+
POST-method
|
|
36
|
+
"""
|
|
37
|
+
return f"{cls.BASE}/corrections"
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def document_status(cls, inn: str, document_id: str) -> str:
|
|
41
|
+
"""
|
|
42
|
+
GET-method
|
|
43
|
+
"""
|
|
44
|
+
return f"{cls.document()}/{inn}/status/{document_id}"
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def itemcode_status(cls, inn: str, itemcode: str) -> str:
|
|
48
|
+
"""
|
|
49
|
+
GET-method
|
|
50
|
+
"""
|
|
51
|
+
return f"{cls.itemcode()}/{inn}/status/{itemcode}"
|
|
52
|
+
|
|
53
|
+
@classmethod
|
|
54
|
+
def corrections_status(cls, inn: str, correction_id: str) -> str:
|
|
55
|
+
"""
|
|
56
|
+
GET-method
|
|
57
|
+
"""
|
|
58
|
+
return f"{cls.corrections()}/{inn}/status/{correction_id}"
|
|
59
|
+
|
|
60
|
+
@classmethod
|
|
61
|
+
def correction12_status(cls, inn: str, correction_id: str) -> str:
|
|
62
|
+
"""
|
|
63
|
+
GET-method
|
|
64
|
+
"""
|
|
65
|
+
return f"{cls.correction12()}/{inn}/status/{correction_id}"
|