documente_shared 0.1.73__py3-none-any.whl → 0.1.75__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.

Potentially problematic release.


This version of documente_shared might be problematic. Click here for more details.

@@ -0,0 +1,129 @@
1
+ from documente_shared.domain.base_enum import BaseEnum
2
+
3
+ from dataclasses import dataclass
4
+ from datetime import datetime
5
+ from typing import List, Optional, Type, Union
6
+ from uuid import UUID
7
+
8
+
9
+
10
+ def camelize_string(value: str) -> str:
11
+ if not value:
12
+ return value
13
+ value = "".join(word.title() for word in value.split("_"))
14
+ return value[:1].lower() + value[1:]
15
+
16
+
17
+ @dataclass
18
+ class QueryParams(object):
19
+ params: Union[dict]
20
+
21
+ def get(self, key, default=None):
22
+ return self.params.get(key, default) or self.params.get(camelize_string(key), default)
23
+
24
+ def get_datetime(self, key: str, default=None):
25
+ try:
26
+ value = self.get_str(key, default)
27
+ if not value:
28
+ return None
29
+ return datetime.strptime(value, "%Y-%m-%d")
30
+ except (ValueError, TypeError):
31
+ return None
32
+
33
+ def get_str(self, key, default=None):
34
+ try:
35
+ return self._get_or_none(key, str, default)
36
+ except (ValueError, TypeError):
37
+ return None
38
+
39
+ def get_int(self, key, default=None):
40
+ try:
41
+ return self._get_or_none(key, int, default)
42
+ except (ValueError, TypeError):
43
+ return None
44
+
45
+ def get_float(self, key, default=None):
46
+ try:
47
+ return self._get_or_none(key, float, default)
48
+ except (ValueError, TypeError):
49
+ return None
50
+
51
+ def get_bool(self, key, default=False):
52
+ try:
53
+ value = self.get(key, default)
54
+ if isinstance(value, bool):
55
+ return value
56
+ elif isinstance(value, str):
57
+ return value in ["true", "True", "TRUE", "1", "active"]
58
+ elif value is None:
59
+ return None
60
+ return False
61
+ except (ValueError, TypeError):
62
+ return None
63
+
64
+ def get_uuid(self, key, default=None):
65
+ try:
66
+ return self._get_or_none(key, UUID, default)
67
+ except (ValueError, TypeError):
68
+ return None
69
+
70
+ def get_uuid_list(self, key, default=None):
71
+ def parse_str(value):
72
+ uuid_list = []
73
+ for uuid_str in value.split(","):
74
+ try:
75
+ uuid_list.append(UUID(uuid_str))
76
+ except ValueError:
77
+ pass
78
+ return uuid_list
79
+
80
+ try:
81
+ return self._get_or_none(key, parse_str, default)
82
+ except (ValueError, TypeError):
83
+ return None
84
+
85
+ def get_list(self, key, default=None):
86
+ default = default or []
87
+ try:
88
+ return self.params.getlist(key) or self.params.getlist(camelize_string(key)) or default
89
+ except (ValueError, TypeError):
90
+ return None
91
+
92
+ def get_enum(
93
+ self,
94
+ key: str,
95
+ enum_class: Type[BaseEnum],
96
+ default: BaseEnum = None,
97
+ ) -> Optional[BaseEnum]:
98
+ try:
99
+ str_value = self.get_str(key) or default
100
+ return enum_class.from_value(str_value) if str_value else None
101
+ except (ValueError, TypeError):
102
+ return None
103
+
104
+ def get_enum_list(
105
+ self,
106
+ key: str,
107
+ enum_class: Type[BaseEnum],
108
+ default: BaseEnum = None,
109
+ ) -> List:
110
+ str_value = self.get_str(key) or default
111
+ if not str_value:
112
+ return []
113
+ converted_enum_list = []
114
+ str_enum_items = str_value.split(",")
115
+ for str_enum_item in str_enum_items:
116
+ enum_value = enum_class.from_value(value=str_enum_item)
117
+ if not enum_value:
118
+ continue
119
+ converted_enum_list.append(enum_value)
120
+ return converted_enum_list
121
+
122
+ def _get_or_none(
123
+ self,
124
+ key: str,
125
+ cast_type: Type[Union[str, int, float, bool, UUID]],
126
+ default=None,
127
+ ) -> Optional[Union[str, int, float, bool, UUID]]:
128
+ item_value = self.get(key, default)
129
+ return cast_type(item_value) if item_value else default
@@ -0,0 +1,48 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from typing import List, Optional
4
+
5
+ from documente_shared.domain.enums.common import ProcessingStatus
6
+ from documente_shared.domain.enums.processing_case import ProcessingCaseType
7
+ from documente_shared.application.query_params import QueryParams
8
+
9
+
10
+ @dataclass
11
+ class ProcessingCaseFilters(object):
12
+ case_ids: Optional[List[str]]
13
+ sort_order: Optional[str]
14
+ search: Optional[str]
15
+ init_date: Optional[datetime]
16
+ end_date: Optional[datetime]
17
+ statuses: List[ProcessingStatus] = None
18
+ case_types: List[ProcessingCaseType] = None
19
+ include_archived: bool = False
20
+
21
+ def __post_init__(self):
22
+ self.statuses = self.statuses or []
23
+ self.case_types = self.case_types or []
24
+
25
+ @classmethod
26
+ def from_params(cls, params: QueryParams) -> "ProcessingCaseFilters":
27
+ search_term = params.get_str(key="search", default=None)
28
+ return ProcessingCaseFilters(
29
+ case_ids=params.get_uuid_list(key="case_ids", default=None),
30
+ sort_order=params.get(key="sort", default="desc"),
31
+ search=search_term.strip() if search_term else None,
32
+ init_date=params.get_datetime(key="init_date", default=None),
33
+ end_date=params.get_datetime(key="end_date", default=None),
34
+ statuses=params.get_enum_list(
35
+ key="statuses",
36
+ enum_class=ProcessingStatus,
37
+ default=None,
38
+ ),
39
+ case_types=params.get_enum_list(
40
+ key="case_types",
41
+ enum_class=ProcessingCaseType,
42
+ default=None,
43
+ ),
44
+ include_archived=params.get_bool(
45
+ key="include_archived",
46
+ default=False,
47
+ ),
48
+ )
@@ -0,0 +1,51 @@
1
+ from dataclasses import dataclass
2
+ from datetime import datetime
3
+ from typing import List, Optional
4
+
5
+ from documente_shared.application.query_params import QueryParams
6
+ from documente_shared.domain.enums.common import ProcessingStatus
7
+ from documente_shared.domain.enums.document import (
8
+ DocumentProcessingStatus,
9
+ )
10
+ from documente_shared.domain.enums.processing_case import ProcessingDocumentType
11
+
12
+
13
+ @dataclass
14
+ class ProcessingCaseItemFilters(object):
15
+ sort_order: Optional[str]
16
+ search: Optional[str]
17
+ init_date: Optional[datetime]
18
+ end_date: Optional[datetime]
19
+ case_id: Optional[str] = None
20
+ statuses: List[ProcessingStatus] = None
21
+ document_types: List[ProcessingDocumentType] = None
22
+ include_archived: bool = False
23
+
24
+ def __post_init__(self):
25
+ self.statuses = self.statuses or []
26
+ self.document_types = self.document_types or []
27
+
28
+ @classmethod
29
+ def from_params(cls, params: QueryParams) -> "ProcessingCaseItemFilters":
30
+ search_term = params.get_str(key="search", default=None)
31
+ return cls(
32
+ sort_order=params.get(key="sort", default="desc"),
33
+ search=search_term.strip() if search_term else None,
34
+ init_date=params.get_datetime(key="init_date", default=None),
35
+ end_date=params.get_datetime(key="end_date", default=None),
36
+ case_id=params.get_str(key="case_id", default=None),
37
+ statuses=params.get_enum_list(
38
+ key="statuses",
39
+ enum_class=DocumentProcessingStatus,
40
+ default=None,
41
+ ),
42
+ document_types=params.get_enum_list(
43
+ key="document_types",
44
+ enum_class=ProcessingDocumentType,
45
+ default=None,
46
+ ),
47
+ include_archived=params.get_bool(
48
+ key="include_archived",
49
+ default=False,
50
+ ),
51
+ )
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
2
2
  from typing import Optional, List
