File size: 5,670 Bytes
b4f2238
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"""Unit tests for ContractCloneWorkflow."""

from __future__ import annotations

import datetime
from unittest.mock import MagicMock, call, patch

import pytest

from apps.contracts.services.contract.admin.workflows.clone_workflow import ContractCloneWorkflow


def _make_workflow() -> tuple[ContractCloneWorkflow, MagicMock]:
    reminder_service = MagicMock()
    reminder_service.export_contract_reminders_internal.return_value = []
    workflow = ContractCloneWorkflow(reminder_service=reminder_service)
    return workflow, reminder_service


def _make_contract(*, parties: list[MagicMock], assignments: list[MagicMock], agreements: list[MagicMock]) -> MagicMock:
    contract = MagicMock()
    contract.id = 1
    contract.contract_parties.all.return_value = parties
    contract.assignments.all.return_value = assignments
    contract.supplementary_agreements.all.return_value = agreements
    return contract


def _make_target_contract() -> MagicMock:
    contract = MagicMock()
    contract.id = 2
    return contract


# โ”€โ”€ ๅฎŒๆ•ดๆต็จ‹ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

def test_clone_related_data_full_flow() -> None:
    party = MagicMock()
    party.client = MagicMock()
    party.role = "plaintiff"

    assignment = MagicMock()
    assignment.lawyer = MagicMock()
    assignment.is_primary = True
    assignment.order = 0

    agreement = MagicMock()
    agreement.name = "่กฅๅ……ๅ่ฎฎ1"
    agreement_party = MagicMock()
    agreement_party.client = MagicMock()
    agreement_party.role = "party"
    agreement.parties.all.return_value = [agreement_party]

    source = _make_contract(parties=[party], assignments=[assignment], agreements=[agreement])
    target = _make_target_contract()

    workflow, reminder_service = _make_workflow()

    with (
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractParty") as MockParty,
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractAssignment") as MockAssignment,
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.SupplementaryAgreement") as MockAgreement,
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.SupplementaryAgreementParty") as MockAgreementParty,
    ):
        MockAgreement.objects.bulk_create.return_value = [MagicMock()]
        workflow.clone_related_data(source_contract=source, target_contract=target)

    MockParty.objects.bulk_create.assert_called_once()
    MockAssignment.objects.bulk_create.assert_called_once()
    MockAgreement.objects.bulk_create.assert_called_once()
    MockAgreementParty.objects.bulk_create.assert_called_once()


# โ”€โ”€ ๆ— ่กฅๅ……ๅ่ฎฎ๏ผˆๆๅ‰ return๏ผ‰โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

def test_clone_related_data_no_agreements_skips_agreement_bulk_create() -> None:
    source = _make_contract(parties=[], assignments=[], agreements=[])
    target = _make_target_contract()

    workflow, _ = _make_workflow()

    with (
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractParty"),
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractAssignment"),
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.SupplementaryAgreement") as MockAgreement,
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.SupplementaryAgreementParty") as MockAgreementParty,
    ):
        workflow.clone_related_data(source_contract=source, target_contract=target)

    MockAgreement.objects.bulk_create.assert_not_called()
    MockAgreementParty.objects.bulk_create.assert_not_called()


# โ”€โ”€ due_at_transform ๅ‚ๆ•ฐ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

def test_clone_related_data_applies_due_at_transform() -> None:
    reminder = {"due_at": datetime.date(2025, 1, 1), "title": "ๆ้†’"}
    source = _make_contract(parties=[], assignments=[], agreements=[])
    target = _make_target_contract()

    workflow, reminder_service = _make_workflow()
    reminder_service.export_contract_reminders_internal.return_value = [reminder]

    transform = MagicMock(return_value=datetime.date(2026, 1, 1))

    with (
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractParty"),
        patch("apps.contracts.services.contract.admin.workflows.clone_workflow.ContractAssignment"),
    ):
        workflow.clone_related_data(source_contract=source, target_contract=target, due_at_transform=transform)

    transform.assert_called_once_with(datetime.date(2025, 1, 1))
    reminder_service.create_contract_reminders_internal.assert_called_once()


# โ”€โ”€ plus_one_year_due_at โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

def test_plus_one_year_due_at_adds_one_year() -> None:
    d = datetime.date(2024, 3, 15)
    result = ContractCloneWorkflow.plus_one_year_due_at(d)
    assert result == datetime.date(2025, 3, 15)


def test_plus_one_year_due_at_none_returns_none() -> None:
    assert ContractCloneWorkflow.plus_one_year_due_at(None) is None


def test_plus_one_year_due_at_falsy_returns_none() -> None:
    assert ContractCloneWorkflow.plus_one_year_due_at("") is None