Issues (2811)

public/htdocs/loan/card.php (3 issues)

1
<?php
2
3
/* Copyright (C) 2014-2023  Alexandre Spangaro          <[email protected]>
4
 * Copyright (C) 2015       Frederic France             <[email protected]>
5
 * Copyright (C) 2017       Laurent Destailleur         <[email protected]>
6
 * Copyright (C) 2020       Maxime DEMAREST             <[email protected]>
7
 * Copyright (C) 2024       Rafael San José             <[email protected]>
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 3 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21
 */
22
23
use Dolibarr\Code\Accountancy\Classes\AccountingAccount;
24
use Dolibarr\Code\Compta\Classes\Account;
25
use Dolibarr\Code\Core\Classes\DolEditor;
26
use Dolibarr\Code\Core\Classes\Form;
27
use Dolibarr\Code\Core\Classes\FormAccounting;
28
use Dolibarr\Code\Core\Classes\FormProjets;
29
use Dolibarr\Code\Loan\Classes\Loan;
30
use Dolibarr\Code\Projet\Classes\Project;
31
use Dolibarr\Lib\ViewMain;
32
33
/**
34
 *   \file
35
 * htdocs/loan/card.php
36
 *   \ingroup    loan
37
 *   \brief      Loan card
38
 */
39
40
// Load Dolibarr environment
41
require constant('DOL_DOCUMENT_ROOT') . '/main.inc.php';
42
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/date.lib.php';
43
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/files.lib.php';
44
require_once constant('DOL_DOCUMENT_ROOT') . '/core/lib/loan.lib.php';
45
46
// Load translation files required by the page
47
$langs->loadLangs(array("bills", "compta", "loan"));
48
49
$id = GETPOSTINT('id');
50
$action = GETPOST('action', 'aZ09');
51
$confirm = GETPOST('confirm');
52
$cancel = GETPOST('cancel', 'alpha');
53
54
$projectid = GETPOSTINT('projectid');
55
56
// Security check
57
$socid = GETPOSTINT('socid');
58
if ($user->socid) {
59
    $socid = $user->socid;
60
}
61
$result = restrictedArea($user, 'loan', $id, '', '');
62
63
$object = new Loan($db);
64
65
$hookmanager->initHooks(array('loancard', 'globalcard'));
66
67
$error = 0;
68
69
70
/*
71
 * Actions
72
 */
73
74
$parameters = array();
75
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
76
if ($reshook < 0) {
77
    setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
78
}
79
if (empty($reshook)) {
80
    // Classify paid
81
    if ($action == 'confirm_paid' && $confirm == 'yes' && $user->hasRight('loan', 'write')) {
82
        $object->fetch($id);
83
        $result = $object->setPaid($user);
84
        if ($result > 0) {
85
            setEventMessages($langs->trans('LoanPaid'), null, 'mesgs');
86
        } else {
87
            setEventMessages($loan->error, null, 'errors');
88
        }
89
    }
90
91
    // Delete loan
92
    if ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('loan', 'write')) {
93
        $object->fetch($id);
94
        $result = $object->delete($user);
95
        if ($result > 0) {
96
            setEventMessages($langs->trans('LoanDeleted'), null, 'mesgs');
97
            header("Location: list.php");
98
            exit;
99
        } else {
100
            setEventMessages($loan->error, null, 'errors');
101
        }
102
    }
103
104
    // Add loan
105
    if ($action == 'add' && $user->hasRight('loan', 'write')) {
106
        if (!$cancel) {
107
            $datestart = dol_mktime(12, 0, 0, GETPOSTINT('startmonth'), GETPOSTINT('startday'), GETPOSTINT('startyear'));
108
            $dateend = dol_mktime(12, 0, 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
109
            $capital = price2num(GETPOST('capital'));
110
            $rate = price2num(GETPOST('rate'));
111
112
            if (!$capital) {
113
                $error++;
114
                $action = 'create';
115
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("LoanCapital")), null, 'errors');
116
            }
117
            if (!$datestart) {
118
                $error++;
119
                $action = 'create';
120
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DateStart")), null, 'errors');
121
            }
122
            if (!$dateend) {
123
                $error++;
124
                $action = 'create';
125
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("DateEnd")), null, 'errors');
126
            }
127
            if ($rate == '') {
128
                $error++;
129
                $action = 'create';
130
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Rate")), null, 'errors');
131
            }
