Jacek Kowalski
2022-08-14 48693f7ddc7438cf59100c12184e202a053a9614
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
<?php
 
namespace SIPL\UCRM\wFirma;
 
use \Webit\WFirmaSDK\Invoices as Invoices;
use \Webit\WFirmaSDK\Payments as Payments;
 
class PaymentSynchronizer {
    protected $wfirma;
    protected $helper;
    protected $ucrmMainDir;
 
    function __construct(\Webit\WFirmaSDK\Entity\ModuleApiFactory $wFirmaApi, UcrmHelper $ucrmHelper) {
        $this->wfirma = $wFirmaApi;
        $this->helper = $ucrmHelper;
 
        $backtrace = debug_backtrace();
        $backtrace = end($backtrace);
        // (...)/web/_plugins/wfirma/public.php
        $this->ucrmMainDir = dirname(dirname(dirname(dirname($backtrace['file']))));
    }
 
    function comparePayment(Payments\Payment $p1, Payments\Payment $p2) {
        return
            [$p1->objectName(), $p1->objectId(), $p1->amount()->value(), $p1->date()->format('Y-m-d'), $p1->paymentMethod()]
            <=>
            [$p2->objectName(), $p2->objectId(), $p2->amount()->value(), $p2->date()->format('Y-m-d'), $p2->paymentMethod()];
    }
 
    function synchronize($ucrmPaymentId) {
        $crm = $this->helper->getApi();
        $wFirmaPaymentsApi = $this->wfirma->paymentsApi();
 
        $invoiceAttributeId = $this->helper->getAttributes()->getIdForCode('invoice');
        $paymentAttributeId = $this->helper->getAttributes()->getIdForCode('payment');
 
        $paymentData = $crm->get('/payments/' . $ucrmPaymentId);
 
        $paymentDate = \DateTime::createFromFormat(\DateTimeInterface::ATOM, $paymentData['createdDate']);
        if ($paymentData['providerPaymentTime']) {
            $paymentDate = \DateTime::createFromFormat(\DateTimeInterface::ATOM, $paymentData['providerPaymentTime']);
        }
 
        $paymentMethod = Payments\PaymentMethod::transfer();
        switch ($paymentData['methodId'] ?? $paymentData['method']) {
            case 2:
            case '6efe0fa8-36b2-4dd1-b049-427bffc7d369':
                $paymentMethod = Payments\PaymentMethod::cash();
                break;
            case $this->helper->getPaymentMethods()->get('Compensation'):
                $paymentMethod = Payments\PaymentMethod::compensation();
                break;
            case $this->helper->getPaymentMethods()->get('Credit card'):
                $paymentMethod = Payments\PaymentMethod::paymentCard();
                break;
        }
 
        $expectedPayments = [];
        foreach ($paymentData['paymentCovers'] as $covered) {
            if (!$covered['invoiceId']) {
                continue;
            }
 
            $invoiceData = $crm->get('/invoices/' . $covered['invoiceId']);
            $wFirmaInvoiceId = NULL;
            foreach ($invoiceData['attributes'] as $attribute) {
                if ($attribute['customAttributeId'] === $invoiceAttributeId) {
                    $wFirmaInvoiceId = $attribute['value'];
                }
            }
 
            if (!$wFirmaInvoiceId) {
                continue;
            }
 
            $expectedPayments[] = Payments\Payment::forInvoiceOfId(
                Invoices\InvoiceId::create($wFirmaInvoiceId),
                Payments\PaymentAmount::forCurrencyAccount($covered['amount']),
                $paymentDate,
                $paymentMethod
            );
        }
        /** @var Payments\Payment[] $expectedPayments */
 
        $wFirmaIds = '';
        foreach ($paymentData['attributes'] as $attribute) {
            if ($attribute['customAttributeId'] === $paymentAttributeId) {
                $wFirmaIds = $attribute['value'];
            }
        }
        if (strlen($wFirmaIds) > 0) {
            $wFirmaIds = explode(',', $wFirmaIds);
        } else {
            $wFirmaIds = [];
        }
 
        $existingPayments = [];
        $wFirmaPaymentIds = [];
 
        foreach ($wFirmaIds as $id) {
            $payment = $wFirmaPaymentsApi->get(
                Payments\PaymentId::create($id)
            );
            $existingPayments[] = $payment;
        }
        /** @var Payments\Payment[] $existingPayments */
 
 
        $changed = FALSE;
 
        foreach ($existingPayments as $o1 => $p1) {
            foreach ($expectedPayments as $o2 => $p2) {
                if ($this->comparePayment($p1, $p2) === 0) {
                    unset($existingPayments[$o1]);
                    unset($expectedPayments[$o2]);
                    $wFirmaPaymentIds[] = (string)$p1->id()->id();
                    break;
                }
            }
        }
 
        foreach ($existingPayments as $o1 => $p1) {
            foreach ($expectedPayments as $o2 => $p2) {
                if ($p1->objectName() === $p2->objectName() && $p1->objectId() === $p2->objectId()) {
                    if ($p1->amount()->value() != $p2->amount()->value()) {
                        $p1->changeAmount($p2->amount());
                    }
                    if ($p1->date()->format('Y-m-d') != $p2->date()->format('Y-m-d')) {
                        $p1->changeDate($p2->date());
                    }
                    if ($p1->paymentMethod() != $p2->paymentMethod()) {
                        $p1->changePaymentMethod($p2->paymentMethod());
                    }
 
                    $p1 = $wFirmaPaymentsApi->edit($p1);
                    $changed = TRUE;
 
                    unset($existingPayments[$o1]);
                    unset($expectedPayments[$o2]);
                    $wFirmaPaymentIds[] = (string)$p1->id()->id();
                    break;
                }
            }
        }
 
        foreach ($existingPayments as $o1 => $p1) {
            $wFirmaPaymentsApi->delete($p1->id());
            $changed = TRUE;
        }
 
        foreach ($expectedPayments as $o2 => $p2) {
            $p2 = $wFirmaPaymentsApi->add($p2);
            $wFirmaPaymentIds[] = (string)$p2->id()->id();
            $changed = TRUE;
        }
 
        sort($wFirmaPaymentIds);
 
        if ($wFirmaIds != $wFirmaPaymentIds) {
            $crm->patch(
                '/payments/' . $ucrmPaymentId,
                [
                    'attributes' => [
                        [
                            'customAttributeId' => $paymentAttributeId,
                            'value' => join(',', $wFirmaPaymentIds),
                        ],
                    ],
                ]
            );
            $changed = TRUE;
        }
 
        return $changed;
    }
}