3
3
 
4
4
  from documente_shared.domain.entities.processing_case import ProcessingCase
5
- from documente_shared.domain.enums.common import ProcessingStatus
5
+ from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
6
6
 
7
7
 
8
8
  class ProcessingCaseRepository(ABC):
@@ -20,5 +20,5 @@ class ProcessingCaseRepository(ABC):
20
20
  raise NotImplementedError
21
21
 
22
22
  @abstractmethod
23
- def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
23
+ def filter(self, tenant_slug: str, filters: ProcessingCaseFilters) -> List[ProcessingCase]:
24
24
  raise NotImplementedError
@@ -3,7 +3,7 @@ from typing import Optional, List
3
3
 
4
4
  from documente_shared.domain.entities.processing_case import ProcessingCase
5
5
  from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
6
- from documente_shared.domain.enums.common import ProcessingStatus
6
+ from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
7
7
 
8
8
 
9
9
  class ProcessingCaseItemRepository(ABC):
@@ -21,9 +21,5 @@ class ProcessingCaseItemRepository(ABC):
21
21
  raise NotImplementedError
22
22
 
23
23
  @abstractmethod
24
- def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
25
- raise NotImplementedError
26
-
27
- @abstractmethod
28
- def filter_by_case_id(self, case_id: str) -> List[ProcessingCase]:
24
+ def filter(self, tenant_slug: str, filters: ProcessingCaseItemFilters) -> List[ProcessingCase]:
29
25
  raise NotImplementedError
