documente_shared 0.1.145__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.
Files changed (63) hide show
  1. documente_shared/__init__.py +0 -0
  2. documente_shared/application/__init__.py +0 -0
  3. documente_shared/application/dates.py +7 -0
  4. documente_shared/application/digest.py +7 -0
  5. documente_shared/application/exceptions.py +23 -0
  6. documente_shared/application/files.py +27 -0
  7. documente_shared/application/json.py +45 -0
  8. documente_shared/application/numbers.py +7 -0
  9. documente_shared/application/payloads.py +29 -0
  10. documente_shared/application/query_params.py +133 -0
  11. documente_shared/application/retry_utils.py +69 -0
  12. documente_shared/application/time_utils.py +13 -0
  13. documente_shared/application/timezone.py +7 -0
  14. documente_shared/domain/__init__.py +0 -0
  15. documente_shared/domain/base_enum.py +54 -0
  16. documente_shared/domain/constants.py +8 -0
  17. documente_shared/domain/entities/__init__.py +0 -0
  18. documente_shared/domain/entities/document.py +410 -0
  19. documente_shared/domain/entities/document_metadata.py +64 -0
  20. documente_shared/domain/entities/in_memory_document.py +75 -0
  21. documente_shared/domain/entities/processing_case.py +215 -0
  22. documente_shared/domain/entities/processing_case_filters.py +51 -0
  23. documente_shared/domain/entities/processing_case_item.py +300 -0
  24. documente_shared/domain/entities/processing_case_item_filters.py +54 -0
  25. documente_shared/domain/entities/processing_documents.py +11 -0
  26. documente_shared/domain/entities/processing_event.py +71 -0
  27. documente_shared/domain/entities/scaling.py +31 -0
  28. documente_shared/domain/enums/__init__.py +0 -0
  29. documente_shared/domain/enums/circular_oficio.py +29 -0
  30. documente_shared/domain/enums/common.py +133 -0
  31. documente_shared/domain/enums/document.py +124 -0
  32. documente_shared/domain/enums/document_type_record.py +13 -0
  33. documente_shared/domain/enums/processing_case.py +66 -0
  34. documente_shared/domain/exceptions.py +5 -0
  35. documente_shared/domain/interfaces/__init__.py +0 -0
  36. documente_shared/domain/interfaces/scaling.py +10 -0
  37. documente_shared/domain/repositories/__init__.py +0 -0
  38. documente_shared/domain/repositories/document.py +24 -0
  39. documente_shared/domain/repositories/processing_case.py +36 -0
  40. documente_shared/domain/repositories/processing_case_item.py +49 -0
  41. documente_shared/infrastructure/__init__.py +0 -0
  42. documente_shared/infrastructure/documente_client.py +27 -0
  43. documente_shared/infrastructure/dynamo_table.py +75 -0
  44. documente_shared/infrastructure/lambdas.py +14 -0
  45. documente_shared/infrastructure/repositories/__init__.py +0 -0
  46. documente_shared/infrastructure/repositories/dynamo_document.py +43 -0
  47. documente_shared/infrastructure/repositories/dynamo_processing_case.py +55 -0
  48. documente_shared/infrastructure/repositories/dynamo_processing_case_item.py +70 -0
  49. documente_shared/infrastructure/repositories/http_document.py +66 -0
  50. documente_shared/infrastructure/repositories/http_processing_case.py +82 -0
  51. documente_shared/infrastructure/repositories/http_processing_case_item.py +118 -0
  52. documente_shared/infrastructure/repositories/mem_document.py +46 -0
  53. documente_shared/infrastructure/repositories/mem_processing_case.py +44 -0
  54. documente_shared/infrastructure/repositories/mem_processing_case_item.py +52 -0
  55. documente_shared/infrastructure/s3_bucket.py +58 -0
  56. documente_shared/infrastructure/services/__init__.py +0 -0
  57. documente_shared/infrastructure/services/http_scaling.py +25 -0
  58. documente_shared/infrastructure/sqs_queue.py +48 -0
  59. documente_shared/presentation/__init__.py +0 -0
  60. documente_shared/presentation/presenters.py +16 -0
  61. documente_shared-0.1.145.dist-info/METADATA +39 -0
  62. documente_shared-0.1.145.dist-info/RECORD +63 -0
  63. documente_shared-0.1.145.dist-info/WHEEL +4 -0
