Merge branch '17.0' into FIX_read_evaluation_of_user_and_subordinates_with_read_right

This commit is contained in:
Laurent Destailleur 2022-12-22 14:43:28 +01:00 committed by GitHub
commit c2894fb8a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 416 additions and 175 deletions

View File

@ -95,19 +95,20 @@ notifications:
install: install:
- | - |
echo "Updating Composer" echo "Updating Composer config"
rm $TRAVIS_BUILD_DIR/composer.json
rm $TRAVIS_BUILD_DIR/composer.lock
composer -V composer -V
composer self-update #rm $TRAVIS_BUILD_DIR/composer.json
composer -n init #rm $TRAVIS_BUILD_DIR/composer.lock
composer -n config vendor-dir htdocs/includes #composer -n init
#composer -n config vendor-dir htdocs/includes
composer -n config -g vendor-dir htdocs/includes composer -n config -g vendor-dir htdocs/includes
echo echo
- | - |
echo "Installing Composer dependencies - PHP Unit, Parallel Lint, PHP CodeSniffer, PHP Vardump check - for $TRAVIS_PHP_VERSION" echo "Update Composer version and Install tools - PHP Unit, Parallel Lint, PHP CodeSniffer, PHP Vardump check - for $TRAVIS_PHP_VERSION"
echo "(version 2.5 is bugged and generate phpunit error Exception: Serialization of 'Closure' is not allowed)"
if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ]; then if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ]; then
composer self-update 2.2.18
composer -n require phpunit/phpunit ^6 \ composer -n require phpunit/phpunit ^6 \
php-parallel-lint/php-parallel-lint ^1 \ php-parallel-lint/php-parallel-lint ^1 \
php-parallel-lint/php-console-highlighter ^0 \ php-parallel-lint/php-console-highlighter ^0 \
@ -115,6 +116,7 @@ install:
squizlabs/php_codesniffer ^3 squizlabs/php_codesniffer ^3
fi fi
if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ]; then if [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ]; then
composer self-update 2.2.18
composer -n require phpunit/phpunit ^7 \ composer -n require phpunit/phpunit ^7 \
php-parallel-lint/php-parallel-lint ^1.2 \ php-parallel-lint/php-parallel-lint ^1.2 \
php-parallel-lint/php-console-highlighter ^0 \ php-parallel-lint/php-console-highlighter ^0 \
@ -123,6 +125,7 @@ install:
fi fi
# phpunit 9 is required for php 8 # phpunit 9 is required for php 8
if [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then if [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then
composer self-update 2.4.4
composer -n require --ignore-platform-reqs phpunit/phpunit ^8 \ composer -n require --ignore-platform-reqs phpunit/phpunit ^8 \
php-parallel-lint/php-parallel-lint ^1.2 \ php-parallel-lint/php-parallel-lint ^1.2 \
php-parallel-lint/php-console-highlighter ^0 \ php-parallel-lint/php-console-highlighter ^0 \

View File

@ -3,6 +3,16 @@ English Dolibarr ChangeLog
-------------------------------------------------------------- --------------------------------------------------------------
***** ChangeLog for 18.0.0 compared to 17.0.0 *****
WARNING:
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* The deprecated method escapeunderscore() of database handlers has been removed. You must use escapeforlike instead.
***** ChangeLog for 17.0.0 compared to 16.0.0 ***** ***** ChangeLog for 17.0.0 compared to 16.0.0 *****
For users: For users:

View File

@ -399,7 +399,7 @@ if ($resql) {
} }
print "</select>"; print "</select>";
print ajax_combobox("chartofaccounts"); print ajax_combobox("chartofaccounts");
print '<input type="'.(empty($conf->use_javascript_ajax) ? 'submit' : 'button').'" class="button button-edit" name="change_chart" id="change_chart" value="'.dol_escape_htmltag($langs->trans("ChangeAndLoad")).'">'; print '<input type="'.(empty($conf->use_javascript_ajax) ? 'submit' : 'button').'" class="button button-edit small" name="change_chart" id="change_chart" value="'.dol_escape_htmltag($langs->trans("ChangeAndLoad")).'">';
print '<br>'; print '<br>';
@ -436,7 +436,7 @@ if ($resql) {
} }
if (!empty($arrayfields['aa.account_parent']['checked'])) { if (!empty($arrayfields['aa.account_parent']['checked'])) {
print '<td class="liste_titre">'; print '<td class="liste_titre">';
print $formaccounting->select_account($search_accountparent, 'search_accountparent', 2); print $formaccounting->select_account($search_accountparent, 'search_accountparent', 2, array(), 0, 0, 'maxwidth150');
print '</td>'; print '</td>';
} }
if (!empty($arrayfields['aa.pcg_type']['checked'])) { if (!empty($arrayfields['aa.pcg_type']['checked'])) {

View File

@ -329,7 +329,8 @@ if ($action == 'create') {
// Account parent // Account parent
print '<tr><td>'.$langs->trans("Accountparent").'</td>'; print '<tr><td>'.$langs->trans("Accountparent").'</td>';
print '<td>'; print '<td>';
print $formaccounting->select_account($object->account_parent, 'account_parent', 1); // Note: We accept disabled account as parent account so we can build a hierarchy and use only childs
print $formaccounting->select_account($object->account_parent, 'account_parent', 1, array(), 0, 0, 'minwidth100 maxwidth300 maxwidthonsmartphone', 1, '');
print '</td></tr>'; print '</td></tr>';
// Chart of accounts type // Chart of accounts type

View File

@ -110,18 +110,22 @@ print '<table class="border centpercent">';
// Select the category // Select the category
print '<tr><td class="titlefield">'.$langs->trans("AccountingCategory").'</td>'; print '<tr><td class="titlefield">'.$langs->trans("AccountingCategory").'</td>';
print '<td>'; print '<td>';
$formaccounting->select_accounting_category($cat_id, 'account_category', 1, 0, 0, 1); $formaccounting->select_accounting_category($cat_id, 'account_category', 1, 0, 0, 0);
print '<input type="submit" class="button" value="'.$langs->trans("Select").'">'; print '<input type="submit" class="button small" value="'.$langs->trans("Select").'">';
print '</td></tr>'; print '</td></tr>';
print '</table>';
print dol_get_fiche_end();
// Select the accounts // Select the accounts
if (!empty($cat_id)) { if (!empty($cat_id)) {
$return = $accountingcategory->getAccountsWithNoCategory($cat_id); $return = $accountingcategory->getAccountsWithNoCategory($cat_id);
if ($return < 0) { if ($return < 0) {
setEventMessages(null, $accountingcategory->errors, 'errors'); setEventMessages(null, $accountingcategory->errors, 'errors');
} }
print '<tr><td>'.$langs->trans("AddAccountFromBookKeepingWithNoCategories").'</td>'; print '<br>';
print '<td>';
$arraykeyvalue = array(); $arraykeyvalue = array();
foreach ($accountingcategory->lines_cptbk as $key => $val) { foreach ($accountingcategory->lines_cptbk as $key => $val) {
@ -130,8 +134,9 @@ if (!empty($cat_id)) {
} }
if (is_array($accountingcategory->lines_cptbk) && count($accountingcategory->lines_cptbk) > 0) { if (is_array($accountingcategory->lines_cptbk) && count($accountingcategory->lines_cptbk) > 0) {
print $form->multiselectarray('cpt_bk', $arraykeyvalue, GETPOST('cpt_bk', 'array'), null, null, null, null, "90%"); print img_picto($langs->trans("AccountingAccount"), 'accounting_account', 'class="pictofixedwith"');
print '<br>'; print $form->multiselectarray('cpt_bk', $arraykeyvalue, GETPOST('cpt_bk', 'array'), null, null, '', 0, "80%", '', '', $langs->transnoentitiesnoconv("AddAccountFromBookKeepingWithNoCategories"));
//print '<br>';
/*print '<select class="flat minwidth200" size="8" name="cpt_bk[]" multiple>'; /*print '<select class="flat minwidth200" size="8" name="cpt_bk[]" multiple>';
foreach ( $accountingcategory->lines_cptbk as $cpt ) { foreach ( $accountingcategory->lines_cptbk as $cpt ) {
print '<option value="' . length_accountg($cpt->numero_compte) . '">' . length_accountg($cpt->numero_compte) . ' (' . $cpt->label_compte . ' ' . $cpt->doc_ref . ')</option>'; print '<option value="' . length_accountg($cpt->numero_compte) . '">' . length_accountg($cpt->numero_compte) . ' (' . $cpt->label_compte . ' ' . $cpt->doc_ref . ')</option>';
@ -139,20 +144,16 @@ if (!empty($cat_id)) {
print '</select><br>'; print '</select><br>';
print ajax_combobox('cpt_bk'); print ajax_combobox('cpt_bk');
*/ */
print '<input type="submit" class="button button-add" id="" class="action-delete" value="'.$langs->trans("Add").'"> '; print '<input type="submit" class="button button-add small" id="" class="action-delete" value="'.$langs->trans("Add").'"> ';
} }
print '</td></tr>';
} }
print '</table>';
print dol_get_fiche_end();
print '</form>'; print '</form>';
if ($action == 'display' || $action == 'delete') { if ($action == 'display' || $action == 'delete') {
print "<table class='noborder' width='100%'>\n"; print '<br>';
print '<table class="noborder centpercent">'."\n";
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
print '<td class="liste_titre">'.$langs->trans("AccountAccounting")."</td>"; print '<td class="liste_titre">'.$langs->trans("AccountAccounting")."</td>";
print '<td class="liste_titre" colspan="2">'.$langs->trans("Label")."</td>"; print '<td class="liste_titre" colspan="2">'.$langs->trans("Label")."</td>";
@ -177,6 +178,8 @@ if ($action == 'display' || $action == 'delete') {
print "</td>"; print "</td>";
print "</tr>\n"; print "</tr>\n";
} }
} else {
print '<tr><td colspan="3"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
} }
} }

View File

@ -190,7 +190,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) {
setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors'); setEventMessages($langs->transnoentities('ErrorCodeCantContainZero'), null, 'errors');
} }
} }
if (!is_numeric(GETPOST('position', 'alpha'))) { if (GETPOST('position') && !is_numeric(GETPOST('position', 'alpha'))) {
$langs->loadLangs(array("errors")); $langs->loadLangs(array("errors"));
$ok = 0; $ok = 0;
setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors'); setEventMessages($langs->transnoentities('ErrorFieldMustBeANumeric', $langs->transnoentities("Position")), null, 'errors');
@ -605,7 +605,7 @@ if ($resql) {
if ($showfield) { if ($showfield) {
if ($value == 'country') { if ($value == 'country') {
print '<td class="liste_titre">'; print '<td class="liste_titre">';
print $form->select_country($search_country_id, 'search_country_id', '', 28, 'maxwidth200 maxwidthonsmartphone'); print $form->select_country($search_country_id, 'search_country_id', '', 28, 'maxwidth150 maxwidthonsmartphone');
print '</td>'; print '</td>';
$filterfound++; $filterfound++;
} else { } else {
@ -725,11 +725,11 @@ if ($resql) {
print '<td></td>'; print '<td></td>';
print '<td></td>'; print '<td></td>';
print '<td class="center">'; print '<td class="center">';
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>';
print '<input type="hidden" name="page" value="'.$page.'">'; print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="rowid" value="'.$rowid.'">'; print '<input type="hidden" name="rowid" value="'.$rowid.'">';
print '<input type="submit" class="button button-edit" name="actionmodify" value="'.$langs->trans("Modify").'">'; print '<input type="submit" class="button button-edit smallpaddingimp" name="actionmodify" value="'.$langs->trans("Modify").'">';
print '<div name="'.(!empty($obj->rowid) ? $obj->rowid : $obj->code).'"></div>'; print '<input type="submit" class="button button-cancel smallpaddingimp" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '<input type="submit" class="button button-cancel" name="actioncancel" value="'.$langs->trans("Cancel").'">';
print '</td>'; print '</td>';
print '<td></td>'; print '<td></td>';
} else { } else {
@ -887,10 +887,10 @@ function fieldListAccountingCategories($fieldlist, $obj = '', $tabname = '', $co
if ($context == 'add') { if ($context == 'add') {
$fieldname = 'country_id'; $fieldname = 'country_id';
$preselectcountrycode = GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : $mysoc->country_code; $preselectcountrycode = GETPOSTISSET('country_id') ? GETPOST('country_id', 'int') : $mysoc->country_code;
print $form->select_country($preselectcountrycode, $fieldname, '', 28, 'maxwidth200 maxwidthonsmartphone'); print $form->select_country($preselectcountrycode, $fieldname, '', 28, 'maxwidth150 maxwidthonsmartphone');
} else { } else {
$preselectcountrycode = (empty($obj->country_code) ? (empty($obj->country) ? $mysoc->country_code : $obj->country) : $obj->country_code); $preselectcountrycode = (empty($obj->country_code) ? (empty($obj->country) ? $mysoc->country_code : $obj->country) : $obj->country_code);
print $form->select_country($preselectcountrycode, $fieldname, '', 28, 'maxwidth200 maxwidthonsmartphone'); print $form->select_country($preselectcountrycode, $fieldname, '', 28, 'maxwidth150 maxwidthonsmartphone');
} }
print '</td>'; print '</td>';
} elseif ($fieldlist[$field] == 'country_id') { } elseif ($fieldlist[$field] == 'country_id') {

View File

@ -408,7 +408,7 @@ if ($resql) {
$s .= '<a class="vendor-back" style="padding-left: 6px; padding-right: 6px" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$obj->rowid.'">'.$langs->trans("Supplier").'</a>'; $s .= '<a class="vendor-back" style="padding-left: 6px; padding-right: 6px" title="'.$langs->trans("Supplier").'" href="'.DOL_URL_ROOT.'/fourn/card.php?socid='.$obj->rowid.'">'.$langs->trans("Supplier").'</a>';
} elseif ($obj->type == 3) { } elseif ($obj->type == 3) {
// User // User
$s .= '<a class="user-back" style="padding-left: 6px; padding-right: 6px" title="'.$langs->trans("Employee").'" href="'.DOL_URL_ROOT.'/user/card.php?id='.$obj->id.'">'.$langs->trans("Employee").'</a>'; $s .= '<a class="user-back" style="padding-left: 6px; padding-right: 6px" title="'.$langs->trans("Employee").'" href="'.DOL_URL_ROOT.'/user/card.php?id='.$obj->rowid.'">'.$langs->trans("Employee").'</a>';
} }
print $s; print $s;
print '</td>'; print '</td>';

View File

@ -529,6 +529,10 @@ if ($result) {
print '</tr>'; print '</tr>';
$i++; $i++;
} }
if ($num_lines == 0) {
print '<tr><td colspan="12"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print '</table>'; print '</table>';
print "</div>"; print "</div>";

View File

@ -749,6 +749,10 @@ if ($result) {
print '</tr>'; print '</tr>';
$i++; $i++;
} }
if ($num_lines == 0) {
print '<tr><td colspan="13"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print '</table>'; print '</table>';
print "</div>"; print "</div>";

View File

@ -427,6 +427,13 @@ if ($result) {
print "</tr>"; print "</tr>";
$i++; $i++;
} }
if ($num_lines == 0) {
$colspan=10;
if (!empty($conf->global->ACCOUNTANCY_USE_EXPENSE_REPORT_VALIDATION_DATE)) {
$colspan++;
}
print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print "</table>"; print "</table>";
print "</div>"; print "</div>";

View File

@ -513,6 +513,9 @@ if ($result) {
print "</tr>"; print "</tr>";
$i++; $i++;
} }
if ($num_lines == 0) {
print '<tr><td colspan="13"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print '</table>'; print '</table>';
print "</div>"; print "</div>";

View File

@ -558,6 +558,10 @@ if ($result) {
print '</tr>'; print '</tr>';
$i++; $i++;
} }
if ($num_lines == 0) {
print '<tr><td colspan="13"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print '</table>'; print '</table>';
print "</div>"; print "</div>";

View File

@ -777,6 +777,9 @@ if ($result) {
print '</tr>'; print '</tr>';
$i++; $i++;
} }
if ($num_lines == 0) {
print '<tr><td colspan="14"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
print '</table>'; print '</table>';
print "</div>"; print "</div>";

View File

@ -50,8 +50,13 @@ llxHeader();
print load_fiche_titre($langs->trans("PerfDolibarr"), '', 'title_setup'); print load_fiche_titre($langs->trans("PerfDolibarr"), '', 'title_setup');
print '<span class="opacitymedium">'.$langs->trans("YouMayFindPerfAdviceHere", 'https://wiki.dolibarr.org/index.php/FAQ_Increase_Performance').'</span> (<a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("Reload").'</a>)<br>'; print '<span class="opacitymedium">'.$langs->trans("YouMayFindPerfAdviceHere", 'https://wiki.dolibarr.org/index.php/FAQ_Increase_Performance').'</span>';
print ' &nbsp; &nbsp; ';
print '<a href="'.$_SERVER["PHP_SELF"].'">';
print img_picto($langs->trans("Reload"), 'refresh').' ';
print $langs->trans("Reload");
print '</a>';
print '<br>';
print '<br>'; print '<br>';
print '<hr>'; print '<hr>';

View File

@ -41,7 +41,7 @@ if (GETPOST('action', 'aZ09') == 'donothing') {
exit; exit;
} }
$execmethod = empty($conf->global->MAIN_EXEC_USE_POPEN) ? 1 : $conf->global->MAIN_EXEC_USE_POPEN; $execmethod = getDolGlobalInt('MAIN_EXEC_USE_POPEN', 1);
/* /*
@ -52,7 +52,13 @@ llxHeader();
print load_fiche_titre($langs->trans("Security"), '', 'title_setup'); print load_fiche_titre($langs->trans("Security"), '', 'title_setup');
print '<span class="opacitymedium">'.$langs->trans("YouMayFindSecurityAdviceHere", 'hhttps://wiki.dolibarr.org/index.php/Security_information').'</span> (<a href="'.$_SERVER["PHP_SELF"].'">'.$langs->trans("Reload").'</a>)<br>'; print '<span class="opacitymedium">'.$langs->trans("YouMayFindSecurityAdviceHere", 'hhttps://wiki.dolibarr.org/index.php/Security_information').'</span>';
print ' &nbsp; &nbsp; ';
print '<a href="'.$_SERVER["PHP_SELF"].'">';
print img_picto($langs->trans("Reload"), 'refresh').' ';
print $langs->trans("Reload");
print '</a>';
print '<br>';
print '<br>'; print '<br>';
print load_fiche_titre($langs->trans("PHPSetup"), '', 'folder'); print load_fiche_titre($langs->trans("PHPSetup"), '', 'folder');
@ -598,7 +604,7 @@ print '</span>';
print '<br>'; print '<br>';
$urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/fail2ban/filter.d/'; $urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/fail2ban/filter.d/';
print '- Login process (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulesbruteforce.conf">fail2ban example on GitHub</a>)<br>'; print '- Login process (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulesbruteforce.conf">fail2ban example on GitHub</a>)<br>';
print '- '.DOL_URL_ROOT.'/passwordforgotten.php (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulespassgorgotten.conf">fail2ban example on GitHub</a>)<br>'; print '- '.DOL_URL_ROOT.'/passwordforgotten.php (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-rulespassforgotten.conf">fail2ban example on GitHub</a>)<br>';
print '- '.DOL_URL_ROOT.'/public/* (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-limitpublic.conf">fail2ban example on GitHub</a>)<br>'; print '- '.DOL_URL_ROOT.'/public/* (see <a target="_blank" rel="noopener" href="'.$urlexamplebase.'web-dolibarr-limitpublic.conf">fail2ban example on GitHub</a>)<br>';
print '<br>'; print '<br>';
$urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/apache/'; $urlexamplebase = 'https://github.com/Dolibarr/dolibarr/blob/develop/dev/setup/apache/';

View File

@ -448,8 +448,8 @@ print '<td class="liste_titre"></td>';
// Status // Status
print '<td class="liste_titre">'; print '<td class="liste_titre">';
$array = array("1"=>$langs->trans("OnlyNonValid")); $array = array("1" => "OnlyNonValid");
print $form->selectarray('search_showonlyerrors', $array, $search_showonlyerrors, 1); print $form->selectarray('search_showonlyerrors', $array, $search_showonlyerrors, 1, 0, 0, '', 1, 0, 0, 'ASC', 'search_status maxwidth200 onrightofpage', 1);
print '</td>'; print '</td>';
// Status note // Status note
@ -530,7 +530,7 @@ if (is_array($blocks)) {
print '<td>'.dol_escape_htmltag($block->id).'</td>'; print '<td>'.dol_escape_htmltag($block->id).'</td>';
// Date // Date
print '<td>'.dol_print_date($block->date_creation, 'dayhour').'</td>'; print '<td class="nowraponall">'.dol_print_date($block->date_creation, 'dayhour').'</td>';
// User // User
print '<td>'; print '<td>';

View File

@ -4331,16 +4331,6 @@ class OrderLine extends CommonOrderLine
dol_syslog("OrderLine::delete", LOG_DEBUG); dol_syslog("OrderLine::delete", LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
// Remove extrafields
if (!$error) {
$this->id = $this->rowid;
$result = $this->deleteExtraFields();
if ($result < 0) {
$error++;
dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
}
}
if (!$error && !$notrigger) { if (!$error && !$notrigger) {
// Call trigger // Call trigger
$result = $this->call_trigger('LINEORDER_DELETE', $user); $result = $this->call_trigger('LINEORDER_DELETE', $user);
@ -4350,6 +4340,15 @@ class OrderLine extends CommonOrderLine
// End call triggers // End call triggers
} }
// Remove extrafields
if (!$error) {
$result = $this->deleteExtraFields();
if ($result < 0) {
$error++;
dol_syslog(get_class($this)."::delete error -4 ".$this->error, LOG_ERR);
}
}
if (!$error) { if (!$error) {
$this->db->commit(); $this->db->commit();
return 1; return 1;

View File

@ -321,7 +321,7 @@ if ($modecompta == 'BOOKKEEPING') {
if ($showaccountdetail == 'no') { if ($showaccountdetail == 'no') {
if ($objp->pcg_type != $oldpcgtype) { if ($objp->pcg_type != $oldpcgtype) {
print '<tr class="trforbreak"><td colspan="3" class="tdforbreak">'.$objp->pcg_type.'</td></tr>'; print '<tr class="trforbreak"><td colspan="3" class="tdforbreak">'.dol_escape_htmltag($objp->pcg_type).'</td></tr>';
$oldpcgtype = $objp->pcg_type; $oldpcgtype = $objp->pcg_type;
} }
} }
@ -330,17 +330,17 @@ if ($modecompta == 'BOOKKEEPING') {
print '<tr class="oddeven">'; print '<tr class="oddeven">';
print '<td></td>'; print '<td></td>';
print '<td>'; print '<td>';
print $objp->pcg_type; print dol_escape_htmltag($objp->pcg_type);
print ($objp->name ? ' ('.$objp->name.')' : ' ('.$langs->trans("Unknown").')'); print ($objp->name ? ' ('.dol_escape_htmltag($objp->name).')' : ' ('.$langs->trans("Unknown").')');
print "</td>\n"; print "</td>\n";
print '<td class="right"><span class="amount">'.price($objp->amount)."</span></td>\n"; print '<td class="right nowraponall"><span class="amount">'.price($objp->amount)."</span></td>\n";
print "</tr>\n"; print "</tr>\n";
} else { } else {
print '<tr class="oddeven trforbreak">'; print '<tr class="oddeven trforbreak">';
print '<td colspan="2" class="tdforbreak">'; print '<td colspan="2" class="tdforbreak">';
print $objp->pcg_type; print dol_escape_htmltag($objp->pcg_type);
print "</td>\n"; print "</td>\n";
print '<td class="right tdforbreak"><span class="amount">'.price($objp->amount)."</span></td>\n"; print '<td class="right nowraponall tdforbreak"><span class="amount">'.price($objp->amount)."</span></td>\n";
print "</tr>\n"; print "</tr>\n";
} }
@ -367,7 +367,7 @@ if ($modecompta == 'BOOKKEEPING') {
$cpts = $AccCat->getCptsCat(0, $tmppredefinedgroupwhere); $cpts = $AccCat->getCptsCat(0, $tmppredefinedgroupwhere);
foreach ($cpts as $j => $cpt) { foreach ($cpts as $j => $cpt) {
$return = $AccCat->getSumDebitCredit($cpt['account_number'], $date_start, $date_end, $cpt['dc']); $return = $AccCat->getSumDebitCredit($cpt['account_number'], $date_start, $date_end, (empty($cpt['dc']) ? 0 : $cpt['dc']));
if ($return < 0) { if ($return < 0) {
setEventMessages(null, $AccCat->errors, 'errors'); setEventMessages(null, $AccCat->errors, 'errors');
$resultN = 0; $resultN = 0;
@ -380,7 +380,7 @@ if ($modecompta == 'BOOKKEEPING') {
print '<tr>'; print '<tr>';
print '<td></td>'; print '<td></td>';
print '<td class="tdoverflowmax200"> &nbsp; &nbsp; '.length_accountg($cpt['account_number']).' - '.$cpt['account_label'].'</td>'; print '<td class="tdoverflowmax200"> &nbsp; &nbsp; '.length_accountg($cpt['account_number']).' - '.$cpt['account_label'].'</td>';
print '<td class="right"><span class="amount">'.price($resultN).'</span></td>'; print '<td class="right nowraponall"><span class="amount">'.price($resultN).'</span></td>';
print "</tr>\n"; print "</tr>\n";
} }
} }
@ -1539,27 +1539,27 @@ print '</tr>';
print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Income").'</td>'; print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Income").'</td>';
if ($modecompta == 'CREANCES-DETTES') { if ($modecompta == 'CREANCES-DETTES') {
print '<td class="liste_total right">'.price(price2num($total_ht_income, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num($total_ht_income, 'MT')).'</td>';
} elseif ($modecompta == 'RECETTES-DEPENSES') { } elseif ($modecompta == 'RECETTES-DEPENSES') {
print '<td></td>'; print '<td></td>';
} }
print '<td class="liste_total right">'.price(price2num($total_ttc_income, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num($total_ttc_income, 'MT')).'</td>';
print '</tr>'; print '</tr>';
print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Outcome").'</td>'; print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Outcome").'</td>';
if ($modecompta == 'CREANCES-DETTES') { if ($modecompta == 'CREANCES-DETTES') {
print '<td class="liste_total right">'.price(price2num(-$total_ht_outcome, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num(-$total_ht_outcome, 'MT')).'</td>';
} elseif ($modecompta == 'RECETTES-DEPENSES') { } elseif ($modecompta == 'RECETTES-DEPENSES') {
print '<td></td>'; print '<td></td>';
} }
print '<td class="liste_total right">'.price(price2num(-$total_ttc_outcome, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num(-$total_ttc_outcome, 'MT')).'</td>';
print '</tr>'; print '</tr>';
print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Profit").'</td>'; print '<tr class="liste_total"><td class="left" colspan="2">'.$langs->trans("Profit").'</td>';
if ($modecompta == 'CREANCES-DETTES') { if ($modecompta == 'CREANCES-DETTES') {
print '<td class="liste_total right">'.price(price2num($total_ht, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num($total_ht, 'MT')).'</td>';
} elseif ($modecompta == 'RECETTES-DEPENSES') { } elseif ($modecompta == 'RECETTES-DEPENSES') {
print '<td></td>'; print '<td></td>';
} }
print '<td class="liste_total right">'.price(price2num($total_ttc, 'MT')).'</td>'; print '<td class="liste_total right nowraponall">'.price(price2num($total_ttc, 'MT')).'</td>';
print '</tr>'; print '</tr>';
print "</table>"; print "</table>";

View File

@ -92,6 +92,7 @@ class box_members_by_type extends ModeleBoxes
if ($user->rights->adherent->lire) { if ($user->rights->adherent->lire) {
$MembersToValidate = array(); $MembersToValidate = array();
$MembersPending = array();
$MembersValidated = array(); $MembersValidated = array();
$MembersUpToDate = array(); $MembersUpToDate = array();
$MembersExcluded = array(); $MembersExcluded = array();
@ -169,34 +170,63 @@ class box_members_by_type extends ModeleBoxes
} }
$this->db->free($result); $this->db->free($result);
} }
// Members pendding (Waiting for first subscription)
$sql = "SELECT count(*) as somme , d.fk_adherent_type";
$sql .= " FROM " . MAIN_DB_PREFIX . "adherent as d, " . MAIN_DB_PREFIX . "adherent_type as t";
$sql .= " WHERE d.entity IN (" . getEntity('adherent') . ")";
$sql .= " AND d.statut = 1 AND (d.datefin IS NULL AND t.subscription = 1)";
$sql .= " AND t.rowid = d.fk_adherent_type";
$sql .= " GROUP BY d.fk_adherent_type";
dol_syslog("index.php::select nb of uptodate members by type", LOG_DEBUG);
$result = $this->db->query($sql);
if ($result) {
$num2 = $this->db->num_rows($result);
$i = 0;
while ($i < $num2) {
$objp = $this->db->fetch_object($result);
$MembersPending[$objp->fk_adherent_type] = $objp->somme;
$i++;
}
$this->db->free($result);
}
$line = 0; $line = 0;
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class=""', 'td' => 'class=""',
'text' => '', 'text' => '',
); );
// Draft
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_DRAFT, 0, 0, 1); $labelstatus = $staticmember->LibStatut($staticmember::STATUS_DRAFT, 0, 0, 1);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"', 'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
'text' => $labelstatus 'text' => $labelstatus
); );
$labelstatus = $langs->trans("UpToDate"); // Pending (Waiting for first subscription)
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, 0, 1);
$this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
'text' => $labelstatus
);
// Up to date
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() + 86400, 1); $labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() + 86400, 1);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"', 'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
'text' => $labelstatus, 'text' => $labelstatus,
); );
$labelstatus = $langs->trans("OutOfDate"); // Expired
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() - 86400, 1); $labelstatus = $staticmember->LibStatut($staticmember::STATUS_VALIDATED, 1, dol_now() - 86400, 1);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"', 'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
'text' => $labelstatus 'text' => $labelstatus
); );
// Excluded
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_EXCLUDED, 0, 0, 1); $labelstatus = $staticmember->LibStatut($staticmember::STATUS_EXCLUDED, 0, 0, 1);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"', 'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
'text' => $labelstatus 'text' => $labelstatus
); );
// Resiliated
$labelstatus = $staticmember->LibStatut($staticmember::STATUS_RESILIATED, 0, 0, 1); $labelstatus = $staticmember->LibStatut($staticmember::STATUS_RESILIATED, 0, 0, 1);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"', 'td' => 'class="right tdoverflowmax100" width="15%" title="'.dol_escape_htmltag($labelstatus).'"',
@ -205,7 +235,8 @@ class box_members_by_type extends ModeleBoxes
$line++; $line++;
foreach ($AdherentType as $key => $adhtype) { foreach ($AdherentType as $key => $adhtype) {
$SumToValidate += isset($MembersToValidate[$key]) ? $MembersToValidate[$key] : 0; $SumToValidate += isset($MembersToValidate[$key]) ? $MembersToValidate[$key] : 0;
$SumValidated += isset($MembersValidated[$key]) ? $MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) : 0; $SumPending += isset($MembersPending[$key]) ? $MembersPending[$key] : 0;
$SumExpired += isset($MembersValidated[$key]) ? $MembersValidated[$key] - (isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0) - (isset($MembersPending[$key]) ? $MembersPending[$key] : 0): 0;
$SumUpToDate += isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0; $SumUpToDate += isset($MembersUpToDate[$key]) ? $MembersUpToDate[$key] : 0;
$SumExcluded += isset($MembersExcluded[$key]) ? $MembersExcluded [$key] : 0; $SumExcluded += isset($MembersExcluded[$key]) ? $MembersExcluded [$key] : 0;
$SumResiliated += isset($MembersResiliated[$key]) ? $MembersResiliated[$key] : 0; $SumResiliated += isset($MembersResiliated[$key]) ? $MembersResiliated[$key] : 0;
@ -220,6 +251,11 @@ class box_members_by_type extends ModeleBoxes
'text' => (isset($MembersToValidate[$key]) && $MembersToValidate[$key] > 0 ? $MembersToValidate[$key] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3), 'text' => (isset($MembersToValidate[$key]) && $MembersToValidate[$key] > 0 ? $MembersToValidate[$key] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3),
'asis' => 1, 'asis' => 1,
); );
$this->info_box_contents[$line][] = array(
'td' => 'class="right"',
'text' => (isset($MembersPending[$key]) && $MembersPending[$key] > 0 ? $MembersPending[$key] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 0, 3),
'asis' => 1,
);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="right"', 'td' => 'class="right"',
'text' => (isset($MembersUpToDate[$key]) && $MembersUpToDate[$key] > 0 ? $MembersUpToDate[$key] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3), 'text' => (isset($MembersUpToDate[$key]) && $MembersUpToDate[$key] > 0 ? $MembersUpToDate[$key] : '') . ' ' . $staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3),
@ -260,6 +296,11 @@ class box_members_by_type extends ModeleBoxes
'text' => $SumToValidate.' '.$staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3), 'text' => $SumToValidate.' '.$staticmember->LibStatut(Adherent::STATUS_DRAFT, 1, 0, 3),
'asis' => 1 'asis' => 1
); );
$this->info_box_contents[$line][] = array(
'td' => 'class="liste_total right"',
'text' => $SumPending.' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 0, 3),
'asis' => 1
);
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="liste_total right"', 'td' => 'class="liste_total right"',
'text' => $SumUpToDate.' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3), 'text' => $SumUpToDate.' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, $now, 3),
@ -267,7 +308,7 @@ class box_members_by_type extends ModeleBoxes
); );
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(
'td' => 'class="liste_total right"', 'td' => 'class="liste_total right"',
'text' => $SumValidated.' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 1, 3), 'text' => $SumExpired.' '.$staticmember->LibStatut(Adherent::STATUS_VALIDATED, 1, 1, 3),
'asis' => 1 'asis' => 1
); );
$this->info_box_contents[$line][] = array( $this->info_box_contents[$line][] = array(

View File

@ -9600,6 +9600,12 @@ abstract class CommonObject
} }
} }
// Delete linked object
$res = $this->deleteObjectLinked();
if ($res < 0) {
$error++;
}
if (!$error && !empty($this->isextrafieldmanaged)) { if (!$error && !empty($this->isextrafieldmanaged)) {
$result = $this->deleteExtraFields(); $result = $this->deleteExtraFields();
if ($result < 0) { if ($result < 0) {
@ -9723,24 +9729,25 @@ abstract class CommonObject
$tmpforobjectclass = get_class($this); $tmpforobjectclass = get_class($this);
$tmpforobjectlineclass = ucfirst($tmpforobjectclass).'Line'; $tmpforobjectlineclass = ucfirst($tmpforobjectclass).'Line';
$this->db->begin();
// Call trigger // Call trigger
$result = $this->call_trigger('LINE'.strtoupper($tmpforobjectclass).'_DELETE', $user); $result = $this->call_trigger('LINE'.strtoupper($tmpforobjectclass).'_DELETE', $user);
if ($result < 0) { if ($result < 0) {
return -1; $error++;
} }
// End call triggers // End call triggers
$this->db->begin(); if (empty($error)) {
$sql = "DELETE FROM ".$this->db->prefix().$this->table_element_line; $sql = "DELETE FROM ".$this->db->prefix().$this->table_element_line;
$sql .= " WHERE rowid = ".((int) $idline); $sql .= " WHERE rowid = ".((int) $idline);
dol_syslog(get_class($this)."::deleteLineCommon", LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if (!$resql) { if (!$resql) {
$this->error = "Error ".$this->db->lasterror(); $this->error = "Error ".$this->db->lasterror();
$error++; $error++;
} }
}
if (empty($error)) { if (empty($error)) {
// Remove extrafields // Remove extrafields

View File

@ -1211,7 +1211,7 @@ class DolGraph
$tmp = str_replace('#', '', $this->datacolor[$i]); $tmp = str_replace('#', '', $this->datacolor[$i]);
if (strpos($tmp, '-') !== false) { if (strpos($tmp, '-') !== false) {
$foundnegativecolor++; $foundnegativecolor++;
$color = '#FFFFFF'; // If $val is '-123' $color = 'rgba(0,0,0,.0)'; // If $val is '-123'
} else { } else {
$color = "#" . $tmp; // If $val is '123' or '#123' $color = "#" . $tmp; // If $val is '123' or '#123'
} }

View File

@ -270,12 +270,16 @@ class FormAccounting extends Form
} }
while ($i < $num) { while ($i < $num) {
$obj = $this->db->fetch_object($resql); $obj = $this->db->fetch_object($resql);
$titletoshowhtml = ($maxlen ? dol_trunc($obj->type, $maxlen) : $obj->type).($obj->range_account ? ' <span class="opacitymedium">('.$obj->range_account.')</span>' : '');
$titletoshow = ($maxlen ? dol_trunc($obj->type, $maxlen) : $obj->type).($obj->range_account ? ' ('.$obj->range_account.')' : '');
$out .= '<option value="'.$obj->rowid.'"'; $out .= '<option value="'.$obj->rowid.'"';
if ($obj->rowid == $selected) { if ($obj->rowid == $selected) {
$out .= ' selected'; $out .= ' selected';
} }
$out .= ' data-html="'.dol_escape_htmltag(dol_string_onlythesehtmltags($titletoshowhtml, 1, 1, 0, 0, array('span'))).'"';
$out .= '>'; $out .= '>';
$titletoshow = dol_string_nohtmltag(($maxlen ? dol_trunc($obj->type, $maxlen) : $obj->type).' ('.$obj->range_account.')');
$out .= dol_escape_htmltag($titletoshow); $out .= dol_escape_htmltag($titletoshow);
$out .= '</option>'; $out .= '</option>';
$i++; $i++;
@ -339,9 +343,10 @@ class FormAccounting extends Form
* @param int $select_out Set value returned by select. 0=rowid (default), 1=account_number * @param int $select_out Set value returned by select. 0=rowid (default), 1=account_number
* @param string $morecss More css non HTML object * @param string $morecss More css non HTML object
* @param string $usecache Key to use to store result into a cache. Next call with same key will reuse the cache. * @param string $usecache Key to use to store result into a cache. Next call with same key will reuse the cache.
* @param string $active Filter on status active or not: '0', '1' or '' for no filter
* @return string String with HTML select * @return string String with HTML select
*/ */
public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss = 'minwidth100 maxwidth300 maxwidthonsmartphone', $usecache = '') public function select_account($selectid, $htmlname = 'account', $showempty = 0, $event = array(), $select_in = 0, $select_out = 0, $morecss = 'minwidth100 maxwidth300 maxwidthonsmartphone', $usecache = '', $active = '1')
{ {
// phpcs:enable // phpcs:enable
global $conf, $langs; global $conf, $langs;
@ -360,14 +365,18 @@ class FormAccounting extends Form
$options = $options + $this->options_cache[$usecache]; // We use + instead of array_merge because we don't want to reindex key from 0 $options = $options + $this->options_cache[$usecache]; // We use + instead of array_merge because we don't want to reindex key from 0
$selected = $selectid; $selected = $selectid;
} else { } else {
$trunclength = empty($conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT) ? 50 : $conf->global->ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT; $trunclength = getDolGlobalInt('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT', 50);
$sql = "SELECT DISTINCT aa.account_number, aa.label, aa.labelshort, aa.rowid, aa.fk_pcg_version"; $sql = "SELECT DISTINCT aa.account_number, aa.label, aa.labelshort, aa.rowid, aa.fk_pcg_version";
$sql .= " FROM ".$this->db->prefix()."accounting_account as aa"; $sql .= " FROM ".$this->db->prefix()."accounting_account as aa";
$sql .= " INNER JOIN ".$this->db->prefix()."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version"; $sql .= " INNER JOIN ".$this->db->prefix()."accounting_system as asy ON aa.fk_pcg_version = asy.pcg_version";
$sql .= " AND asy.rowid = ".((int) $conf->global->CHARTOFACCOUNTS); $sql .= " AND asy.rowid = ".((int) $conf->global->CHARTOFACCOUNTS);
if ($active === '1') {
$sql .= " AND aa.active = 1"; $sql .= " AND aa.active = 1";
$sql .= " AND aa.entity=".$conf->entity; } elseif ($active === '0') {
$sql .= " AND aa.active = 0";
}
$sql .= " AND aa.entity=".((int) $conf->entity);
$sql .= " ORDER BY aa.account_number"; $sql .= " ORDER BY aa.account_number";
dol_syslog(get_class($this)."::select_account", LOG_DEBUG); dol_syslog(get_class($this)."::select_account", LOG_DEBUG);

View File

@ -191,7 +191,7 @@ class Validate
*/ */
public function isMinLength($string, $length) public function isMinLength($string, $length)
{ {
if (!strlen($string) < $length) { if (strlen($string) < $length) {
$this->error = $this->outputLang->trans('RequireMinLength', $length); $this->error = $this->outputLang->trans('RequireMinLength', $length);
return false; return false;
} }

View File

@ -110,6 +110,7 @@ if (!defined('JS_JQUERY_DISABLE_DROPDOWN')) {
console.log("toggle dropdown dt a"); console.log("toggle dropdown dt a");
//$(this).parent().parent().find(\'dd ul\').slideToggle(\'fast\'); //$(this).parent().parent().find(\'dd ul\').slideToggle(\'fast\');
$(".ulselectedfields").removeClass("open");
$(this).parent().parent().find(\'dd ul\').toggleClass("open"); $(this).parent().parent().find(\'dd ul\').toggleClass("open");
if ($(this).parent().parent().find(\'dd ul\').hasClass("open")) { if ($(this).parent().parent().find(\'dd ul\').hasClass("open")) {

View File

@ -6914,24 +6914,27 @@ function dol_string_nohtmltag($stringtoclean, $removelinefeed = 1, $pagecodeto =
/** /**
* Clean a string to keep only desirable HTML tags. * Clean a string to keep only desirable HTML tags.
* WARNING: This also clean HTML comments (used to obfuscate tag name). * WARNING: This also clean HTML comments (because they can be used to obfuscate tag name).
* *
* @param string $stringtoclean String to clean * @param string $stringtoclean String to clean
* @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles * @param int $cleanalsosomestyles Remove absolute/fixed positioning from inline styles
* @param int $removeclassattribute 1=Remove the class attribute from tags * @param int $removeclassattribute 1=Remove the class attribute from tags
* @param int $cleanalsojavascript Remove also occurence of 'javascript:'. * @param int $cleanalsojavascript Remove also occurence of 'javascript:'.
* @param int $allowiframe Allow iframe tags. * @param int $allowiframe Allow iframe tags.
* @param array $allowed_tags List of allowed tags to replace the default list
* @return string String cleaned * @return string String cleaned
* *
* @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags() * @see dol_escape_htmltag() strip_tags() dol_string_nohtmltag() dol_string_neverthesehtmltags()
*/ */
function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1, $removeclassattribute = 1, $cleanalsojavascript = 0, $allowiframe = 0) function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1, $removeclassattribute = 1, $cleanalsojavascript = 0, $allowiframe = 0, $allowed_tags = array())
{ {
if (empty($allowed_tags)) {
$allowed_tags = array( $allowed_tags = array(
"html", "head", "meta", "body", "article", "a", "abbr", "b", "blockquote", "br", "cite", "div", "dl", "dd", "dt", "em", "font", "img", "ins", "hr", "i", "li", "link", "html", "head", "meta", "body", "article", "a", "abbr", "b", "blockquote", "br", "cite", "div", "dl", "dd", "dt", "em", "font", "img", "ins", "hr", "i", "li", "link",
"ol", "p", "q", "s", "section", "span", "strike", "strong", "title", "table", "tr", "th", "td", "u", "ul", "sup", "sub", "blockquote", "pre", "h1", "h2", "h3", "h4", "h5", "h6", "ol", "p", "q", "s", "section", "span", "strike", "strong", "title", "table", "tr", "th", "td", "u", "ul", "sup", "sub", "blockquote", "pre", "h1", "h2", "h3", "h4", "h5", "h6"
"comment" // this tags is added to manage comment <!--...--> that are replaced into <comment>...</comment>
); );
}
$allowed_tags[] = "comment"; // this tags is added to manage comment <!--...--> that are replaced into <comment>...</comment>
if ($allowiframe) { if ($allowiframe) {
$allowed_tags[] = "iframe"; $allowed_tags[] = "iframe";
} }
@ -6949,7 +6952,7 @@ function dol_string_onlythesehtmltags($stringtoclean, $cleanalsosomestyles = 1,
$stringtoclean = preg_replace('/&colon;/i', ':', $stringtoclean); $stringtoclean = preg_replace('/&colon;/i', ':', $stringtoclean);
$stringtoclean = preg_replace('/&#58;|&#0+58|&#x3A/i', '', $stringtoclean); // refused string ':' encoded (no reason to have a : encoded like this) to disable 'javascript:...' $stringtoclean = preg_replace('/&#58;|&#0+58|&#x3A/i', '', $stringtoclean); // refused string ':' encoded (no reason to have a : encoded like this) to disable 'javascript:...'
$temp = strip_tags($stringtoclean, $allowed_tags_string); // Warning: This remove also undesired </> changing string obfuscated with </> that pass injection detection into harmfull string $temp = strip_tags($stringtoclean, $allowed_tags_string); // Warning: This remove also undesired </>, so may changes string obfuscated with </> that pass the injection detection into a harmfull string
if ($cleanalsosomestyles) { // Clean for remaining html tags if ($cleanalsosomestyles) { // Clean for remaining html tags
$temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless $temp = preg_replace('/position\s*:\s*(absolute|fixed)\s*!\s*important/i', '', $temp); // Note: If hacker try to introduce css comment into string to bypass this regex, the string must also be encoded by the dol_htmlentitiesbr during output so it become harmless

View File

@ -63,7 +63,7 @@ class modAsset extends DolibarrModules
$this->descriptionlong = "Asset module to manage assets module and depreciation charge on Dolibarr"; $this->descriptionlong = "Asset module to manage assets module and depreciation charge on Dolibarr";
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z' // Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
$this->version = 'experimental'; $this->version = 'development';
// Key used in llx_const table to save module status enabled/disabled (where ASSETS is value of property name of module in uppercase) // Key used in llx_const table to save module status enabled/disabled (where ASSETS is value of property name of module in uppercase)
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name); $this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
// Name of image file used for this module. // Name of image file used for this module.

View File

@ -796,7 +796,7 @@ IMG;
// Export to PDF using LibreOffice // Export to PDF using LibreOffice
if ($conf->global->MAIN_ODT_AS_PDF == 'libreoffice') { if (getDolGlobalString('MAIN_ODT_AS_PDF') == 'libreoffice') {
dol_mkdir($conf->user->dir_temp); // We must be sure the directory exists and is writable dol_mkdir($conf->user->dir_temp); // We must be sure the directory exists and is writable
// We delete and recreate a subdir because the soffice may have change pemrissions on it // We delete and recreate a subdir because the soffice may have change pemrissions on it
@ -808,7 +808,7 @@ IMG;
// using linux/mac libreoffice that must be in path // using linux/mac libreoffice that must be in path
// Note PHP Config "fastcgi.impersonate=0" must set to 0 - Default is 1 // Note PHP Config "fastcgi.impersonate=0" must set to 0 - Default is 1
$command ='soffice --headless -env:UserInstallation=file:\''.$conf->user->dir_temp.'/odtaspdf\' --convert-to pdf --outdir '. escapeshellarg(dirname($name)). " ".escapeshellarg($name); $command ='soffice --headless -env:UserInstallation=file:\''.$conf->user->dir_temp.'/odtaspdf\' --convert-to pdf --outdir '. escapeshellarg(dirname($name)). " ".escapeshellarg($name);
} elseif (preg_match('/unoconv/', $conf->global->MAIN_ODT_AS_PDF)) { } elseif (preg_match('/unoconv/', getDolGlobalString('MAIN_ODT_AS_PDF'))) {
// If issue with unoconv, see https://github.com/dagwieers/unoconv/issues/87 // If issue with unoconv, see https://github.com/dagwieers/unoconv/issues/87
// MAIN_ODT_AS_PDF should be "sudo -u unoconv /usr/bin/unoconv" and userunoconv must have sudo to be root by adding file /etc/sudoers.d/unoconv with content www-data ALL=(unoconv) NOPASSWD: /usr/bin/unoconv . // MAIN_ODT_AS_PDF should be "sudo -u unoconv /usr/bin/unoconv" and userunoconv must have sudo to be root by adding file /etc/sudoers.d/unoconv with content www-data ALL=(unoconv) NOPASSWD: /usr/bin/unoconv .
@ -833,17 +833,17 @@ IMG;
// - set shell of user to bash instead of nologin. // - set shell of user to bash instead of nologin.
// - set permission to read/write to user on home directory /var/www so user can create the libreoffice , dconf and .cache dir and files then set permission back // - set permission to read/write to user on home directory /var/www so user can create the libreoffice , dconf and .cache dir and files then set permission back
$command = $conf->global->MAIN_ODT_AS_PDF.' '.escapeshellcmd($name); $command = getDolGlobalString('MAIN_ODT_AS_PDF').' '.escapeshellcmd($name);
//$command = '/usr/bin/unoconv -vvv '.escapeshellcmd($name); //$command = '/usr/bin/unoconv -vvv '.escapeshellcmd($name);
} else { } else {
// deprecated old method using odt2pdf.sh (native, jodconverter, ...) // deprecated old method using odt2pdf.sh (native, jodconverter, ...)
$tmpname=preg_replace('/\.odt/i', '', $name); $tmpname=preg_replace('/\.odt/i', '', $name);
if (!empty($conf->global->MAIN_DOL_SCRIPTS_ROOT)) { if (getDolGlobalString('MAIN_DOL_SCRIPTS_ROOT')) {
$command = $conf->global->MAIN_DOL_SCRIPTS_ROOT.'/scripts/odt2pdf/odt2pdf.sh '.escapeshellcmd($tmpname).' '.(is_numeric($conf->global->MAIN_ODT_AS_PDF)?'jodconverter':$conf->global->MAIN_ODT_AS_PDF); $command = getDolGlobalString('MAIN_DOL_SCRIPTS_ROOT').'/scripts/odt2pdf/odt2pdf.sh '.escapeshellcmd($tmpname).' '.(is_numeric(getDolGlobalString('MAIN_ODT_AS_PDF'))?'jodconverter':getDolGlobalString('MAIN_ODT_AS_PDF'));
} else { } else {
dol_syslog(get_class($this).'::exportAsAttachedPDF is used but the constant MAIN_DOL_SCRIPTS_ROOT with path to script directory was not defined.', LOG_WARNING); dol_syslog(get_class($this).'::exportAsAttachedPDF is used but the constant MAIN_DOL_SCRIPTS_ROOT with path to script directory was not defined.', LOG_WARNING);
$command = '../../scripts/odt2pdf/odt2pdf.sh '.escapeshellcmd($tmpname).' '.(is_numeric($conf->global->MAIN_ODT_AS_PDF)?'jodconverter':$conf->global->MAIN_ODT_AS_PDF); $command = '../../scripts/odt2pdf/odt2pdf.sh '.escapeshellcmd($tmpname).' '.(is_numeric(getDolGlobalString('MAIN_ODT_AS_PDF'))?'jodconverter':getDolGlobalString('MAIN_ODT_AS_PDF'));
} }
} }

View File

@ -271,13 +271,13 @@ Reconcilable=Reconcilable
TotalVente=Total turnover before tax TotalVente=Total turnover before tax
TotalMarge=Total sales margin TotalMarge=Total sales margin
DescVentilCustomer=Consult here the list of customer invoice lines bound (or not) to a product accounting account DescVentilCustomer=Consult here the list of customer invoice lines bound (or not) to a product account from chart of account
DescVentilMore=In most cases, if you use predefined products or services and you set the account number on the product/service card, the application will be able to make all the binding between your invoice lines and the accounting account of your chart of accounts, just in one click with the button <strong>"%s"</strong>. If account was not set on product/service cards or if you still have some lines not bound to an account, you will have to make a manual binding from the menu "<strong>%s</strong>". DescVentilMore=In most cases, if you use predefined products or services and you set the account (from chart of account) on the product/service card, the application will be able to make all the binding between your invoice lines and the accounting account of your chart of accounts, just in one click with the button <strong>"%s"</strong>. If account was not set on product/service cards or if you still have some lines not bound to an account, you will have to make a manual binding from the menu "<strong>%s</strong>".
DescVentilDoneCustomer=Consult here the list of the lines of invoices customers and their product accounting account DescVentilDoneCustomer=Consult here the list of the lines of invoices customers and their product account from chart of account
DescVentilTodoCustomer=Bind invoice lines not already bound with a product accounting account DescVentilTodoCustomer=Bind invoice lines not already bound with a product account from chart of account
ChangeAccount=Change the product/service accounting account for selected lines with the following accounting account: ChangeAccount=Change the product/service account (from chart of account) for the selected lines with the following account:
Vide=- Vide=-
DescVentilSupplier=Consult here the list of vendor invoice lines bound or not yet bound to a product accounting account (only record not already transfered in accountancy are visible) DescVentilSupplier=Consult here the list of vendor invoice lines bound or not yet bound to a product account from chart of account (only record not already transfered in accountancy are visible)
DescVentilDoneSupplier=Consult here the list of the lines of vendor invoices and their accounting account DescVentilDoneSupplier=Consult here the list of the lines of vendor invoices and their accounting account
DescVentilTodoExpenseReport=Bind expense report lines not already bound with a fee accounting account DescVentilTodoExpenseReport=Bind expense report lines not already bound with a fee accounting account
DescVentilExpenseReport=Consult here the list of expense report lines bound (or not) to a fee accounting account DescVentilExpenseReport=Consult here the list of expense report lines bound (or not) to a fee accounting account
@ -295,14 +295,14 @@ DescValidateMovements=Any modification or deletion of writing, lettering and del
ValidateHistory=Bind Automatically ValidateHistory=Bind Automatically
AutomaticBindingDone=Automatic bindings done (%s) - Automatic binding not possible for some record (%s) AutomaticBindingDone=Automatic bindings done (%s) - Automatic binding not possible for some record (%s)
ErrorAccountancyCodeIsAlreadyUse=Error, you cannot delete this accounting account because it is used ErrorAccountancyCodeIsAlreadyUse=Error, you cannot remove or disable this account of chart of account because it is used
MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s & Credit = %s MvtNotCorrectlyBalanced=Movement not correctly balanced. Debit = %s & Credit = %s
Balancing=Balancing Balancing=Balancing
FicheVentilation=Binding card FicheVentilation=Binding card
GeneralLedgerIsWritten=Transactions are written in the Ledger GeneralLedgerIsWritten=Transactions are written in the Ledger
GeneralLedgerSomeRecordWasNotRecorded=Some of the transactions could not be journalized. If there is no other error message, this is probably because they were already journalized. GeneralLedgerSomeRecordWasNotRecorded=Some of the transactions could not be journalized. If there is no other error message, this is probably because they were already journalized.
NoNewRecordSaved=No more record to transfer NoNewRecordSaved=No more record to transfer
ListOfProductsWithoutAccountingAccount=List of products not bound to any accounting account ListOfProductsWithoutAccountingAccount=List of products not bound to any account of chart of account
ChangeBinding=Change the binding ChangeBinding=Change the binding
Accounted=Accounted in ledger Accounted=Accounted in ledger
NotYetAccounted=Not yet transferred to accounting NotYetAccounted=Not yet transferred to accounting

View File

@ -2225,12 +2225,12 @@ MailToPartnership=Partnership
AGENDA_EVENT_DEFAULT_STATUS=Default event status when creating a event from the form AGENDA_EVENT_DEFAULT_STATUS=Default event status when creating a event from the form
YouShouldDisablePHPFunctions=You should disable PHP functions YouShouldDisablePHPFunctions=You should disable PHP functions
IfCLINotRequiredYouShouldDisablePHPFunctions=Except if you need to run system commands in custom code, you shoud disable PHP functions IfCLINotRequiredYouShouldDisablePHPFunctions=Except if you need to run system commands in custom code, you shoud disable PHP functions
PHPFunctionsRequiredForCLI=For shell purpose (like scheduled job backup or running an anitivurs program), you must keep PHP functions PHPFunctionsRequiredForCLI=For shell purpose (like scheduled job backup or running an antivirus program), you must keep PHP functions
NoWritableFilesFoundIntoRootDir=No writable files or directories of the common programs were found into your root directory (Good) NoWritableFilesFoundIntoRootDir=No writable files or directories of the common programs were found into your root directory (Good)
RecommendedValueIs=Recommended: %s RecommendedValueIs=Recommended: %s
Recommended=Recommended Recommended=Recommended
NotRecommended=Not recommended NotRecommended=Not recommended
ARestrictedPath=Some restricted path ARestrictedPath=Some restricted path for data files
CheckForModuleUpdate=Check for external modules updates CheckForModuleUpdate=Check for external modules updates
CheckForModuleUpdateHelp=This action will connect to editors of external modules to check if a new version is available. CheckForModuleUpdateHelp=This action will connect to editors of external modules to check if a new version is available.
ModuleUpdateAvailable=An update is available ModuleUpdateAvailable=An update is available

View File

@ -125,7 +125,8 @@ ValidateProject=Validate projet
ConfirmValidateProject=Are you sure you want to validate this project? ConfirmValidateProject=Are you sure you want to validate this project?
CloseAProject=Close project CloseAProject=Close project
ConfirmCloseAProject=Are you sure you want to close this project? ConfirmCloseAProject=Are you sure you want to close this project?
AlsoCloseAProject=Also close project (keep it open if you still need to follow production tasks on it) AlsoCloseAProject=Also close project
AlsoCloseAProjectTooltip=Keep it open if you still need to follow production tasks on it
ReOpenAProject=Open project ReOpenAProject=Open project
ConfirmReOpenAProject=Are you sure you want to re-open this project? ConfirmReOpenAProject=Are you sure you want to re-open this project?
ProjectContact=Contacts of project ProjectContact=Contacts of project
@ -168,7 +169,7 @@ OpportunityProbability=Lead probability
OpportunityProbabilityShort=Lead probab. OpportunityProbabilityShort=Lead probab.
OpportunityAmount=Lead amount OpportunityAmount=Lead amount
OpportunityAmountShort=Lead amount OpportunityAmountShort=Lead amount
OpportunityWeightedAmount=Opportunity weighted amount OpportunityWeightedAmount=Amount of opportunity, weighted by probability
OpportunityWeightedAmountShort=Opp. weighted amount OpportunityWeightedAmountShort=Opp. weighted amount
OpportunityAmountAverageShort=Average lead amount OpportunityAmountAverageShort=Average lead amount
OpportunityAmountWeigthedShort=Weighted lead amount OpportunityAmountWeigthedShort=Weighted lead amount

View File

@ -27,6 +27,7 @@ Permission56003=Delete tickets
Permission56004=Manage tickets Permission56004=Manage tickets
Permission56005=See tickets of all third parties (not effective for external users, always be limited to the third party they depend on) Permission56005=See tickets of all third parties (not effective for external users, always be limited to the third party they depend on)
Tickets=Tickets
TicketDictType=Ticket - Types TicketDictType=Ticket - Types
TicketDictCategory=Ticket - Groupes TicketDictCategory=Ticket - Groupes
TicketDictSeverity=Ticket - Severities TicketDictSeverity=Ticket - Severities

View File

@ -998,7 +998,7 @@ if (!defined('NOLOGIN')) {
$hookmanager->initHooks(array('main')); $hookmanager->initHooks(array('main'));
// Code for search criteria persistence. // Code for search criteria persistence.
if (!empty($_GET['save_lastsearch_values'])) { // We must use $_GET here if (!empty($_GET['save_lastsearch_values']) && !empty($_SERVER["HTTP_REFERER"])) { // We must use $_GET here
$relativepathstring = preg_replace('/\?.*$/', '', $_SERVER["HTTP_REFERER"]); $relativepathstring = preg_replace('/\?.*$/', '', $_SERVER["HTTP_REFERER"]);
$relativepathstring = preg_replace('/^https?:\/\/[^\/]*/', '', $relativepathstring); // Get full path except host server $relativepathstring = preg_replace('/^https?:\/\/[^\/]*/', '', $relativepathstring); // Get full path except host server
// Clean $relativepathstring // Clean $relativepathstring

View File

@ -55,6 +55,9 @@ global $langs, $user;
// Libraries // Libraries
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php"; require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
require_once '../lib/mymodule.lib.php'; require_once '../lib/mymodule.lib.php';
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
//require_once "../class/myclass.class.php"; //require_once "../class/myclass.class.php";
// Translations // Translations

View File

@ -853,7 +853,7 @@ class MyObject extends CommonObject
//if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : ''); //if ($withpicto != 2) $result.=(($addlabel && $this->label) ? $sep . dol_trunc($this->label, ($addlabel > 1 ? $addlabel : 0)) : '');
global $action, $hookmanager; global $action, $hookmanager;
$hookmanager->initHooks(array('myobjectdao')); $hookmanager->initHooks(array($this->element.'dao'));
$parameters = array('id'=>$this->id, 'getnomurl' => &$result); $parameters = array('id'=>$this->id, 'getnomurl' => &$result);
$reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks $reshook = $hookmanager->executeHooks('getNomUrl', $parameters, $this, $action); // Note that $action and $object may have been modified by some hooks
if ($reshook > 0) { if ($reshook > 0) {

View File

@ -500,11 +500,11 @@ llxHeader("", $title, $help_url);
$titleboth = $langs->trans("LeadsOrProjects"); $titleboth = $langs->trans("LeadsOrProjects");
$titlenew = $langs->trans("NewLeadOrProject"); // Leads and opportunities by default $titlenew = $langs->trans("NewLeadOrProject"); // Leads and opportunities by default
if (empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { if (!getDolGlobalInt('PROJECT_USE_OPPORTUNITIES')) {
$titleboth = $langs->trans("Projects"); $titleboth = $langs->trans("Projects");
$titlenew = $langs->trans("NewProject"); $titlenew = $langs->trans("NewProject");
} }
if ($conf->global->PROJECT_USE_OPPORTUNITIES == 2) { // 2 = leads only if (getDolGlobalInt('PROJECT_USE_OPPORTUNITIES') == 2) { // 2 = leads only
$titleboth = $langs->trans("Leads"); $titleboth = $langs->trans("Leads");
$titlenew = $langs->trans("NewLead"); $titlenew = $langs->trans("NewLead");
} }
@ -567,7 +567,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '</td></tr>'; print '</td></tr>';
// Label // Label
print '<tr><td><span class="fieldrequired">'.$langs->trans("ProjectLabel").'</span></td><td><input class="width500 maxwidth150onsmartphone" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus></td></tr>'; print '<tr><td><span class="fieldrequired">'.$langs->trans("Label").'</span></td><td><input class="width500 maxwidth150onsmartphone" type="text" name="title" value="'.dol_escape_htmltag(GETPOST("title", 'alphanohtml')).'" autofocus></td></tr>';
// Usage (opp, task, bill time, ...) // Usage (opp, task, bill time, ...)
if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) { if (!empty($conf->global->PROJECT_USE_OPPORTUNITIES) || empty($conf->global->PROJECT_HIDE_TASKS) || isModEnabled('eventorganization')) {
@ -602,12 +602,46 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '<input type="checkbox" id="usage_task" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'"> '; print '<input type="checkbox" id="usage_task" name="usage_task"'.(GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') ? ' checked="checked"' : '') : ' checked="checked"').'"> ';
$htmltext = $langs->trans("ProjectFollowTasks"); $htmltext = $langs->trans("ProjectFollowTasks");
print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>'; print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
print '<script>';
print '$( document ).ready(function() {
jQuery("#usage_task").change(function() {
if (jQuery("#usage_task").prop("checked")) {
console.log("Show task fields");
jQuery(".classusetask").show();
} else {
console.log("Hide tasks fields "+jQuery("#usage_task").prop("checked"));
jQuery(".classusetask").hide();
}
});
';
if (GETPOSTISSET('usage_task') && !GETPOST('usage_task')) {
print 'jQuery(".classusetask").hide();';
}
print '});';
print '</script>';
print '<br>'; print '<br>';
} }
if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) { if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') ? ' checked="checked"' : '') : '').'"> '; print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"'.(GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') ? ' checked="checked"' : '') : '').'"> ';
$htmltext = $langs->trans("ProjectBillTimeDescription"); $htmltext = $langs->trans("ProjectBillTimeDescription");
print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>'; print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
print '<script>';
print '$( document ).ready(function() {
jQuery("#usage_bill_time").change(function() {
if (jQuery("#usage_bill_time").prop("checked")) {
console.log("Show bill time fields");
jQuery(".classusebilltime").show();
} else {
console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
jQuery(".classusebilltime").hide();
}
});
';
if (GETPOSTISSET('usage_bill_time') && !GETPOST('usage_bill_time')) {
print 'jQuery(".classusebilltime").hide();';
}
print '});';
print '</script>';
print '<br>'; print '<br>';
} }
if (isModEnabled('eventorganization')) { if (isModEnabled('eventorganization')) {
@ -706,24 +740,26 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityStatus").'</td>'; print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityStatus").'</td>';
print '<td class="maxwidthonsmartphone">'; print '<td class="maxwidthonsmartphone">';
print $formproject->selectOpportunityStatus('opp_status', GETPOSTISSET('opp_status') ? GETPOST('opp_status') : $object->opp_status, 1, 0, 0, 0, '', 0, 1); print $formproject->selectOpportunityStatus('opp_status', GETPOSTISSET('opp_status') ? GETPOST('opp_status') : $object->opp_status, 1, 0, 0, 0, '', 0, 1);
print '</tr>';
// Opportunity probability // Opportunity probability
print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityProbability").'</td>'; print ' <input class="width50 right" type="text" id="opp_percent" name="opp_percent" title="'.dol_escape_htmltag($langs->trans("OpportunityProbability")).'" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : '').'"><span class="hideonsmartphone"> %</span>';
print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : '').'"><span class="hideonsmartphone"> %</span>';
print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? '0' : '1').'">'; print '<input type="hidden" name="opp_percent_not_set" id="opp_percent_not_set" value="'.dol_escape_htmltag(GETPOSTISSET('opp_percent') ? '0' : '1').'">';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
// Opportunity amount // Opportunity amount
print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityAmount").'</td>'; print '<tr class="classuseopportunity"><td>'.$langs->trans("OpportunityAmount").'</td>';
print '<td><input size="5" type="text" name="opp_amount" value="'.dol_escape_htmltag(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : '').'"></td>'; print '<td><input class="width75 right" type="text" name="opp_amount" value="'.dol_escape_htmltag(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : '').'">';
print ' '.$langs->getCurrencySymbol($conf->currency);
print '</td>';
print '</tr>'; print '</tr>';
} }
// Budget // Budget
print '<tr><td>'.$langs->trans("Budget").'</td>'; print '<tr class="classusetask classusebilltime"><td>'.$langs->trans("Budget").'</td>';
print '<td><input size="5" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'"></td>'; print '<td><input class="width75 right" type="text" name="budget_amount" value="'.dol_escape_htmltag(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : '').'">';
print ' '.$langs->getCurrencySymbol($conf->currency);
print '</td>';
print '</tr>'; print '</tr>';
// Date project // Date project
@ -780,6 +816,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '</form>'; print '</form>';
// Change probability from status or role of project // Change probability from status or role of project
// Set also dependencies between use taks and bill time
print '<script type="text/javascript"> print '<script type="text/javascript">
jQuery(document).ready(function() { jQuery(document).ready(function() {
function change_percent() function change_percent()
@ -886,7 +923,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '</td></tr>'; print '</td></tr>';
// Label // Label
print '<tr><td class="fieldrequired">'.$langs->trans("ProjectLabel").'</td>'; print '<tr><td class="fieldrequired">'.$langs->trans("Label").'</td>';
print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>'; print '<td><input class="quatrevingtpercent" name="title" value="'.dol_escape_htmltag($object->title).'"></td></tr>';
// Status // Status
@ -912,6 +949,13 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '<script>'; print '<script>';
print '$( document ).ready(function() { print '$( document ).ready(function() {
jQuery("#usage_opportunity").change(function() { jQuery("#usage_opportunity").change(function() {
set_usage_opportunity();
});
set_usage_opportunity();
function set_usage_opportunity() {
console.log("set_usage_opportunity");
if (jQuery("#usage_opportunity").prop("checked")) { if (jQuery("#usage_opportunity").prop("checked")) {
console.log("Show opportunities fields"); console.log("Show opportunities fields");
jQuery(".classuseopportunity").show(); jQuery(".classuseopportunity").show();
@ -919,9 +963,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked")); console.log("Hide opportunities fields "+jQuery("#usage_opportunity").prop("checked"));
jQuery(".classuseopportunity").hide(); jQuery(".classuseopportunity").hide();
} }
}); };
';
print '
});'; });';
print '</script>'; print '</script>';
print '<br>'; print '<br>';
@ -930,12 +972,52 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '<input type="checkbox" id="usage_task" name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '"> '; print '<input type="checkbox" id="usage_task" name="usage_task"' . (GETPOSTISSET('usage_task') ? (GETPOST('usage_task', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_task ? ' checked="checked"' : '')) . '"> ';
$htmltext = $langs->trans("ProjectFollowTasks"); $htmltext = $langs->trans("ProjectFollowTasks");
print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>'; print '<label for="usage_task">'.$form->textwithpicto($langs->trans("ProjectFollowTasks"), $htmltext).'</label>';
print '<script>';
print '$( document ).ready(function() {
jQuery("#usage_task").change(function() {
set_usage_task();
});
set_usage_task();
function set_usage_task() {
console.log("set_usage_task");
if (jQuery("#usage_task").prop("checked")) {
console.log("Show task fields");
jQuery(".classusetask").show();
} else {
console.log("Hide task fields "+jQuery("#usage_task").prop("checked"));
jQuery(".classusetask").hide();
}
};
});';
print '</script>';
print '<br>'; print '<br>';
} }
if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) { if (empty($conf->global->PROJECT_HIDE_TASKS) && !empty($conf->global->PROJECT_BILL_TIME_SPENT)) {
print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"' . (GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')) . '"> '; print '<input type="checkbox" id="usage_bill_time" name="usage_bill_time"' . (GETPOSTISSET('usage_bill_time') ? (GETPOST('usage_bill_time', 'alpha') != '' ? ' checked="checked"' : '') : ($object->usage_bill_time ? ' checked="checked"' : '')) . '"> ';
$htmltext = $langs->trans("ProjectBillTimeDescription"); $htmltext = $langs->trans("ProjectBillTimeDescription");
print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>'; print '<label for="usage_bill_time">'.$form->textwithpicto($langs->trans("BillTime"), $htmltext).'</label>';
print '<script>';
print '$( document ).ready(function() {
jQuery("#usage_bill_time").change(function() {
set_usage_bill_time();
});
set_usage_bill_time();
function set_usage_bill_time() {
console.log("set_usage_bill_time");
if (jQuery("#usage_bill_time").prop("checked")) {
console.log("Show bill time fields");
jQuery(".classusebilltime").show();
} else {
console.log("Hide bill time fields "+jQuery("#usage_bill_time").prop("checked"));
jQuery(".classusebilltime").hide();
}
};
});';
print '</script>';
print '<br>'; print '<br>';
} }
if (isModEnabled('eventorganization')) { if (isModEnabled('eventorganization')) {
@ -945,6 +1027,13 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '<script>'; print '<script>';
print '$( document ).ready(function() { print '$( document ).ready(function() {
jQuery("#usage_organize_event").change(function() { jQuery("#usage_organize_event").change(function() {
set_usage_event();
});
set_usage_event();
function set_usage_event() {
console.log("set_usage_event");
if (jQuery("#usage_organize_event").prop("checked")) { if (jQuery("#usage_organize_event").prop("checked")) {
console.log("Show organize event fields"); console.log("Show organize event fields");
jQuery(".classuseorganizeevent").show(); jQuery(".classuseorganizeevent").show();
@ -952,9 +1041,7 @@ if ($action == 'create' && $user->rights->projet->creer) {
console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked")); console.log("Hide organize event fields "+jQuery("#usage_organize_event").prop("checked"));
jQuery(".classuseorganizeevent").hide(); jQuery(".classuseorganizeevent").hide();
} }
}); };
';
print '
});'; });';
print '</script>'; print '</script>';
} }
@ -1013,32 +1100,34 @@ if ($action == 'create' && $user->rights->projet->creer) {
// Opportunity status // Opportunity status
print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>'; print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityStatus").'</td>';
print '<td>'; print '<td>';
print $formproject->selectOpportunityStatus('opp_status', $object->opp_status, 1, 0, 0, 0, 'inline-block valignmiddle', 0, 1); print '<div>';
print '<div id="divtocloseproject" class="inline-block valign" style="display: none;"> &nbsp; &nbsp; '; print $formproject->selectOpportunityStatus('opp_status', $object->opp_status, 1, 0, 0, 0, 'inline-block valignmiddle', 1, 1);
print '<input type="checkbox" id="inputcloseproject" name="closeproject" />';
print '<label for="inputcloseproject">'.$langs->trans("AlsoCloseAProject").'</label>';
print '</div>';
print '</td>';
print '</tr>';
// Opportunity probability // Opportunity probability
print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityProbability").'</td>'; print ' <input class="width50 right" type="text" id="opp_percent" name="opp_percent" title="'.dol_escape_htmltag($langs->trans("OpportunityProbability")).'" value="'.(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : (strcmp($object->opp_percent, '') ?vatrate($object->opp_percent) : '')).'"> %';
print '<td><input size="5" type="text" id="opp_percent" name="opp_percent" value="'.(GETPOSTISSET('opp_percent') ? GETPOST('opp_percent') : (strcmp($object->opp_percent, '') ?vatrate($object->opp_percent) : '')).'"> %'; print '<span id="oldopppercent" class="opacitymedium"></span>';
print '<span id="oldopppercent"></span>'; print '</div>';
print '<div id="divtocloseproject" class="inline-block valign clearboth paddingtop" style="display: none;">';
print '<input type="checkbox" id="inputcloseproject" name="closeproject" />';
print '<label for="inputcloseproject">';
print $form->textwithpicto($langs->trans("AlsoCloseAProject"), $langs->trans("AlsoCloseAProjectTooltip")).'</label>';
print ' </div>';
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
// Opportunity amount // Opportunity amount
print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityAmount").'</td>'; print '<tr class="classuseopportunity'.$classfortr.'"><td>'.$langs->trans("OpportunityAmount").'</td>';
print '<td><input size="5" type="text" name="opp_amount" value="'.(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : (strcmp($object->opp_amount, '') ? price2num($object->opp_amount) : '')).'">'; print '<td><input class="width75 right" type="text" name="opp_amount" value="'.(GETPOSTISSET('opp_amount') ? GETPOST('opp_amount') : (strcmp($object->opp_amount, '') ? price2num($object->opp_amount) : '')).'">';
print $langs->getCurrencySymbol($conf->currency); print $langs->getCurrencySymbol($conf->currency);
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
} }
// Budget // Budget
print '<tr><td>'.$langs->trans("Budget").'</td>'; print '<tr class="classusetask classusebilltime"><td>'.$langs->trans("Budget").'</td>';
print '<td><input size="5" type="text" name="budget_amount" value="'.(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : (strcmp($object->budget_amount, '') ? price2num($object->budget_amount) : '')).'">'; print '<td><input class="width75 right" type="text" name="budget_amount" value="'.(GETPOSTISSET('budget_amount') ? GETPOST('budget_amount') : (strcmp($object->budget_amount, '') ? price2num($object->budget_amount) : '')).'">';
print $langs->getCurrencySymbol($conf->currency); print $langs->getCurrencySymbol($conf->currency);
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';
@ -1180,14 +1269,13 @@ if ($action == 'create' && $user->rights->projet->creer) {
if ($code) { if ($code) {
print $langs->trans("OppStatus".$code); print $langs->trans("OppStatus".$code);
} }
print '</td></tr>';
// Opportunity percent // Opportunity percent
print '<tr><td>'.$langs->trans("OpportunityProbability").'</td><td>'; print ' <span title="'.$langs->trans("OpportunityProbability").'"> / ';
if (strcmp($object->opp_percent, '')) { if (strcmp($object->opp_percent, '')) {
print price($object->opp_percent, 0, $langs, 1, 0).' %'; print price($object->opp_percent, 0, $langs, 1, 0).' %';
} }
print '</td></tr>'; print '</span></td></tr>';
// Opportunity Amount // Opportunity Amount
print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>'; print '<tr><td>'.$langs->trans("OpportunityAmount").'</td><td>';
@ -1268,6 +1356,25 @@ if ($action == 'create' && $user->rights->projet->creer) {
print '</form>'; print '</form>';
// Set also dependencies between use taks and bill time
print '<script type="text/javascript">
jQuery(document).ready(function() {
jQuery("#usage_task").change(function() {
console.log("We click on usage task "+jQuery("#usage_task").is(":checked"));
if (! jQuery("#usage_task").is(":checked")) {
jQuery("#usage_bill_time").prop("checked", false);
}
});
jQuery("#usage_bill_time").change(function() {
console.log("We click on usage to bill time");
if (jQuery("#usage_bill_time").is(":checked")) {
jQuery("#usage_task").prop("checked", true);
}
});
});
</script>';
// Change probability from status // Change probability from status
if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PROJECT_USE_OPPORTUNITIES)) { if (!empty($conf->use_javascript_ajax) && !empty($conf->global->PROJECT_USE_OPPORTUNITIES)) {
// Default value to close or not when we set opp to 'WON'. // Default value to close or not when we set opp to 'WON'.
@ -1308,19 +1415,23 @@ if ($action == 'create' && $user->rights->projet->creer) {
} }
/* Change percent with default percent (defaultpercent) if new status (defaultpercent) is higher than current (jQuery("#opp_percent").val()) */ /* Change percent with default percent (defaultpercent) if new status (defaultpercent) is higher than current (jQuery("#opp_percent").val()) */
console.log("oldpercent="+oldpercent);
if (oldpercent != \'\' && (parseFloat(defaultpercent) < parseFloat(oldpercent))) if (oldpercent != \'\' && (parseFloat(defaultpercent) < parseFloat(oldpercent)))
{ {
if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+oldpercent+\' %\'); console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent+" def < old");
if (parseFloat(oldpercent) != 100) { jQuery("#opp_percent").val(oldpercent); } if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') {
else { jQuery("#opp_percent").val(defaultpercent); } jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
}
if (parseFloat(oldpercent) != 100 && elemcode != \'LOST\') { jQuery("#opp_percent").val(oldpercent); }
else { jQuery("#opp_percent").val(price2numjs(defaultpercent)); }
} }
else else
{ {
console.log("oldpercent="+oldpercent+" defaultpercent="+defaultpercent);
if ((parseFloat(jQuery("#opp_percent").val()) < parseFloat(defaultpercent))); if ((parseFloat(jQuery("#opp_percent").val()) < parseFloat(defaultpercent)));
{ {
if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+oldpercent+\' %\'); if (jQuery("#opp_percent").val() != \'\' && oldpercent != \'\') jQuery("#oldopppercent").text(\' - '.dol_escape_js($langs->transnoentities("PreviousValue")).': \'+price2numjs(oldpercent)+\' %\');
jQuery("#opp_percent").val(defaultpercent); jQuery("#opp_percent").val(price2numjs(defaultpercent));
} }
} }
} }

View File

@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
include_once DOL_DOCUMENT_ROOT.'/core/class/stats.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/stats.class.php';
include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
@ -194,6 +195,7 @@ class TaskStats extends Stats
return $res; return $res;
} }
/** /**
* Return the Task amount by month for a year * Return the Task amount by month for a year
* *

View File

@ -191,7 +191,7 @@ if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x'
$search_project_ref = ''; $search_project_ref = '';
$search_project_label = ''; $search_project_label = '';
$search_task_label = ''; $search_task_label = '';
$search_user = 0; $search_user = -1;
$search_valuebilled = ''; $search_valuebilled = '';
$search_product_ref = ''; $search_product_ref = '';
$toselect = array(); $toselect = array();
@ -1561,7 +1561,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
if (empty($search_user)) { if (empty($search_user)) {
$search_user = $user->id; $search_user = $user->id;
} }
$sql .= " AND t.fk_user = ".((int) $search_user); if ($search_user > 0) $sql .= " AND t.fk_user = ".((int) $search_user);
} }
if ($search_note) { if ($search_note) {

View File

@ -1094,7 +1094,7 @@ function Print(id, gift){
function TakeposPrinting(id){ function TakeposPrinting(id){
var receipt; var receipt;
console.log("TakeposPrinting" + id); console.log("TakeposPrinting" + id);
$.get("receipt.php?facid="+id, function(data, status){ $.get("receipt.php?facid="+id, function(data, status) {
receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, ''); receipt=data.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '');
$.ajax({ $.ajax({
type: "POST", type: "POST",

View File

@ -85,7 +85,7 @@ $hookmanager->initHooks(array('takeposfrontend'), $facid);
$reshook = $hookmanager->executeHooks('TakeposReceipt', $parameters, $object); $reshook = $hookmanager->executeHooks('TakeposReceipt', $parameters, $object);
if (!empty($hookmanager->resPrint)) { if (!empty($hookmanager->resPrint)) {
print $hookmanager->resPrint; print $hookmanager->resPrint;
exit; return; // Receipt page can be called by the takepos/send.php page that use ob_start/end so we must use return and not exit to stop page
} }
// IMPORTANT: This file is sended to 'Takepos Printing' application. Keep basic file. No external files as css, js... If you need images use absolute path. // IMPORTANT: This file is sended to 'Takepos Printing' application. Keep basic file. No external files as css, js... If you need images use absolute path.

View File

@ -69,19 +69,19 @@ if ($action == "send") {
include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php';
$formmail = new FormMail($db); $formmail = new FormMail($db);
$outputlangs = new Translate('', $conf); $outputlangs = new Translate('', $conf);
$model_id = $conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE; $model_id = getDolGlobalString('TAKEPOS_EMAIL_TEMPLATE_INVOICE');
$arraydefaultmessage = $formmail->getEMailTemplate($db, 'facture_send', $user, $outputlangs, $model_id); $arraydefaultmessage = $formmail->getEMailTemplate($db, 'facture_send', $user, $outputlangs, $model_id);
$subject = $arraydefaultmessage->topic; $subject = $arraydefaultmessage->topic;
ob_start(); // turn on output receipt ob_start(); // turn on output receipt
include 'receipt.php'; include DOL_DOCUMENT_ROOT.'/takepos/receipt.php';
$receipt = ob_get_contents(); // get the contents of the output buffer $receipt = ob_get_contents(); // get the contents of the output buffer
ob_end_clean(); ob_end_clean();
$msg = "<html>".$arraydefaultmessage->content."<br>".$receipt."</html>"; $msg = "<html>".$arraydefaultmessage->content."<br>".$receipt."</html>";
$sendto = $email; $sendto = $email;
$from = $mysoc->email; $from = $mysoc->email;
$mail = new CMailFile($subject, $sendto, $from, $msg, array(), array(), array(), '', '', 0, 1); $mail = new CMailFile($subject, $sendto, $from, $msg, array(), array(), array(), '', '', 0, 1, '', '', '', '', '', '', DOL_DOCUMENT_ROOT.'/documents/takepos/temp');
if ($mail->error || !empty($mail->errors)) { if ($mail->error || !empty($mail->errors)) {
setEventMessages($mail->error, $mail->errors, 'errors'); setEventMessages($mail->error, $mail->errors, 'errors');
} else { } else {

View File

@ -246,7 +246,7 @@ function _createStatusBadgeCss($statusName, $statusVarNamePrefix = '', $commentL
if (in_array((string) $statusName, $TBadgeBorderOnly)) { if (in_array((string) $statusName, $TBadgeBorderOnly)) {
$thisBadgeTextColor = '#212529'; $thisBadgeTextColor = '#212529';
$thisBadgeBackgroundColor = "#fff"; $thisBadgeBackgroundColor = "";
} }
if (in_array((string) $statusName, array('0', '5', '9'))) { if (in_array((string) $statusName, array('0', '5', '9'))) {

View File

@ -53,6 +53,7 @@
--productlinestockod: #002200; --productlinestockod: #002200;
--productlinestocktoolow: #884400; --productlinestocktoolow: #884400;
--infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #fff, #fff, #fff, #e4efe8); --infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #fff, #fff, #fff, #e4efe8);
--tablevalidbgcolor: rgb(252, 248, 227);
} }
<?php <?php
@ -103,6 +104,7 @@ if (!empty($conf->global->THEME_DARKMODEENABLED)) {
--amountpaymentcomplete:rgb(101,184,77); --amountpaymentcomplete:rgb(101,184,77);
--amountremaintopaybackcolor:rbg(245,130,46); --amountremaintopaybackcolor:rbg(245,130,46);
--infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #000, #000, #000, #274231); --infoboxmoduleenabledbgcolor : linear-gradient(0.4turn, #000, #000, #000, #274231);
--tablevalidbgcolor: rgb(80, 64, 33);
} }
body, button { body, button {
@ -5001,7 +5003,7 @@ table.valid {
padding-right: 4px; padding-right: 4px;
padding-bottom: 4px; padding-bottom: 4px;
margin: 0px 0px; margin: 0px 0px;
background: #fcf8e3; background: var(--tablevalidbgcolor);
} }
.validtitre { .validtitre {

View File

@ -236,7 +236,7 @@ class Ticket extends CommonObject
const STATUS_READ = 1; const STATUS_READ = 1;
const STATUS_ASSIGNED = 2; const STATUS_ASSIGNED = 2;
const STATUS_IN_PROGRESS = 3; const STATUS_IN_PROGRESS = 3;
const STATUS_NEED_MORE_INFO = 5; const STATUS_NEED_MORE_INFO = 5; // waiting requester feedback
const STATUS_WAITING = 7; // on hold const STATUS_WAITING = 7; // on hold
const STATUS_CLOSED = 8; // Closed - Solved const STATUS_CLOSED = 8; // Closed - Solved
const STATUS_CANCELED = 9; // Closed - Not solved const STATUS_CANCELED = 9; // Closed - Not solved
@ -2667,7 +2667,10 @@ class Ticket extends CommonObject
} }
// Set status to "answered" if not set yet, but only if internal user and not private message // Set status to "answered" if not set yet, but only if internal user and not private message
if ($object->status < 3 && !$user->socid && !$private) { // Or set status to "answered" if the client has answered and if the ticket has started
if (($object->status < self::STATUS_IN_PROGRESS && !$user->socid && !$private) ||
($object->status > self::STATUS_IN_PROGRESS && $public_area)
) {
$object->setStatut(3); $object->setStatut(3);
} }
return 1; return 1;

View File

@ -42,6 +42,9 @@ if ($user->socid > 0) {
$optioncss = GETPOST('optioncss', 'alpha'); $optioncss = GETPOST('optioncss', 'alpha');
$contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'userlist'; // To manage different context of search $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'userlist'; // To manage different context of search
$mode = GETPOST("mode", 'alpha'); $mode = GETPOST("mode", 'alpha');
if (empty($mode)) {
$mode = 'hierarchy';
}
$sortfield = GETPOST('sortfield', 'aZ09comma'); $sortfield = GETPOST('sortfield', 'aZ09comma');
$sortorder = GETPOST('sortorder', 'aZ09comma'); $sortorder = GETPOST('sortorder', 'aZ09comma');

View File

@ -46,6 +46,7 @@ $conf->global->MAIN_DISABLE_ALL_MAILS=1;
*/ */
class AdminLibTest extends PHPUnit\Framework\TestCase class AdminLibTest extends PHPUnit\Framework\TestCase
{ {
protected $backupGlobalsBlacklist = array('conf', 'user', 'langs', 'db');
protected $savconf; protected $savconf;
protected $savuser; protected $savuser;
protected $savlangs; protected $savlangs;
@ -69,6 +70,7 @@ class AdminLibTest extends PHPUnit\Framework\TestCase
$this->savdb=$db; $this->savdb=$db;
print __METHOD__." db->type=".$db->type." user->id=".$user->id; print __METHOD__." db->type=".$db->type." user->id=".$user->id;
//print " - db ".$db->db; //print " - db ".$db->db;
print "\n"; print "\n";
} }

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE phpunit SYSTEM "phpunit.dtd" > <!DOCTYPE phpunit SYSTEM "phpunit.dtd" >
<phpunit <phpunit
backupGlobals="true" backupGlobals="false"
backupStaticAttributes="false" backupStaticAttributes="true"
convertErrorsToExceptions="true" convertErrorsToExceptions="true"
convertNoticesToExceptions="true" convertNoticesToExceptions="true"
convertWarningsToExceptions="true" convertWarningsToExceptions="true"