dolibarr 25.0.0-alpha
card.php
Go to the documentation of this file.
1<?php
2/* Copyright (C) 2011-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
3 * Copyright (C) 2014-2020 Laurent Destailleur <eldy@users.sourceforge.net>
4 * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
5 * Copyright (C) 2015 Charlie BENKE <charlie@patas-monkey.com>
6 * Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
7 * Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
8 * Copyright (C) 2023 Maxime Nicolas <maxime@oarces.com>
9 * Copyright (C) 2023 Benjamin GREMBI <benjamin@oarces.com>
10 * Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
11 * Copyright (C) 2024-2025 Nick Fragoulis
12 * Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27
34// Load Dolibarr environment
35require '../main.inc.php';
43require_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
44require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
45require_once DOL_DOCUMENT_ROOT.'/salaries/class/salary.class.php';
46require_once DOL_DOCUMENT_ROOT.'/salaries/class/paymentsalary.class.php';
47require_once DOL_DOCUMENT_ROOT.'/compta/bank/class/account.class.php';
48require_once DOL_DOCUMENT_ROOT.'/core/lib/salaries.lib.php';
49require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
50require_once DOL_DOCUMENT_ROOT.'/accountancy/class/accountingjournal.class.php';
51require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
52if (isModEnabled('project')) {
53 require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
54 require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
55}
56
57// Load translation files required by the page
58$langs->loadLangs(array("compta", "banks", "bills", "users", "salaries", "hrm", "trips"));
59if (isModEnabled('project')) {
60 $langs->load("projects");
61}
62
63$id = GETPOSTINT('id');
64$ref = GETPOST('ref', 'alpha');
65$action = GETPOST('action', 'aZ09');
66$cancel = GETPOST('cancel', 'alpha');
67$backtopage = GETPOST('backtopage', 'alpha');
68$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
69$confirm = GETPOST('confirm');
70$backurlforlist = GETPOST('backtopage', 'alpha');
71
72$label = GETPOST('label', 'alphanohtml');
73$projectid = GETPOSTINT('projectid') ? GETPOSTINT('projectid') : GETPOSTINT('fk_project');
74$accountid = GETPOSTINT('accountid') > 0 ? GETPOSTINT('accountid') : 0;
75if (GETPOSTISSET('auto_create_paiement') || $action === 'add') {
76 $auto_create_paiement = GETPOSTINT("auto_create_paiement");
77} else {
78 $auto_create_paiement = !getDolGlobalString('CREATE_NEW_SALARY_WITHOUT_AUTO_PAYMENT');
79}
80
81$datep = dol_mktime(12, 0, 0, GETPOSTINT("datepmonth"), GETPOSTINT("datepday"), GETPOSTINT("datepyear"));
82$datev = dol_mktime(12, 0, 0, GETPOSTINT("datevmonth"), GETPOSTINT("datevday"), GETPOSTINT("datevyear"));
83$datesp = dol_mktime(12, 0, 0, GETPOSTINT("datespmonth"), GETPOSTINT("datespday"), GETPOSTINT("datespyear"));
84$dateep = dol_mktime(12, 0, 0, GETPOSTINT("dateepmonth"), GETPOSTINT("dateepday"), GETPOSTINT("dateepyear"));
85$fk_user = GETPOSTINT('userid');
86
87$object = new Salary($db);
88$extrafields = new ExtraFields($db);
89
90$childids = $user->getAllChildIds(1);
91
92// fetch optionals attributes and labels
93$extrafields->fetch_name_optionals_label($object->table_element);
94
95// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
96$hookmanager->initHooks(array('salarycard', 'globalcard'));
97
98if ($id > 0) {
99 $object->fetch($id);
100
101 // Check current user can read this salary
102 $canread = 0;
103 if ($user->hasRight('salaries', 'readall')) {
104 $canread = 1;
105 }
106 if ($user->hasRight('salaries', 'read') && $object->fk_user > 0 && in_array($object->fk_user, $childids)) {
107 $canread = 1;
108 }
109 if (!$canread) {
111 }
112}
113
114// Security check
115$socid = GETPOSTINT('socid');
116if ($user->socid) {
117 $socid = $user->socid;
118}
119
120restrictedArea($user, 'salaries', $id, 'salary', '');
121
122$permissiontoread = $user->hasRight('salaries', 'read');
123$permissiontoadd = $user->hasRight('salaries', 'write'); // Used by the include of actions_addupdatedelete.inc.php and actions_lineupdown.inc.php
124$permissiontodelete = $user->hasRight('salaries', 'delete') || ($permissiontoadd && isset($object->status) && $object->status == $object::STATUS_UNPAID);
125$permissiontoeditextra = $permissiontoadd;
126if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
127 // For action 'update_extras', is there a specific permission set for the attribute to update
128 $permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
129}
130
131$upload_dir = $conf->salaries->multidir_output[$conf->entity];
132
133$error = 0;
134$resteapayer = 0;
135
136/*
137 * Actions
138 */
139
140$parameters = array();
141$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action);
142if ($reshook < 0) {
143 setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
144}
145
146if (empty($reshook)) {
147 $error = 0;
148
149 // Actions to build the document
150 $upload_dir = $conf->salaries->dir_output;
151 $permissiontoadd = $user->hasRight('salaries', 'write');
152
153 // $object->element = 'salary';
154 if (empty($object->ref) && !empty($object->id)) {
155 $object->ref = (string) $object->id;
156 }
157
158 include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
159
160 // Actions to send emails
161 $trackid = 'sal'.$object->id;
162 include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
163}
164
165// Link to a project
166if ($action == 'classin' && $permissiontoadd) {
167 $object->fetch($id);
168 $object->setProject($projectid);
169}
170
171// set label
172if ($action == 'setlabel' && $permissiontoadd) {
173 $object->fetch($id);
174 $object->label = $label;
175 $result = $object->update($user);
176 if ($result < 0) {
177 setEventMessages($object->error, $object->errors, 'errors');
178 }
179}
180
181// Classify paid
182if ($action == 'confirm_paid' && $permissiontoadd && $confirm == 'yes') {
183 $object->fetch($id);
184 $result = $object->setPaid($user);
185}
186
187if ($action == 'setfk_user' && $permissiontoadd) {
188 $result = $object->fetch($id);
189 if ($result > 0) {
190 $object->fk_user = $fk_user;
191 $result = $object->update($user);
192 if ($result < 0) {
193 setEventMessages($object->error, $object->errors, 'errors');
194 }
195 } else {
196 dol_print_error($db);
197 exit;
198 }
199}
200
201if ($action == 'reopen' && $permissiontoadd) {
202 $result = $object->fetch($id);
203 if ($object->paye) {
204 $result = $object->set_unpaid($user);
205 if ($result > 0) {
206 header('Location: '.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $id]));
207 exit();
208 } else {
209 setEventMessages($object->error, $object->errors, 'errors');
210 }
211 }
212}
213
214// payment mode
215if ($action == 'setmode' && $permissiontoadd) {
216 $object->fetch($id);
217 $result = $object->setPaymentMethods(GETPOSTINT('mode_reglement_id'));
218 if ($result < 0) {
219 setEventMessages($object->error, $object->errors, 'errors');
220 }
221}
222
223// bank account
224if ($action == 'setbankaccount' && $permissiontoadd) {
225 $object->fetch($id);
226 $result = $object->setBankAccount(GETPOSTINT('fk_account'));
227 if ($result < 0) {
228 setEventMessages($object->error, $object->errors, 'errors');
229 }
230}
231
232if ($action == 'add' && empty($cancel) && $permissiontoadd) {
233 $error = 0;
234
235 if (empty($datev)) {
236 $datev = $datep;
237 }
238
239 $type_payment = GETPOSTINT("paymenttype");
240 $amount = price2num(GETPOST("amount", 'alpha'), 'MT', 2);
241
242 $object->accountid = GETPOSTINT("accountid") > 0 ? GETPOSTINT("accountid") : 0;
243 $object->fk_user = GETPOSTINT("fk_user") > 0 ? GETPOSTINT("fk_user") : 0;
244 $object->datev = $datev;
245 $object->datep = $datep;
246 $object->amount = $amount;
247 $object->label = GETPOST("label", 'alphanohtml');
248 $object->datesp = $datesp;
249 $object->dateep = $dateep;
250 $object->note = GETPOST("note", 'restricthtml');
251 $object->type_payment = ($type_payment > 0 ? $type_payment : 0);
252 $object->fk_user_author = $user->id;
253 $object->fk_project = $projectid;
254
255 // Set user current salary as ref salary for the payment
256 $fuser = new User($db);
257 $fuser->fetch(GETPOSTINT("fk_user"));
258 $object->salary = $fuser->salary;
259
260 // Fill array 'array_options' with data from add form
261 $ret = $extrafields->setOptionalsFromPost(null, $object);
262 if ($ret < 0) {
263 $error++;
264 }
265
266 if (!empty($auto_create_paiement) && empty($datep)) {
267 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("DATE_PAIEMENT")), null, 'errors');
268 $error++;
269 }
270 if (empty($datesp) || empty($dateep)) {
271 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
272 $error++;
273 }
274 if (empty($object->fk_user) || $object->fk_user < 0) {
275 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Employee")), null, 'errors');
276 $error++;
277 }
278 if (!empty($auto_create_paiement) && (empty($type_payment) || $type_payment < 0)) {
279 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("PaymentMode")), null, 'errors');
280 $error++;
281 }
282 if (empty($object->amount)) {
283 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Amount")), null, 'errors');
284 $error++;
285 }
286 if (isModEnabled("bank") && !empty($auto_create_paiement) && !$object->accountid > 0) {
287 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("BankAccount")), null, 'errors');
288 $error++;
289 }
290
291 if (!$error) {
292 $db->begin();
293
294 $ret = $object->create($user);
295 if ($ret < 0) {
296 setEventMessages($object->error, $object->errors, 'errors');
297 $error++;
298 }
299 if (!empty($auto_create_paiement) && !$error) {
300 // Create a line of payments
301 $paiement = new PaymentSalary($db);
302 $paiement->fk_salary = $object->id;
303 $paiement->chid = $object->id; // deprecated
304 $paiement->datep = $datep;
305 $paiement->datev = $datev;
306 $paiement->amounts = array($object->id => $amount); // Amount array
307 $paiement->fk_typepayment = $type_payment;
308 $paiement->num_payment = GETPOST("num_payment", 'alphanohtml');
309 $paiement->note_private = GETPOST("note", 'restricthtml');
310
311 if (!$error) {
312 $paymentid = $paiement->create($user, (int) GETPOST('closepaidsalary'));
313 if ($paymentid < 0) {
314 $error++;
315 setEventMessages($paiement->error, null, 'errors');
316 $action = 'create';
317 }
318 }
319
320 if (!$error) {
321 $result = $paiement->addPaymentToBank($user, 'payment_salary', '(SalaryPayment)', GETPOSTINT('accountid'), '', '');
322 if (!($result > 0)) {
323 $error++;
324 setEventMessages($paiement->error, null, 'errors');
325 }
326 }
327 }
328
329 if (empty($error)) {
330 $db->commit();
331
332 if (GETPOST('saveandnew', 'alpha')) {
333 setEventMessages($langs->trans("RecordSaved"), null);
334 $query = [
335 'action' => 'create',
336 'fk_project' => $projectid,
337 'accountid' => $accountid,
338 'paymenttype' => GETPOSTINT('paymenttype'),
339 'datepday' => GETPOSTINT("datepday"),
340 'datepmonth' => GETPOSTINT("datepmonth"),
341 'datepyear' => GETPOSTINT("datepyear"),
342 ];
343 header("Location: ". dolBuildUrl($_SERVER['PHP_SELF'], $query));
344 exit;
345 } else {
346 header("Location: " . dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id]));
347 exit;
348 }
349 } else {
350 $db->rollback();
351 }
352 }
353
354 $action = 'create';
355}
356
357if ($action == 'confirm_delete' && $permissiontodelete) {
358 $result = $object->fetch($id);
359 $totalpaid = $object->getSommePaiement();
360
361 if (empty($totalpaid)) {
362 $db->begin();
363
364 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
365 $ret = $object->delete($user);
366 if ($ret > 0) {
367 $db->commit();
368 header("Location: ".dolBuildUrl(DOL_URL_ROOT.'/salaries/list.php'));
369 exit;
370 } else {
371 $db->rollback();
372 setEventMessages($object->error, $object->errors, 'errors');
373 }
374 } else {
375 setEventMessages($langs->trans('DisabledBecausePayments'), null, 'errors');
376 }
377}
378
379
380if ($action == 'update' && !GETPOST("cancel") && $permissiontoadd) {
381 $amount = price2num(GETPOST('amount'), 'MT', 2);
382
383 if (empty($amount)) {
384 setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentities("Amount")), null, 'errors');
385 $action = 'edit';
386 } elseif (!is_numeric($amount)) {
387 setEventMessages($langs->trans("ErrorFieldMustBeANumeric", $langs->transnoentities("Amount")), null, 'errors');
388 $action = 'create';
389 } else {
390 $result = $object->fetch($id);
391
392 $object->amount = price2num($amount);
393 $object->datesp = price2num($datesp);
394 $object->dateep = price2num($dateep);
395
396 $result = $object->update($user);
397 if ($result <= 0) {
398 setEventMessages($object->error, $object->errors, 'errors');
399 }
400 }
401}
402
403if ($action == 'confirm_clone' && $confirm != 'yes') { // Test on permission not required here
404 $action = '';
405}
406
407if ($action == 'confirm_clone' && $confirm == 'yes' && $permissiontoadd) {
408 $db->begin();
409
410 $originalId = $id;
411
412 $object->fetch($id);
413
414 if ($object->id > 0) {
415 $object->paye = 0;
416 $object->id = 0;
417 $object->ref = '';
418
419 if (GETPOST('amount', 'alphanohtml')) {
420 $object->amount = price2num(GETPOST('amount', 'alphanohtml'), 'MT', 2);
421 }
422
423 if (GETPOST('clone_label', 'alphanohtml')) {
424 $object->label = GETPOST('clone_label', 'alphanohtml');
425 } else {
426 $object->label = $langs->trans("CopyOf").' '.$object->label;
427 }
428
429 $newdatestart = dol_mktime(0, 0, 0, GETPOSTINT('clone_date_startmonth'), GETPOSTINT('clone_date_startday'), GETPOSTINT('clone_date_startyear'));
430 $newdateend = dol_mktime(0, 0, 0, GETPOSTINT('clone_date_endmonth'), GETPOSTINT('clone_date_endday'), GETPOSTINT('clone_date_endyear'));
431
432 if ($newdatestart) {
433 $object->datesp = $newdatestart;
434 }
435 if ($newdateend) {
436 $object->dateep = $newdateend;
437 }
438
439 $id = $object->create($user);
440 if ($id > 0) {
441 $db->commit();
442 $db->close();
443
444 header("Location: ".dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $id]));
445 exit;
446 } else {
447 $id = $originalId;
448 $db->rollback();
449
450 setEventMessages($object->error, $object->errors, 'errors');
451 }
452 } else {
453 $db->rollback();
454 dol_print_error($db, $object->error);
455 }
456}
457
458
459// Action to update one extrafield
460if ($action == 'update_extras' && $permissiontoeditextra) {
461 $object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
462
463 $attribute = GETPOST('attribute', 'aZ09');
464
465 // Fill array 'array_options' with data from update form
466 $ret = $extrafields->setOptionalsFromPost(null, $object, $attribute);
467 if ($ret < 0) {
468 setEventMessages($extrafields->error, $object->errors, 'errors');
469 $error++;
470 }
471
472 if (!$error) {
473 $result = $object->updateExtraField($attribute, 'SALARY_MODIFY');
474 if ($result < 0) {
475 setEventMessages($object->error, $object->errors, 'errors');
476 $error++;
477 }
478 }
479
480 if ($error) {
481 $action = 'edit_extras';
482 }
483}
484
485/*
486 * View
487 */
488
489$form = new Form($db);
490$formfile = new FormFile($db);
491if (isModEnabled('project')) {
492 $formproject = new FormProjets($db);
493}
494
495$title = $langs->trans('Salary')." - ".$object->ref;
496if ($action == 'create') {
497 $title = $langs->trans("NewSalary");
498}
499$help_url = "";
500llxHeader('', $title, $help_url);
501
502
503if ($id > 0) {
504 $result = $object->fetch($id);
505 if ($result <= 0) {
506 recordNotFound('', 0);
507 }
508}
509
510// Create
511if ($action == 'create' && $permissiontoadd) {
512 $year_current = (int) dol_print_date(dol_now('gmt'), "%Y", 'gmt');
513 $pastmonth = (int) dol_print_date(dol_now(), "%m") - 1;
514 $pastmonthyear = $year_current;
515 if ($pastmonth == 0) {
516 $pastmonth = 12;
517 $pastmonthyear--;
518 }
519
520 $datespmonth = GETPOSTINT('datespmonth');
521 $datespday = GETPOSTINT('datespday');
522 $datespyear = GETPOSTINT('datespyear');
523 $dateepmonth = GETPOSTINT('dateepmonth');
524 $dateepday = GETPOSTINT('dateepday');
525 $dateepyear = GETPOSTINT('dateepyear');
526 $datesp = dol_mktime(0, 0, 0, $datespmonth, $datespday, $datespyear);
527 $dateep = dol_mktime(23, 59, 59, $dateepmonth, $dateepday, $dateepyear);
528
529 if (empty($datesp) || empty($dateep)) { // We define date_start and date_end
530 $datesp = dol_get_first_day($pastmonthyear, $pastmonth, false);
531 $dateep = dol_get_last_day($pastmonthyear, $pastmonth, false);
532 }
533
534 print '<form name="salary" action="'.dolBuildUrl($_SERVER["PHP_SELF"]).'" method="POST">';
535 print '<input type="hidden" name="token" value="'.newToken().'">';
536 print '<input type="hidden" name="action" value="add">';
537 if ($backtopage) {
538 print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
539 }
540 if ($backtopageforcancel) {
541 print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
542 }
543
544 print load_fiche_titre($langs->trans("NewSalary"), '', 'salary');
545
546 if (!empty($conf->use_javascript_ajax)) {
547 print "\n".'<script type="text/javascript">';
548 print '
549 $(document).ready(function () {
550 let onAutoCreatePaiementChange = function () {
551 if($("#auto_create_paiement").is(":checked")) {
552 $("#label_fk_account").find("span").addClass("fieldrequired");
553 $("#label_type_payment").find("span").addClass("fieldrequired");
554 $(".hide_if_no_auto_create_payment").show();
555 } else {
556 $("#label_fk_account").find("span").removeClass("fieldrequired");
557 $("#label_type_payment").find("span").removeClass("fieldrequired");
558 $(".hide_if_no_auto_create_payment").hide();
559 }
560 };
561 $("#radiopayment").click(function() {
562 $("#label").val($(this).data("label"));
563 });
564 $("#radiorefund").click(function() {
565 $("#label").val($(this).data("label"));
566 });
567 $("#auto_create_paiement").click(function () {
568 onAutoCreatePaiementChange();
569 });
570 onAutoCreatePaiementChange();
571 });
572
573 // Month shortcut keys for datesp / dateep
574 window.setSalaryDatePeriod = function(offset) {
575 var now = new Date();
576 var year = now.getFullYear();
577 var month = now.getMonth() + 1 + parseInt(offset);
578
579 if (month < 1) { month = 12; year--; }
580 if (month > 12) { month = 1; year++; }
581
582 var lastDay = new Date(year, month, 0).getDate();
583
584 var mm = String(month).padStart(2, "0");
585 var ld = String(lastDay).padStart(2, "0");
586 var yy = String(year);
587
588 // Start date
589 $("#datespday").val("01");
590 $("#datespmonth").val(mm);
591 $("#datespyear").val(yy);
592 $("#datesp").val("01/" + mm + "/" + yy);
593
594 // End date
595 $("#dateepday").val(ld);
596 $("#dateepmonth").val(mm);
597 $("#dateepyear").val(yy);
598 $("#dateep").val(ld + "/" + mm + "/" + yy);
599 };
600 ';
601 print '</script>'."\n";
602 }
603
604 print dol_get_fiche_head();
605
606 print '<table class="border centpercent">';
607
608 // Employee
609 print '<tr><td class="titlefieldcreate">';
610 print $form->editfieldkey('Employee', 'fk_user', '', $object, 0, 'string', '', 1).'</td><td>';
611 $noactive = 0; // We keep active and unactive users
612 print img_picto('', 'user', 'class="pictofixedwidth"').$form->select_dolusers(GETPOSTINT('fk_user'), 'fk_user', 1, null, 0, '', '', '0', 0, 0, 'employee:=:1', 0, '', 'maxwidth300', $noactive);
613 print '</td></tr>';
614
615 // Label
616 print '<tr><td>';
617 print $form->editfieldkey('Label', 'label', '', $object, 0, 'string', '', 1).'</td><td>';
618 print '<input name="label" id="label" class="minwidth300" value="'.(GETPOST("label") ? GETPOST("label") : $langs->trans("Salary")).'">';
619 print '</td></tr>';
620
621 // Date start period
622 print '<tr><td>';
623 print $form->editfieldkey('DateStartPeriod', 'datesp', '', $object, 0, 'string', '', 1).'</td><td>';
624 print $form->selectDate($datesp, "datesp", 0, 0, 0, 'add');
625
626 // Shortcut buttons: previous month / current month / next month
627 if (!empty($conf->use_javascript_ajax)) {
628 print '<button type="button" class="dpInvisibleButtons" style="color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;" onclick="setSalaryDatePeriod(-1)">'.$langs->trans('PreviousMonthShort').'</button> ';
629 print '<button type="button" class="dpInvisibleButtons" style="color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;" onclick="setSalaryDatePeriod(0)">'.$langs->trans('CurrentMonthShort').'</button> ';
630 print '<button type="button" class="dpInvisibleButtons" style="color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;" onclick="setSalaryDatePeriod(1)">'.$langs->trans('NextMonthShort').'</button>';
631 }
632 print '</td></tr>';
633
634 // Date end period
635 print '<tr><td>';
636 print $form->editfieldkey('DateEndPeriod', 'dateep', '', $object, 0, 'string', '', 1).'</td><td>';
637 print $form->selectDate($dateep, "dateep", 0, 0, 0, 'add');
638 print '</td></tr>';
639
640 // Amount
641 print '<tr><td>';
642 print $form->editfieldkey('Amount', 'amount', '', $object, 0, 'string', '', 1).'</td><td>';
643 print '<input name="amount" id="amount" class="minwidth75 maxwidth100" value="'.GETPOST("amount").'"> &nbsp;';
644 print ' <button class="dpInvisibleButtons datenowlink" id="updateAmountWithLastSalary" name="_useless" type="button">'.$langs->trans('UpdateAmountWithLastSalary').'</a>';
645 print '</td>';
646 print '</tr>';
647
648 // Project
649 if (isModEnabled('project')) {
650 $formproject = new FormProjets($db);
651
652 print '<tr><td>'.$langs->trans("Project").'</td><td>';
653 print img_picto('', 'project', 'class="pictofixedwidth"');
654 print $formproject->select_projects(-1, (string) $projectid, 'fk_project', 0, 0, 1, 1, 0, 0, 0, '', 1);
655 print '</td></tr>';
656 }
657
658 // Comments
659 print '<tr>';
660 print '<td class="tdtop">'.$langs->trans("Comments").'</td>';
661 print '<td class="tdtop"><textarea name="note" wrap="soft" cols="60" rows="'.ROWS_3.'">'.GETPOST('note', 'restricthtml').'</textarea></td>';
662 print '</tr>';
663
664
665 print '<tr><td colspan="2"><hr></td></tr>';
666
667
668 // Auto create payment
669 print '<tr><td><label for="auto_create_paiement">'.$langs->trans('AutomaticCreationPayment').'</label></td>';
670 print '<td><input id="auto_create_paiement" name="auto_create_paiement" type="checkbox" ' . (empty($auto_create_paiement) ? '' : 'checked="checked"') . ' value="1"></td></tr>'."\n"; // Date payment
671
672 // Bank
673 if (isModEnabled("bank")) {
674 print '<tr><td id="label_fk_account">';
675 print $form->editfieldkey('BankAccount', 'selectaccountid', '', $object, 0, 'string', '', 1).'</td><td>';
676 print img_picto('', 'bank_account', 'class="pictofixedwidth"');
677 $form->select_comptes($accountid, "accountid", 0, '', 1); // Affiche liste des comptes courant
678 print '</td></tr>';
679 }
680
681 // Type payment
682 print '<tr><td id="label_type_payment">';
683 print $form->editfieldkey('PaymentMode', 'selectpaymenttype', '', $object, 0, 'string', '', 1).'</td><td>';
684 print img_picto('', 'bank', 'class="pictofixedwidth"');
685 print $form->select_types_paiements(GETPOST("paymenttype", 'aZ09'), "paymenttype", '');
686 print '</td></tr>';
687
688 // Date payment
689 print '<tr class="hide_if_no_auto_create_payment"><td>';
690 print $form->editfieldkey('DatePayment', 'datep', '', $object, 0, 'string', '', 1).'</td><td>';
691 print $form->selectDate((empty($datep) ? '' : $datep), "datep", 0, 0, 0, 'add', 1, 1);
692 print '</td></tr>';
693
694 // Date value for bank
695 print '<tr class="hide_if_no_auto_create_payment"><td>';
696 print $form->editfieldkey('DateValue', 'datev', '', $object, 0).'</td><td>';
697 print $form->selectDate((empty($datev) ? -1 : $datev), "datev", 0, 0, 0, 'add', 1, 1);
698 print '</td></tr>';
699
700 // Number
701 if (isModEnabled("bank")) {
702 // Number
703 print '<tr class="hide_if_no_auto_create_payment"><td><label for="num_payment">'.$langs->trans('Numero');
704 print ' <em>('.$langs->trans("ChequeOrTransferNumber").')</em>';
705 print '</label></td>';
706 print '<td><input name="num_payment" id="num_payment" type="text" value="'.GETPOST("num_payment").'"></td></tr>'."\n";
707 }
708
709 // Other attributes
710 $parameters = array();
711 $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
712 print $hookmanager->resPrint;
713 if (empty($reshook)) {
714 print $object->showOptionals($extrafields, 'create');
715 }
716
717 print '</table>';
718
719 print dol_get_fiche_end();
720
721 print '<div class="center">';
722
723 print '<div class="hide_if_no_auto_create_payment paddingbottom">';
724 print '<input type="checkbox" checked value="1" name="closepaidsalary" id="closepaidsalary" class="marginrightonly"><label for="closepaidsalary" class="opacitymedium">'.$langs->trans("ClosePaidSalaryAutomatically").'</label>';
725 print '</div>';
726
727 print '</div>';
728
729 $addition_button = array(
730 'name' => 'saveandnew',
731 'label_key' => 'SaveAndNew',
732 );
733 print $form->buttonsSaveCancel("Save", "Cancel", $addition_button);
734
735 print '</form>';
736 print '<script>';
737 print '$( document ).ready(function() {';
738 print '$("#updateAmountWithLastSalary").on("click", function updateAmountWithLastSalary() {
739 var fk_user = $("#fk_user").val()
740 var url = "'.DOL_URL_ROOT.'/salaries/ajax/ajaxsalaries.php?fk_user="+fk_user;
741 console.log("We click on link to autofill salary amount url="+url);
742
743 if (fk_user != -1) {
744 $.get(
745 url,
746 function( data ) {
747 console.log("Data returned: "+data);
748 if (data != null) {
749 if (typeof data == "object") {
750 console.log("data is already type object, no need to parse it");
751 item = data;
752 } else {
753 console.log("data is type "+(typeof data));
754 item = JSON.parse(data);
755 }
756 if (item[0].key == "Amount") {
757 value = item[0].value;
758 console.log("amount returned = "+value);
759 if (value != null) {
760 $("#amount").val(item[0].value);
761 } else {
762 console.error("Error: Ajax url "+url+" has returned a null value.");
763 }
764 } else {
765 console.error("Error: Ajax url "+url+" has returned the wrong key.");
766 }
767 } else {
768 console.error("Error: Ajax url "+url+" has returned an empty page.");
769 }
770 }
771 );
772
773 } else {
774 alert(\''.dol_escape_js($langs->transnoentitiesnoconv("FillFieldFirst")).'\');
775 }
776 });
777
778 })';
779 print '</script>';
780}
781
782// View mode
783if ($id > 0) {
784 $head = salaries_prepare_head($object);
785 $formconfirm = '';
786 $pageurl = dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id]);
787
788 if ($action === 'clone') {
789 $formquestion = array(
790 array('type' => 'text', 'name' => 'clone_label', 'label' => $langs->trans("Label"), 'value' => $langs->trans("CopyOf").' '.$object->label),
791 );
792
793 //$formquestion[] = array('type' => 'date', 'name' => 'clone_date_ech', 'label' => $langs->trans("Date"), 'value' => -1);
794 if (!empty($object->dateep)) {
795 $formquestion[] = array('type' => 'date', 'name' => 'clone_date_start', 'label' => $langs->trans("DateStart"), 'value' => ($object->dateep) + 86400);
796 } else {
797 $formquestion[] = array('type' => 'date', 'name' => 'clone_date_start', 'label' => $langs->trans("DateStart"), 'value' => -1);
798 }
799 $formquestion[] = array('type' => 'date', 'name' => 'clone_date_end', 'label' => $langs->trans("DateEnd"), 'value' => -1);
800 $formquestion[] = array('type' => 'text', 'name' => 'amount', 'label' => $langs->trans("Amount"), 'value' => price($object->amount), 'morecss' => 'width100 right');
801
802 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('ToClone'), $langs->trans('ConfirmCloneSalary', $object->ref), 'confirm_clone', $formquestion, 'yes', 1, 0);
803
804 // Add buttons to fill start and end dates
805 $formconfirm .= "<script>
806 // Buttons for start date: previous month, current month, previous week, current week
807 $('#clone_date_start').after(
808 $('<button id=\"start_prev_month\" class=\"dpInvisibleButtons\" style=\"color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;\" type=\"button\">".$langs->trans('PreviousMonthShort')."</button>')
809 .add('<button id=\"start_curr_month\" class=\"dpInvisibleButtons\" style=\"color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;\" type=\"button\">".$langs->trans('CurrentMonthShort')."</button>')
810 ";
811 if (getDolGlobalString('SALARY_MANAGEMENT_PER_WEEK')) {
812 $formconfirm .= "
813 .add('<button id=\"start_prev_week\" class=\"dpInvisibleButtons\" style=\"color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;\" type=\"button\">".$langs->trans('PreviousWeekShort')."</button>')
814 .add('<button id=\"start_curr_week\" class=\"dpInvisibleButtons\" style=\"color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;\" type=\"button\">".$langs->trans('CurrentWeekShort')."</button>')";
815 }
816 $formconfirm .= "
817 );
818
819 $('#start_prev_month').click(function(){
820 var now = new Date();
821 var startPrevMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
822 setStartDate(startPrevMonth);
823 });
824
825 $('#start_curr_month').click(function(){
826 var now = new Date();
827 var startCurrMonth = new Date(now.getFullYear(), now.getMonth(), 1);
828 setStartDate(startCurrMonth);
829 });
830
831 $('#start_prev_week').click(function(){
832 var now = new Date();
833 var startPrevWeek = new Date(now.setDate(now.getDate() - now.getDay() - 7));
834 startPrevWeek.setDate(startPrevWeek.getDate() + 1);
835 setStartDate(startPrevWeek);
836 });
837
838 $('#start_curr_week').click(function(){
839 var now = new Date();
840 var startCurrWeek = new Date(now.setDate(now.getDate() - now.getDay() + 1));
841 setStartDate(startCurrWeek);
842 });
843
844 function setStartDate(date) {
845 $('#clone_date_start').val(formatDate(date, '".$langs->trans("FormatDateShortJavaInput")."'));
846 $('#clone_date_startday').val(date.getDate());
847 $('#clone_date_startmonth').val(date.getMonth() + 1);
848 $('#clone_date_startyear').val(date.getFullYear());
849 }
850
851 // Button for end date
852 $('#clone_date_end').after($('<button id=\"fill_end_of_month\" class=\"dpInvisibleButtons\" style=\"color: var(--colortextlink);font-size: 0.8em;opacity: 0.7;margin-left:4px;\" type=\"button\">".$langs->trans('FillEndOfMonth')."</button>'));
853 $('#fill_end_of_month').click(function(){
854 var clone_date_startmonth = +$('#clone_date_startmonth').val();
855 var clone_date_startyear = +$('#clone_date_startyear').val();
856 var end_date;
857
858 if (clone_date_startmonth && clone_date_startyear) {
859 end_date = new Date(clone_date_startyear, clone_date_startmonth, 0);
860 } else {
861 var currentDate = new Date();
862 var currentDay = currentDate.getDate();
863 if (currentDay <= 15) {
864 end_date = new Date(currentDate.getFullYear(), currentDate.getMonth(), 0);
865 } else {
866 end_date = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 0);
867 }
868 }
869
870 $('#clone_date_end').val(formatDate(end_date,'".$langs->trans("FormatDateShortJavaInput")."'));
871 $('#clone_date_endday').val(end_date.getDate());
872 $('#clone_date_endmonth').val(end_date.getMonth() + 1);
873 $('#clone_date_endyear').val(end_date.getFullYear());
874 });
875 </script>";
876 }
877
878 if ($action == 'paid') {
879 $text = $langs->trans('ConfirmPaySalary');
880 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('PaySalary'), $text, "confirm_paid", '', '', 2);
881 }
882
883 if ($action == 'delete') {
884 $text = $langs->trans('ConfirmDeleteSalary');
885 $formconfirm = $form->formconfirm(dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id]), $langs->trans('DeleteSalary'), $text, 'confirm_delete', '', '', 2);
886 }
887
888 if ($action == 'edit') {
889 print '<form name="charge" action="'.dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id, 'action' => 'update']).'" method="post">';
890 print '<input type="hidden" name="token" value="'.newToken().'">';
891 }
892
893 // Call Hook formConfirm
894 $parameters = array('formConfirm' => $formconfirm);
895 $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
896 if (empty($reshook)) {
897 $formconfirm .= $hookmanager->resPrint;
898 } elseif ($reshook > 0) {
899 $formconfirm = $hookmanager->resPrint;
900 }
901
902 // Print form confirm
903 print $formconfirm;
904
905
906 print dol_get_fiche_head($head, 'card', $langs->trans("SalaryPayment"), -1, 'salary', 0, '', '', 0, '', ($action == 'edit' ? 0 : 1));
907
908 $linkback = '<a href="'.dolBuildUrl(DOL_URL_ROOT.'/salaries/list.php', ['restore_lastsearch_values' => 1]).(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
909
910 $morehtmlref = '<div class="refidno">';
911
912 // Label
913 if ($action != 'editlabel') {
914 $morehtmlref .= $form->editfieldkey("Label", 'label', $object->label, $object, $permissiontoadd, 'string', '', 0, 1);
915 $morehtmlref .= $object->label;
916 } else {
917 $morehtmlref .= $langs->trans('Label').' :&nbsp;';
918 $morehtmlref .= '<form method="post" action="'.$pageurl.'">';
919 $morehtmlref .= '<input type="hidden" name="action" value="setlabel">';
920 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
921 $morehtmlref .= '<input type="text" name="label" value="'.$object->label.'"/>';
922 $morehtmlref .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
923 $morehtmlref .= '</form>';
924 }
925
926 // Employee
927 if ($action != 'editfk_user') {
928 if ($object->getSommePaiement() > 0 && !empty($object->fk_user)) {
929 $userstatic = new User($db);
930 $result = $userstatic->fetch($object->fk_user);
931 if ($result > 0) {
932 $morehtmlref .= '<br>'.$userstatic->getNomUrl(-1);
933 }
934 } else {
935 $morehtmlref .= '<br>' . $form->editfieldkey("", 'fk_user', $object->label, $object, $permissiontoadd, 'string', '', 0, 1);
936
937 if (!empty($object->fk_user)) {
938 $userstatic = new User($db);
939 $result = $userstatic->fetch($object->fk_user);
940 if ($result > 0) {
941 $morehtmlref .= $userstatic->getNomUrl(-1);
942 } else {
943 dol_print_error($db);
944 exit();
945 }
946 }
947 }
948 } else {
949 $morehtmlref .= '<br>';
950 $morehtmlref .= '<form method="post" action="'.$pageurl.'">';
951 $morehtmlref .= '<input type="hidden" name="action" value="setfk_user">';
952 $morehtmlref .= '<input type="hidden" name="token" value="'.newToken().'">';
953 $morehtmlref .= $form->select_dolusers($object->fk_user, 'userid', 1);
954 $morehtmlref .= '<input type="submit" class="button valignmiddle smallpaddingimp" value="'.$langs->trans("Modify").'">';
955 $morehtmlref .= '</form>';
956 }
957
958 $usercancreate = $permissiontoadd;
959
960 // Project
961 if (isModEnabled('project')) {
962 $langs->load("projects");
963 $morehtmlref .= '<br>';
964 if ($usercancreate) {
965 $morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
966 if ($action != 'classify') {
967 $morehtmlref .= '<a class="editfielda" href="'.dolBuildUrl($_SERVER['PHP_SELF'], ['action' => 'classify', 'id' => $object->id], true).'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
968 }
969 $morehtmlref .= $form->form_project($pageurl, -1, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
970 } else {
971 if (!empty($object->fk_project)) {
972 $proj = new Project($db);
973 $proj->fetch($object->fk_project);
974 $morehtmlref .= $proj->getNomUrl(1);
975 if ($proj->title) {
976 $morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
977 }
978 }
979 }
980 }
981
982 $morehtmlref .= '</div>';
983
984 $totalpaid = $object->getSommePaiement();
985
986 $object->totalpaid = $totalpaid;
987 $object->alreadypaid = $totalpaid; // Same then $totalpaid because there is no amount of credit note or deposits for salary payments.
988
989 dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'ref', $morehtmlref, '', 0, '', '');
990
991 print '<div class="fichecenter">';
992 print '<div class="fichehalfleft">';
993 print '<div class="underbanner clearboth"></div>';
994
995 print '<table class="border centpercent tableforfield">';
996
997 if ($action == 'edit') {
998 print '<tr><td class="titlefieldmiddle">'.$langs->trans("DateStartPeriod")."</td><td>";
999 print $form->selectDate($object->datesp, 'datesp', 0, 0, 0, 'datesp', 1);
1000 print "</td></tr>";
1001 } else {
1002 print "<tr>";
1003 print '<td class="titlefieldmiddle">' . $langs->trans("DateStartPeriod") . '</td><td>';
1004 print dol_print_date($object->datesp, 'day');
1005 print '</td></tr>';
1006 }
1007
1008 if ($action == 'edit') {
1009 print '<tr><td>'.$langs->trans("DateEndPeriod")."</td><td>";
1010 print $form->selectDate($object->dateep, 'dateep', 0, 0, 0, 'dateep', 1);
1011 print "</td></tr>";
1012 } else {
1013 print "<tr>";
1014 print '<td>' . $langs->trans("DateEndPeriod") . '</td><td>';
1015 print dol_print_date($object->dateep, 'day');
1016 print '</td></tr>';
1017 }
1018
1019 if ($action == 'edit') {
1020 print '<tr><td class="fieldrequired">' . $langs->trans("Amount") . '</td><td><input name="amount" size="10" value="' . price($object->amount) . '"></td></tr>';
1021 } else {
1022 print '<tr><td>' . $langs->trans("Amount") . '</td><td><span class="amount">' . price($object->amount, 0, $langs, 1, -1, -1, $conf->currency) . '</span></td></tr>';
1023 }
1024
1025 // Default mode of payment
1026 print '<tr><td>';
1027 print '<table class="nobordernopadding" width="100%"><tr><td>';
1028 print $langs->trans('DefaultPaymentMode');
1029 print '</td>';
1030 if ($action != 'editmode') {
1031 print '<td class="right"><a class="editfielda" href="'.dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'editmode', 'id' => $object->id], true).'">'.img_edit($langs->trans('SetMode'), 1).'</a></td>';
1032 }
1033 print '</tr></table>';
1034 print '</td><td>';
1035
1036 if ($action == 'editmode') {
1037 $form->form_modes_reglement($pageurl, (string) $object->type_payment, 'mode_reglement_id');
1038 } else {
1039 $form->form_modes_reglement($pageurl, (string) $object->type_payment, 'none');
1040 }
1041 print '</td></tr>';
1042
1043 // Default Bank Account
1044 if (isModEnabled("bank")) {
1045 print '<tr><td class="nowrap">';
1046 print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
1047 print $langs->trans('DefaultBankAccount');
1048 print '<td>';
1049 if ($action != 'editbankaccount' && $permissiontoadd) {
1050 print '<td class="right"><a class="editfielda" href="'.dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'editbankaccount', 'id' => $object->id], true).'">'.img_edit($langs->trans('SetBankAccount'), 1).'</a></td>';
1051 }
1052 print '</tr></table>';
1053 print '</td><td>';
1054 if ($action == 'editbankaccount') {
1055 $form->formSelectAccount($pageurl, (string) $object->fk_account, 'fk_account', 1);
1056 } else {
1057 $form->formSelectAccount($pageurl, (string) $object->fk_account, 'none');
1058 }
1059 print '</td>';
1060 print '</tr>';
1061 }
1062
1063 // Other attributes
1064 include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
1065
1066 print '</table>';
1067
1068 print '</div>';
1069
1070 print '<div class="fichehalfright">';
1071
1072 $nbcols = 3;
1073 if (isModEnabled("bank")) {
1074 $nbcols++;
1075 }
1076
1077 /*
1078 * Payments
1079 */
1080 $sql = "SELECT p.rowid, p.num_payment as num_payment, p.datep as dp, p.amount,";
1081 $sql .= " c.code as type_code,c.libelle as paiement_type,";
1082 $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.currency_code as bacurrency_code, ba.fk_accountancy_journal';
1083 $sql .= " FROM ".MAIN_DB_PREFIX."payment_salary as p";
1084 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank as b ON p.fk_bank = b.rowid';
1085 $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'bank_account as ba ON b.fk_account = ba.rowid';
1086 $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_paiement as c ON p.fk_typepayment = c.id";
1087 $sql .= ", ".MAIN_DB_PREFIX."salary as salaire";
1088 $sql .= " WHERE p.fk_salary = ".((int) $id);
1089 $sql .= " AND p.fk_salary = salaire.rowid";
1090 $sql .= " AND salaire.entity IN (".getEntity('tax').")";
1091 $sql .= " ORDER BY dp DESC";
1092 //print $sql;
1093 $resql = $db->query($sql);
1094 if ($resql) {
1095 $totalpaid = 0;
1096
1097 $num = $db->num_rows($resql);
1098 $i = 0;
1099
1100 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
1101 print '<table class="noborder paymenttable">';
1102 print '<tr class="liste_titre">';
1103 print '<td>'.$langs->trans("RefPayment").'</td>';
1104 print '<td>'.$langs->trans("Date").'</td>';
1105 print '<td>'.$langs->trans("Type").'</td>';
1106 if (isModEnabled("bank")) {
1107 print '<td class="liste_titre right">'.$langs->trans('BankAccount').'</td>';
1108 }
1109 print '<td class="right">'.$langs->trans("Amount").'</td>';
1110 print '</tr>';
1111
1112 $paymentsalarytemp = new PaymentSalary($db);
1113
1114 if ($num > 0) {
1115 $bankaccountstatic = new Account($db);
1116 $objp = $objp ?? null;
1117 while ($i < $num) {
1118 $objp = $db->fetch_object($resql);
1119
1120 $paymentsalarytemp->id = $objp->rowid;
1121 $paymentsalarytemp->ref = $objp->rowid;
1122 $paymentsalarytemp->num_payment = $objp->num_payment;
1123 $paymentsalarytemp->datep = $objp->dp;
1124
1125 print '<tr class="oddeven"><td>';
1126 print $paymentsalarytemp->getNomUrl(1);
1127 print '</td>';
1128 print '<td>'.dol_print_date($db->jdate($objp->dp), 'dayhour', 'tzuserrel')."</td>\n";
1129 $labeltype = $langs->trans("PaymentType".$objp->type_code) != "PaymentType".$objp->type_code ? $langs->trans("PaymentType".$objp->type_code) : $objp->paiement_type;
1130 print "<td>".$labeltype.' '.$objp->num_payment."</td>\n";
1131 if (isModEnabled("bank")) {
1132 $bankaccountstatic->id = $objp->baid;
1133 $bankaccountstatic->ref = $objp->baref;
1134 $bankaccountstatic->label = $objp->baref;
1135 $bankaccountstatic->number = $objp->banumber;
1136 $bankaccountstatic->currency_code = $objp->bacurrency_code;
1137
1138 if (isModEnabled('accounting')) {
1139 $bankaccountstatic->account_number = $objp->account_number;
1140
1141 $accountingjournal = new AccountingJournal($db);
1142 $accountingjournal->fetch($objp->fk_accountancy_journal);
1143 $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0, 1, 1, '', 1);
1144 }
1145
1146 print '<td class="right">';
1147 if ($bankaccountstatic->id) {
1148 print $bankaccountstatic->getNomUrl(1, 'transactions');
1149 }
1150 print '</td>';
1151 }
1152 print '<td class="right nowrap amountcard">'.price($objp->amount)."</td>\n";
1153 print "</tr>";
1154 $totalpaid += $objp->amount;
1155 $i++;
1156 }
1157 } else {
1158 print '<tr class="oddeven"><td><span class="opacitymedium">'.$langs->trans("None").'</span></td>';
1159 print '<td></td><td></td><td></td><td></td>';
1160 print '</tr>';
1161 }
1162
1163 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans("AlreadyPaid").' :</td><td class="right nowrap amountcard">'.price($totalpaid)."</td></tr>\n";
1164 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans("AmountExpected").' :</td><td class="right nowrap amountcard">'.price($object->amount)."</td></tr>\n";
1165
1166 $resteapayer = (float) $object->amount - $totalpaid;
1167 $cssforamountpaymentcomplete = 'amountpaymentcomplete';
1168
1169 print '<tr><td colspan="'.$nbcols.'" class="right">'.$langs->trans("RemainderToPay")." :</td>";
1170 print '<td class="right nowrap'.($resteapayer ? ' amountremaintopay' : (' '.$cssforamountpaymentcomplete)).'">'.price($resteapayer)."</td></tr>\n";
1171
1172 print "</table>";
1173 print '</div>';
1174
1175 $db->free($resql);
1176 } else {
1177 dol_print_error($db);
1178 }
1179
1180 print '</div>';
1181 print '</div>';
1182
1183 print '<div class="clearboth"></div>';
1184
1185 print dol_get_fiche_end();
1186
1187 if ($action == 'edit') {
1188 print $form->buttonsSaveCancel();
1189 print "</form>";
1190 }
1191
1192 $resteapayer = price2num($resteapayer, 'MT');
1193
1194
1195 /*
1196 * Action bar
1197 */
1198
1199 print '<div class="tabsAction">'."\n";
1200 if ($action != 'edit') {
1201 // Dynamic send mail button
1202 $parameters = array();
1203 $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1204 if (empty($reshook)) {
1205 if (empty($user->socid)) {
1206 $canSendMail = true;
1207
1208 print dolGetButtonAction($langs->trans('SendMail'), '', 'default', dolBuildUrl($_SERVER['PHP_SELF'], ['id' => $object->id, 'action' => 'presend', 'mode' => 'init'], true).'#formmailbeforetitle', '', $canSendMail);
1209 }
1210 }
1211
1212 // Reopen
1213 if ($object->status == $object::STATUS_PAID && $permissiontoadd) {
1214 print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'reopen', 'id' => $object->id], true), '');
1215 }
1216
1217 // Edit
1218 if ($object->status == $object::STATUS_UNPAID && $permissiontoadd) {
1219 print dolGetButtonAction('', $langs->trans('Modify'), 'default', dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'edit', 'id' => $object->id]), '');
1220 }
1221
1222 // Transfer request
1223 if ($object->status == $object::STATUS_UNPAID && ((price2num($object->amount) < 0 && $resteapayer < 0) || (price2num($object->amount) > 0 && $resteapayer > 0)) && $permissiontoadd) {
1224 print dolGetButtonAction('', $langs->trans('MakeTransferRequest'), 'default', dolBuildUrl(DOL_URL_ROOT . '/salaries/virement_request.php', ['id' => $object->id]), '');
1225 }
1226
1227 // Emit payment
1228 if ($object->status == $object::STATUS_UNPAID && ((price2num($object->amount) < 0 && $resteapayer < 0) || (price2num($object->amount) > 0 && $resteapayer > 0)) && $permissiontoadd) {
1229 print dolGetButtonAction('', $langs->trans('DoPayment'), 'default', dolBuildUrl(DOL_URL_ROOT.'/salaries/payment_salary.php', ['action' => 'create', 'id' => $object->id], false), '');
1230 }
1231
1232 // Classify 'paid'
1233 // If payment complete $resteapayer <= 0 on a positive salary, or if amount is negative, we allow to classify as paid.
1234 if ($object->status == $object::STATUS_UNPAID && (($resteapayer <= 0 && $object->amount > 0) || ($object->amount <= 0)) && $permissiontoadd) {
1235 print dolGetButtonAction('', $langs->trans('ClassifyPaid'), 'default', dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'paid', 'id' => $object->id], true), '');
1236 }
1237
1238 // Clone
1239 if ($permissiontoadd) {
1240 print dolGetButtonAction($langs->trans('ToClone'), $langs->trans('ToClone'), 'clone', dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'clone', 'id' => $object->id], true), '', true, array('attr' => array('class' => 'reposition')));
1241 }
1242
1243 if ($permissiontodelete && empty($totalpaid)) {
1244 print dolGetButtonAction($langs->trans('Delete'), $langs->trans('Delete'), 'delete', dolBuildUrl($_SERVER["PHP_SELF"], ['action' => 'delete', 'id' => $object->id], true), '', true, array('attr' => array('class' => 'reposition')))."\n";
1245 } else {
1246 print dolGetButtonAction($langs->trans('DisabledBecausePayments'), $langs->trans('Delete'), 'default', dolBuildUrl($_SERVER['PHP_SELF']).'#', '', false);
1247 }
1248 }
1249 print "</div>";
1250
1251
1252
1253 // Select mail models is same action as presend
1254 if (GETPOST('modelselected')) {
1255 $action = 'presend';
1256 }
1257
1258 if ($action != 'presend') {
1259 print '<div class="fichecenter"><div class="fichehalfleft">';
1260 print '<a name="builddoc"></a>'; // ancre
1261
1262 $includedocgeneration = 1;
1263
1264 // Documents
1265 if ($includedocgeneration) {
1266 // Force values if object properties are missing
1267 $object->element = 'salary';
1268 if (empty($object->ref)) $object->ref = (string) $object->id;
1269
1270 $objref = dol_sanitizeFileName($object->ref);
1271 $filedir = $conf->salaries->dir_output.'/'.$object->element.'/'.$objref;
1272 $urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
1273
1274 $genallowed = 1;
1275 $genallowed = ($user->hasRight('salaries', 'read') || $user->hasRight('salaries', 'readall'));
1276 $delallowed = $user->hasRight('salaries', 'write');
1277
1278 print $formfile->showdocuments(
1279 'salaries:Salary',
1280 $object->element.'/'.$objref,
1281 $filedir,
1282 $urlsource,
1283 (int) $genallowed,
1284 $delallowed,
1285 $object->model_pdf,
1286 1, 0, 0, 28, 0, '', '', '', $langs->defaultlang
1287 );
1288 }
1289
1290 // Show links to link elements
1291 /*
1292 $tmparray = $form->showLinkToObjectBlock($object, array(), array('salaries'), 1);
1293 $linktoelem = $tmparray['linktoelem'];
1294 $htmltoenteralink = $tmparray['htmltoenteralink'];
1295 print $htmltoenteralink;
1296
1297 $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
1298 */
1299
1300 print '</div><div class="fichehalfright">';
1301
1302 $MAXEVENT = 10;
1303
1304 $morehtmlcenter = dolGetButtonTitle($langs->trans('SeeAll'), '', 'fa fa-bars imgforviewmode', dol_buildpath('/mymodule/myobject_agenda.php', 1).'?id='.$object->id);
1305
1306 // List of actions on element
1307 include_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
1308 $formactions = new FormActions($db);
1309 //$somethingshown = $formactions->showactions($object, $object->element.'@'.$object->module, (is_object($object->thirdparty) ? $object->thirdparty->id : 0), 1, '', $MAXEVENT, '', $morehtmlcenter);
1310
1311 print '</div></div>';
1312 }
1313
1314 // Select mail models is same action as presend
1315 if (GETPOST('modelselected')) {
1316 $action = 'presend';
1317 }
1318
1319 // Presend form
1320 $modelmail = 'salary';
1321 $defaulttopic = 'InformationMessage';
1322 $diroutput = $conf->salaries->dir_output;
1323 $trackid = 'salary'.$object->id;
1324
1325 include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
1326
1327 // Hook to add more things on page
1328 $parameters = array();
1329 $reshook = $hookmanager->executeHooks('salaryCardTabAddMore', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
1330}
1331
1332// End of page
1333llxFooter();
1334$db->close();
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
$propal type
'integer', 'integer:ObjectClass:PathToClass[:AddCreateButtonOrNot[:Filter[:Sortfield]]]',...
Definition propal.php:280
llxFooter($comment='', $zone='private', $disabledoutputofmessages=0)
Empty footer.
Definition wrapper.php:91
if(!defined('NOREQUIRESOC')) if(!defined( 'NOREQUIRETRAN')) if(!defined('NOTOKENRENEWAL')) if(!defined( 'NOREQUIREMENU')) if(!defined('NOREQUIREHTML')) if(!defined( 'NOREQUIREAJAX')) llxHeader($head='', $title='', $help_url='', $target='', $disablejs=0, $disablehead=0, $arrayofjs='', $arrayofcss='', $morequerystring='', $morecssonbody='', $replacemainareaby='', $disablenofollow=0, $disablenoindex=0)
Empty header.
Definition wrapper.php:73
Class to manage bank accounts.
Class to manage accounting journals.
Class to manage standard extra fields.
Class to manage building of HTML components.
Class to offer components to list and upload files.
Class to manage generation of HTML components Only common components must be here.
Class to manage building of HTML components.
Class to manage payments of salaries.
Class to manage projects.
Class to manage salary payments.
Class to manage Dolibarr users.
dol_get_first_day($year, $month=1, $gm=false)
Return GMT time for first day of a month or year.
Definition date.lib.php:616
dol_get_last_day($year, $month=12, $gm=false)
Return GMT time for last day of a month or year.
Definition date.lib.php:635
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
dol_now($mode='gmt')
Return date for now.
recordNotFound($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Displays an error page when a record is not found.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
price2num($amount, $rounding='', $option=0)
Function that return a number with universal decimal format (decimal separator is '.
dolBuildUrl($url, $params=[], $addtoken=false, $anchor='')
Return path of url.
dol_eval($s, $returnvalue=1, $hideerrors=1, $onlysimplestring='1')
Replace eval function to add more security.
dol_sanitizeFileName($str, $newstr='_', $unaccent=1, $includequotes=0, $allowdash=0)
Clean a string to use it as a file name.
price($amount, $form=0, $outlangs='', $trunc=1, $rounding=-1, $forcerounding=-1, $currency_code='')
Function to format a value into an amount for visual output Function used into PDF and HTML pages.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_buildpath($path, $type=0, $returnemptyifnotfound=0)
Return path of url or filesystem.
dol_clone($srcobject, $native=2)
Create a clone of instance of object (new instance with same value for each properties) With native =...
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
GETPOSTISSET($paramname)
Return true if we are in a context of submitting the parameter $paramname from a POST of a form.
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
multi select button
0 = Do not include form tag and submit button -1 = Do not include form tag but include submit button
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:540
dolGetButtonTitle($label, $helpText='', $iconClass='fa fa-file', $url='', $id='', $status=1, $params=array())
Function dolGetButtonTitle : this kind of buttons are used in title in list.
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:738
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as p p num_paiement as f pf amount as amount
Definition receipt.php:494
print $langs trans('Date')." left Ref Label right Qty right Price right TotalHT right TotalTTC right right right right right right right right right centpercent right TotalHT right n right VAT right n right TotalVAT right n No sujeto a RE IRPF right TotalLT1 right n right TotalLT2 right n right TotalTTC right n takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency takeposcustomercurrency right TotalTTC takeposcustomercurrency right takeposcustomercurrency n right Paid right PaymentTypeShortLIQ right SELECT p pos_change as p datep as date
Definition receipt.php:492
$conf db name
Only used if Module[ID]Name translation string is not found.
Definition repair.php:140
restrictedArea(User $user, $features, $object=0, $tableandshare='', $feature2='', $dbt_keyfield='fk_soc', $dbt_select='rowid', $isdraft=0, $nodie=0, $mode='')
Check permissions of a user to show a page and an object.
accessforbidden($message='', $printheader=1, $printfooter=1, $showonlymessage=0, $params=null)
Show a message to say access is forbidden and stop program.