@@ -0,0 +1,75 @@
1
+ import boto3
2
+
3
+ from dataclasses import dataclass
4
+ from boto3.dynamodb.conditions import Key
5
+
6
+
7
+ RETURN_VALUES = 'UPDATED_NEW'
8
+
9
+
10
+ @dataclass
11
+ class DynamoDBTable(object):
12
+ table_name: str
13
+
14
+ def __post_init__(self):
15
+ self._table = boto3.resource('dynamodb').Table(self.table_name)
16
+
17
+ def get(self, key: dict):
18
+ return self._table.get_item(Key=key).get('Item')
19
+
20
+ def get_all(self):
21
+ return self._table.scan().get('Items')
22
+
23
+ def upsert(self, key, attributes):
24
+ return self.put({**key, **attributes})
25
+
26
+
27
+ def filter_by(self, attribute: str, target_value: str):
28
+ return self._table.query(
29
+ FilterExpression=Key(attribute).eq(target_value),
30
+ ).get('Items')
31
+
32
+ def put(self, attributes: dict, condition: dict = None):
33
+ extra_args = {}
34
+ if condition:
35
+ extra_args['ConditionExpression'] = condition
36
+ return self._table.put_item(Item=attributes, **extra_args)
37
+
38
+
39
+ def update(self, key: str, attributes: dict):
40
+ return self._table.update_item(
41
+ Key=key,
42
+ UpdateExpression=self._update_expression(attributes),
43
+ ExpressionAttributeNames=self._expression_attribute_names(attributes),
44
+ ExpressionAttributeValues=self._expression_attribute_values(attributes),
45
+ ReturnValues=RETURN_VALUES,
46
+ )
47
+
48
+ def delete(self, key: dict):
49
+ return self._table.delete_item(Key=key)
50
+
51
+ def count(self) -> int:
52
+ return self._table.item_count
53
+
54
+ @classmethod
55
+ def _update_expression(cls, attributes):
56
+ return 'SET {param}'.format(
57
+ param=','.join(
58
+ '#{key}=:{key}'.format(
59
+ key=key,
60
+ )
61
+ for key in attributes
62
+ ),
63
+ )
64
+
65
+ @classmethod
66
+ def _expression_attribute_names(cls, attributes):
67
+ return {
68
+ '#{key}'.format(key=key): key for key in attributes
69
+ }
70
+
71
+ @classmethod
72
+ def _expression_attribute_values(cls, attributes):
73
+ return {
74
+ ':{key}'.format(key=key): attr for key, attr in attributes.items()
75
+ }
@@ -0,0 +1,14 @@
1
+ import json
2
+ import boto3
3
+
4
+
5
+ def invoke_lambda(function_name: str, payload: dict) -> dict | list | None:
6
+ client = boto3.client('lambda')
7
+
8
+ response = client.invoke(
9
+ FunctionName=function_name,
10
+ InvocationType='RequestResponse',
11
+ Payload=json.dumps(payload),
12
+ )
13
+
14
+ return json.loads(response['Payload'].read().decode('utf-8'))
@@ -0,0 +1,43 @@
1
+ from typing import Optional, List
2
+
3
+ from boto3.dynamodb.conditions import Key
4
+
5
+ from documente_shared.domain.entities.document import DocumentProcessing
6
+ from documente_shared.domain.enums.document import DocumentProcessingStatus
7
+ from documente_shared.domain.repositories.document import DocumentProcessingRepository
8
+
9
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
10
+
11
+
12
+ class DynamoDocumentProcessingRepository(
13
+ DynamoDBTable,
14
+ DocumentProcessingRepository,
15
+ ):
16
+ def find(self, digest: str, read_bytes: bool = False) -> Optional[DocumentProcessing]:
17
+ item = self.get(key={'digest': digest})
18
+ if item:
19
+ return DocumentProcessing.from_dict(item)
20
+ return None
21
+
22
+ def persist(self, instance: DocumentProcessing, read_bytes: bool = False) -> DocumentProcessing:
23
+ self.put(instance.to_simple_dict)
24
+ return instance
25
+
26
+ def remove(self, instance: DocumentProcessing):
27
+ self.delete(key={'digest': instance.digest})
28
+
29
+ def filter(self, statuses: List[DocumentProcessingStatus]) -> List[DocumentProcessing]:
30
+ items = []
31
+
32
+ for status in statuses:
33
+ response = self._table.query(
34
+ IndexName='status',
35
+ KeyConditionExpression=Key('status').eq(status.value),
36
+ )
37
+ status_items = response.get('Items', [])
38
+ items.extend(status_items)
39
+
40
+ return [
41
+ DocumentProcessing.from_dict(item)
42
+ for item in items
43
+ ]
@@ -0,0 +1,55 @@
1
+ from typing import Optional, List
2
+
3
+ from boto3.dynamodb.conditions import Key
4
+
5
+ from documente_shared.domain.entities.processing_case import ProcessingCase
6
+ from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
7
+ from documente_shared.domain.enums.common import DocumentViewFormat
8
+ from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
9
+
10
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
11
+
12
+
13
+ class DynamoProcessingCaseRepository(
14
+ DynamoDBTable,
15
+ ProcessingCaseRepository,
16
+ ):
17
+ def find(
18
+ self,
19
+ uuid: str,
20
+ include_items: bool = False,
21
+ include_items_bytes: bool = False,
22
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
23
+ ) -> Optional[ProcessingCase]:
24
+ item = self.get(key={'uuid': uuid})
25
+ if item:
26
+ return ProcessingCase.from_dict(item)
27
+ return None
28
+
29
+ def persist(
30
+ self,
31
+ instance: ProcessingCase,
32
+ persist_items: bool = False,
33
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
34
+ ) -> ProcessingCase:
35
+ self.put(instance.to_persist_dict)
36
+ return instance
37
+
38
+ def remove(self, instance: ProcessingCase):
39
+ self.delete(key={'uuid': instance.uuid})
40
+
41
+ def filter(self, filters: ProcessingCaseFilters) -> List[ProcessingCase]:
42
+ items = []
43
+
44
+ for status in filters.statuses:
45
+ response = self._table.query(
46
+ IndexName='status',
47
+ KeyConditionExpression=Key('status').eq(status.value),
48
+ )
49
+ status_items = response.get('Items', [])
50
+ items.extend(status_items)
51
+
52
+ return [
53
+ ProcessingCase.from_dict(item)
54
+ for item in items
55
+ ]
@@ -0,0 +1,70 @@
1
+ from typing import Optional, List
2
+
3
+ from boto3.dynamodb.conditions import Key
4
+
5
+ from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
6
+ from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
7
+ from documente_shared.domain.enums.common import DocumentViewFormat
8
+ from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
9
+
10
+ from documente_shared.infrastructure.dynamo_table import DynamoDBTable
11
+
12
+
13
+ class DynamoProcessingCaseItemRepository(
14
+ DynamoDBTable,
15
+ ProcessingCaseItemRepository,
16
+ ):
17
+ def find(
18
+ self,
19
+ uuid: str,
20
+ read_bytes: bool = False,
21
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
22
+ ) -> Optional[ProcessingCaseItem]:
23
+ item = self.get(key={'digest': uuid})
24
+ if item:
25
+ return ProcessingCaseItem.from_dict(item)
26
+ return None
27
+
28
+ def find_by_digest(
29
+ self,
30
+ digest: str,
31
+ read_bytes: bool = False,
32
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
33
+ ) -> Optional[ProcessingCaseItem]:
34
+ item = self.get(key={'digest': digest})
35
+ if item:
36
+ return ProcessingCaseItem.from_dict(item)
37
+ return None
38
+
39
+ def persist(
40
+ self,
41
+ instance: ProcessingCaseItem,
42
+ read_bytes: bool = False,
43
+ persist_bytes: bool = False,
44
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
45
+ ) -> ProcessingCaseItem:
46
+ self.put(instance.to_simple_dict)
47
+ return instance
48
+
49
+ def remove(self, instance: ProcessingCaseItem):
50
+ self.delete(key={'case_id': instance.case_id})
51
+
52
+ def filter(
53
+ self,
54
+ filters: ProcessingCaseItemFilters,
55
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
56
+ ) -> List[ProcessingCaseItem]:
57
+ items = []
58
+
59
+ for status in filters.statuses:
60
+ response = self._table.query(
61
+ IndexName='status',
62
+ KeyConditionExpression=Key('status').eq(status.value),
63
+ )
64
+ status_items = response.get('Items', [])
65
+ items.extend(status_items)
66
+
67
+ return [
68
+ ProcessingCaseItem.from_dict(item)
69
+ for item in items
70
+ ]
@@ -0,0 +1,66 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from loguru import logger
5
+ from requests import Response
6
+
7
+ from documente_shared.application.payloads import camel_to_snake
8
+ from documente_shared.application.query_params import parse_bool_to_str
9
+ from documente_shared.domain.entities.document import DocumentProcessing
10
+ from documente_shared.domain.enums.document import DocumentProcessingStatus
11
+ from documente_shared.domain.repositories.document import DocumentProcessingRepository
12
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
13
+
14
+
15
+ @dataclass
16
+ class HttpDocumentProcessingRepository(
17
+ DocumenteClientMixin,
18
+ DocumentProcessingRepository,
19
+ ):
20
+ def find(self, digest: str, read_bytes: bool = False) -> Optional[DocumentProcessing]:
21
+ params = {
22
+ "read_bytes": parse_bool_to_str(read_bytes),
23
+ }
24
+ response = self.session.get(
25
+ url=f"{self.api_url}/v1/documents/{digest}/",
26
+ params=params,
27
+ )
28
+ if response.status_code not in [200, 201]:
29
+ return None
30
+ return self._build_document_processing(response)
31
+
32
+ def persist(self, instance: DocumentProcessing, read_bytes: bool = False) -> DocumentProcessing:
33
+ logger.info(f"PERSISTING_DOCUMENT: data={instance.to_simple_dict}")
34
+ params = {
35
+ "read_bytes": parse_bool_to_str(read_bytes),
36
+ }
37
+ response = self.session.put(
38
+ url=f"{self.api_url}/v1/documents/{instance.digest}/",
39
+ params=params,
40
+ json=instance.to_simple_dict,
41
+ )
42
+ if response.status_code not in [200, 201]:
43
+ raise Exception(f'Error persisting document processing: {response.text}')
44
+ return self._build_document_processing(response)
45
+
46
+ def remove(self, instance: DocumentProcessing):
47
+ self.session.delete(f"{self.api_url}/v1/documents/{instance.digest}/")
48
+
49
+ def filter(self, statuses: List[DocumentProcessingStatus]) -> List[DocumentProcessing]:
50
+ response = self.session.get(f"{self.api_url}/v1/documents/?statuses={statuses}")
51
+ if response.status_code not in [200, 201]:
52
+ return []
53
+ raw_response = response.json()
54
+ return [
55
+ DocumentProcessing.from_dict(camel_to_snake(item['documentProcessing']))
56
+ for item in raw_response.get('data', [])
57
+ ]
58
+
59
+
60
+ @classmethod
61
+ def _build_document_processing(cls, response: Response) -> DocumentProcessing:
62
+ response_json = response.json()
63
+ instance_data = response_json.get('data', {})
64
+ return DocumentProcessing.from_dict(camel_to_snake(instance_data))
65
+
66
+
@@ -0,0 +1,82 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from loguru import logger
5
+ from requests import Response
6
+
7
+ from documente_shared.application.payloads import camel_to_snake
8
+ from documente_shared.application.query_params import parse_bool_to_str
9
+ from documente_shared.domain.entities.processing_case import ProcessingCase
10
+ from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
11
+ from documente_shared.domain.enums.common import DocumentViewFormat
12
+ from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
13
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
14
+
15
+
16
+ @dataclass
17
+ class HttpProcessingCaseRepository(
18
+ DocumenteClientMixin,
19
+ ProcessingCaseRepository,
20
+ ):
21
+ def find(
22
+ self,
23
+ uuid: str,
24
+ include_items: bool = False,
25
+ include_items_bytes: bool = False,
26
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
27
+ ) -> Optional[ProcessingCase]:
28
+ params = {
29
+ "view_format": str(view_format),
30
+ }
31
+ response = self.session.get(
32
+ url=f"{self.api_url}/v1/processing-cases/{uuid}/",
33
+ params=params,
34
+ )
35
+ if response.status_code not in [200, 201]:
36
+ return None
37
+ return self._build_processing_case(response)
38
+
39
+ def persist(
40
+ self,
41
+ instance: ProcessingCase,
42
+ persist_items: bool = False,
43
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
44
+ ) -> ProcessingCase:
45
+ logger.info(f"PERSISTING_PROCESSING_CASE: data={instance.to_queue_dict}")
46
+ params = {
47
+ "persist_items": parse_bool_to_str(persist_items),
48
+ "view_format": str(view_format),
49
+ }
50
+ response = self.session.put(
51
+ url=f"{self.api_url}/v1/processing-cases/{instance.uuid}/",
52
+ params=params,
53
+ json=instance.to_dict,
54
+ )
55
+ if response.status_code not in [200, 201]:
56
+ raise Exception(f'Error persisting processing case: {response.text}')
57
+ return self._build_processing_case(response)
58
+
59
+ def remove(self, instance: ProcessingCase):
60
+ self.session.delete(f"{self.api_url}/v1/processing-cases/{instance.uuid}/")
61
+
62
+ def filter(self, filters: ProcessingCaseFilters) -> List[ProcessingCase]:
63
+ response = self.session.get(
64
+ url=f"{self.api_url}/v1/processing-cases/",
65
+ headers={
66
+ "X-Tenant": filters.tenant_slug,
67
+ }
68
+ )
69
+ if response.status_code not in [200, 201]:
70
+ return []
71
+ raw_response = response.json()
72
+ return [
73
+ ProcessingCase.from_persist_dict(camel_to_snake(item_data))
74
+ for item_data in raw_response.get('data', [])
75
+ ]
76
+
77
+
78
+ @classmethod
79
+ def _build_processing_case(cls, response: Response) -> ProcessingCase:
80
+ response_json = response.json()
81
+ instance_data = response_json.get('data', {})
82
+ return ProcessingCase.from_persist_dict(camel_to_snake(instance_data))
@@ -0,0 +1,118 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from loguru import logger
5
+ from requests import Response
6
+
7
+ from documente_shared.application.payloads import camel_to_snake
8
+ from documente_shared.application.query_params import parse_bool_to_str
9
+ from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
10
+ from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
11
+ from documente_shared.domain.enums.common import DocumentViewFormat
12
+ from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
13
+ from documente_shared.infrastructure.documente_client import DocumenteClientMixin
14
+
15
+
16
+ @dataclass
17
+ class HttpProcessingCaseItemRepository(
18
+ DocumenteClientMixin,
19
+ ProcessingCaseItemRepository,
20
+ ):
21
+ def find(
22
+ self,
23
+ uuid: str,
24
+ read_bytes: bool = False,
25
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
26
+ ) -> Optional[ProcessingCaseItem]:
27
+ response = self.session.get(
28
+ url=f"{self.api_url}/v1/processing-case-items/{uuid}/?read_bytes={parse_bool_to_str(read_bytes)}",
29
+ )
30
+ if response.status_code not in [200, 201]:
31
+ return None
32
+ return self._build_processing_case_item(response)
33
+
34
+ def find_by_digest(
35
+ self,
36
+ digest: str,
37
+ read_bytes: bool = False,
38
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
39
+ ) -> Optional[ProcessingCaseItem]:
40
+ params = {
41
+ "read_bytes": parse_bool_to_str(read_bytes),
42
+ "view_format": str(view_format),
43
+ }
44
+ response = self.session.get(
45
+ url=f"{self.api_url}/v1/processing-case-items/{digest}/",
46
+ params=params,
47
+ )
48
+ if response.status_code not in [200, 201]:
49
+ return None
50
+ return self._build_processing_case_item(response)
51
+
52
+ def persist(
53
+ self,
54
+ instance: ProcessingCaseItem,
55
+ read_bytes: bool = False,
56
+ persist_bytes: bool = False,
57
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
58
+ ) -> ProcessingCaseItem:
59
+ logger.info(f"PERSISTING_PROCESSING_CASE_ITEM: data={instance.to_queue_dict}")
60
+ params = {
61
+ "read_bytes": parse_bool_to_str(read_bytes),
62
+ "view_format": str(view_format),
63
+ }
64
+ response: Response = self.session.put(
65
+ url=f"{self.api_url}/v1/processing-case-items/{instance.uuid}/",
66
+ params=params,
67
+ json=(
68
+ instance.to_persist_dict
69
+ if persist_bytes else instance.to_queue_dict
70
+ ),
71
+ )
72
+ if response.status_code not in [200, 201]:
73
+ logger.info(f"PERSISTING_PROCESSING_CASE_ITEM ERROR: data={response.text}")
74
+ return instance
75
+ return self._build_processing_case_item(response)
76
+
77
+ def remove(self, instance: ProcessingCaseItem):
78
+ self.session.delete(f"{self.api_url}/v1/processing-case-items/{instance.uuid}/")
79
+
80
+ def filter(
81
+ self,
82
+ filters: ProcessingCaseItemFilters,
83
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
84
+ ) -> List[ProcessingCaseItem]:
85
+ params = {
86
+ "view_format": str(view_format),
87
+ }
88
+ response = self.session.get(
89
+ url=f"{self.api_url}/v1/processing-case-items/",
90
+ params=params,
91
+ )
92
+ if response.status_code not in [200, 201]:
93
+ return []
94
+ raw_response = response.json()
95
+ return [
96
+ ProcessingCaseItem.from_dict(camel_to_snake(item_data))
97
+ for item_data in raw_response.get('data', [])
98
+ ]
99
+
100
+ def filter_with_tenant(
101
+ self,
102
+ tenant_slug: str,
103
+ filters: ProcessingCaseItemFilters,
104
+ ) -> List[ProcessingCaseItem]:
105
+ response = self.session.get(f"{self.api_url}/v1/processing-case-items/")
106
+ if response.status_code not in [200, 201]:
107
+ return []
108
+ raw_response = response.json()
109
+ return [
110
+ ProcessingCaseItem.from_dict(camel_to_snake(item_data))
111
+ for item_data in raw_response.get('data', [])
112
+ ]
113
+
114
+ @classmethod
115
+ def _build_processing_case_item(cls, response: Response) -> ProcessingCaseItem:
116
+ response_json = response.json()
117
+ instance_data = response_json.get('data', {})
118
+ return ProcessingCaseItem.from_dict(camel_to_snake(instance_data))
@@ -0,0 +1,46 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from documente_shared.domain.entities.document import DocumentProcessing
5
+ from documente_shared.domain.enums.common import DocumentViewFormat
6
+ from documente_shared.domain.enums.document import DocumentProcessingStatus
7
+ from documente_shared.domain.repositories.document import DocumentProcessingRepository
8
+
9
+
10
+ @dataclass
11
+ class MemoryDocumentProcessingRepository(DocumentProcessingRepository):
12
+ collection: dict[str, DocumentProcessing] = None
13
+
14
+ def __post_init__(self):
15
+ self.collection = self.collection or {}
16
+
17
+ def find(
18
+ self,
19
+ digest: str,
20
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
21
+ ) -> Optional[DocumentProcessing]:
22
+ if digest in self.collection:
23
+ return self.collection[digest]
24
+ return None
25
+
26
+
27
+ def persist(
28
+ self,
29
+ instance: DocumentProcessing,
30
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
31
+ ) -> DocumentProcessing:
32
+ self.collection[instance.digest] = instance
33
+ return instance
34
+
35
+ def remove(self, instance: DocumentProcessing):
36
+ if instance.digest in self.collection:
37
+ del self.collection[instance.digest]
38
+ return None
39
+
40
+ def filter(self, statuses: List[DocumentProcessingStatus]) -> List[DocumentProcessing]:
41
+ items = []
42
+ for status in statuses:
43
+ items.extend(
44
+ [item for item in self.collection.values() if item.status == status]
45
+ )
46
+ return items
@@ -0,0 +1,44 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from documente_shared.domain.entities.processing_case import ProcessingCase
5
+ from documente_shared.domain.entities.processing_case_filters import ProcessingCaseFilters
6
+ from documente_shared.domain.enums.common import DocumentViewFormat
7
+
8
+ from documente_shared.domain.repositories.processing_case import ProcessingCaseRepository
9
+
10
+
11
+ @dataclass
12
+ class MemoryProcessingCaseRepository(ProcessingCaseRepository):
13
+ collection: dict[str, ProcessingCase] = None
14
+
15
+ def __post_init__(self):
16
+ self.collection = self.collection or {}
17
+
18
+ def find(
19
+ self,
20
+ uuid: str,
21
+ include_items: bool = False,
22
+ include_items_bytes: bool = False,
23
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
24
+ ) -> Optional[ProcessingCase]:
25
+ if uuid in self.collection:
26
+ return self.collection[uuid]
27
+ return None
28
+
29
+ def persist(
30
+ self,
31
+ instance: ProcessingCase,
32
+ persist_items: bool = False,
33
+ view_format: DocumentViewFormat = DocumentViewFormat.PUBLIC_URL,
34
+ ) -> ProcessingCase:
35
+ self.collection[instance.uuid] = instance
36
+ return instance
37
+
38
+ def remove(self, instance: ProcessingCase):
39
+ if instance.uuid in self.collection:
40
+ del self.collection[instance.uuid]
41
+ return None
42
+
43
+ def filter(self, filters: ProcessingCaseFilters) -> List[ProcessingCase]:
44
+ return []
@@ -0,0 +1,52 @@
1
+ from dataclasses import dataclass
2
+ from typing import List, Optional
3
+
4
+ from documente_shared.domain.entities.processing_case_item import ProcessingCaseItem
5
+ from documente_shared.domain.entities.processing_case_item_filters import ProcessingCaseItemFilters
6
+
7
+ from documente_shared.domain.repositories.processing_case_item import ProcessingCaseItemRepository
8
+
9
+
10
+ @dataclass
11
+ class MemoryProcessingCaseItemRepository(ProcessingCaseItemRepository):
12
+ collection: dict[str, ProcessingCaseItem] = None
13
+
14
+ def __post_init__(self):
15
+ self.collection = self.collection or {}
16
+
17
+ def find(
18
+ self,
19
+ uuid: str,
20
+ read_items: bool = False,
21
+ ) -> Optional[ProcessingCaseItem]:
22
+ if uuid in self.collection:
23
+ return self.collection[uuid]
24
+ return None
25
+
26
+ def find_by_digest(
27
+ self,
28
+ digest: str,
29
+ read_bytes: bool = False
30
+ ) -> Optional[ProcessingCaseItem]:
31
+ for item in self.collection.values():
32
+ if item.digest == digest:
33
+ return item
34
+ return None
35
+
36
+
37
+ def persist(
38
+ self,
39
+ instance: ProcessingCaseItem,
40
+ read_bytes: bool = False,
41
+ persist_bytes: bool = False,
42
+ ) -> ProcessingCaseItem:
43
+ self.collection[instance.uuid] = instance
44
+ return instance
45
+
46
+ def remove(self, instance: ProcessingCaseItem):
47
+ if instance.uuid in self.collection:
48
+ del self.collection[instance.uuid]
49
+ return None
50
+
51
+ def filter(self, filters: ProcessingCaseItemFilters) -> List[ProcessingCaseItem]:
52
+ return []