Completed
Push — master ( 5594ea...e43a77 )
by Laurent
03:34 queued 01:39
created

CreateExpenseNoteCommandHandler::__invoke()   B

Complexity

Conditions 8
Paths 12

Size

Total Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
nc 12
nop 1
dl 0
loc 45
rs 7.9555
c 0
b 0
f 0
1
<?php
2
/**
3
 *
4
 */
5
6
namespace flightlog\command;
7
8
use DoliDB;
9
use Exception;
10
use ExpenseReport;
11
use ExpenseReportLine;
12
use flightlog\exceptions\NoMissionException;
13
use flightlog\model\missions\FlightMission;
14
use flightlog\query\FlightForQuarterAndPilotQuery;
15
use flightlog\query\FlightForQuarterAndPilotQueryHandler;
16
use flightlog\query\GetPilotsWithMissionsQuery;
17
use flightlog\query\GetPilotsWithMissionsQueryHandler;
18
use PilotMissions;
19
use stdClass;
20
use Translate;
21
use User;
22
use Webmozart\Assert\Assert;
23
24
/**
25
 * Create the expense not for flights.
26
 *
27
 * @author Laurent De Coninck <[email protected]>
28
 */
29
class CreateExpenseNoteCommandHandler
30
{
31
    const FLIGHT_ELEMENT = 'flightlog_bbcvols';
32
33
    /**
34
     * @var stdClass
35
     */
36
    protected $conf;
37
38
    /**
39
     * @var Translate
40
     */
41
    protected $langs;
42
43
    /**
44
     * @var User
45
     */
46
    protected $user;
47
48
    /**
49
     * @var DoliDB
50
     */
51
    protected $db;
52
53
    /**
54
     * @var GetPilotsWithMissionsQueryHandler
55
     */
56
    private $getMissionsQueryHandler;
57
58
    /**
59
     * @var FlightForQuarterAndPilotQueryHandler
60
     */
61
    private $flightForQuarterAndPilotHandler;
62
63
64
    /**
65
     * @param DoliDB                               $db
66
     * @param stdClass                             $conf
67
     * @param User                                 $user
68
     * @param Translate                            $langs
69
     * @param GetPilotsWithMissionsQueryHandler    $missionsQueryHandler
70
     * @param FlightForQuarterAndPilotQueryHandler $flightForQuarterAndPilotQueryHandler
71
     */
72
    public function __construct(
73
        $db,
74
        $conf,
75
        $user,
76
        $langs,
77
        GetPilotsWithMissionsQueryHandler $missionsQueryHandler,
78
        FlightForQuarterAndPilotQueryHandler $flightForQuarterAndPilotQueryHandler
79
    ) {
80
        $this->db = $db;
81
        $this->conf = $conf;
82
        $this->user = $user;
83
        $this->langs = $langs;
84
        $this->getMissionsQueryHandler = $missionsQueryHandler;
85
        $this->flightForQuarterAndPilotHandler = $flightForQuarterAndPilotQueryHandler;
86
    }
87
88
    /**
89
     * @param CreateExpenseNoteCommand $command
90
     *
91
     * @throws Exception
92
     */
93
    public function __invoke(CreateExpenseNoteCommand $command)
94
    {
95
        $missions = $this->getMissionsQueryHandler->__invoke(new GetPilotsWithMissionsQuery($command->getYear(),
96
            $command->getQuartile()));
97
98
        if (!$missions->hasMission()) {
99
            throw new NoMissionException();
100
        }
101
102
        /** @var PilotMissions $currentMission */
103
        foreach ($missions as $currentMission) {
104
            $expenseNote = $this->createExpenseNote($command);
105
            $expenseNoteId = $this->saveExpenseNote($currentMission->getPilotId(), $expenseNote);
106
            if ($expenseNoteId < 0) {
107
                dol_htmloutput_errors("Erreur lors de la création de la note de frais", $expenseNote->errors);
108
                continue;
109
            }
110
111
            $flightsForQuarter = $this->flightForQuarterAndPilotHandler->__invoke(new FlightForQuarterAndPilotQuery($currentMission->getPilotId(),
112
                $command->getQuartile(), $command->getYear()));
113
114
            $isFlightInError = false;
115
            /** @var FlightMission $currentFlightForQuarter */
116
            foreach ($flightsForQuarter as $currentFlightForQuarter) {
117
                $isFlightInError = $this->addFlight($currentFlightForQuarter, $expenseNote) || $isFlightInError;
118
            }
119
120
            if (!$isFlightInError) {
121
                $expenseNote->fetch($expenseNoteId);
122
                $expenseNote->setValidate($this->user);
123
                $expenseNote->setApproved($this->user);
124
125
                $expenseNote->fetch($expenseNoteId);
126
                $expenseNote->setDocModel($this->user, "standard");
127
                $error = $expenseNote->generateDocument($expenseNote->modelpdf, $this->langs) <= 0;
128
129
                if (!$error) {
130
                    dol_htmloutput_mesg(sprintf("Notes de frais crée pour %s", $currentMission->getPilotName()));
131
                    continue;
132
                }
133
            }
134
135
            dol_htmloutput_errors(sprintf("Notes de frais non crée pour %s", $currentMission->getPilotName()));
136
        }
137
    }
138
139
    /**
140
     * @param FlightMission $currentFlightForQuarter
141
     * @param int           $expenseNoteId
142
     *
143
     * @return boolean
144
     */
145
    private function addKilometersLine(FlightMission $currentFlightForQuarter, $expenseNoteId)
146
    {
147
        $object_ligne = new ExpenseReportLine($this->db);
148
        $object_ligne->comments = $this->langs->trans(sprintf("Vol (id: %d) %s à %s  détail: %s",
149
            $currentFlightForQuarter->getId(), $currentFlightForQuarter->getStartPoint(),
150
            $currentFlightForQuarter->getEndPoint(), $currentFlightForQuarter->getKilometersComment()));
151
        $object_ligne->qty = $currentFlightForQuarter->getNumberOfKilometers();
152
        $object_ligne->value_unit = $this->getAmountByKilometer();
153
154
        $object_ligne->date = $currentFlightForQuarter->getDate()->format('Y-m-d');
155
156
        $object_ligne->fk_c_type_fees = 2;
157
        $object_ligne->fk_expensereport = $expenseNoteId;
158
        $object_ligne->fk_projet = '';
159
160
        $object_ligne->vatrate = price2num($this->getVatRate());
161
162
        $tmp = calcul_price_total($object_ligne->qty, $object_ligne->value_unit, 0, $this->getVatRate(), 0, 0, 0, 'TTC',
163
            0,
164
            0, '');
165
        $object_ligne->total_ttc = $tmp[2];
166
        $object_ligne->total_ht = $tmp[0];
167
        $object_ligne->total_tva = $tmp[1];
168
169
        return $object_ligne->insert() > 0;
170
    }
171
172
    /**
173
     * @param FlightMission $currentFlightForQuarter
174
     * @param ExpenseReport $expenseReport
175
     *
176
     * @return bool
177
     */
178
    private function addMissionLine(FlightMission $currentFlightForQuarter, ExpenseReport $expenseReport)
179
    {
180
        $object_ligne = new ExpenseReportLine($this->db);
181
        $object_ligne->comments = sprintf("Vol (id: %d) %s à %s", $currentFlightForQuarter->getId(),
182
            $currentFlightForQuarter->getStartPoint(), $currentFlightForQuarter->getEndPoint());
183
        $object_ligne->qty = 1;
184
        $object_ligne->value_unit = $this->getAmountByMission();
185
186
        $object_ligne->date = $currentFlightForQuarter->getDate()->format('Y-m-d');
187
188
        $object_ligne->fk_c_type_fees = 8;
189
        $object_ligne->fk_expensereport = $expenseReport->id;
190
        $object_ligne->fk_projet = '';
191
192
        $object_ligne->vatrate = price2num($this->getVatRate());
193
194
        $tmp = calcul_price_total($object_ligne->qty, $object_ligne->value_unit, 0, $this->getVatRate(), 0, 0, 0, 'TTC',
195
            0,
196
            0, '');
197
        $object_ligne->total_ttc = $tmp[2];
198
        $object_ligne->total_ht = $tmp[0];
199
        $object_ligne->total_tva = $tmp[1];
200
201
        $isError = $object_ligne->insert() <= 0;
202
203
        if (!$isError) {
204
            $expenseReport->add_object_linked(self::FLIGHT_ELEMENT, $currentFlightForQuarter->getId());
205
        }
206
207
        return !$isError;
208
    }
209
210
    /**
211
     * @param FlightMission $currentFlightForQuarter
212
     * @param ExpenseReport $expenseNote
213
     *
214
     * @return boolean
215
     */
216
    private function addFlight(FlightMission $currentFlightForQuarter, ExpenseReport $expenseNote)
217
    {
218
        $error = false;
219
220
        $error = $this->addKilometersLine($currentFlightForQuarter, $expenseNote->id) && $error;
221
        $error = $this->addMissionLine($currentFlightForQuarter, $expenseNote) && $error;
222
223
        return $error;
224
    }
225
226
    /**
227
     * Get the unit price pe KM.
228
     *
229
     * @return int
230
     */
231
    private function getAmountByKilometer()
232
    {
233
        return isset($this->conf->global->BBC_FLIGHT_LOG_TAUX_REMB_KM) ? $this->conf->global->BBC_FLIGHT_LOG_TAUX_REMB_KM : 0;
234
    }
235
236
    /**
237
     * @return mixed
238
     */
239
    private function getAmountByMission()
240
    {
241
        return $this->conf->global->BBC_FLIGHT_LOG_UNIT_PRICE_MISSION;
242
    }
243
244
    /**
245
     * @return string
246
     */
247
    private function getVatRate()
248
    {
249
        return '0.000';
250
    }
251
252
    /**
253
     * @param CreateExpenseNoteCommand $command
254
     *
255
     * @return ExpenseReport
256
     * @throws Exception
257
     */
258
    private function createExpenseNote(CreateExpenseNoteCommand $command)
259
    {
260
        $startDate = new \DateTime();
261
        $startDate->setDate($command->getYear(), (($command->getQuartile() - 1) * 3) + 1, 1);
262
263
        $endDate = new \DateTime();
264
        $endDate->setDate($command->getYear(), $command->getQuartile() * 3, 1);
265
        $endDate->add(new \DateInterval("P1M"))->sub(new \DateInterval("P1D"));
266
267
        $object = new ExpenseReport($this->db);
268
        $object->date_debut = $startDate->format("Y-m-d");
269
        $object->date_fin = $endDate->format("Y-m-d");
270
271
        $object->fk_statut = 1;
272
        $object->fk_user_validator = $command->getUserValidatorId();
273
        $object->note_public = $command->getPublicNote();
274
        $object->note_private = $command->getPrivateNote();
275
276
        return $object;
277
    }
278
279
    /**
280
     * @param int           $currentMissionUserId
281
     * @param ExpenseReport $expenseNote
282
     *
283
     * @return mixed
284
     */
285
    private function saveExpenseNote($currentMissionUserId, ExpenseReport $expenseNote)
286
    {
287
        Assert::integerish($currentMissionUserId);
288
289
        $expenseNoteUser = new User($this->db);
290
        $expenseNoteUser->id = $currentMissionUserId;
291
        return $expenseNote->create($expenseNoteUser);
292
    }
293
294
}