attime-star-api-python-sdk 1.9.0__tar.gz → 1.9.3__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.
- {attime_star_api_python_sdk-1.9.0/src/attime_star_api_python_sdk.egg-info → attime_star_api_python_sdk-1.9.3}/PKG-INFO +1 -1
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/pyproject.toml +1 -1
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/apis/attime001.py +9 -2
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/ecommerce.py +25 -2
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3/src/attime_star_api_python_sdk.egg-info}/PKG-INFO +1 -1
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/tests/test_attime001_importar_ecommerce.py +36 -5
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/LICENSE +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/README.md +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/setup.cfg +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/api.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/apis/__init__.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/apis/bvix.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/apis/infocar.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/__init__.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/attime001.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/bvix.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/enums.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/infocar.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/serde.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime_star_api_python_sdk.egg-info/SOURCES.txt +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime_star_api_python_sdk.egg-info/dependency_links.txt +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime_star_api_python_sdk.egg-info/top_level.txt +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/tests/test_attime001_atualizacoes.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/tests/test_attime001_cancelamento.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/tests/test_attime001_insere_item.py +0 -0
- {attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/tests/test_attime001_relacao.py +0 -0
|
@@ -187,9 +187,15 @@ class Attime001Api(ATTimeStarApi):
|
|
|
187
187
|
)
|
|
188
188
|
|
|
189
189
|
def importar_ecommerce(
|
|
190
|
-
self,
|
|
190
|
+
self,
|
|
191
|
+
item: ApiAttime001ImportarEcommerceDTO | dict,
|
|
192
|
+
*,
|
|
193
|
+
request_timeout: int = 600,
|
|
191
194
|
) -> ApiAttime001ImportarEcommerceDTO:
|
|
192
|
-
"""POST /btc/ABTP0004/ApiAttime001/ImportarEcommerce.
|
|
195
|
+
"""POST /btc/ABTP0004/ApiAttime001/ImportarEcommerce.
|
|
196
|
+
|
|
197
|
+
Timeout default 600s: frota grande pode demorar vários minutos no STAR.
|
|
198
|
+
"""
|
|
193
199
|
logging.info('importing ecommerce via ApiAttime001 ImportarEcommerce...')
|
|
194
200
|
if isinstance(item, ApiAttime001ImportarEcommerceDTO):
|
|
195
201
|
payload = item.to_dict()
|
|
@@ -213,6 +219,7 @@ class Attime001Api(ATTimeStarApi):
|
|
|
213
219
|
http_method=HTTPMethod.POST,
|
|
214
220
|
request_url=url,
|
|
215
221
|
payload=payload,
|
|
222
|
+
request_timeout=request_timeout,
|
|
216
223
|
)
|
|
217
224
|
res = jsonpickle.decode(res)
|
|
218
225
|
return _parse_attime001_object_response(
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
|
|
4
4
|
POST /btc/ABTP0004/ApiAttime001/ImportarEcommerce
|
|
5
5
|
|
|
6
|
-
``formaPagamento.dadosPagamento``
|
|
6
|
+
``formaPagamento.dadosPagamento`` é ``dict`` livre:
|
|
7
|
+
boleto → ``{EnderecoCobranca: ""}``; cartão/PIX tipagem ainda pendente.
|
|
7
8
|
"""
|
|
8
9
|
from __future__ import annotations
|
|
9
10
|
|
|
@@ -67,6 +68,18 @@ class EcommerceTelefoneDto:
|
|
|
67
68
|
return from_dataclass(cls, data)
|
|
68
69
|
|
|
69
70
|
|
|
71
|
+
# Alinhamento STAR Homol: para PJ estes campos devem ir no JSON como null
|
|
72
|
+
# (não omitidos). PF continua com omit_none quando vazios.
|
|
73
|
+
# ``nomeSocial`` em PJ vai como string vazia (``""``), não null.
|
|
74
|
+
_PJ_NULL_WIRE_FIELDS = (
|
|
75
|
+
'codigoSexo',
|
|
76
|
+
'codigoEstadoCivil',
|
|
77
|
+
'tipoDocumentoIdentificacao',
|
|
78
|
+
'numeroDocumento',
|
|
79
|
+
'codigoProfissao',
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
|
|
70
83
|
@dataclass
|
|
71
84
|
class EcommerceClienteDto:
|
|
72
85
|
cpfCnpj: Optional[str] = None
|
|
@@ -82,8 +95,13 @@ class EcommerceClienteDto:
|
|
|
82
95
|
endereco: Optional[list[EcommerceEnderecoDto]] = None
|
|
83
96
|
telefone: Optional[list[EcommerceTelefoneDto]] = None
|
|
84
97
|
|
|
98
|
+
@staticmethod
|
|
99
|
+
def _is_cnpj(cpf_cnpj: Optional[str]) -> bool:
|
|
100
|
+
digits = ''.join(ch for ch in str(cpf_cnpj or '') if ch.isdigit())
|
|
101
|
+
return len(digits) >= 14
|
|
102
|
+
|
|
85
103
|
def to_dict(self) -> dict:
|
|
86
|
-
|
|
104
|
+
data = omit_none({
|
|
87
105
|
'cpfCnpj': self.cpfCnpj,
|
|
88
106
|
'nomeCompleto': self.nomeCompleto,
|
|
89
107
|
'dataNascimentoFundacao': self.dataNascimentoFundacao,
|
|
@@ -97,6 +115,11 @@ class EcommerceClienteDto:
|
|
|
97
115
|
'endereco': to_wire(self.endereco),
|
|
98
116
|
'telefone': to_wire(self.telefone),
|
|
99
117
|
})
|
|
118
|
+
if self._is_cnpj(self.cpfCnpj):
|
|
119
|
+
for key in _PJ_NULL_WIRE_FIELDS:
|
|
120
|
+
data[key] = None
|
|
121
|
+
data['nomeSocial'] = ''
|
|
122
|
+
return data
|
|
100
123
|
|
|
101
124
|
@classmethod
|
|
102
125
|
def from_dict(cls, data: dict | EcommerceClienteDto | None):
|
|
@@ -68,7 +68,7 @@ def _minimal_payload() -> ApiAttime001ImportarEcommerceDTO:
|
|
|
68
68
|
tipoItem=TipoItem.AUTOMOVEL,
|
|
69
69
|
formaPagamento=EcommerceFormaPagamentoDto(
|
|
70
70
|
diaVencimentoParcelaFatura=10,
|
|
71
|
-
dadosPagamento={'
|
|
71
|
+
dadosPagamento={'EnderecoCobranca': ''},
|
|
72
72
|
),
|
|
73
73
|
itens=[
|
|
74
74
|
EcommerceItemDto(
|
|
@@ -102,13 +102,44 @@ class TestApiAttime001ImportarEcommerceDTO(unittest.TestCase):
|
|
|
102
102
|
)
|
|
103
103
|
self.assertEqual(data['emissao']['contratos']['tipoItem'], 20)
|
|
104
104
|
self.assertEqual(
|
|
105
|
-
data['emissao']['contratos']['formaPagamento']['dadosPagamento']
|
|
106
|
-
'
|
|
105
|
+
data['emissao']['contratos']['formaPagamento']['dadosPagamento'],
|
|
106
|
+
{'EnderecoCobranca': ''},
|
|
107
107
|
)
|
|
108
108
|
again = ApiAttime001ImportarEcommerceDTO.from_dict(data)
|
|
109
109
|
self.assertEqual(again.emissao.clientes.cpfCnpj, '12345678901')
|
|
110
110
|
self.assertEqual(again.emissao.contratos.itens[0].caracteristicas[0].codigo, 39)
|
|
111
111
|
|
|
112
|
+
def test_pj_cliente_wires_pf_attrs_as_null(self):
|
|
113
|
+
"""STAR Homol: PJ deve enviar as chaves PF com null (não omitir)."""
|
|
114
|
+
cliente = EcommerceClienteDto(
|
|
115
|
+
cpfCnpj='41413609000170',
|
|
116
|
+
nomeCompleto='RMA TRANSPORTE',
|
|
117
|
+
dataNascimentoFundacao='2020-01-01T00:00:00',
|
|
118
|
+
)
|
|
119
|
+
data = cliente.to_dict()
|
|
120
|
+
for key in (
|
|
121
|
+
'codigoSexo',
|
|
122
|
+
'codigoEstadoCivil',
|
|
123
|
+
'tipoDocumentoIdentificacao',
|
|
124
|
+
'numeroDocumento',
|
|
125
|
+
'codigoProfissao',
|
|
126
|
+
):
|
|
127
|
+
self.assertIn(key, data)
|
|
128
|
+
self.assertIsNone(data[key])
|
|
129
|
+
self.assertIn('nomeSocial', data)
|
|
130
|
+
self.assertEqual(data['nomeSocial'], '')
|
|
131
|
+
|
|
132
|
+
def test_pf_cliente_omits_empty_optional_pf_attrs(self):
|
|
133
|
+
cliente = EcommerceClienteDto(
|
|
134
|
+
cpfCnpj='12345678901',
|
|
135
|
+
nomeCompleto='JOAO',
|
|
136
|
+
codigoSexo=Sexo.MASCULINO,
|
|
137
|
+
)
|
|
138
|
+
data = cliente.to_dict()
|
|
139
|
+
self.assertEqual(data['codigoSexo'], 'M')
|
|
140
|
+
self.assertNotIn('tipoDocumentoIdentificacao', data)
|
|
141
|
+
self.assertNotIn('numeroDocumento', data)
|
|
142
|
+
|
|
112
143
|
def test_dados_pagamento_must_be_dict(self):
|
|
113
144
|
with self.assertRaises(TypeError):
|
|
114
145
|
EcommerceFormaPagamentoDto.from_dict({
|
|
@@ -149,8 +180,8 @@ class TestAttime001ApiImportarEcommerce(unittest.TestCase):
|
|
|
149
180
|
self.assertEqual(
|
|
150
181
|
kwargs['payload']['emissao']['contratos']['formaPagamento'][
|
|
151
182
|
'dadosPagamento'
|
|
152
|
-
]
|
|
153
|
-
'
|
|
183
|
+
],
|
|
184
|
+
{'EnderecoCobranca': ''},
|
|
154
185
|
)
|
|
155
186
|
|
|
156
187
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/api.py
RENAMED
|
File without changes
|
|
File without changes
|
{attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/apis/bvix.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/bvix.py
RENAMED
|
File without changes
|
{attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/enums.py
RENAMED
|
File without changes
|
|
File without changes
|
{attime_star_api_python_sdk-1.9.0 → attime_star_api_python_sdk-1.9.3}/src/attime/star/dtos/serde.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|