132
133
            if (!$error) {
134
                $object->label = GETPOST('label');
0 ignored issues
show
Documentation Bug introduced by
It seems like GETPOST('label') can also be of type array or array or array. However, the property $label is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
135
                $object->fk_bank = GETPOSTINT('accountid');
136
                $object->capital = $capital;
137
                $object->datestart = $datestart;
138
                $object->dateend = $dateend;
139
                $object->nbterm = GETPOST('nbterm');
140
                $object->rate = $rate;
141
                $object->note_private = GETPOST('note_private', 'restricthtml');
0 ignored issues
show
Documentation Bug introduced by
It seems like GETPOST('note_private', 'restricthtml') can also be of type array or array or array. However, the property $note_private is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
142
                $object->note_public = GETPOST('note_public', 'restricthtml');
0 ignored issues
show
Documentation Bug introduced by
It seems like GETPOST('note_public', 'restricthtml') can also be of type array or array or array. However, the property $note_public is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
143
                $object->fk_project = GETPOSTINT('projectid');
144
                $object->insurance_amount = GETPOSTINT('insurance_amount');
145
146
                $accountancy_account_capital = GETPOST('accountancy_account_capital');
147
                $accountancy_account_insurance = GETPOST('accountancy_account_insurance');
148
                $accountancy_account_interest = GETPOST('accountancy_account_interest');
149
150
                if ($accountancy_account_capital <= 0) {
151
                    $object->account_capital = '';
152
                } else {
153
                    $object->account_capital = $accountancy_account_capital;
154
                }
155
                if ($accountancy_account_insurance <= 0) {
156
                    $object->account_insurance = '';
157
                } else {
158
                    $object->account_insurance = $accountancy_account_insurance;
159
                }
160
                if ($accountancy_account_interest <= 0) {
161
                    $object->account_interest = '';
162
                } else {
163
                    $object->account_interest = $accountancy_account_interest;
164
                }
165
166
                $id = $object->create($user);
167
                if ($id <= 0) {
168
                    $error++;
169
                    setEventMessages($object->error, $object->errors, 'errors');
170
                    $action = 'create';
171
                }
172
            }
173
        } else {
174
            header("Location: list.php");
175
            exit();
176
        }
177
    } elseif ($action == 'update' && $user->hasRight('loan', 'write')) {
178
        // Update record
179
        if (!$cancel) {
180
            $result = $object->fetch($id);
181
182
            $datestart = dol_mktime(12, 0, 0, GETPOSTINT('startmonth'), GETPOSTINT('startday'), GETPOSTINT('startyear'));
183
            $dateend = dol_mktime(12, 0, 0, GETPOSTINT('endmonth'), GETPOSTINT('endday'), GETPOSTINT('endyear'));
184
            $capital = price2num(GETPOST('capital'));
185
186
            if (!$capital) {
187
                setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("LoanCapital")), null, 'errors');
188
                $action = 'edit';
189
            } else {
190
                $object->datestart = $datestart;
191
                $object->dateend = $dateend;
192
                $object->capital = $capital;
193
                $object->nbterm = GETPOSTINT("nbterm");
194
                $object->rate = price2num(GETPOST("rate", 'alpha'));
195
                $object->insurance_amount = price2num(GETPOSTINT('insurance_amount'));
196
197
                $accountancy_account_capital = GETPOST('accountancy_account_capital');
198
                $accountancy_account_insurance = GETPOST('accountancy_account_insurance');
199
                $accountancy_account_interest = GETPOST('accountancy_account_interest');
200
201
                if ($accountancy_account_capital <= 0) {
202
                    $object->account_capital = '';
203
                } else {
204
                    $object->account_capital = $accountancy_account_capital;
205
                }
206
                if ($accountancy_account_insurance <= 0) {
207
                    $object->account_insurance = '';
208
                } else {
209
                    $object->account_insurance = $accountancy_account_insurance;
210
                }
211
                if ($accountancy_account_interest <= 0) {
212
                    $object->account_interest = '';
213
                } else {
214
                    $object->account_interest = $accountancy_account_interest;
215
                }
216
            }
217
218
            $result = $object->update($user);
219
220
            if ($result > 0) {
221
                header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
222
                exit;
223
            } else {
224
                $error++;
225
                setEventMessages($object->error, $object->errors, 'errors');
226
            }