@@ -41,14 +41,3 @@ class DynamoProcessingCaseItemRepository(
41
41
  ProcessingCaseItem.from_dict(item)
42
42
  for item in items
43
43
  ]
44
-
45
- def filter_by_case_id(self, case_id: str) -> List[ProcessingCaseItem]:
46
- response = self._table.query(
47
- IndexName='case_id',
48
- KeyConditionExpression=Key('case_id').eq(case_id),
49
- )
50
- items = response.get('Items', [])
51
- return [
52
- ProcessingCaseItem.from_dict(item)
53
- for item in items
54
- ]
@@ -2,7 +2,7 @@ from dataclasses import dataclass
2
2
  from typing import List, Optional
3
3
 
4
4
  from documente_shared.domain.entities.processing_case import ProcessingCase
5
- from documente_shared.domain.enums.common import ProcessingStatus
5
+ from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
6
6
  from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
7
7
  from documente_shared.infrastructure.documente_client import DocumenteClientMixin
8
8
 
@@ -30,7 +30,7 @@ class HttpProcessingCaseRepository(
30
30
  def remove(self, instance: ProcessingCase):
31
31
  self.session.delete(f"{self.api_url}/processing-cases/{instance.uuid}/")
32
32
 
33
- def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
33
+ def filter(self, tenant_slug: str, filters: ProcessingCaseFilters) -> List[ProcessingCase]:
34
34
  response = self.session.get(f"{self.api_url}/processing-cases/")
35
35
  if response.status_code == 200:
36
36
  raw_response = response.json()
@@ -3,6 +3,7 @@ from typing import List, Optional
3
3
 
4
4
  from documente_shared.domain.entities.processing_case import ProcessingCase
5
5
  from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
6
+ from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
6
7
  from documente_shared.domain.enums.common import ProcessingStatus
7
8
  from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
8
9
  from documente_shared.infrastructure.documente_client import DocumenteClientMixin
@@ -32,22 +33,16 @@ class HttpProcessingCaseItemRepository(
32
33
  def remove(self, instance: ProcessingCaseItem):
33
34
  self.session.delete(f"{self.api_url}/processing-case-items/{instance.uuid}/")
34
35
 
35
- def filter(self, statuses: List[ProcessingStatus]) -> List[ProcessingCase]:
36
+ def filter(
37
+ self,
38
+ tenant_slug: str,
39
+ filters: ProcessingCaseItemFilters,
40
+ ) -> List[ProcessingCaseItem]:
36
41
  response = self.session.get(f"{self.api_url}/processing-case-items/")
37
42
  if response.status_code == 200:
38
43
  raw_response = response.json()
39
44
  return [
40
- ProcessingCase.from_dict(item)
45
+ ProcessingCaseItem.from_dict(item)
41
46
  for item in raw_response.get('data', [])
42
47
  ]
43
48
  return []
44
-
45
- def filter_by_case_id(self, case_id: str) -> List[ProcessingCase]:
46
- response = self.session.get(f"{self.api_url}/processing-case-items/?case_id={case_id}")
47
- if response.status_code == 200:
48
- raw_response = response.json()
49
- return [
50
- ProcessingCase.from_dict(item)
51
- for item in raw_response.get('data', [])
52
- ]
53
- return []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: documente_shared
3
- Version: 0.1.73
3
+ Version: 0.1.75
4
4
  Summary: Shared utilities for Documente AI projects
5
5
  License: MIT
6
6
  Author: Tech
@@ -3,6 +3,7 @@ documente_shared/application/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NM
3
3
  documente_shared/application/digest.py,sha256=Um6E8WfFri2_lly4RFWydJyvSfPZGFcOX-opEOzDCWc,172
4
4
  documente_shared/application/exceptions.py,sha256=lQM8m7wmI9OTLGva0gd7s7YT7ldaTk_Ln4t32PpzNf8,654
5
5
  documente_shared/application/files.py,sha256=ADiWi6Mk3YQGx3boGsDqdb5wk8qmabkGRy7bhNFa1OY,649
6
+ documente_shared/application/query_params.py,sha256=JscPqFBx28p-x9i2g6waY7Yl4FQM1zn2zSbEoTrkK1k,3938
6
7
  documente_shared/application/time_utils.py,sha256=_fxgh8VoGPkdsft47COJ16vFwt8pMbHIJCgDFHLSlrU,435
7
8
  documente_shared/application/timezone.py,sha256=NHpzTzOPD_fWQiJ4BrRqt_TIDs5XyB5ZMR7x8vUk8gQ,183
8
9
  documente_shared/domain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -13,7 +14,9 @@ documente_shared/domain/entities/document.py,sha256=AthTUyA-QZE3WAT7lMoKVr_Z8mO_
13
14
  documente_shared/domain/entities/document_metadata.py,sha256=ygyFIC5qwxlm8DUM5kvVFny9zJfPQS8vNLM2br5XsQ8,2353
14
15
  documente_shared/domain/entities/in_memory_result.py,sha256=Q1E9vnLL5Hz5xunOqWtQmJOMjoK5KN42LZr18GlBAZo,1246
15
16
  documente_shared/domain/entities/processing_case.py,sha256=3bL6BgFwWe6F5keZ6A1K_lLsrwGpkcKg98roM_i6kEQ,5167
17
+ documente_shared/domain/entities/processing_case_filters.py,sha256=146fnvzB-GvDPEzFHX3ckaFM9nLqG-4deUaEhl7Epwg,1784
16
18
  documente_shared/domain/entities/processing_case_item.py,sha256=hglyPhZBSjlMKVdEVccyHXU3aQRdZ8hfZlXDJnkf7wA,7996
19
+ documente_shared/domain/entities/processing_case_item_filters.py,sha256=YUsMk5BTtjUNzKy-nlkZg4NLPlPT1MnhP49rLhwlyB8,1891
17
20
  documente_shared/domain/entities/processing_event.py,sha256=m1O0gcNaE_SszeIhxM3uYPHSpyOUmize6mfRw1_bYZo,1723
18
21
  documente_shared/domain/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
22
  documente_shared/domain/enums/common.py,sha256=vXldMUPhhWo0PfTgYwDSjI8bur_lYcImZYiV7yAO7DQ,2262
@@ -21,19 +24,19 @@ documente_shared/domain/enums/document.py,sha256=NltZA1YVgJ7dVfSQdJFIE0ZUGf9Y-nx
21
24
  documente_shared/domain/enums/processing_case.py,sha256=LhFhcoWlockxcpplsVdC6M2kpXn7sOdzQySf24wFhx8,1572
22
25
  documente_shared/domain/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
26
  documente_shared/domain/repositories/document.py,sha256=vJzr6c92gqBzyhaEdjrvnoneKRrWmJ0AsvocPnhxiLU,767
24
- documente_shared/domain/repositories/processing_case.py,sha256=E2AivKrtoWdGiI9XLZp6-8xN7YZrd_is8jl3GOyYYvQ,726
25
- documente_shared/domain/repositories/processing_case_item.py,sha256=XZLmYsHkaJ0gyMlACHZX2FywxdcH9oJ6-rvWdJgWpbs,957
27
+ documente_shared/domain/repositories/processing_case.py,sha256=bpks3SAM_L4wx29P29iFo5g-oi4fxSXQEzhveARjo3c,767
28
+ documente_shared/domain/repositories/processing_case_item.py,sha256=ZlG3h-e6twMPt_WkXB6ZU0dIs2BI1k1rcMqDZk6g6dM,885
26
29
  documente_shared/infrastructure/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
30
  documente_shared/infrastructure/documente_client.py,sha256=UjVWs9DKa-yhw5DVbcEs8iJxalHOarusVayi_ob6QhE,494
28
31
  documente_shared/infrastructure/dynamo_table.py,sha256=TMQbcuty7wjDMbuhI8PbT0IGXelgELsNTtqTEQeZ824,2112
29
32
  documente_shared/infrastructure/repositories/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
33
  documente_shared/infrastructure/repositories/dynamo_document.py,sha256=_Yp4gtA-n-hJ2w2wAM5BMCs2Mf46Q2Kq3eHqlxudkL4,1443
31
34
  documente_shared/infrastructure/repositories/dynamo_processing_case.py,sha256=UJcROnmfKvE5k_GZOHvaYDvnNSX4Rm22xCB7tUaUUEU,1386
32
- documente_shared/infrastructure/repositories/dynamo_processing_case_item.py,sha256=reHtgWmLXbLhWUw14sG22Mj7RVzs8XZmTt13kElUcpA,1812
33
- documente_shared/infrastructure/repositories/http_processing_case.py,sha256=0etYPjeWW2bWvKtBvgeaZQxj-qw91T228biIbJSGsGo,1683
34
- documente_shared/infrastructure/repositories/http_processing_case_item.py,sha256=2-I2Oq4PFI1WsSnOzNC5OlqU1NE2QdZ5X3U_CjA-cls,2187
35
+ documente_shared/infrastructure/repositories/dynamo_processing_case_item.py,sha256=bqD6uFoMmG_CgLcY4Q5VLGVD5A1bA927_dzllHTZ7O8,1447
36
+ documente_shared/infrastructure/repositories/http_processing_case.py,sha256=4PHNqbzDlt8Bicv3IUwJ58e4WNlIU_Hxq0cPuaLFgtw,1724
37
+ documente_shared/infrastructure/repositories/http_processing_case_item.py,sha256=TybbIO6Kp92xVvKedQgiI7s63U7SFnu6P0RkOrXemT8,1939
35
38
  documente_shared/infrastructure/s3_bucket.py,sha256=vT_yN42RFQXubtUn8ln-j13Os_-25UGClVtXg5Bkv6I,1932
36
39
  documente_shared/infrastructure/sqs_queue.py,sha256=KZWeHZ9zmXmrxoNpOQX7GEdDhZ1knbPXgwSwFwJblGg,1504
37
- documente_shared-0.1.73.dist-info/METADATA,sha256=KVhxyT5zo7u_nG8RjY2pzflZ3SvZxyw_4-KQNu-QCIs,881
38
- documente_shared-0.1.73.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
39
- documente_shared-0.1.73.dist-info/RECORD,,
40
+ documente_shared-0.1.75.dist-info/METADATA,sha256=d8vHY11kCF7tC653YZaYcpf6B5udVxcAc5ILGRuvMbs,881
41
+ documente_shared-0.1.75.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
42
+ documente_shared-0.1.75.dist-info/RECORD,,