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.
- documente_shared/__init__.py +0 -0
- documente_shared/application/__init__.py +0 -0
- documente_shared/application/dates.py +7 -0
- documente_shared/application/digest.py +7 -0
- documente_shared/application/exceptions.py +23 -0
- documente_shared/application/files.py +27 -0
- documente_shared/application/json.py +45 -0
- documente_shared/application/numbers.py +7 -0
- documente_shared/application/payloads.py +29 -0
- documente_shared/application/query_params.py +133 -0
- documente_shared/application/retry_utils.py +69 -0
- documente_shared/application/time_utils.py +13 -0
- documente_shared/application/timezone.py +7 -0
- documente_shared/domain/__init__.py +0 -0
- documente_shared/domain/base_enum.py +54 -0
- documente_shared/domain/constants.py +8 -0
- documente_shared/domain/entities/__init__.py +0 -0
- documente_shared/domain/entities/document.py +410 -0
- documente_shared/domain/entities/document_metadata.py +64 -0
- documente_shared/domain/entities/in_memory_document.py +75 -0
- documente_shared/domain/entities/processing_case.py +215 -0
- documente_shared/domain/entities/processing_case_filters.py +51 -0
- documente_shared/domain/entities/processing_case_item.py +300 -0
- documente_shared/domain/entities/processing_case_item_filters.py +54 -0
- documente_shared/domain/entities/processing_documents.py +11 -0
- documente_shared/domain/entities/processing_event.py +71 -0
- documente_shared/domain/entities/scaling.py +31 -0
- documente_shared/domain/enums/__init__.py +0 -0
- documente_shared/domain/enums/circular_oficio.py +29 -0
- documente_shared/domain/enums/common.py +133 -0
- documente_shared/domain/enums/document.py +124 -0
- documente_shared/domain/enums/document_type_record.py +13 -0
- documente_shared/domain/enums/processing_case.py +66 -0
- documente_shared/domain/exceptions.py +5 -0
- documente_shared/domain/interfaces/__init__.py +0 -0
- documente_shared/domain/interfaces/scaling.py +10 -0
- documente_shared/domain/repositories/__init__.py +0 -0
- documente_shared/domain/repositories/document.py +24 -0
- documente_shared/domain/repositories/processing_case.py +36 -0
- documente_shared/domain/repositories/processing_case_item.py +49 -0
- documente_shared/infrastructure/__init__.py +0 -0
- documente_shared/infrastructure/documente_client.py +27 -0
- documente_shared/infrastructure/dynamo_table.py +75 -0
- documente_shared/infrastructure/lambdas.py +14 -0
- documente_shared/infrastructure/repositories/__init__.py +0 -0
- documente_shared/infrastructure/repositories/dynamo_document.py +43 -0
- documente_shared/infrastructure/repositories/dynamo_processing_case.py +55 -0
- documente_shared/infrastructure/repositories/dynamo_processing_case_item.py +70 -0
- documente_shared/infrastructure/repositories/http_document.py +66 -0
- documente_shared/infrastructure/repositories/http_processing_case.py +82 -0
- documente_shared/infrastructure/repositories/http_processing_case_item.py +118 -0
- documente_shared/infrastructure/repositories/mem_document.py +46 -0
- documente_shared/infrastructure/repositories/mem_processing_case.py +44 -0
- documente_shared/infrastructure/repositories/mem_processing_case_item.py +52 -0
- documente_shared/infrastructure/s3_bucket.py +58 -0
- documente_shared/infrastructure/services/__init__.py +0 -0
- documente_shared/infrastructure/services/http_scaling.py +25 -0
- documente_shared/infrastructure/sqs_queue.py +48 -0
- documente_shared/presentation/__init__.py +0 -0
- documente_shared/presentation/presenters.py +16 -0
- documente_shared-0.1.145.dist-info/METADATA +39 -0
- documente_shared-0.1.145.dist-info/RECORD +63 -0
- 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'))
|
|
File without changes
|
|
@@ -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 []
|