227
        } else {
228
            header("Location: " . $_SERVER["PHP_SELF"] . "?id=" . $id);
229
            exit;
230
        }
231
    }
232
233
    // Link to a project
234
    if ($action == 'classin' && $user->hasRight('loan', 'write')) {
235
        $object->fetch($id);
236
        $result = $object->setProject($projectid);
237
        if ($result < 0) {
238
            setEventMessages($object->error, $object->errors, 'errors');
239
        }
240
    }
241
242
    if ($action == 'setlabel' && $user->hasRight('loan', 'write')) {
243
        $object->fetch($id);
244
        $result = $object->setValueFrom('label', GETPOST('label'), '', '', 'text', '', $user, 'LOAN_MODIFY');
245
        if ($result < 0) {
246
            setEventMessages($object->error, $object->errors, 'errors');
247
        }
248
    }
249
250
    // Actions to build doc
251
    include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
252
}
253
254
/*
255
 * View
256
 */
257
258
$form = new Form($db);
259
$formproject = new FormProjets($db);
260
$morehtmlstatus = '';
261
$outputlangs = $langs;
262
if (isModEnabled('accounting')) {
263
    $formaccounting = new FormAccounting($db);
264
}
265
266
$title = $langs->trans("Loan") . ' - ' . $langs->trans("Card");
267
$help_url = 'EN:Module_Loan|FR:Module_Emprunt';
268
ViewMain::llxHeader("", $title, $help_url);
269
270
// Create mode
271
if ($action == 'create') {
272
    //WYSIWYG Editor
273
274
    print load_fiche_titre($langs->trans("NewLoan"), '', 'money-bill-alt');
275
276
    $datec = dol_mktime(12, 0, 0, GETPOSTINT('remonth'), GETPOSTINT('reday'), GETPOSTINT('reyear'));
277
278
    print '<form name="loan" method="POST" action="' . $_SERVER["PHP_SELF"] . '">' . "\n";
279
    print '<input type="hidden" name="token" value="' . newToken() . '">';
280
    print '<input type="hidden" name="action" value="add">';
281
282
    print dol_get_fiche_head();
283
284
    print '<table class="border centpercent">';
285
286
    // Label
287
    print '<tr><td class="fieldrequired titlefieldcreate">' . $langs->trans("Label") . '</td><td><input name="label" class="minwidth300" maxlength="255" value="' . dol_escape_htmltag(GETPOST('label')) . '" autofocus="autofocus"></td></tr>';
288
289
    // Bank account
290
    if (isModEnabled("bank")) {
291
        print '<tr><td class="fieldrequired">' . $langs->trans("BankAccount") . '</td><td>';
292
        $form->select_comptes(GETPOST("accountid"), "accountid", 0, "courant=1", 1); // Show list of bank account with courant
293
        print '</td></tr>';
294
    } else {
295
        print '<tr><td>' . $langs->trans("BankAccount") . '</td><td>';
296
        print $langs->trans("NoBankAccountDefined");
297
        print '</td></tr>';
298
    }
299
300
    // Capital
301
    print '<tr><td class="fieldrequired">' . $langs->trans("LoanCapital") . '</td><td><input name="capital" size="10" value="' . dol_escape_htmltag(GETPOST("capital")) . '"></td></tr>';
302
303
    // Date Start
304
    print "<tr>";
305
    print '<td class="fieldrequired">' . $langs->trans("DateStart") . '</td><td>';
306
    print $form->selectDate(!empty($datestart) ? $datestart : -1, 'start', 0, 0, 0, 'add', 1, 1);
307
    print '</td></tr>';
308
309
    // Date End
310
    print "<tr>";
311
    print '<td class="fieldrequired">' . $langs->trans("DateEnd") . '</td><td>';
312
    print $form->selectDate(!empty($dateend) ? $dateend : -1, 'end', 0, 0, 0, 'add', 1, 1);
313
    print '</td></tr>';
314
315
    // Number of terms
316
    print '<tr><td class="fieldrequired">' . $langs->trans("Nbterms") . '</td><td><input name="nbterm" size="5" value="' . dol_escape_htmltag(GETPOST('nbterm')) . '"></td></tr>';
317
318
    // Rate
319
    print '<tr><td class="fieldrequired">' . $langs->trans("Rate") . '</td><td><input name="rate" size="5" value="' . dol_escape_htmltag(GETPOST("rate")) . '"> %</td></tr>';
320
321
    // Insurance amount
322
    print '<tr><td>' . $langs->trans("Insurance") . '</td><td><input name="insurance_amount" size="10" value="' . dol_escape_htmltag(GETPOST("insurance_amount")) . '" placeholder="' . $langs->trans('Amount') . '"></td></tr>';
323
324
    // Project
325
    if (isModEnabled('project')) {
326
        $formproject = new FormProjets($db);
327
328
        // Projet associe
329
        $langs->loadLangs(array("projects"));
330
331
        print '<tr><td>' . $langs->trans("Project") . '</td><td>';
332
333
        $numproject = $formproject->select_projects(-1, $projectid, 'projectid', 16, 0, 1, 1);
334
335
        print '</td></tr>';
336
    }
337
338
    // Note Private
339
    print '<tr>';
340
    print '<td class="tdtop">' . $langs->trans('NotePrivate') . '</td>';
341
    print '<td>';
342
343
    $doleditor = new DolEditor('note_private', GETPOST('note_private', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_6, '90%');
344
    print $doleditor->Create(1);
345
346
    print '</td></tr>';
347
348
    // Note Public
349
    print '<tr>';
350
    print '<td class="tdtop">' . $langs->trans('NotePublic') . '</td>';
351
    print '<td>';
352
    $doleditor = new DolEditor('note_public', GETPOST('note_public', 'alpha'), '', 160, 'dolibarr_notes', 'In', false, true, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_6, '90%');
353
    print $doleditor->Create(1);
354
    print '</td></tr>';
355
356
    // Accountancy
357
    if (isModEnabled('accounting')) {
358
        // Accountancy_account_capital
359
        print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans("LoanAccountancyCapitalCode") . '</td>';
360
        print '<td>';
361
        print $formaccounting->select_account(GETPOST('accountancy_account_capital') ? GETPOST('accountancy_account_capital') : getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_CAPITAL'), 'accountancy_account_capital', 1, '', 1, 1);
362
        print '</td></tr>';
363
364
        // Accountancy_account_insurance
365
        print '<tr><td class="fieldrequired">' . $langs->trans("LoanAccountancyInsuranceCode") . '</td>';
366
        print '<td>';
367
        print $formaccounting->select_account(GETPOST('accountancy_account_insurance') ? GETPOST('accountancy_account_insurance') : getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_INSURANCE'), 'accountancy_account_insurance', 1, '', 1, 1);
368
        print '</td></tr>';
369
370
        // Accountancy_account_interest
371
        print '<tr><td class="fieldrequired">' . $langs->trans("LoanAccountancyInterestCode") . '</td>';
372
        print '<td>';
373
        print $formaccounting->select_account(GETPOST('accountancy_account_interest') ? GETPOST('accountancy_account_interest') : getDolGlobalString('LOAN_ACCOUNTING_ACCOUNT_INTEREST'), 'accountancy_account_interest', 1, '', 1, 1);
374
        print '</td></tr>';
375
    } else {
376
        // For external software
377
        // Accountancy_account_capital
378
        print '<tr><td class="titlefieldcreate">' . $langs->trans("LoanAccountancyCapitalCode") . '</td>';
379
        print '<td><input name="accountancy_account_capital" size="16" value="' . $object->accountancy_account_capital . '">';
380
        print '</td></tr>';
381
382
        // Accountancy_account_insurance
383
        print '<tr><td>' . $langs->trans("LoanAccountancyInsuranceCode") . '</td>';
384
        print '<td><input name="accountancy_account_insurance" size="16" value="' . $object->accountancy_account_insurance . '">';
385
        print '</td></tr>';
386
387
        // Accountancy_account_interest
388
        print '<tr><td>' . $langs->trans("LoanAccountancyInterestCode") . '</td>';
389
        print '<td><input name="accountancy_account_interest" size="16" value="' . $object->accountancy_account_interest . '">';
390
        print '</td></tr>';
391
    }
392
    print '</table>';
393
394
    print dol_get_fiche_end();
395
396
    print $form->buttonsSaveCancel("Add");
397
398
    print '</form>';
399
}
400
401
// View
402
if ($id > 0) {
403
    $object = new Loan($db);
404
    $result = $object->fetch($id);
405
406
    if ($result > 0) {
407
        $head = loan_prepare_head($object);
408
409
        $totalpaid = $object->getSumPayment();
410
411
        // Confirm for loan
412
        if ($action == 'paid') {
413
            $text = $langs->trans('ConfirmPayLoan');
414
            print $form->formconfirm($_SERVER["PHP_SELF"] . "?id=" . $object->id, $langs->trans('PayLoan'), $text, "confirm_paid", '', '', 2);
415
        }
416
417
        if ($action == 'delete') {
418
            $text = $langs->trans('ConfirmDeleteLoan');
419
            print $form->formconfirm($_SERVER['PHP_SELF'] . '?id=' . $object->id, $langs->trans('DeleteLoan'), $text, 'confirm_delete', '', '', 2);
420
        }
421
422
        if ($action == 'edit') {
423
            print '<form name="update" action="' . $_SERVER["PHP_SELF"] . '" method="POST">' . "\n";
424
            print '<input type="hidden" name="token" value="' . newToken() . '">';
425
            print '<input type="hidden" name="action" value="update">';
426
            print '<input type="hidden" name="id" value="' . $id . '">';
427
        }
428
429
        print dol_get_fiche_head($head, 'card', $langs->trans("Loan"), -1, 'money-bill-alt', 0, '', '', 0, '', 1);
430
431
        // Loan card
432
        $linkback = '<a href="' . constant('BASE_URL') . '/loan/list.php?restore_lastsearch_values=1">' . $langs->trans("BackToList") . '</a>';
433
434
        $morehtmlref = '<div class="refidno">';
435
        // Ref loan
436
        $morehtmlref .= $form->editfieldkey("Label", 'label', $object->label, $object, $user->hasRight('loan', 'write'), 'string', '', 0, 1);
437
        $morehtmlref .= $form->editfieldval("Label", 'label', $object->label, $object, $user->hasRight('loan', 'write'), 'string', '', null, null, '', 1);
438
        // Project
439
        if (isModEnabled('project')) {
440
            $langs->loadLangs(array("projects"));
441
            $morehtmlref .= '<br>' . $langs->trans('Project') . ' ';
442
            if ($user->hasRight('loan', 'write')) {
443
                if ($action != 'classify') {
444
                    $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
445
                }
446
                if ($action == 'classify') {
447
                    //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
448
                    $morehtmlref .= '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
449
                    $morehtmlref .= '<input type="hidden" name="action" value="classin">';
450
                    $morehtmlref .= '<input type="hidden" name="token" value="' . newToken() . '">';
451
                    $morehtmlref .= $formproject->select_projects(-1, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
452
                    $morehtmlref .= '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
453
                    $morehtmlref .= '</form>';
454
                } else {
455
                    $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, -1, $object->fk_project, 'none', 0, 0, 0, 1, '', 'maxwidth300');
456
                }
457
            } else {
458
                if (!empty($object->fk_project)) {
459
                    $proj = new Project($db);
460
                    $proj->fetch($object->fk_project);
461
                    $morehtmlref .= ' : ' . $proj->getNomUrl(1);
462
                    if ($proj->title) {
463
                        $morehtmlref .= ' - ' . $proj->title;
464
                    }
465
                } else {
466
                    $morehtmlref .= '';
467
                }
468
            }
469
        }
470
        $morehtmlref .= '</div>';
471
472
        $object->totalpaid = $totalpaid; // To give a chance to dol_banner_tab to use already paid amount to show correct status
473
474
        dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', $morehtmlstatus);
475
476
        print '<div class="fichecenter">';
477
        print '<div class="fichehalfleft">';
478
        print '<div class="underbanner clearboth"></div>';
479
480
        print '<table class="border centpercent tableforfield">';
481
482
        // Capital
483
        if ($action == 'edit') {
484
            print '<tr><td class="fieldrequired titlefield">' . $langs->trans("LoanCapital") . '</td><td>';
485
            print '<input name="capital" size="10" value="' . $object->capital . '"></td></tr>';
486
            print '</td></tr>';
487
        } else {
488
            print '<tr><td class="titlefield">' . $langs->trans("LoanCapital") . '</td><td><span class="amount">' . price($object->capital, 0, $outputlangs, 1, -1, -1, $conf->currency) . '</span></td></tr>';
489
        }
490
491
        // Insurance
492
        if ($action == 'edit') {
493
            print '<tr><td class="titlefield">' . $langs->trans("Insurance") . '</td><td>';
494
            print '<input name="insurance_amount" size="10" value="' . $object->insurance_amount . '"></td></tr>';
495
            print '</td></tr>';
496
        } else {
497
            print '<tr><td class="titlefield">' . $langs->trans("Insurance") . '</td><td><span class="amount">' . price($object->insurance_amount, 0, $outputlangs, 1, -1, -1, $conf->currency) . '</span></td></tr>';
498
        }
499
500
        // Date start
501
        print '<tr><td>' . $langs->trans("DateStart") . "</td>";
502
        print "<td>";
503
        if ($action == 'edit') {
504
            print $form->selectDate($object->datestart, 'start', 0, 0, 0, 'update', 1, 0);
505
        } else {
506
            print dol_print_date($object->datestart, "day");
507
        }
508
        print "</td></tr>";
509
510
        // Date end
511
        print '<tr><td>' . $langs->trans("DateEnd") . "</td>";
512
        print "<td>";
513
        if ($action == 'edit') {
514
            print $form->selectDate($object->dateend, 'end', 0, 0, 0, 'update', 1, 0);
515
        } else {
516
            print dol_print_date($object->dateend, "day");
517
        }
518
        print "</td></tr>";
519
520
        // Nbterms
521
        print '<tr><td>' . $langs->trans("Nbterms") . '</td>';
522
        print '<td>';
523
        if ($action == 'edit') {
524
            print '<input name="nbterm" size="4" value="' . $object->nbterm . '">';
525
        } else {
526
            print $object->nbterm;
527
        }
528
        print '</td></tr>';
529
530
        // Rate
531
        print '<tr><td>' . $langs->trans("Rate") . '</td>';
532
        print '<td>';
533
        if ($action == 'edit') {
534
            print '<input name="rate" size="4" value="' . $object->rate . '">%';
535
        } else {
536
            print price($object->rate) . '%';
537
        }
538
        print '</td></tr>';
539
540
        // Accountancy account capital
541
        print '<tr>';
542
        if ($action == 'edit') {
543
            print '<td class="nowrap fieldrequired">';
544
            print $langs->trans("LoanAccountancyCapitalCode");
545
            print '</td><td>';
546
547
            if (isModEnabled('accounting')) {
548
                print $formaccounting->select_account($object->account_capital, 'accountancy_account_capital', 1, '', 1, 1);
549
            } else {
550
                print '<input name="accountancy_account_capital" size="16" value="' . $object->account_capital . '">';
551
            }
552
            print '</td>';
553
        } else {
554
            print '<td class="nowrap">';
555
            print $langs->trans("LoanAccountancyCapitalCode");
556
            print '</td><td>';
557
558
            if (isModEnabled('accounting')) {
559
                $accountingaccount = new AccountingAccount($db);
560
                $accountingaccount->fetch('', $object->account_capital, 1);
561
562
                print $accountingaccount->getNomUrl(0, 1, 1, '', 1);
563
            } else {
564
                print $object->account_capital;
565
            }
566
567
            print '</td>';
568
        }
569
        print '</tr>';
570
571
        // Accountancy account insurance
572
        print '<tr>';
573
        if ($action == 'edit') {
574
            print '<td class="nowrap fieldrequired">';
575
            print $langs->trans("LoanAccountancyInsuranceCode");
576
            print '</td><td>';
577
578
            if (isModEnabled('accounting')) {
579
                print $formaccounting->select_account($object->account_insurance, 'accountancy_account_insurance', 1, '', 1, 1);
580
            } else {
581
                print '<input name="accountancy_account_insurance" size="16" value="' . $object->account_insurance . '">';
582
            }
583
            print '</td>';
584
        } else {
585
            print '<td class="nowrap">';
586
            print $langs->trans("LoanAccountancyInsuranceCode");
587
            print '</td><td>';
588
589
            if (isModEnabled('accounting')) {
590
                $accountingaccount = new AccountingAccount($db);
591
                $accountingaccount->fetch('', $object->account_insurance, 1);
592
593
                print $accountingaccount->getNomUrl(0, 1, 1, '', 1);
594
            } else {
595
                print $object->account_insurance;
596
            }
597
598
            print '</td>';
599
        }
600
        print '</tr>';
601
602
        // Accountancy account interest
603
        print '<tr>';
604
        if ($action == 'edit') {
605
            print '<td class="nowrap fieldrequired">';
606
            print $langs->trans("LoanAccountancyInterestCode");
607
            print '</td><td>';
608
609
            if (isModEnabled('accounting')) {
610
                print $formaccounting->select_account($object->account_interest, 'accountancy_account_interest', 1, '', 1, 1);
611
            } else {
612
                print '<input name="accountancy_account_interest" size="16" value="' . $object->account_interest . '">';
613
            }
614
            print '</td>';
615
        } else {
616
            print '<td class="nowrap">';
617
            print $langs->trans("LoanAccountancyInterestCode");
618
            print '</td><td>';
619
620
            if (isModEnabled('accounting')) {
621
                $accountingaccount = new AccountingAccount($db);
622
                $accountingaccount->fetch('', $object->account_interest, 1);
623
624
                print $accountingaccount->getNomUrl(0, 1, 1, '', 1);
625
            } else {
626
                print $object->account_interest;
627
            }
628
629
            print '</td>';
630
        }
631
        print '</tr>';
632
633
        // Other attributes
634
        $parameters = array();
635
        $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
636
        print $hookmanager->resPrint;
637
638
        print '</table>';
639
640
        print '</div>';
641
        print '<div class="fichehalfright">';
642
643
        /*
644
         * Payments
645
         */
646
        $sql = "SELECT p.rowid, p.num_payment, p.datep as dp,";
647
        $sql .= " p.amount_capital, p.amount_insurance, p.amount_interest,";
648
        $sql .= " b.fk_account,";
649
        $sql .= " c.libelle as paiement_type";
650
        $sql .= " FROM " . MAIN_DB_PREFIX . "payment_loan as p";
651
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "bank as b ON p.fk_bank = b.rowid";
652
        $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "c_paiement as c ON p.fk_typepayment = c.id,";
653
        $sql .= " " . MAIN_DB_PREFIX . "loan as l";
654
        $sql .= " WHERE p.fk_loan = " . ((int)$id);
655
        $sql .= " AND p.fk_loan = l.rowid";
656
        $sql .= " AND l.entity IN ( " . getEntity('loan') . ")";
657
        $sql .= " ORDER BY dp DESC";
658
659
        //print $sql;
660
        $resql = $db->query($sql);
661
        if ($resql) {
662
            $num = $db->num_rows($resql);
663
            $i = 0;
664
            $total_insurance = 0;
665
            $total_interest = 0;
666
            $total_capital = 0;
667
668
            print '<div class="div-table-responsive-no-min">'; // You can use div-table-responsive-no-min if you don't need reserved height for your table
669
            print '<table class="noborder paymenttable">';
670
            print '<tr class="liste_titre">';
671
            print '<td>' . $langs->trans("RefPayment") . '</td>';
672
            print '<td>' . $langs->trans("Date") . '</td>';
673
            print '<td>' . $langs->trans("Type") . '</td>';
674
            print '<td>' . $langs->trans("BankAccount") . '</td>';
675
            print '<td class="right">' . $langs->trans("Insurance") . '</td>';
676
            print '<td class="right">' . $langs->trans("Interest") . '</td>';
677
            print '<td class="right">' . $langs->trans("LoanCapital") . '</td>';
678
            print '</tr>';
679
680
            $conf->cache['bankaccount'] = array();
681
682
            while ($i < $num) {
683
                $objp = $db->fetch_object($resql);
684
685
                print '<tr class="oddeven">';
686
                print '<td><a href="' . constant('BASE_URL') . '/loan/payment/card.php?id=' . $objp->rowid . '">' . img_object($langs->trans("Payment"), "payment") . ' ' . $objp->rowid . '</a></td>';
687
                print '<td>' . dol_print_date($db->jdate($objp->dp), 'day') . "</td>\n";
688
                print "<td>" . $objp->paiement_type . ' ' . $objp->num_payment . "</td>\n";
689
                print "<td>";
690
                if (!empty($conf->cache['bankaccount'][$objp->fk_account])) {
691
                    $tmpbank = $conf->cache['bankaccount'][$objp->fk_account];
692
                } else {
693
                    $tmpbank = new Account($db);
694
                    $tmpbank->fetch($objp->fk_account);
695
                    $conf->cache['bankaccount'][$objp->fk_account] = $tmpbank;
696
                }
697
                print $tmpbank->getNomUrl(1);
698
                print "</td>\n";
699
                print '<td class="nowrap right"><span class="amount">' . price($objp->amount_insurance, 0, $outputlangs, 1, -1, -1, $conf->currency) . "</span></td>\n";
700
                print '<td class="nowrap right"><span class="amount">' . price($objp->amount_interest, 0, $outputlangs, 1, -1, -1, $conf->currency) . "</span></td>\n";
701
                print '<td class="nowrap right"><span class="amount">' . price($objp->amount_capital, 0, $outputlangs, 1, -1, -1, $conf->currency) . "</span></td>\n";
702
                print "</tr>";
703
                $total_capital += $objp->amount_capital;
704
                $i++;
705
            }
706
707
            $totalpaid = $total_capital;
708
709
            if ($object->paid == 0 || $object->paid == 2) {
710
                print '<tr><td colspan="6" class="right">' . $langs->trans("AlreadyPaid") . ' :</td><td class="nowrap right">' . price($totalpaid, 0, $langs, 0, -1, -1, $conf->currency) . '</td></tr>';
711
                print '<tr><td colspan="6" class="right">' . $langs->trans("AmountExpected") . ' :</td><td class="nowrap right">' . price($object->capital, 0, $outputlangs, 1, -1, -1, $conf->currency) . '</td></tr>';
712
713
                $staytopay = $object->capital - $totalpaid;
714
715
                print '<tr><td colspan="6" class="right">' . $langs->trans("RemainderToPay") . ' :</td>';
716
                print '<td class="nowrap right' . ($staytopay ? ' amountremaintopay' : ' amountpaymentcomplete') . '">';
717
                print price($staytopay, 0, $langs, 0, -1, -1, $conf->currency);
718
                print '</td></tr>';
719
            }
720
            print "</table>";
721
            print '</div>';
722
723
            $db->free($resql);
724
        } else {
725
            dol_print_error($db);
726
        }
727
728
        print '</div>';
729
        print '</div>';
730
731
        print '<div class="clearboth"></div>';
732
733
        print dol_get_fiche_end();
734
735
        if ($action == 'edit') {
736
            print $form->buttonsSaveCancel();
737
738
            print '</form>';
739
        }
740
741
        /*
742
         *  Buttons actions
743
         */
744
        if ($action != 'edit') {
745
            $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
746
            if (empty($reshook)) {
747
                print '<div class="tabsAction">';
748
749
                // Edit
750
                if (($object->paid == 0 || $object->paid == 2) && $user->hasRight('loan', 'write')) {
751
                    print '<div class="inline-block divButAction"><a class="butAction" href="' . constant('BASE_URL') . '/loan/card.php?id=' . $object->id . '&action=edit&token=' . newToken() . '">' . $langs->trans("Modify") . '</a></div>';
752
                }
753
754
                // Emit payment
755
                if (($object->paid == 0 || $object->paid == 2) && ((price2num($object->capital) > 0 && round($staytopay) < 0) || (price2num($object->capital) > 0 && round($staytopay) > 0)) && $user->hasRight('loan', 'write')) {
756
                    print '<div class="inline-block divButAction"><a class="butAction" href="' . constant('BASE_URL') . '/loan/payment/payment.php?id=' . $object->id . '&action=create&token=' . newToken() . '">' . $langs->trans("DoPayment") . '</a></div>';
757
                }
758
759
                // Classify 'paid'
760
                if (($object->paid == 0 || $object->paid == 2) && round($staytopay) <= 0 && $user->hasRight('loan', 'write')) {
761
                    print '<div class="inline-block divButAction"><a class="butAction" href="' . constant('BASE_URL') . '/loan/card.php?id=' . $object->id . '&action=paid&token=' . newToken() . '">' . $langs->trans("ClassifyPaid") . '</a></div>';
762
                }
763
764
                // Delete
765
                if (($object->paid == 0 || $object->paid == 2) && $user->hasRight('loan', 'delete')) {
766
                    print '<div class="inline-block divButAction"><a class="butActionDelete" href="' . constant('BASE_URL') . '/loan/card.php?id=' . $object->id . '&action=delete&token=' . newToken() . '">' . $langs->trans("Delete") . '</a></div>';
767
                }
768
769
                print "</div>";
770
            }
771
        }
772
    } else {
773
        // Loan not found
774
        dol_print_error(null, $object->error);
775
    }
776
}
777
778
// End of page
779
ViewMain::llxFooter();
780
$db->close();
781