attime-star-api-python-sdk 1.8.0__tar.gz → 1.9.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.
Files changed (26) hide show
  1. {attime_star_api_python_sdk-1.8.0/src/attime_star_api_python_sdk.egg-info → attime_star_api_python_sdk-1.9.0}/PKG-INFO +1 -1
  2. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/pyproject.toml +1 -1
  3. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/apis/attime001.py +20 -20
  4. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/attime001.py +21 -36
  5. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0/src/attime_star_api_python_sdk.egg-info}/PKG-INFO +1 -1
  6. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/tests/test_attime001_atualizacoes.py +9 -11
  7. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/tests/test_attime001_cancelamento.py +16 -28
  8. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/LICENSE +0 -0
  9. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/README.md +0 -0
  10. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/setup.cfg +0 -0
  11. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/api.py +0 -0
  12. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/apis/__init__.py +0 -0
  13. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/apis/bvix.py +0 -0
  14. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/apis/infocar.py +0 -0
  15. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/__init__.py +0 -0
  16. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/bvix.py +0 -0
  17. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/ecommerce.py +0 -0
  18. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/enums.py +0 -0
  19. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/infocar.py +0 -0
  20. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime/star/dtos/serde.py +0 -0
  21. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime_star_api_python_sdk.egg-info/SOURCES.txt +0 -0
  22. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime_star_api_python_sdk.egg-info/dependency_links.txt +0 -0
  23. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/src/attime_star_api_python_sdk.egg-info/top_level.txt +0 -0
  24. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/tests/test_attime001_importar_ecommerce.py +0 -0
  25. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/tests/test_attime001_insere_item.py +0 -0
  26. {attime_star_api_python_sdk-1.8.0 → attime_star_api_python_sdk-1.9.0}/tests/test_attime001_relacao.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: attime-star-api-python-sdk
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: Client HTTP de comunicacao com a API da ATTime Star
5
5
  Author-email: Filipe Coelho <filipe@fmconsult.com.br>
6
6
  License: MIT License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "attime-star-api-python-sdk"
7
- version = "1.8.0"
7
+ version = "1.9.0"
8
8
  description = "Client HTTP de comunicacao com a API da ATTime Star"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -16,24 +16,27 @@ from attime.star.dtos.attime001 import (
16
16
  ApiAttime001EmitirItemDTO,
17
17
  ApiAttime001RelacaoContratoCpfItemDTO,
18
18
  ApiAttime001RelacaoItemDTO,
19
- EscopoOperacao,
20
19
  )
21
20
  from attime.star.dtos.ecommerce import ApiAttime001ImportarEcommerceDTO
22
21
 
23
22
  T = TypeVar('T')
24
23
 
25
24
 
26
- def _require_escopo_e_contrato(payload: dict) -> None:
27
- if payload.get('escopoOperacao') in (None, ''):
28
- raise ValueError('escopoOperacao é obrigatório')
25
+ def _require_numero_contrato(payload: dict) -> None:
29
26
  if payload.get('numeroContrato') in (None, ''):
30
27
  raise ValueError('numeroContrato é obrigatório')
31
28
 
32
29
 
33
- def _escopo_is(value: object, expected: EscopoOperacao) -> bool:
34
- if value is None:
35
- return False
36
- return str(value).casefold() == expected.value.casefold()
30
+ def _require_cancelamento_payload(payload: dict) -> None:
31
+ """Escopo via campos: declinio, ou identificadorItem ("" = contrato)."""
32
+ _require_numero_contrato(payload)
33
+ if payload.get('declinio'):
34
+ return
35
+ if 'identificadorItem' not in payload:
36
+ raise ValueError(
37
+ 'identificadorItem é obrigatório ("" para contrato; CAC 25/nº para item) '
38
+ 'ou informe o bloco declinio'
39
+ )
37
40
 
38
41
 
