Compare commits

...

77 Commits

Author SHA1 Message Date
Laurent Destailleur
8fe5d2758a Fix CI 2025-12-04 21:48:44 +01:00
Laurent Destailleur
9d307a4238 Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2025-12-04 19:07:33 +01:00
Laurent Destailleur
222cd76799 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-12-04 18:53:04 +01:00
Laurent Destailleur
47799b88cf Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2025-12-04 18:40:23 +01:00
Laurent Destailleur
78ca968db6 Merge pull request #36517 from atm-florianm/SEC/commented-out-restrictedArea
SEC: FIX #36430 permissions not checked on other tabs of HRM evaluation card
2025-12-04 18:37:46 +01:00
Laurent Destailleur
aa8fac1deb Merge pull request #36429 from atm-adrien/FIX/MulticompanyStockCompatibility
FIX : Implementation of multi-company compatibility with inventory/warehouse management
2025-12-04 10:42:35 +01:00
Eric - CAP-REL
2ebdcfda5c Merge pull request #35788 from Easya-Solutions/18_allow_credit_invoice_on_situation
FIX : remove useless condition to create credit on situation invoice …
2025-12-04 09:56:30 +01:00
Eric - CAP-REL
70431043af Merge pull request #36398 from Easya-Solutions/18.0_fix-invoice-card-variables
FIX undefined variables on create invoice from shipment card (backport from v20)
2025-12-04 09:30:56 +01:00
lvessiller-opendsi
ad37ece7bc Merge pull request #36494 from atm-florianm/FIX/155/date/minute-second-vs-min-sec
FIX 18.0: `GETPOSTDATE()` and `buildParamDate()` assumed wrong HTTP param names
2025-12-04 09:27:44 +01:00
atm-florian
a1476fd221 SEC: permissions not checked on other tabs of HRM evaluation card 2025-12-03 17:11:14 +01:00
atm-florian
0e1c580f11 FIX 18.0: GETPOSTDATE and buildParamDate assumed HTTP param names 'minute' and 'second' instead of 'min' and 'sec' 2025-12-01 13:47:50 +01:00
Laurent Destailleur
4223ff08ce Merge pull request #36491 from Easya-Solutions/18.0_fix-update-extras
FIX not remove value of others extra-fields on update extras action
2025-12-01 13:10:08 +01:00
VESSILLER
d16f8b68db FIX not remove value of others extra-fields on update extras action 2025-12-01 11:14:16 +01:00
Laurent Destailleur
f4bcf47008 Merge pull request #36467 from emheyarssi/35061
FIX #35061
2025-11-29 11:28:03 +01:00
marc
5c6b4f62c8 FIX #35061
Signed-off-by: marc <marc.baur@ptmsoft.fr>
2025-11-28 18:25:00 +01:00
Laurent Destailleur
d8891130f5 Merge pull request #36463 from vold-lu/18.0
NEW: Automatically release docker image for each GitHub release
2025-11-28 18:13:47 +01:00
Aloïs Micard
b2f9de7489 Add new workflow to trigger Docker build 2025-11-28 17:27:32 +01:00
Laurent Destailleur
6775fa611d Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2025-11-26 21:16:36 +01:00
Laurent Destailleur
17ff2bea5d Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-11-26 21:16:11 +01:00
Laurent Destailleur
1002557746 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2025-11-26 21:12:58 +01:00
Laurent Destailleur
908880c82c SEC: fix IDOR attack on employee evaluation. Missing permision test 7ed0af2a13
SEC: empty commit for CI automata
2025-11-26 15:41:53 +01:00
atm-florian
3608e9b102 SEC: 7ed0af2a13 2025-11-26 14:44:38 +01:00
Adrien Raze
c1c2358e75 FIX : Implementation of multi-company compatibility with inventory/warehouse management 2025-11-26 12:30:22 +01:00
Laurent Destailleur
b01bbd5c8f Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2025-11-25 21:09:55 +01:00
Laurent Destailleur
69ac8cebbf Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-11-25 21:09:26 +01:00
Laurent Destailleur
1e16bf5160 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2025-11-25 21:09:04 +01:00
Jon Bendtsen
5044b3a102 Qual: Undefined variable $errormessage in /var/www/html/core/customreports.php on line 951 (#36392)
* checking if variable is set before testing the contents

* more PHP warnings fixes detected during #35096

* using the fixed set above

* backport eldy's fix

---------

Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
2025-11-25 17:40:07 +01:00
Alexandre SPANGARO
d9b8abe3e4 FIX #36310 Accountancy - Data - Wrong account labels (cache) on write bookkeeping action (#36410)
* FIX #36310 Accountancy - Data - Wrong account labels (cache) on writebookkeeping action (#36379)

* Fix
2025-11-25 14:20:05 +01:00
Florian Mortgat
7f27552a95 FIX: empty origin type passed to addline when creating invoices from expeditions using massaction (confirm_createbills) (#36413) 2025-11-25 14:18:12 +01:00
Laurent Destailleur
71dc6dc1db Fix #35096 #36393 2025-11-24 19:18:31 +01:00
Florian Mortgat
c2635f5242 FIX 17.0: perweek.php resets task progress to 0% when: (#36401)
* FIX 17.0: perweek.php resets task progress to 0% when:
1. the column "Declared real progress" is hidden (which means the corresponding form inputs won't be displayed)
2. and the user doesn't enter any time for that task (= leaves the input empty)

If the column is shown, the bug doesn't occur because the correct value is sent with $_POST.
If the user enters time, the bug doesn't occur because there is a GETPOSTISSET test for that case.

* Apply suggestion from @atm-florianm

variable name ($taskid vs $tmptaskid)
2025-11-24 16:32:27 +01:00
Laurent Destailleur
b9e6243ec8 Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2025-11-24 16:16:00 +01:00
Laurent Destailleur
9394f24cf7 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-11-24 16:15:26 +01:00
Laurent Destailleur
b1a4520059 Merge branch '17.0' of git@github.com:Dolibarr/dolibarr.git into 18.0 2025-11-24 16:10:29 +01:00
Laurent Destailleur
2935a245a3 Merge branch '16.0' of git@github.com:/Dolibarr/dolibarr.git into 17.0 2025-11-24 16:07:46 +01:00
Laurent Destailleur
5589ed71b2 Merge branch '15.0' of git@github.com:Dolibarr/dolibarr.git into 16.0 2025-11-24 16:07:22 +01:00
Laurent Destailleur
32f160355b Merge branch '14.0' of git@github.com:Dolibarr/dolibarr.git into 15.0 2025-11-24 16:03:52 +01:00
Florian Mortgat
5a61cc9393 FIX DA027383: permissions not checked on HRM evaluation card (#36328) (#36399)
Permissions involved:
- hrm->evaluation->readall: the user can view anyone's evaluations
- hrm->evaluation->read: the user can only view their or their subordinates' evaluations
2025-11-24 14:57:20 +01:00
Florian Mortgat
7ed0af2a13 FIX DA027383: permissions not checked on HRM evaluation card (#36328)
Permissions involved:
- hrm->evaluation->readall: the user can view anyone's evaluations
- hrm->evaluation->read: the user can only view their or their subordinates' evaluations
2025-11-24 12:21:51 +01:00
VESSILLER
1cd3ca3222 FIX undefined variables on create invoice from shipment card (backport from v20) 2025-11-24 10:30:08 +01:00
iLLixM
0e8d4461c4 Fix: Prevent negative payment amount in EPC-QR Code (#36364) 2025-11-21 18:34:24 +01:00
Regis Houssin
0e1ac03fb0 FIX #36347 (#36358) 2025-11-21 11:15:34 +01:00
Eric - CAP-REL
c8acd48e34 setErrors does not exists, same solution as dolibarr v19.0 (#36107)
* setErrors does not exists, same solution as dolibarr v19.0

* reload ci

* reload ci 2

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: lvessiller-opendsi <lvessiller@open-dsi.fr>
2025-11-20 23:58:15 +01:00
Laurent Destailleur
734ef58a2a Fix CI 2025-11-20 20:27:43 +01:00
ldestailleur
9e8460c3dc Fix CI 2025-11-20 15:17:01 +01:00
ldestailleur
70f5e20572 Fix CI 2025-11-20 15:16:04 +01:00
Laurent Destailleur
3a617ed772 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-11-20 15:14:27 +01:00
Laurent Destailleur
f32386208d Fix CI 2025-11-20 15:14:09 +01:00
Laurent Destailleur
1adf4ce67f Fix CI 2025-11-20 15:13:52 +01:00
Laurent Destailleur
ecda16a5f6 Merge branch '19.0' of git@github.com:Dolibarr/dolibarr.git into 20.0 2025-11-20 11:48:23 +01:00
Laurent Destailleur
515a615915 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into 19.0 2025-11-20 11:44:40 +01:00
noec764
ac4820b4cb FIX: TakePOS Missing Thirdparty Id when getting more products (#36341)
Co-authored-by: Noé <noe@scopen.fr>
2025-11-20 11:34:06 +01:00
Eric Seigne
f9d285c416 Merge branch '18.0' of https://github.com/Dolibarr/dolibarr into 18.0 2025-11-20 10:09:57 +01:00
Eric Seigne
f1f7ea93b0 fix assign-and-label-v18 2025-11-20 10:09:29 +01:00
lvessiller-opendsi
1f6cec841f Merge pull request #35795 from hregis/fix_18_multicompany_compatibility
FIX Multicompany compatibility with "project_task"
2025-11-20 10:03:38 +01:00
lvessiller-opendsi
4dcbd826e6 Merge pull request #35812 from Easya-Solutions/18__fix_situation_remove_from_cycle
FIX remove situation invoice from cycle
2025-11-20 10:03:02 +01:00
Eric Seigne
fd5c9b0562 update github actions for race conditions of author/reviewer 2025-11-20 09:46:59 +01:00
iLLixM
8d038f32bc FIX #33148 - partial payments are taken into account in EPC QR codes (#36338)
When generating EPC QR codes on an invoice, any partial payments already made are taken into account. The remaining balance (the value of "Remaining unpaid") is then entered as the amount in the EPC QR code.
2025-11-20 01:49:24 +01:00
Florian Mortgat
c0850d9a3f FIX DA027383: permissions not checked on HRM evaluation card (#36328)
Permissions involved:
- hrm->evaluation->readall: the user can view anyone's evaluations
- hrm->evaluation->read: the user can only view their or their subordinates' evaluations
2025-11-19 19:19:55 +01:00
Florian Mortgat
8e30fc0bd1 FIX 19.0 - attachments upload dir for invoices not always determined correctly (doesn't always take multi-entity into account) (#36302) 2025-11-18 11:39:45 +01:00
Regis Houssin
2027f9c951 FIX avoid php warnings (#36301) 2025-11-18 11:31:38 +01:00
Regis Houssin
21843e68b0 FIX #36149 (#36150) 2025-11-18 10:12:05 +01:00
noec764
cd984fa6c5 FIX: Object should be cloned here (#36289)
Co-authored-by: Noé <noe@scopen.fr>
2025-11-17 21:18:28 +01:00
Laurent Destailleur
278983c4e7 Fix CI 2025-11-17 21:16:46 +01:00
lvessiller-opendsi
30ecf80732 FIX keep user who validate proposal on update (#36257) 2025-11-14 15:53:31 +01:00
lvessiller-opendsi
9de04b1c48 Merge pull request #35809 from marc-dll/18.0_FIX_expensereport_bankaccount_access
FIX: expense report card: do not show bank account if user cannot see them
2025-11-13 09:39:39 +01:00
Eric - CAP-REL
7e7939d234 Merge pull request #35893 from RyAbn/18.0_FIX_Email_collector_no_msg_parts_fatal_error
FIX: Email Collector Module
2025-11-13 09:22:44 +01:00
Noé Cendrier
e5480945bc FIX: Mo::deleteLine() - stock movement correction (#34733)
* FIX: Mo::deleteLine() - stock movement correction should not rely on linked lines

* FIX: do not permit product line to consume removal if product consumption started
2025-11-12 23:59:15 +01:00
Regis Houssin
3ad30f8622 FIX use array_intersect instead in_array 2025-11-07 12:07:50 +01:00
Regis Houssin
3b7cda03f3 Merge branch '18.0' of git@github.com:Dolibarr/dolibarr.git into fix_18_multicompany_compatibility 2025-11-07 12:04:44 +01:00
Marc de Lima Lucio
223326610e FIX: expense report card: use correct bank module designator for detection 2025-10-31 13:43:21 +01:00
Ryad ABANI
38980a935c FIX: Email Collector Module: manage error when imap_fetchstructure return false. Previously it generated warning and fatal error because the returned value was not of type class 2025-10-22 11:56:07 +02:00
tnegre
66d72d0bba FIX allow a situation with credit to be removed from cycle 2025-10-17 14:13:25 +02:00
Marc de Lima Lucio
403dad1660 FIX: expense report card: do not show bank account if user cannot see them 2025-10-17 13:56:07 +02:00
Regis Houssin
12d078c651 FIXX clean code 2025-10-16 19:33:38 +02:00
Regis Houssin
0dbbd453e5 FIX Multicompany compatibility with "project_task" 2025-10-16 19:10:32 +02:00
tnegre
8ddf9f6075 FIX : remove useless condition to create credit on situation invoice (#35786) 2025-10-16 11:57:49 +02:00
36 changed files with 274 additions and 176 deletions

24
.github/workflows/ci-on-release.yml vendored Normal file
View File

@@ -0,0 +1,24 @@
name: "CI-RELEASE"
on:
release:
types: [published]
jobs:
trigger-docker:
runs-on: ubuntu-latest
steps:
- name: Generate a token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ vars.RELEASE_DOCKER_ID }}
private-key: ${{ secrets.RELEASE_DOCKER_SECRET }}
- uses: peter-evans/repository-dispatch@v4
with:
token: ${{ steps.generate-token.outputs.token }}
repository: Dolibarr/dolibarr-docker
event-type: new-release
client-payload: '{"version": "${{ github.event.release.tag_name }}"}'

View File

@@ -321,6 +321,16 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
if (!$errorforline) {
foreach ($tabht[$key] as $k => $mt) {
if ($mt) {
if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
$accountingaccount = new AccountingAccount($db);
$accountingaccount->fetch(0, $k, true);
$conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
} else {
$accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
}
$account_label = $accountingaccount->label;
// get compte id and label
if ($accountingaccount->fetch(null, $k, true)) {
$bookkeeping = new BookKeeping($db);
@@ -335,9 +345,9 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
$bookkeeping->subledger_label = '';
$bookkeeping->numero_compte = $k;
$bookkeeping->label_compte = $accountingaccount->label;
$bookkeeping->label_compte = $account_label;
$bookkeeping->label_operation = $accountingaccount->label;
$bookkeeping->label_operation = $account_label;
$bookkeeping->montant = $mt;
$bookkeeping->sens = ($mt < 0) ? 'C' : 'D';
$bookkeeping->debit = ($mt > 0) ? $mt : 0;
@@ -383,12 +393,12 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
foreach ($arrayofvat[$key] as $k => $mt) {
if ($mt) {
if (empty($conf->cache['accountingaccountincurrententity'][$k])) {
if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
$accountingaccount = new AccountingAccount($db);
$accountingaccount->fetch(0, $k, true);
$conf->cache['accountingaccountincurrententity'][$k] = $accountingaccount;
$conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
} else {
$accountingaccount = $conf->cache['accountingaccountincurrententity'][$k];
$accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
}
$account_label = $accountingaccount->label;

View File

@@ -616,7 +616,14 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
foreach ($arrayofvat[$key] as $k => $mt) {
if ($mt) {
$accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
$accountingaccount = new AccountingAccount($db);
$accountingaccount->fetch(0, $k, true);
$conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
} else {
$accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
}
$label_account = $accountingaccount->label;
$bookkeeping = new BookKeeping($db);

View File

@@ -679,7 +679,14 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
foreach ($arrayofvat[$key] as $k => $mt) {
if ($mt) {
$accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
if (empty($conf->cache['accountingaccountincurrententity_vat'][$k])) {
$accountingaccount = new AccountingAccount($db);
$accountingaccount->fetch(0, $k, true);
$conf->cache['accountingaccountincurrententity_vat'][$k] = $accountingaccount;
} else {
$accountingaccount = $conf->cache['accountingaccountincurrententity_vat'][$k];
}
$label_account = $accountingaccount->label;
$bookkeeping = new BookKeeping($db);
@@ -740,7 +747,14 @@ if ($action == 'writebookkeeping' && !$error && $user->hasRight('accounting', 'b
if (isset($tabrevenuestamp[$key]) && is_array($tabrevenuestamp[$key])) {
foreach ($tabrevenuestamp[$key] as $k => $mt) {
if ($mt) {
$accountingaccount->fetch(null, $k, true); // TODO Use a cache for label
if (empty($conf->cache['accountingaccountincurrententity_rs'][$k])) {
$accountingaccount = new AccountingAccount($db);
$accountingaccount->fetch(0, $k, true);
$conf->cache['accountingaccountincurrententity_rs'][$k] = $accountingaccount;
} else {
$accountingaccount = $conf->cache['accountingaccountincurrententity_rs'][$k];
}
$label_account = $accountingaccount->label;
$bookkeeping = new BookKeeping($db);

View File

@@ -958,7 +958,7 @@ class Categorie extends CommonObject
$obj->id = 0;
$obj->fetch($rec['fk_object']);
if ($obj->id > 0) { // Failing fetch may happen for example when a category supplier was set and third party was moved as customer only. The object supplier can't be loaded.
$objs[] = $obj;
$objs[] = clone $obj;
}
}
}

View File

@@ -1768,7 +1768,7 @@ class Propal extends CommonObject
$sql .= " total_ttc=".(isset($this->total_ttc) ? $this->total_ttc : "null").",";
$sql .= " fk_statut=".(isset($this->statut) ? $this->statut : "null").",";
$sql .= " fk_user_author=".(isset($this->user_author_id) ? $this->user_author_id : "null").",";
$sql .= " fk_user_valid=".(isset($this->user_validation_id) ? $this->user_validation_id : "null").",";
$sql .= " fk_user_valid = ".(!empty($this->user_validation_id) ? (int) $this->user_validation_id : "null").",";
$sql .= " fk_projet=".(isset($this->fk_project) ? $this->fk_project : "null").",";
$sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->cond_reglement_id : "null").",";
$sql .= " deposit_percent=".(!empty($this->deposit_percent) ? "'".$this->db->escape($this->deposit_percent)."'" : "null").",";
@@ -2064,7 +2064,6 @@ class Propal extends CommonObject
$this->ref = $num;
$this->statut = self::STATUS_VALIDATED;
$this->status = self::STATUS_VALIDATED;
$this->user_validation_id = $user->id;
$this->datev = $now;
$this->date_validation = $now;

View File

@@ -223,7 +223,7 @@ if ($resql) {
$transactionspertype = array();
$amountpertype = array();
$totalarray = array('nbfield' => 0, 'pos' => array());
$totalarray = array('nbfield' => 0, 'pos' => array(), 'val' => array('totaldebfield' => 0, 'totalcredfield' => 0));
while ($i < $num) {
$objp = $db->fetch_object($resql);

View File

@@ -2526,7 +2526,7 @@ if (empty($reshook)) {
}
// Insert line
$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, GETPOSTINT('progress'), 0, $fk_unit, $pu_ht_devise);
$result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, 0, $price_base_type, $pu_ttc, $type, min($rank, count($object->lines) + 1), $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, GETPOST('progress'), 0, $fk_unit, $pu_ht_devise);
if ($result > 0) {
// Define output language and generate document
@@ -5230,6 +5230,7 @@ if ($action == 'create') {
print '<td>'.$langs->trans('ListOfSituationInvoices').'</td>';
print '<td></td>';
print '<td class="center">'.$langs->trans('Situation').'</td>';
if (isModEnabled("bank")) {
print '<td class="right"></td>';
}
@@ -5321,7 +5322,9 @@ if ($action == 'create') {
$total_next_ht = $total_next_ttc = 0;
foreach ($object->tab_next_situation_invoice as $next_invoice) {
$totalpaid = $next_invoice->getSommePaiement();
$next_invoice_total_paid = $next_invoice->getSommePaiement(0);
$next_invoice_totalcreditnotes = $next_invoice->getSumCreditNotesUsed(0);
$next_invoice_totaldeposits = $next_invoice->getSumDepositsUsed(0);
$total_next_ht += $next_invoice->total_ht;
$total_next_ttc += $next_invoice->total_ttc;
@@ -5334,7 +5337,7 @@ if ($action == 'create') {
}
print '<td class="right"><span class="amount">'.price($next_invoice->total_ht).'</span></td>';
print '<td class="right"><span class="amount">'.price($next_invoice->total_ttc).'</span></td>';
print '<td class="right">'.$next_invoice->getLibStatut(3, $totalpaid).'</td>';
print '<td class="right">'.$next_invoice->getLibStatut(3, $next_invoice_total_paid + $next_invoice_totalcreditnotes + $next_invoice_totaldeposits).'</td>';
print '</tr>';
}
@@ -6000,7 +6003,6 @@ if ($action == 'create') {
// For situation invoice with excess received
if ($object->status > Facture::STATUS_DRAFT
&& $object->type == Facture::TYPE_SITUATION
&& ($object->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits) > 0
&& $usercancreate
&& !$objectidnext
&& $object->is_last_in_cycle()

View File

@@ -68,11 +68,13 @@ if (!$sortfield) {
}
$object = new Facture($db);
if ($object->fetch($id, $ref)) {
if ($object->fetch($id, $ref) > 0) {
$object->fetch_thirdparty();
$upload_dir = $conf->facture->dir_output."/".dol_sanitizeFileName($object->ref);
}
$upload_dir = $conf->facture->multidir_output[isset($object->entity) ? $object->entity : 1].'/'.dol_sanitizeFileName($object->ref);
$permissiontoadd = $user->hasRight('facture', 'creer');
// Security check
@@ -119,7 +121,6 @@ if ($id > 0 || !empty($ref)) {
if ($object->fetch($id, $ref) > 0) {
$object->fetch_thirdparty();
$upload_dir = $conf->facture->multidir_output[$object->entity].'/'.dol_sanitizeFileName($object->ref);
$head = facture_prepare_head($object);
print dol_get_fiche_head($head, 'documents', $langs->trans('InvoiceCustomer'), -1, 'bill');

View File

@@ -396,7 +396,7 @@ if ($action == "update_extras" && GETPOSTINT('id') > 0 && !empty($permissiontoad
$object->oldcopy = dol_clone($object, 2);
$attribute = GETPOST('attribute', 'alphanohtml');
$attribute = GETPOST('attribute', 'aZ09');
$error = 0;

View File

@@ -57,6 +57,10 @@ class CLeadStatus extends CommonDict
*/
public $percent;
public $fields = array(
'rowid' => array('type' => 'integer', 'label' => 'TechnicalID', 'enabled' => 1, 'position' => 1, 'notnull' => 1, 'visible' => 0, 'noteditable' => 1, 'index' => 1, 'css' => 'left', 'comment' => "Id"),
'label' => array('type' => 'varchar(128)', 'label' => 'Label', 'enabled' => 1, 'position' => 20, 'notnull' => 1, 'visible' => 1, 'index' => 1, 'searchall' => 1, 'showoncombobox' => 1, 'comment' => "Label of status"),
);
/**
* Constructor

View File

@@ -1660,8 +1660,20 @@ abstract class CommonInvoice extends CommonObject
{
global $mysoc;
// Convert total_ttc to a string with 2 decimal places
$totalTTCString = number_format($this->total_ttc, 2, '.', '');
// Get the amount to pay
if (method_exists($this, 'getRemainToPay')) {
// Get remaining amount to pay
$amount_to_pay = $this->getRemainToPay();
} else {
// Use Total amount with taxes
$amount_to_pay = $this->total_ttc;
}
// Prevent negative values (e.g. overpayments)
$amount_to_pay = max(0, $amount_to_pay);
// Ensure numeric formatting for EPC QR code
$amount_to_pay = price2num($amount_to_pay, 'MT');
// Initialize an array to hold the lines of the QR code
$lines = array();
@@ -1689,7 +1701,7 @@ abstract class CommonInvoice extends CommonObject
}
// Add the amount and reference
$lines[] = 'EUR' . $totalTTCString; // Amount (optional)
$lines[] = 'EUR' . $amount_to_pay; // Amount (optional)
$lines[] = ''; // Purpose (optional)
$lines[] = ''; // Payment reference (optional)
$lines[] = $this->ref; // Remittance Information (optional)

View File

@@ -267,7 +267,6 @@ class FormSetup
$this->errors = $hookmanager->errors;
return -1;
}
if ($reshook > 0) {
return $reshook;
}

View File

@@ -121,6 +121,7 @@ $hookmanager->initHooks(array('customreport')); // Note that conf->hooks_modules
$title = '';
$picto = '';
$errormessage = null;
$head = array();
$ObjectClassName = '';
// Objects available by default
@@ -201,7 +202,11 @@ if ($user->socid > 0) { // Protection if external user
$extrafields->fetch_name_optionals_label('all'); // We load all extrafields definitions for all objects
//$extrafields->fetch_name_optionals_label($object->table_element_line);
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
if (!empty($object->table_element)) {
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
} else {
$search_array_options = array();
}
$search_component_params = array('');
$search_component_params_hidden = trim(GETPOST('search_component_params_hidden', 'alphanohtml'));
@@ -309,7 +314,11 @@ $arrayofgroupby = array();
$arrayofyaxis = array();
$arrayofvaluesforgroupby = array();
$features = $object->element;
if (!empty($object->element)) {
$features = $object->element;
} else {
$features = '';
}
if (!empty($object->element_for_permission)) {
$features = $object->element_for_permission;
} else {
@@ -1133,10 +1142,14 @@ if ($mode == 'graph') {
$dir = $conf->user->dir_temp;
dol_mkdir($dir);
// $customreportkey may be defined when using customreports.php as an include
$filenamekey = $dir.'/customreport_'.$object->element.(empty($customreportkey) ? '' : $customreportkey).'.png';
$fileurlkey = DOL_URL_ROOT.'/viewimage.php?modulepart=user&file=customreport_'.$object->element.(empty($customreportkey) ? '' : $customreportkey).'.png';
if (!empty($object->element)) {
$filenamekey = $dir.'/customreport_'.$object->element.(empty($customreportkey) ? '' : $customreportkey).'.png';
$fileurlkey = DOL_URL_ROOT.'/viewimage.php?modulepart=user&file=customreport_'.$object->element.(empty($customreportkey) ? '' : $customreportkey).'.png';
}
$px1->draw($filenamekey, $fileurlkey);
if (isset($filenamekey) && isset($fileurlkey)) {
$px1->draw($filenamekey, $fileurlkey);
}
$texttoshow = $langs->trans("NoRecordFound");
if (!GETPOSTISSET('search_measures') || !GETPOSTISSET('search_xaxis')) {

View File

@@ -3943,46 +3943,18 @@ function dol_print_socialnetworks($value, $cid, $socid, $type, $dictsocialnetwor
$htmllink .= ($link ? ' '.$link : '');
}
} else {
$networkconstname = 'MAIN_INFO_SOCIETE_'.strtoupper($type).'_URL';
if (getDolGlobalString($networkconstname)) {
$link = str_replace('{socialid}', $value, getDolGlobalString($networkconstname));
if (preg_match('/^https?:\/\//i', $link)) {
$htmllink .= '<a href="'.dol_sanitizeUrl($link, 0).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
} else {
$htmllink .= '<a href="'.dol_sanitizeUrl($link, 1).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
}
} elseif (!empty($dictsocialnetworks[$type]['url'])) {
$tmpvirginurl = preg_replace('/\/?{socialid}/', '', $dictsocialnetworks[$type]['url']);
if ($tmpvirginurl) {
$value = preg_replace('/^www\.'.preg_quote($tmpvirginurl, '/').'\/?/', '', $value);
$value = preg_replace('/^'.preg_quote($tmpvirginurl, '/').'\/?/', '', $value);
$tmpvirginurl3 = preg_replace('/^https:\/\//i', 'https://www.', $tmpvirginurl);
if ($tmpvirginurl3) {
$value = preg_replace('/^www\.'.preg_quote($tmpvirginurl3, '/').'\/?/', '', $value);
$value = preg_replace('/^'.preg_quote($tmpvirginurl3, '/').'\/?/', '', $value);
}
$tmpvirginurl2 = preg_replace('/^https?:\/\//i', '', $tmpvirginurl);
if ($tmpvirginurl2) {
$value = preg_replace('/^www\.'.preg_quote($tmpvirginurl2, '/').'\/?/', '', $value);
$value = preg_replace('/^'.preg_quote($tmpvirginurl2, '/').'\/?/', '', $value);
}
}
if (!empty($dictsocialnetworks[$type]['url'])) {
$link = str_replace('{socialid}', $value, $dictsocialnetworks[$type]['url']);
if (preg_match('/^https?:\/\//i', $link)) {
$htmllink .= '<a href="'.dol_sanitizeUrl($link, 0).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
if (preg_match('/^https?:\/\//i', $value)) {
$htmllink .= '<a href="'.dol_sanitizeUrl($value, 0).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
} else {
$htmllink .= '<a href="'.dol_sanitizeUrl($link, 1).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
$htmllink .= '<a href="'.dol_sanitizeUrl($link, 0).'" target="_blank" rel="noopener noreferrer">'.dol_escape_htmltag($value).'</a>';
}
} else {
$htmllink .= dol_escape_htmltag($value);
}
}
$htmllink .= '</div>';
} else {
$langs->load("errors");
$htmllink .= img_warning($langs->trans("ErrorBadSocialNetworkValue", $value));
}
return $htmllink;
}
@@ -14676,8 +14648,8 @@ function GETPOSTDATE($prefix, $hourTime = '', $gm = 'auto')
$m = array();
if ($hourTime === 'getpost') {
$hour = GETPOSTINT($prefix . 'hour');
$minute = GETPOSTINT($prefix . 'minute');
$second = GETPOSTINT($prefix . 'second');
$minute = GETPOSTINT($prefix . 'min');
$second = GETPOSTINT($prefix . 'sec');
} elseif (preg_match('/^(\d\d):(\d\d):(\d\d)$/', $hourTime, $m)) {
$hour = intval($m[1]);
$minute = intval($m[2]);
@@ -14716,8 +14688,8 @@ function buildParamDate($prefix, $timestamp = null, $hourTime = '', $gm = 'auto'
if ($hourTime === 'getpost' || ($timestamp !== null && dol_print_date($timestamp, '%H:%M:%S') !== '00:00:00')) {
$TParam = array_merge($TParam, array(
$prefix . 'hour' => intval(dol_print_date($timestamp, '%H')),
$prefix . 'minute' => intval(dol_print_date($timestamp, '%M')),
$prefix . 'second' => intval(dol_print_date($timestamp, '%S'))
$prefix . 'min' => intval(dol_print_date($timestamp, '%M')),
$prefix . 'sec' => intval(dol_print_date($timestamp, '%S'))
));
}

View File

@@ -109,6 +109,9 @@ function facture_prepare_head($object)
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php';
$upload_dir = $conf->facture->dir_output."/".dol_sanitizeFileName($object->ref);
if (!empty($conf->facture->multidir_output[$object->entity])) {
$upload_dir = $conf->facture->multidir_output[$object->entity]."/".dol_sanitizeFileName($object->ref);
}
$nbFiles = count(dol_dir_list($upload_dir, 'files', 0, '', '(\.meta|_preview.*\.png)$'));
$nbLinks = Link::count($db, $object->element, $object->id);
$head[$h][0] = DOL_URL_ROOT.'/compta/facture/document.php?id='.$object->id;

View File

@@ -447,6 +447,10 @@ function restrictedArea(User $user, $features, $object = 0, $tableandshare = '',
$tableandshare = 'paiementcharge';
$parentfortableentity = 'fk_charge@chargesociales';
}
if ($features == 'evaluation') {
$features = 'hrm';
$feature2 = 'evaluation';
}
//print $features.' - '.$tableandshare.' - '.$feature2.' - '.$dbt_select."\n";
@@ -885,8 +889,11 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
if ($feature == 'project') {
$feature = 'projet';
}
if ($feature == 'task') {
$feature = 'projet_task';
if ($feature == 'projet' && !empty($feature2) && is_array($feature2) && !empty(array_intersect(array('project_task', 'projet_task'), $feature2))) {
$feature = 'project_task';
}
if ($feature == 'task' || $feature == 'projet_task') {
$feature = 'project_task';
}
if ($feature == 'eventorganization') {
$feature = 'agenda';
@@ -903,14 +910,14 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
$checkonentitydone = 0;
// Array to define rules of checks to do
$check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales', 'knowledgemanagement'); // Test on entity only (Objects with no link to company)
$check = array('adherent', 'banque', 'bom', 'don', 'mrp', 'user', 'usergroup', 'payment', 'payment_supplier', 'payment_sc', 'product', 'produit', 'service', 'produit|service', 'categorie', 'resource', 'expensereport', 'holiday', 'salaries', 'website', 'recruitment', 'chargesociales', 'knowledgemanagement', 'stock'); // Test on entity only (Objects with no link to company)
$checksoc = array('societe'); // Test for object Societe
$checkparentsoc = array('agenda', 'contact', 'contrat'); // Test on entity + link to third party on field $dbt_keyfield. Allowed if link is empty (Ex: contacts...).
$checkproject = array('projet', 'project'); // Test for project object
$checktask = array('projet_task'); // Test for task object
$checkhierarchy = array('expensereport', 'holiday'); // check permission among the hierarchy of user
$checktask = array('projet_task', 'project_task'); // Test for task object
$checkhierarchy = array('expensereport', 'holiday', 'hrm'); // check permission among the hierarchy of user
$checkuser = array('bookmark'); // check permission among the fk_user (must be myself or null)
$nocheck = array('barcode', 'stock'); // No test
$nocheck = array('barcode'); // No test
//$checkdefault = 'all other not already defined'; // Test on entity + link to third party on field $dbt_keyfield. Not allowed if link is empty (Ex: invoice, orders...).
@@ -1047,6 +1054,7 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
return false;
}
} else {
$sharedelement = 'project'; // for multicompany compatibility
$sql = "SELECT COUNT(dbt.".$dbt_select.") as nb";
$sql .= " FROM ".MAIN_DB_PREFIX.$dbtablename." as dbt";
$sql .= " WHERE dbt.".$dbt_select." IN (".$db->sanitize($objectid, 1).")";
@@ -1135,6 +1143,20 @@ function checkUserAccessToObject($user, array $featuresarray, $object = 0, $tabl
}
}
}
if ($feature == 'hrm' && in_array('evaluation', $feature2)) {
$useridtocheck = $object->fk_user;
if ($user->hasRight('hrm', 'evaluation', 'readall')) {
// the user can view evaluations for anyone
return true;
}
if (!$user->hasRight('hrm', 'evaluation', 'read')) {
// the user can't view any evaluations
return false;
}
// the user can only their own evaluations or their subordinates'
return in_array($useridtocheck, $childids);
}
}
// For some object, we also have to check it is public or owned by user

View File

@@ -20,7 +20,7 @@ if (isset($totalarray['pos'])) {
printTotalValCell($totalarray['type'][$i] ?? '', empty($totalarray['val'][$totalarray['pos'][$i]]) ? 0 : $totalarray['val'][$totalarray['pos'][$i]]);
} else {
if ($i == 1) {
if ((is_null($limit) || $num < $limit) && empty($offset)) {
if ((!isset($limit) || is_null($limit) || $num < $limit) && empty($offset)) {
print '<td>'.$langs->trans("Total").'</td>';
} else {
print '<td>';

View File

@@ -556,7 +556,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
if (isModEnabled('contract') && isModEnabled('ticket') && isModEnabled('workflow') && getDolGlobalString('WORKFLOW_TICKET_LINK_CONTRACT') && getDolGlobalString('TICKET_PRODUCT_CATEGORY') && !empty($object->fk_soc)) {
$societe = new Societe($this->db);
$company_ids = (!getDolGlobalString('WORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS')) ? [$object->fk_soc] : $societe->getParentsForCompany($object->fk_soc, [$object->fk_soc]);
require_once DOL_DOCUMENT_ROOT.'/contrat/class/contrat.class.php';
$contrat = new Contrat($this->db);
$number_contracts_found = 0;
foreach ($company_ids as $company_id) {

View File

@@ -447,7 +447,7 @@ class InterfaceTicketEmail extends DolibarrTriggers
$message_customer .= '<p>'.$langs->trans('Message').' : <br><br>'.$message.'</p><br>';
if (getDolGlobalInt('TICKET_ENABLE_PUBLIC_INTERFACE')) {
$url_public_ticket = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/', 2)).'view.php?track_id='.((int) $object->track_id);
$url_public_ticket = getDolGlobalString('TICKET_URL_PUBLIC_INTERFACE', dol_buildpath('/public/ticket/', 2)).'view.php?track_id='.urlencode($object->track_id);
$message_customer .= '<p>'.$langs->trans($see_ticket).' : <a href="'.$url_public_ticket.'">'.$url_public_ticket.'</a></p>';
$message_customer .= '<p>'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'</p>';
} else {

View File

@@ -845,10 +845,9 @@ class EmailCollector extends CommonObject
{
global $user;
$nberror = 0;
$nbErrors = 0;
$arrayofcollectors = $this->fetchAll($user, 1);
// Loop on each collector
foreach ($arrayofcollectors as $emailcollector) {
$result = $emailcollector->doCollectOneCollector(0);
@@ -857,11 +856,12 @@ class EmailCollector extends CommonObject
$this->error .= 'EmailCollector ID '.$emailcollector->id.':'.$emailcollector->error.'<br>';
if (!empty($emailcollector->errors)) {
$this->error .= implode('<br>', $emailcollector->errors);
$nbErrors++;
}
$this->output .= 'EmailCollector ID '.$emailcollector->id.': '.$emailcollector->lastresult.'<br>';
}
return $nberror;
return $nbErrors;
}
/**
@@ -1907,7 +1907,11 @@ class EmailCollector extends CommonObject
$attachments = [];
}
} else {
$this->getmsg($connection, $imapemail); // This set global var $charset, $htmlmsg, $plainmsg, $attachments
$getMsg = $this->getmsg($connection, $imapemail); // This set global var $charset, $htmlmsg, $plainmsg, $attachments
if ($getMsg < 0) {
$this->errors = array_merge($this->errors, [$this->error]);
return $getMsg;
}
}
'@phan-var-force Webklex\PHPIMAP\Attachment[] $attachments';
@@ -3217,7 +3221,11 @@ class EmailCollector extends CommonObject
$this->saveAttachment($destdir, $filename, $content);
}
} else {
$this->getmsg($connection, $imapemail, $destdir);
$getMsg = $this->getmsg($connection, $imapemail, $destdir);
if ($getMsg < 0) {
$this->errors = array_merge($this->errors, [$this->error]);
return $getMsg;
}
}
$operationslog .= '<br>Project created with attachments -> id='.dol_escape_htmltag($projecttocreate->id);
@@ -3373,7 +3381,11 @@ class EmailCollector extends CommonObject
$this->saveAttachment($destdir, $filename, $content);
}
} else {
$this->getmsg($connection, $imapemail, $destdir);
$getMsg = $this->getmsg($connection, $imapemail, $destdir);
if ($getMsg < 0) {
$this->errors = array_merge($this->errors, [$this->error]);
return $getMsg;
}
}
$operationslog .= '<br>Ticket created with attachments -> id='.dol_escape_htmltag($tickettocreate->id);
@@ -3701,9 +3713,9 @@ class EmailCollector extends CommonObject
* @param Object $mbox Structure
* @param string $mid UID email
* @param string $destdir Target dir for attachments. Leave blank to parse without writing to disk.
* @return void
* @return int
*/
private function getmsg($mbox, $mid, $destdir = '')
private function getmsg($mbox, $mid, $destdir = ''): int
{
// input $mbox = IMAP stream, $mid = message id
// output all the following:
@@ -3717,9 +3729,12 @@ class EmailCollector extends CommonObject
// BODY @phan-suppress-next-line PhanTypeMismatchArgumentInternal
$s = imap_fetchstructure($mbox, $mid, FT_UID);
if ($s === false) {
$this->errors = array_merge($this->errors, [imap_last_error()]);
return -1;
}
if (!$s->parts) {
if (empty($s->parts)) {
// simple
$this->getpart($mbox, $mid, $s, 0); // pass 0 as part-number
} else {
@@ -3728,6 +3743,8 @@ class EmailCollector extends CommonObject
$this->getpart($mbox, $mid, $p, $partno0 + 1, $destdir);
}
}
return 1;
}
/* partno string

View File

@@ -122,8 +122,10 @@ function getAttachments($jk, $mbox)
$fpos = 2;
$attachments = array();
$nb = count($parts);
if ($nb && !empty($parts)) {
if (!empty($parts)) {
$nb = count($parts);
for ($i = 1; $i < $nb; $i++) {
$part = $parts[$i];
@@ -140,6 +142,7 @@ function getAttachments($jk, $mbox)
$fpos++;
}
}
return $attachments;
}

View File

@@ -429,7 +429,7 @@ if (empty($reshook)) {
$product_type,
$rang,
$lines[$i]->special_code,
$objecttmp->origin,
$objecttmp->origin_type,
$lines[$i]->rowid,
$fk_parent_line,
$lines[$i]->fk_fournprice,

View File

@@ -1951,9 +1951,10 @@ if ($action == 'create') {
print '</tr>';
// List of payments already done
$canSeeBankAccount = isModEnabled('bank') && $user->hasRight('banque', 'lire');
$nbcols = 3;
$nbrows = 0;
if (isModEnabled("bank")) {
if ($canSeeBankAccount) {
$nbrows++;
$nbcols++;
}
@@ -1964,7 +1965,7 @@ if ($action == 'create') {
print '<td class="liste_titre">'.$langs->trans('Payments').'</td>';
print '<td class="liste_titre">'.$langs->trans('Date').'</td>';
print '<td class="liste_titre">'.$langs->trans('Type').'</td>';
if (isModEnabled("bank")) {
if ($canSeeBankAccount) {
print '<td class="liste_titre right">'.$langs->trans('BankAccount').'</td>';
}
print '<td class="liste_titre right">'.$langs->trans('Amount').'</td>';
@@ -2007,7 +2008,7 @@ if ($action == 'create') {
$labeltype = $langs->trans("PaymentType".$objp->payment_code) != "PaymentType".$objp->payment_code ? $langs->trans("PaymentType".$objp->payment_code) : $objp->payment_type;
print "<td>".$labeltype.' '.$objp->num_payment."</td>\n";
// Bank account
if (isModEnabled("bank")) {
if ($canSeeBankAccount) {
$bankaccountstatic->id = $objp->baid;
$bankaccountstatic->ref = $objp->baref;
$bankaccountstatic->label = $objp->baref;

View File

@@ -96,8 +96,9 @@ $permissiontoread = $user->hasRight('hrm', 'evaluation', 'read'); // Used by the
// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->module, $object->id, $object->table_element, $object->element, 'fk_soc', 'rowid', $isdraft);
$isdraft = $object->status == Evaluation::STATUS_DRAFT ? 1 : 0;
restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (!isModEnabled('hrm')) {
accessforbidden();
}

View File

@@ -92,8 +92,8 @@ $upload_dir = $conf->hrm->multidir_output[isset($object->entity) ? $object->enti
// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
$isdraft = ($object->status == Evaluation::STATUS_DRAFT) ? 1 : 0;
restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (!isModEnabled("hrm")) {
accessforbidden();
}

View File

@@ -62,10 +62,8 @@ $permission = $user->hasRight('hrm', 'evaluation', 'write');
// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
//if (empty($conf->hrm->enabled)) accessforbidden();
//if (!$permissiontoread) accessforbidden();
$isdraft = $object->status == Evaluation::STATUS_DRAFT ? 1 : 0;
restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);

View File

@@ -85,16 +85,12 @@ $permissiontoadd = $user->hasRight('hrm', 'evaluation', 'write'); // Used by th
$permissiontoread = $user->hasRight('hrm', 'evaluation', 'read');
// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (empty($conf->hrm->enabled)) {
accessforbidden();
}
if (!$permissiontoread) {
accessforbidden();
}
$isdraft = $object->status == Evaluation::STATUS_DRAFT ? 1 : 0;
restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (!isModEnabled('hrm')) accessforbidden();
if (!$permissiontoread) accessforbidden();
/*

View File

@@ -66,10 +66,10 @@ $permissiontoread = $user->hasRight('hrm', 'evaluation', 'read'); // Used by th
// Security check (enable the most restrictive one)
//if ($user->socid > 0) accessforbidden();
//if ($user->socid > 0) $socid = $user->socid;
//$isdraft = (($object->status == $object::STATUS_DRAFT) ? 1 : 0);
//restrictedArea($user, $object->element, $object->id, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
//if (empty($conf->hrm->enabled)) accessforbidden();
//if (!$permissiontoread) accessforbidden();
$isdraft = (($object->status == Evaluation::STATUS_DRAFT) ? 1 : 0);
restrictedArea($user, $object->element, $object, $object->table_element, '', 'fk_soc', 'rowid', $isdraft);
if (empty($conf->hrm->enabled)) accessforbidden();
if (!$permissiontoread) accessforbidden();
/*

View File

@@ -1,8 +1,9 @@
<?php
/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2020 Lenin Rivas <lenin@leninrivas.com>
* Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
/* Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2020 Lenin Rivas <lenin@leninrivas.com>
* Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Noé Cendrier <noe.cendrier@altairis.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -919,75 +920,74 @@ class Mo extends CommonObject
$this->db->begin();
if (!empty($arrayoflines)) {
// If there is child lines
if (!empty($fk_movement) || !empty($arrayoflines)) {
$stockmove = new MouvementStock($this->db);
$stockmove->setOrigin($this->element, $this->id);
}
if (!empty($fk_movement)) {
// The fk_movement was not recorded so we try to guess the product and quantity to restore.
$moline = new MoLine($this->db);
$TArrayMoLine = $moline->fetchAll('', '', 1, 0, '(fk_stock_movement:=:'.((int) $fk_movement).')');
$moline = array_shift($TArrayMoLine);
if (!empty($fk_movement)) {
// The fk_movement was not recorded so we try to guess the product and quantity to restore.
$moline = new MoLine($this->db);
$TArrayMoLine = $moline->fetchAll('', '', 1, 0, '(fk_stock_movement:=:'.((int) $fk_movement).')');
$moline = array_shift($TArrayMoLine);
$movement = new MouvementStock($this->db);
$movement->fetch($fk_movement);
$productstatic->fetch($movement->product_id);
$qtytoprocess = $movement->qty;
$movement = new MouvementStock($this->db);
$movement->fetch($fk_movement);
$productstatic->fetch($movement->product_id);
$qtytoprocess = $movement->qty;
// Reverse stock movement
$labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
$codemovementCancel = $langs->trans("StockIncrease");
if (($qtytoprocess >= 0)) {
$idstockmove = $stockmove->reception($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, '', '', $movement->batch, dol_now(), 0, $codemovementCancel);
} else {
$idstockmove = $stockmove->livraison($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $movement->batch, 0, $codemovementCancel);
}
if ($idstockmove < 0) {
$this->error++;
setEventMessages($stockmove->error, $stockmove->errors, 'errors');
} else {
$result = $moline->delete($user, $notrigger);
}
} elseif (!empty($arrayoflines)) {
// Loop on each child lines
foreach ($arrayoflines as $key => $arrayofline) {
$lineDetails = $arrayoflines[$key];
$productstatic->fetch($lineDetails['fk_product']);
$qtytoprocess = $lineDetails['qty'];
// Reverse stock movement
$labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
$codemovementCancel = $langs->trans("StockIncrease");
if (($qtytoprocess >= 0)) {
$idstockmove = $stockmove->reception($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, '', '', $movement->batch, dol_now(), 0, $codemovementCancel);
if ($qtytoprocess >= 0) {
$idstockmove = $stockmove->reception($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, '', '', $lineDetails['batch'], dol_now(), 0, $codemovementCancel);
} else {
$idstockmove = $stockmove->livraison($user, $movement->product_id, $movement->warehouse_id, $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $movement->batch, 0, $codemovementCancel);
$idstockmove = $stockmove->livraison($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $lineDetails['batch'], 0, $codemovementCancel);
}
if ($idstockmove < 0) {
$this->error++;
setEventMessages($stockmove->error, $stockmove->errors, 'errors');
} else {
$result = $moline->delete($user, $notrigger);
}
} else {
// Loop on each child lines
foreach ($arrayoflines as $key => $arrayofline) {
$lineDetails = $arrayoflines[$key];
$productstatic->fetch($lineDetails['fk_product']);
$qtytoprocess = $lineDetails['qty'];
$moline = new MoLine($this->db);
$moline->fetch($lineDetails['rowid']);
// Reverse stock movement
$labelmovementCancel = $langs->trans("CancelProductionForRef", $productstatic->ref);
$codemovementCancel = $langs->trans("StockIncrease");
if ($qtytoprocess >= 0) {
$idstockmove = $stockmove->reception($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, '', '', $lineDetails['batch'], dol_now(), 0, $codemovementCancel);
} else {
$idstockmove = $stockmove->livraison($user, $lineDetails['fk_product'], $lineDetails['fk_warehouse'], $qtytoprocess, 0, $labelmovementCancel, dol_now(), '', '', $lineDetails['batch'], 0, $codemovementCancel);
}
if ($idstockmove < 0) {
$resdel = $moline->delete($user, $notrigger);
if ($resdel < 0) {
$this->error++;
setEventMessages($stockmove->error, $stockmove->errors, 'errors');
} else {
$moline = new MoLine($this->db);
$moline->fetch($lineDetails['rowid']);
$resdel = $moline->delete($user, $notrigger);
if ($resdel < 0) {
$this->error++;
setEventMessages($moline->error, $moline->errors, 'errors');
}
setEventMessages($moline->error, $moline->errors, 'errors');
}
}
if (empty($this->error)) {
$result = $this->deleteLineCommon($user, $idline, $notrigger);
}
}
if (empty($this->error)) {
$result = $this->deleteLineCommon($user, $idline, $notrigger);
}
} else {
// No child lines
// No child lines and no associated movement
$result = $this->deleteLineCommon($user, $idline, $notrigger);
}

View File

@@ -2,8 +2,9 @@
/* Copyright (C) 2019-2020 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2023 Christian Humpel <christian.humpel@gmail.com>
* Copyright (C) 2023 Vincent de Grandpré <vincent@de-grandpre.quebec>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Noé Cendrier <noe.cendrier@altairis.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1239,8 +1240,8 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea
print '</td>';
}
// Action delete line
if ($permissiontodelete) {
// Action delete line, if no consumption has occurred for this product
if ($permissiontodelete && empty($arrayoflines)) {
$href = $_SERVER["PHP_SELF"] . '?id=' . ((int) $object->id) . '&action=deleteline&token=' . newToken() . '&lineid=' . ((int) $line->id);
print '<td class="center">';
print '<a class="reposition" href="' . $href . '">';

View File

@@ -43,9 +43,9 @@ $backtopage = GETPOST('backtopage', 'alpha');
$include_sub_warehouse = !empty(GETPOST('include_sub_warehouse')) ? GETPOST('include_sub_warehouse') : 0;
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
$result = restrictedArea($user, 'stock', $id);
$result = restrictedArea($user, 'stock', $id, 'inventory&stock');
} else {
$result = restrictedArea($user, 'stock', $id, '', 'inventory_advance');
$result = restrictedArea($user, 'stock', $id, 'inventory&stock', 'inventory_advance');
}
// Initialize technical objects

View File

@@ -59,9 +59,9 @@ $batch = GETPOST('batch', 'alphanohtml');
$totalExpectedValuation = 0;
$totalRealValuation = 0;
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS')) {
$result = restrictedArea($user, 'stock', $id);
$result = restrictedArea($user, 'stock', $id, 'inventory&stock');
} else {
$result = restrictedArea($user, 'stock', $id, '', 'inventory_advance');
$result = restrictedArea($user, 'stock', $id, 'inventory&stock', 'inventory_advance');
}
// Initialize technical objects

View File

@@ -73,8 +73,7 @@ if (!$sortorder) {
}
// Security check
//$result=restrictedArea($user,'stock', $id, 'entrepot&stock');
$result = restrictedArea($user, 'stock');
$result=restrictedArea($user,'stock', $id, 'entrepot&stock');
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
$hookmanager->initHooks(array('warehousecard', 'stocklist', 'globalcard'));

View File

@@ -309,7 +309,7 @@ if ($action == 'addtime' && $user->hasRight('projet', 'lire') && GETPOST('formfi
}
}
if (!$updateoftaskdone) { // Check to update progress if no update were done on task.
if (!$updateoftaskdone && GETPOSTISSET($taskid.'progress')) { // Check to update progress if no update were done on task.
$object->fetch($tmptaskid);
//var_dump($object->progress);
//var_dump(GETPOST($tmptaskid . 'progress', 'int')); exit;

View File

@@ -472,7 +472,7 @@ function MoreProducts(moreorless) {
var nb_cat_shown = $('.div5 div.wrapper2[data-iscat=1]').length;
var offset = <?php echo($MAXPRODUCT - 2); ?> * pageproducts - nb_cat_shown;
// Only show products for sale (tosell=1)
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) {
$.getJSON('<?php echo DOL_URL_ROOT ?>/takepos/ajax/ajax.php?action=getProducts&token=<?php echo newToken();?>&thirdpartyid=' + jQuery('#thirdpartyid').val() + '&category='+currentcat+'&tosell=1&limit='+limit+'&offset='+offset, function(data) {
console.log("Call ajax.php (in MoreProducts) to get Products of category "+currentcat);
if (typeof (data[0]) == "undefined" && moreorless=="more"){ // Return if no more pages