2024-08-11 00:10:27 +03:00
|
|
|
''' Models: Change propagation facade - managing all changes in OSS. '''
|
2024-10-28 14:52:30 +03:00
|
|
|
from typing import Optional
|
|
|
|
|
|
2025-11-08 19:32:42 +03:00
|
|
|
from apps.library.models import LibraryItem
|
2025-08-21 21:26:40 +03:00
|
|
|
from apps.rsform.models import Attribution, Constituenta, CstType, RSFormCached
|
2024-08-11 00:10:27 +03:00
|
|
|
|
2025-08-01 18:31:23 +03:00
|
|
|
from .OperationSchemaCached import CstSubstitution, OperationSchemaCached
|
2024-08-11 00:10:27 +03:00
|
|
|
|
|
|
|
|
|
2025-11-08 19:32:42 +03:00
|
|
|
def _get_oss_hosts(schemaID: int) -> list[int]:
|
|
|
|
|
''' Get all hosts for schema. '''
|
|
|
|
|
return list(LibraryItem.objects.filter(operations__result_id=schemaID).values_list('pk', flat=True))
|
2024-08-11 00:10:27 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
class PropagationFacade:
|
|
|
|
|
''' Change propagation API. '''
|
|
|
|
|
|
2025-11-08 19:32:42 +03:00
|
|
|
_oss: dict[int, OperationSchemaCached] = {}
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def get_oss(schemaID: int) -> OperationSchemaCached:
|
|
|
|
|
''' Get OperationSchemaCached for schemaID. '''
|
|
|
|
|
if schemaID not in PropagationFacade._oss:
|
|
|
|
|
PropagationFacade._oss[schemaID] = OperationSchemaCached(schemaID)
|
|
|
|
|
return PropagationFacade._oss[schemaID]
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def reset_cache() -> None:
|
|
|
|
|
''' Reset cache. '''
|
|
|
|
|
PropagationFacade._oss = {}
|
|
|
|
|
|
2024-08-13 23:37:32 +03:00
|
|
|
@staticmethod
|
2025-08-01 10:43:51 +03:00
|
|
|
def after_create_cst(source: RSFormCached, new_cst: list[Constituenta],
|
|
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2025-04-16 11:18:27 +03:00
|
|
|
''' Trigger cascade resolutions when new constituenta is created. '''
|
2025-11-08 19:32:42 +03:00
|
|
|
hosts = _get_oss_hosts(source.pk)
|
2024-08-11 00:10:27 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).after_create_cst(source, new_cst)
|
2024-08-11 00:10:27 +03:00
|
|
|
|
2024-08-13 23:37:32 +03:00
|
|
|
@staticmethod
|
2025-08-03 15:28:16 +03:00
|
|
|
def after_change_cst_type(sourceID: int, target: int, new_type: CstType,
|
|
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2024-08-11 00:10:27 +03:00
|
|
|
''' Trigger cascade resolutions when constituenta type is changed. '''
|
2025-08-03 15:28:16 +03:00
|
|
|
hosts = _get_oss_hosts(sourceID)
|
2024-08-11 00:10:27 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).after_change_cst_type(sourceID, target, new_type)
|
2024-08-11 00:10:27 +03:00
|
|
|
|
2024-08-13 23:37:32 +03:00
|
|
|
@staticmethod
|
2024-10-28 14:52:30 +03:00
|
|
|
def after_update_cst(
|
2025-08-01 10:43:51 +03:00
|
|
|
source: RSFormCached,
|
2025-08-03 15:28:16 +03:00
|
|
|
target: int,
|
2024-10-28 14:52:30 +03:00
|
|
|
data: dict,
|
|
|
|
|
old_data: dict,
|
|
|
|
|
exclude: Optional[list[int]] = None
|
|
|
|
|
) -> None:
|
2024-08-11 00:10:27 +03:00
|
|
|
''' Trigger cascade resolutions when constituenta data is changed. '''
|
2025-11-08 19:32:42 +03:00
|
|
|
hosts = _get_oss_hosts(source.pk)
|
2024-08-11 00:10:27 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).after_update_cst(source, target, data, old_data)
|
2024-08-11 00:10:27 +03:00
|
|
|
|
2024-08-13 23:37:32 +03:00
|
|
|
@staticmethod
|
2025-08-03 15:28:16 +03:00
|
|
|
def before_delete_cst(sourceID: int, target: list[int],
|
2025-08-01 10:43:51 +03:00
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2024-08-11 00:10:27 +03:00
|
|
|
''' Trigger cascade resolutions before constituents are deleted. '''
|
2025-08-03 15:28:16 +03:00
|
|
|
hosts = _get_oss_hosts(sourceID)
|
2024-08-11 12:37:18 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).before_delete_cst(sourceID, target)
|
2024-08-12 16:51:24 +03:00
|
|
|
|
2024-08-13 23:37:32 +03:00
|
|
|
@staticmethod
|
2025-08-03 11:37:27 +03:00
|
|
|
def before_substitute(sourceID: int, substitutions: CstSubstitution,
|
2025-08-01 10:43:51 +03:00
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2024-08-12 16:51:24 +03:00
|
|
|
''' Trigger cascade resolutions before constituents are substituted. '''
|
2025-08-10 12:40:23 +03:00
|
|
|
if not substitutions:
|
2025-08-03 11:37:27 +03:00
|
|
|
return
|
|
|
|
|
hosts = _get_oss_hosts(sourceID)
|
2024-08-12 16:51:24 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).before_substitute(sourceID, substitutions)
|
2024-08-15 23:23:10 +03:00
|
|
|
|
|
|
|
|
@staticmethod
|
2025-11-08 19:32:42 +03:00
|
|
|
def before_delete_schema(target: int, exclude: Optional[list[int]] = None) -> None:
|
2024-08-15 23:23:10 +03:00
|
|
|
''' Trigger cascade resolutions before schema is deleted. '''
|
2025-11-08 19:32:42 +03:00
|
|
|
hosts = _get_oss_hosts(target)
|
2025-08-10 12:40:23 +03:00
|
|
|
if not hosts:
|
2024-08-15 23:23:10 +03:00
|
|
|
return
|
|
|
|
|
|
2025-11-08 19:32:42 +03:00
|
|
|
ids = list(Constituenta.objects.filter(schema_id=target).order_by('order').values_list('pk', flat=True))
|
2025-08-10 12:40:23 +03:00
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).before_delete_cst(target, ids)
|
|
|
|
|
del PropagationFacade._oss[host]
|
2025-08-12 20:31:35 +03:00
|
|
|
|
|
|
|
|
@staticmethod
|
2025-11-08 19:32:42 +03:00
|
|
|
def after_create_attribution(sourceID: int,
|
|
|
|
|
attributions: list[Attribution],
|
2025-08-12 20:31:35 +03:00
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2025-08-21 21:26:40 +03:00
|
|
|
''' Trigger cascade resolutions when Attribution is created. '''
|
2025-08-12 20:31:35 +03:00
|
|
|
hosts = _get_oss_hosts(sourceID)
|
|
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).after_create_attribution(sourceID, attributions)
|
2025-08-12 20:31:35 +03:00
|
|
|
|
|
|
|
|
@staticmethod
|
2025-08-21 21:26:40 +03:00
|
|
|
def before_delete_attribution(sourceID: int,
|
2025-11-07 00:06:06 +03:00
|
|
|
attributions: list[Attribution],
|
2025-08-12 20:31:35 +03:00
|
|
|
exclude: Optional[list[int]] = None) -> None:
|
2025-08-21 21:26:40 +03:00
|
|
|
''' Trigger cascade resolutions before Attribution is deleted. '''
|
2025-08-12 20:31:35 +03:00
|
|
|
hosts = _get_oss_hosts(sourceID)
|
|
|
|
|
for host in hosts:
|
2025-11-08 19:32:42 +03:00
|
|
|
if exclude is None or host not in exclude:
|
|
|
|
|
PropagationFacade.get_oss(host).before_delete_attribution(sourceID, attributions)
|