39
42
  def _parse_attime001_list_response(
@@ -96,27 +99,23 @@ class Attime001Api(ATTimeStarApi):
96
99
  def cancelamento(
97
100
  self, item: ApiAttime001CancelamentoDTO | dict
98
101
  ) -> list[ApiAttime001CancelamentoDTO]:
99
- """POST /btc/ABTP0004/ApiAttime001/Cancelamento."""
102
+ """PUT /btc/ABTP0004/ApiAttime001/Cancelamento."""
100
103
  logging.info('cancelling via ApiAttime001 Cancelamento...')
101
104
  if isinstance(item, ApiAttime001CancelamentoDTO):
102
105
  payload = item.to_dict()
103
106
  else:
104
107
  payload = dict(item)
108
+ # Compat: ignore legacy field if caller still sends it.
109
+ payload.pop('escopoOperacao', None)
105
110
 
106
- _require_escopo_e_contrato(payload)
107
- if _escopo_is(payload.get('escopoOperacao'), EscopoOperacao.DECLINIO) and not payload.get(
108
- 'declinio'
109
- ):
110
- raise ValueError(
111
- f'declinio é obrigatório quando escopoOperacao={EscopoOperacao.DECLINIO}'
112
- )
111
+ _require_cancelamento_payload(payload)
113
112
 
114
113
  url = UrlUtil().make_url(
115
114
  self.base_url,
116
115
  ['btc', 'ABTP0004', 'ApiAttime001', 'Cancelamento'],
117
116
  )
118
117
  res = self.call_request(
119
- http_method=HTTPMethod.POST,
118
+ http_method=HTTPMethod.PUT,
120
119
  request_url=url,
121
120
  payload=payload,
122
121
  )
@@ -130,21 +129,22 @@ class Attime001Api(ATTimeStarApi):
130
129
  def atualizacoes(
131
130
  self, item: ApiAttime001AtualizacoesDTO | dict
132
131
  ) -> list[ApiAttime001AtualizacoesDTO]:
133
- """POST /btc/ABTP0004/ApiAttime001/Atualizacoes."""
132
+ """PUT /btc/ABTP0004/ApiAttime001/Atualizacoes."""
134
133
  logging.info('updating via ApiAttime001 Atualizacoes...')
135
134
  if isinstance(item, ApiAttime001AtualizacoesDTO):
136
135
  payload = item.to_dict()
137
136
  else:
138
137
  payload = dict(item)
138
+ payload.pop('escopoOperacao', None)
139
139
 
140
- _require_escopo_e_contrato(payload)
140
+ _require_numero_contrato(payload)
141
141
 
142
142
  url = UrlUtil().make_url(
143
143
  self.base_url,
144
144
  ['btc', 'ABTP0004', 'ApiAttime001', 'Atualizacoes'],
145
145
  )
146
146
  res = self.call_request(
147
- http_method=HTTPMethod.POST,
147
+ http_method=HTTPMethod.PUT,
148
148
  request_url=url,
149
149
  payload=payload,
150
150
  )
@@ -1,19 +1,20 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """DTOs ApiAttime001 (ABTP0004).
3
3
 
4
- Cancelamento: POST /btc/ABTP0004/ApiAttime001/Cancelamento
5
- Atualizacoes: POST /btc/ABTP0004/ApiAttime001/Atualizacoes
4
+ Cancelamento: PUT /btc/ABTP0004/ApiAttime001/Cancelamento
5
+ Atualizacoes: PUT /btc/ABTP0004/ApiAttime001/Atualizacoes
6
6
  InsereItem: POST /btc/ABTP0004/ApiAttime001/InsereItem
7
7
  RelacaoContrato: GET /btc/ABTP0004/ApiAttime001/RelacaoContrato
8
8
  RelacaoItens: GET /btc/ABTP0004/ApiAttime001/RelacaoItens
9
9
 
10
10
  Enums de domínio compartilhados: ``attime.star.dtos.enums``.
11
- ``EscopoOperacao`` permanece aqui (específico Cancelamento/Atualizacoes).
11
+
12
+ Escopo de Cancelamento/Atualizacoes é inferido pelos campos preenchidos
13
+ (STAR removeu ``escopoOperacao`` do JSON).
12
14
  """
13
15
  from __future__ import annotations
14
16
 
15
17
  from dataclasses import dataclass
16
- from enum import StrEnum
17
18
  from typing import Optional
18
19
 
19
20
  from attime.star.dtos.enums import (
@@ -36,21 +37,6 @@ _WIRE_CARACTERISTICA = {
36
37
  _WIRE_CARACTERISTICA_REV = {v: k for k, v in _WIRE_CARACTERISTICA.items()}
37
38
 
38
39
 
39
- class EscopoOperacao(StrEnum):
40
- """Literais de ``escopoOperacao`` conforme description do OpenAPI (Title Case).
41
-
42
- Cancelamento inclui DECLINIO; Atualizacoes não. Específico deste endpoint.
43
- """
44
-
45
- CONTRATO = 'Contrato'
46
- ITEM = 'Item'
47
- CARACTERISTICA = 'Caracteristica'
48
- COBERTURA = 'Cobertura'
49
- SERVICO = 'Servico'
50
- BENEFICIARIO = 'Beneficiario'
51
- DECLINIO = 'Declinio'
52
-
53
-
54
40
  # ---------------------------------------------------------------------------
55
41
  # Cancelamento
56
42
  # ---------------------------------------------------------------------------
@@ -103,9 +89,13 @@ class DeclinioDto:
103
89
 
104
90
  @dataclass
105
91
  class ApiAttime001CancelamentoDTO:
106
- """Payload/resposta de Cancelamento (ApiAttime001CancelamentoDTO)."""
92
+ """Payload/resposta de Cancelamento (ApiAttime001CancelamentoDTO).
93
+
94
+ Escopo é inferido pelos campos: contrato inteiro usa ``identificadorItem=""``;
95
+ item/parcial exige ``identificadorItem`` (CAC 25 ou nº do item); Declínio
96
+ exige o bloco ``declinio``.
97
+ """
107
98
 
108
- escopoOperacao: str | EscopoOperacao
109
99
  numeroContrato: str
110
100
  manutencaoUsuarioCpf: Optional[str] = None
111
101
  manutencaoUsuarioDataHora: Optional[str] = None # ISO date-time
@@ -118,7 +108,6 @@ class ApiAttime001CancelamentoDTO:
118
108
 
119
109
  def to_dict(self) -> dict:
120
110
  return omit_none({
121
- 'escopoOperacao': to_wire(self.escopoOperacao),
122
111
  'numeroContrato': self.numeroContrato,
123
112
  'manutencaoUsuarioCpf': self.manutencaoUsuarioCpf,
124
113
  'manutencaoUsuarioDataHora': self.manutencaoUsuarioDataHora,
@@ -143,7 +132,6 @@ class ApiAttime001CancelamentoDTO:
143
132
  f'ApiAttime001CancelamentoDTO.from_dict espera dict, recebeu {type(data)!r}'
144
133
  )
145
134
  return cls(
146
- escopoOperacao=data.get('escopoOperacao'),
147
135
  numeroContrato=data.get('numeroContrato'),
148
136
  manutencaoUsuarioCpf=data.get('manutencaoUsuarioCpf'),
149
137
  manutencaoUsuarioDataHora=data.get('manutencaoUsuarioDataHora'),
@@ -163,11 +151,9 @@ class ApiAttime001CancelamentoDTO:
163
151
  identificadorItem: str,
164
152
  manutencaoUsuarioCpf: Optional[str] = None,
165
153
  manutencaoUsuarioDataHora: Optional[str] = None,
166
- escopoOperacao: str = EscopoOperacao.ITEM,
167
154
  ) -> ApiAttime001CancelamentoDTO:
168
- """Atalho para cancelar um item do contrato."""
155
+ """Atalho para cancelar um item (CAC 25 ou número do item)."""
169
156
  return cls(
170
- escopoOperacao=escopoOperacao,
171
157
  numeroContrato=numeroContrato,
172
158
  identificadorItem=identificadorItem,
173
159
  manutencaoUsuarioCpf=manutencaoUsuarioCpf,
@@ -181,12 +167,11 @@ class ApiAttime001CancelamentoDTO:
181
167
  numeroContrato: str,
182
168
  manutencaoUsuarioCpf: Optional[str] = None,
183
169
  manutencaoUsuarioDataHora: Optional[str] = None,
184
- escopoOperacao: str = EscopoOperacao.CONTRATO,
185
170
  ) -> ApiAttime001CancelamentoDTO:
186
- """Atalho para cancelar o contrato inteiro."""
171
+ """Atalho para cancelar o contrato inteiro (``identificadorItem=""``)."""
187
172
  return cls(
188
- escopoOperacao=escopoOperacao,
189
173
  numeroContrato=numeroContrato,
174
+ identificadorItem='',
190
175
  manutencaoUsuarioCpf=manutencaoUsuarioCpf,
191
176
  manutencaoUsuarioDataHora=manutencaoUsuarioDataHora,
192
177
  )
@@ -199,16 +184,14 @@ class ApiAttime001CancelamentoDTO:
199
184
  declinio_itens: list[DeclinioItemCobertura] | list[dict],
200
185
  manutencaoUsuarioCpf: Optional[str] = None,
201
186
  manutencaoUsuarioDataHora: Optional[str] = None,
202
- escopoOperacao: str = EscopoOperacao.DECLINIO,
203
187
  ) -> ApiAttime001CancelamentoDTO:
204
- """Atalho para escopo Declínio (bloco declinio obrigatório)."""
188
+ """Atalho para Declínio (bloco ``declinio`` obrigatório)."""
205
189
  itens: list[DeclinioItemCobertura] = []
206
190
  for row in declinio_itens:
207
191
  parsed = DeclinioItemCobertura.from_dict(row)
208
192
  if parsed is not None:
209
193
  itens.append(parsed)
210
194
  return cls(
211
- escopoOperacao=escopoOperacao,
212
195
  numeroContrato=numeroContrato,
213
196
  manutencaoUsuarioCpf=manutencaoUsuarioCpf,
214
197
  manutencaoUsuarioDataHora=manutencaoUsuarioDataHora,
@@ -391,9 +374,13 @@ class AtualizacaoItemBeneficiarioDto:
391
374
 
392
375
  @dataclass
393
376
  class ApiAttime001AtualizacoesDTO:
394
- """Payload/resposta de Atualizacoes (ApiAttime001AtualizacoesDTO)."""
377
+ """Payload/resposta de Atualizacoes (ApiAttime001AtualizacoesDTO).
378
+
379
+ Escopo é inferido pelos blocos presentes (``contrato``, ``item``,
380
+ ``itemCaracteristica``, ``itemCobertura``, ``itemCoberturaServico``,
381
+ ``itemBeneficiario``).
382
+ """
395
383
 
396
- escopoOperacao: str | EscopoOperacao
397
384
  numeroContrato: str
398
385
  manutencaoUsuarioCpf: Optional[str] = None
399
386
  manutencaoUsuarioDataHora: Optional[str] = None
@@ -406,7 +393,6 @@ class ApiAttime001AtualizacoesDTO:
406
393
 
407
394
  def to_dict(self) -> dict:
408
395
  return omit_none({
409
- 'escopoOperacao': to_wire(self.escopoOperacao),
410
396
  'numeroContrato': self.numeroContrato,
411
397
  'manutencaoUsuarioCpf': self.manutencaoUsuarioCpf,
412
398
  'manutencaoUsuarioDataHora': self.manutencaoUsuarioDataHora,
@@ -438,7 +424,6 @@ class ApiAttime001AtualizacoesDTO:
438
424
  return [nested_cls.from_dict(i) for i in rows if i is not None]
439
425
 
440
426
  return cls(
441
- escopoOperacao=data.get('escopoOperacao'),
442
427
  numeroContrato=data.get('numeroContrato'),
443
428
  manutencaoUsuarioCpf=data.get('manutencaoUsuarioCpf'),
444
429
  manutencaoUsuarioDataHora=data.get('manutencaoUsuarioDataHora'),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: attime-star-api-python-sdk
3
- Version: 1.8.0
3
+ Version: 1.9.0
4
4
  Summary: Client HTTP de comunicacao com a API da ATTime Star
5
5
  Author-email: Filipe Coelho <filipe@fmconsult.com.br>
6
6
  License: MIT License
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import unittest
6
+ from http import HTTPMethod
6
7
  from unittest.mock import MagicMock, patch
7
8
 
8
9
  from attime.star.dtos.attime001 import (
@@ -10,7 +11,6 @@ from attime.star.dtos.attime001 import (
10
11
  AtualizacaoContratoDto,
11
12
  AtualizacaoItemCaracteristicaDto,
12
13
  AtualizacaoItemCoberturaDto,
13
- EscopoOperacao,
14
14
  )
15
15
  from attime.star.dtos.enums import Sexo, SimNao
16
16
 
@@ -18,7 +18,6 @@ from attime.star.dtos.enums import Sexo, SimNao
18
18
  class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
19
19
  def test_to_dict_omits_none_and_maps_caracteristica_wire(self):
20
20
  dto = ApiAttime001AtualizacoesDTO(
21
- escopoOperacao=EscopoOperacao.CARACTERISTICA,
22
21
  numeroContrato='016501000280',
23
22
  itemCaracteristica=[
24
23
  AtualizacaoItemCaracteristicaDto(
@@ -29,6 +28,7 @@ class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
29
28
  ],
30
29
  )
31
30
  data = dto.to_dict()
31
+ self.assertNotIn('escopoOperacao', data)
32
32
  self.assertNotIn('contrato', data)
33
33
  self.assertNotIn('itemCobertura', data)
34
34
  row = data['itemCaracteristica'][0]
@@ -38,7 +38,6 @@ class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
38
38
 
39
39
  def test_from_dict_accepts_openapi_typo(self):
40
40
  raw = {
41
- 'escopoOperacao': 'CARACTERISTICA',
42
41
  'numeroContrato': '016501000280',
43
42
  'itemCaracteristica': [
44
43
  {
@@ -56,7 +55,6 @@ class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
56
55
 
57
56
  def test_contrato_and_cobertura_roundtrip(self):
58
57
  dto = ApiAttime001AtualizacoesDTO(
59
- escopoOperacao=EscopoOperacao.CONTRATO,
60
58
  numeroContrato='016501000280',
61
59
  manutencaoUsuarioCpf='12345678901',
62
60
  contrato=AtualizacaoContratoDto(
@@ -74,7 +72,7 @@ class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
74
72
  ],
75
73
  )
76
74
  data = dto.to_dict()
77
- self.assertEqual(data['escopoOperacao'], 'Contrato')
75
+ self.assertNotIn('escopoOperacao', data)
78
76
  self.assertEqual(data['contrato']['sexo'], 'M')
79
77
  self.assertEqual(data['contrato']['contratoGarantia'], 'N')
80
78
  again = ApiAttime001AtualizacoesDTO.from_dict(data)
@@ -83,17 +81,17 @@ class TestApiAttime001AtualizacoesDTO(unittest.TestCase):
83
81
 
84
82
 
85
83
  class TestAttime001ApiAtualizacoes(unittest.TestCase):
86
- def test_requires_escopo_and_numero(self):
84
+ def test_requires_numero(self):
87
85
  from attime.star.apis.attime001 import Attime001Api
88
86
 
89
87
  with patch.object(Attime001Api, '__init__', lambda self: None):
90
88
  api = Attime001Api()
91
89
  with self.assertRaises(ValueError):
92
- api.atualizacoes({'numeroContrato': '016501000280'})
90
+ api.atualizacoes({})
93
91
  with self.assertRaises(ValueError):
94
92
  api.atualizacoes({'escopoOperacao': 'ITEM'})
95
93
 
96
- def test_posts_to_atualizacoes_path(self):
94
+ def test_puts_to_atualizacoes_path(self):
97
95
  from attime.star.apis.attime001 import Attime001Api
98
96
 
99
97
  with patch.object(Attime001Api, '__init__', lambda self: None):
@@ -103,22 +101,22 @@ class TestAttime001ApiAtualizacoes(unittest.TestCase):
103
101
  with patch('attime.star.apis.attime001.jsonpickle.decode') as decode:
104
102
  decode.return_value = [
105
103
  {
106
- 'escopoOperacao': 'ITEM',
107
104
  'numeroContrato': '016501000280',
108
105
  'item': [{'itemNumero': 1, 'dataFimVigencia': '2027-01-01'}],
109
106
  }
110
107
  ]
111
108
  rows = api.atualizacoes(
112
109
  ApiAttime001AtualizacoesDTO(
113
- escopoOperacao=EscopoOperacao.ITEM,
114
110
  numeroContrato='016501000280',
111
+ item=[{'itemNumero': 1, 'dataFimVigencia': '2027-01-01'}],
115
112
  )
116
113
  )
117
114
  self.assertEqual(len(rows), 1)
118
115
  self.assertEqual(rows[0].item[0].itemNumero, 1)
119
116
  kwargs = api.call_request.call_args.kwargs
117
+ self.assertEqual(kwargs['http_method'], HTTPMethod.PUT)
120
118
  self.assertIn('/ABTP0004/ApiAttime001/Atualizacoes', kwargs['request_url'])
121
- self.assertEqual(kwargs['payload']['escopoOperacao'], 'Item')
119
+ self.assertNotIn('escopoOperacao', kwargs['payload'])
122
120
 
123
121
 
124
122
  if __name__ == '__main__':
@@ -3,12 +3,12 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import unittest
6
+ from http import HTTPMethod
6
7
  from unittest.mock import MagicMock, patch
7
8
 
8
9
  from attime.star.dtos.attime001 import (
9
10
  ApiAttime001CancelamentoDTO,
10
11
  DeclinioItemCobertura,
11
- EscopoOperacao,
12
12
  )
13
13
 
14
14
 
@@ -19,7 +19,7 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
19
19
  identificadorItem='12345678901',
20
20
  )
21
21
  data = dto.to_dict()
22
- self.assertEqual(data['escopoOperacao'], EscopoOperacao.ITEM)
22
+ self.assertNotIn('escopoOperacao', data)
23
23
  self.assertEqual(data['numeroContrato'], '002501000089')
24
24
  self.assertEqual(data['identificadorItem'], '12345678901')
25
25
  self.assertNotIn('coberturaCodigo', data)
@@ -28,7 +28,6 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
28
28
 
29
29
  def test_from_dict_roundtrip(self):
30
30
  raw = {
31
- 'escopoOperacao': 'ITEM',
32
31
  'numeroContrato': '002501000089',
33
32
  'identificadorItem': '999',
34
33
  'coberturaCodigo': 81,
@@ -37,11 +36,13 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
37
36
  self.assertIsNotNone(dto)
38
37
  self.assertEqual(dto.coberturaCodigo, 81)
39
38
  self.assertEqual(dto.to_dict()['coberturaCodigo'], 81)
39
+ self.assertNotIn('escopoOperacao', dto.to_dict())
40
40
 
41
- def test_for_contrato(self):
41
+ def test_for_contrato_uses_empty_identificador(self):
42
42
  dto = ApiAttime001CancelamentoDTO.for_contrato(numeroContrato='002501000001')
43
- self.assertEqual(dto.escopoOperacao, EscopoOperacao.CONTRATO)
44
- self.assertIsNone(dto.identificadorItem)
43
+ data = dto.to_dict()
44
+ self.assertEqual(data['identificadorItem'], '')
45
+ self.assertNotIn('escopoOperacao', data)
45
46
 
46
47
  def test_for_declinio_serializes_nested(self):
47
48
  dto = ApiAttime001CancelamentoDTO.for_declinio(
@@ -56,8 +57,7 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
56
57
  ],
57
58
  )
58
59
  data = dto.to_dict()
59
- self.assertEqual(data['escopoOperacao'], 'Declinio')
60
- self.assertEqual(data['escopoOperacao'], EscopoOperacao.DECLINIO)
60
+ self.assertNotIn('escopoOperacao', data)
61
61
  self.assertEqual(
62
62
  data['declinio']['declinioItemCobertura'][0]['coberturaCodigo'], 101
63
63
  )
@@ -67,7 +67,6 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
67
67
 
68
68
  def test_declinio_from_dict_roundtrip(self):
69
69
  raw = {
70
- 'escopoOperacao': 'DECLINIO',
71
70
  'numeroContrato': '016501000280',
72
71
  'declinio': {
73
72
  'declinioItemCobertura': [
@@ -86,41 +85,28 @@ class TestApiAttime001CancelamentoDTO(unittest.TestCase):
86
85
 
87
86
 
88
87
  class TestAttime001ApiCancelamento(unittest.TestCase):
89
- def test_requires_escopo_and_numero(self):
88
+ def test_requires_numero_and_identificador_or_declinio(self):
90
89
  from attime.star.apis.attime001 import Attime001Api
91
90
 
92
91
  with patch.object(Attime001Api, '__init__', lambda self: None):
93
92
  api = Attime001Api()
94
93
  with self.assertRaises(ValueError):
95
- api.cancelamento({'numeroContrato': '002501000001'})
94
+ api.cancelamento({})
96
95
  with self.assertRaises(ValueError):
97
- api.cancelamento({'escopoOperacao': 'ITEM'})
98
-
99
- def test_requires_declinio_block(self):
100
- from attime.star.apis.attime001 import Attime001Api
101
-
102
- with patch.object(Attime001Api, '__init__', lambda self: None):
103
- api = Attime001Api()
104
- with self.assertRaises(ValueError) as ctx:
105
- api.cancelamento({
106
- 'escopoOperacao': 'DECLINIO',
107
- 'numeroContrato': '016501000280',
108
- })
109
- self.assertIn('declinio', str(ctx.exception))
96
+ api.cancelamento({'numeroContrato': '002501000001'})
110
97
 
111
- def test_posts_to_cancelamento_path(self):
98
+ def test_puts_to_cancelamento_path(self):
112
99
  from attime.star.apis.attime001 import Attime001Api
113
100
 
114
101
  with patch.object(Attime001Api, '__init__', lambda self: None):
115
102
  api = Attime001Api()
116
103
  api.base_url = 'https://starbackhom.attime.inf.br'
117
104
  api.call_request = MagicMock(
118
- return_value='[{"escopoOperacao":"ITEM","numeroContrato":"002501000089","identificadorItem":"1"}]'
105
+ return_value='[{"numeroContrato":"002501000089","identificadorItem":"1"}]'
119
106
  )
120
107
  with patch('attime.star.apis.attime001.jsonpickle.decode') as decode:
121
108
  decode.return_value = [
122
109
  {
123
- 'escopoOperacao': 'ITEM',
124
110
  'numeroContrato': '002501000089',
125
111
  'identificadorItem': '1',
126
112
  }
@@ -134,8 +120,10 @@ class TestAttime001ApiCancelamento(unittest.TestCase):
134
120
  self.assertEqual(len(rows), 1)
135
121
  self.assertEqual(rows[0].identificadorItem, '1')
136
122
  kwargs = api.call_request.call_args.kwargs
123
+ self.assertEqual(kwargs['http_method'], HTTPMethod.PUT)
137
124
  self.assertIn('/ABTP0004/ApiAttime001/Cancelamento', kwargs['request_url'])
138
- self.assertEqual(kwargs['payload']['escopoOperacao'], 'Item')
125
+ self.assertNotIn('escopoOperacao', kwargs['payload'])
126
+ self.assertEqual(kwargs['payload']['identificadorItem'], '1')
139
127
 
140
128
 
141
129
  if __name__ == '__main__':