Merge remote-tracking branch 'upstream/develop' into 18a5

This commit is contained in:
Alexandre SPANGARO 2023-04-12 11:26:16 +02:00
commit 1ee7a525f1
41 changed files with 775 additions and 352 deletions

View File

@ -53,6 +53,10 @@ addons:
- php8.1-mysqli - php8.1-mysqli
- php8.1-xml - php8.1-xml
- php8.1-intl - php8.1-intl
- php8.2-pgsql
- php8.2-mysqli
- php8.2-xml
- php8.2-intl
env: env:
global: global:
@ -73,8 +77,8 @@ jobs:
php: '8.1' php: '8.1'
env: DB=mysql env: DB=mysql
- stage: PHP Dev - stage: PHP Dev
if: type = push AND branch = 17.0 if: type = push AND branch = develop
php: nightly php: '8.2'
env: DB=mysql env: DB=mysql
notifications: notifications:
@ -120,7 +124,7 @@ install:
squizlabs/php_codesniffer ^3 squizlabs/php_codesniffer ^3
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" = '8.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then
composer self-update 2.4.4 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 \
@ -260,7 +264,7 @@ before_script:
# enable php-fpm # enable php-fpm
- sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf - sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.conf
- | - |
if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = '7.3' ] || [ "$TRAVIS_PHP_VERSION" = '7.4' ] || [ "$TRAVIS_PHP_VERSION" = '8.0' ] || [ "$TRAVIS_PHP_VERSION" = '8.1' ] || [ "$TRAVIS_PHP_VERSION" = '8.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then
# Copy the included pool # Copy the included pool
sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf sudo cp ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$(phpenv version-name)/etc/php-fpm.d/www.conf
fi fi

View File

@ -231,7 +231,7 @@ if ($action == 'install') {
if (!$error) { if (!$error) {
@dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the target directory @dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the target directory
$submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulenameval; $submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/'.$modulenameval;
if (!dol_is_dir($modulenamedir)) { if (!dol_is_dir($submodulenamedir)) {
$submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval; $submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval;
} }
dol_syslog("We copy now directory ".$submodulenamedir." into target dir ".$dirins.'/'.$modulenameval); dol_syslog("We copy now directory ".$submodulenamedir." into target dir ".$dirins.'/'.$modulenameval);
@ -476,7 +476,7 @@ foreach ($modulesdir as $dir) {
dol_syslog("Module ".get_class($objMod)." not qualified"); dol_syslog("Module ".get_class($objMod)." not qualified");
} }
} else { } else {
print "Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>"; print "admin/modules.php Warning bad descriptor file : ".$dir.$file." (Class ".$modName." not found into file)<br>";
} }
} catch (Exception $e) { } catch (Exception $e) {
dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR); dol_syslog("Failed to load ".$dir.$file." ".$e->getMessage(), LOG_ERR);

View File

@ -181,16 +181,25 @@ $formproduct = new FormProduct($db);
$disabled = ''; $disabled = '';
if (isModEnabled('productbatch')) { if (isModEnabled('productbatch')) {
// If module lot/serial enabled, we force the inc/dec mode to STOCK_CALCULATE_ON_SHIPMENT_CLOSE and STOCK_CALCULATE_ON_RECEPTION_CLOSE
$langs->load("productbatch"); $langs->load("productbatch");
$disabled = ' disabled'; $disabled = ' disabled';
print info_admin($langs->trans("WhenProductBatchModuleOnOptionAreForced"));
// STOCK_CALCULATE_ON_SHIPMENT_CLOSE
$descmode = $langs->trans('DeStockOnShipmentOnClosing');
if (!isModEnabled('reception')) {
// STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER
$incmode = $langs->trans('ReStockOnDispatchOrder');
} else {
// STOCK_CALCULATE_ON_RECEPTION_CLOSE
$incmode = $langs->trans('StockOnReceptionOnClosing');
}
print info_admin($langs->trans("WhenProductBatchModuleOnOptionAreForced", $descmode, $incmode));
} }
//if (!empty($conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER) || !empty($conf->global->STOCK_CALCULATE_ON_SHIPMENT))
//{
print info_admin($langs->trans("IfYouUsePointOfSaleCheckModule")); print info_admin($langs->trans("IfYouUsePointOfSaleCheckModule"));
print '<br>'; print '<br>';
//}
print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">'; print '<form method="POST" action="'.$_SERVER['PHP_SELF'].'">';
@ -221,7 +230,7 @@ if (isModEnabled('facture')) {
print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_BILL); print $form->selectarray("STOCK_CALCULATE_ON_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_BILL);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module30Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -242,7 +251,7 @@ if (isModEnabled('commande')) {
print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER); print $form->selectarray("STOCK_CALCULATE_ON_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_VALIDATE_ORDER);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module25Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -261,7 +270,7 @@ if (isModEnabled("expedition")) {
print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT); print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -278,7 +287,7 @@ if (isModEnabled("expedition")) {
print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE); print $form->selectarray("STOCK_CALCULATE_ON_SHIPMENT_CLOSE", $arrval, $conf->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module80Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -313,7 +322,7 @@ if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMO
print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_BILL", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_BILL);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -335,7 +344,7 @@ if ((isModEnabled("fournisseur") && empty($conf->global->MAIN_USE_NEW_SUPPLIERMO
print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;
@ -380,7 +389,7 @@ if (isModEnabled("reception")) {
print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER); print $form->selectarray("STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER", $arrval, $conf->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER);
} }
} else { } else {
print $langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")); print '<span class="opacitymedium">'.$langs->trans("ModuleMustBeEnabledFirst", $langs->transnoentitiesnoconv("Module40Name")).'</span>';
} }
print "</td>\n</tr>\n"; print "</td>\n</tr>\n";
$found++; $found++;

View File

@ -746,12 +746,22 @@ if (empty($reshook)) {
$fk_unit = GETPOST('unit', 'alpha'); $fk_unit = GETPOST('unit', 'alpha');
// update price_ht with discount
// TODO Use object->updateline instead objedtline->update
$price_ht = price2num(GETPOST('elprice'), 'MU');
$remise_percent = price2num(GETPOST('elremise_percent'), 2);
if ($remise_percent > 0) {
$remise = round(($price_ht * $remise_percent / 100), 2);
$price_ht = ($price_ht - $remise);
}
$objectline->fk_product = GETPOST('idprod', 'int'); $objectline->fk_product = GETPOST('idprod', 'int');
$objectline->description = GETPOST('product_desc', 'restricthtml'); $objectline->description = GETPOST('product_desc', 'restricthtml');
$objectline->price_ht = price2num(GETPOST('elprice'), 'MU'); $objectline->price_ht = $price_ht;
$objectline->subprice = price2num(GETPOST('elprice'), 'MU'); $objectline->subprice = price2num(GETPOST('elprice'), 'MU');
$objectline->qty = price2num(GETPOST('elqty'), 'MS'); $objectline->qty = price2num(GETPOST('elqty'), 'MS');
$objectline->remise_percent = price2num(GETPOST('elremise_percent'), 2); $objectline->remise_percent = $remise_percent;
$objectline->tva_tx = ($txtva ? $txtva : 0); // Field may be disabled, so we use vat rate 0 $objectline->tva_tx = ($txtva ? $txtva : 0); // Field may be disabled, so we use vat rate 0
$objectline->vat_src_code = $vat_src_code; $objectline->vat_src_code = $vat_src_code;
$objectline->localtax1_tx = is_numeric($localtax1_tx) ? $localtax1_tx : 0; $objectline->localtax1_tx = is_numeric($localtax1_tx) ? $localtax1_tx : 0;

View File

@ -6461,6 +6461,14 @@ abstract class CommonObject
dol_syslog('Error bad setup of extrafield', LOG_WARNING); dol_syslog('Error bad setup of extrafield', LOG_WARNING);
} }
break; break;
case 'checkbox':
case 'chkbxlst':
if (is_array($this->array_options[$key])) {
$new_array_options[$key] = implode(',', $this->array_options[$key]);
} else {
$new_array_options[$key] = $this->array_options[$key];
}
break;
} }
} }
@ -6814,6 +6822,14 @@ abstract class CommonObject
} }
break; break;
*/ */
case 'checkbox':
case 'chkbxlst':
if (is_array($this->array_options[$key])) {
$new_array_options[$key] = implode(',', $this->array_options[$key]);
} else {
$new_array_options[$key] = $this->array_options[$key];
}
break;
} }
$this->db->begin(); $this->db->begin();
@ -8256,7 +8272,7 @@ abstract class CommonObject
// Test on 'enabled' ('enabled' is different than 'list' = 'visibility') // Test on 'enabled' ('enabled' is different than 'list' = 'visibility')
$enabled = 1; $enabled = 1;
if ($enabled && isset($extrafields->attributes[$this->table_element]['enabled'][$key])) { if ($enabled && isset($extrafields->attributes[$this->table_element]['enabled'][$key])) {
$enabled = dol_eval($extrafields->attributes[$this->table_element]['enabled'][$key], 1, 1, '1'); $enabled = dol_eval($extrafields->attributes[$this->table_element]['enabled'][$key], 1, 1, '2');
} }
if (empty($enabled)) { if (empty($enabled)) {
continue; continue;
@ -8264,12 +8280,12 @@ abstract class CommonObject
$visibility = 1; $visibility = 1;
if ($visibility && isset($extrafields->attributes[$this->table_element]['list'][$key])) { if ($visibility && isset($extrafields->attributes[$this->table_element]['list'][$key])) {
$visibility = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1, 1, '1'); $visibility = dol_eval($extrafields->attributes[$this->table_element]['list'][$key], 1, 1, '2');
} }
$perms = 1; $perms = 1;
if ($perms && isset($extrafields->attributes[$this->table_element]['perms'][$key])) { if ($perms && isset($extrafields->attributes[$this->table_element]['perms'][$key])) {
$perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1, 1, '1'); $perms = dol_eval($extrafields->attributes[$this->table_element]['perms'][$key], 1, 1, '2');
} }
if (($mode == 'create') && abs($visibility) != 1 && abs($visibility) != 3) { if (($mode == 'create') && abs($visibility) != 1 && abs($visibility) != 3) {
@ -9982,7 +9998,7 @@ abstract class CommonObject
$this->db->begin(); $this->db->begin();
$statusfield = 'status'; $statusfield = 'status';
if ($this->element == 'don' || $this->element == 'donation') { if (in_array($this->element, array('don', 'donation', 'shipping'))) {
$statusfield = 'fk_statut'; $statusfield = 'fk_statut';
} }

View File

@ -109,6 +109,24 @@ class Conf
public $tzuserinputkey = 'tzserver'; // Use 'tzuserrel' to always store date in GMT and show date in time zone of user. public $tzuserinputkey = 'tzserver'; // Use 'tzuserrel' to always store date in GMT and show date in time zone of user.
// TODO Remove this part.
public $fournisseur;
public $product;
public $service;
public $contrat;
public $actions;
public $agenda;
public $commande;
public $propal;
public $facture;
public $user;
public $adherent;
public $bank;
public $notification;
public $expensereport;
public $productbatch;
/** /**
* Constructor * Constructor
@ -165,7 +183,6 @@ class Conf
$this->commande = new stdClass(); $this->commande = new stdClass();
$this->propal = new stdClass(); $this->propal = new stdClass();
$this->facture = new stdClass(); $this->facture = new stdClass();
$this->contrat = new stdClass();
$this->user = new stdClass(); $this->user = new stdClass();
$this->adherent = new stdClass(); $this->adherent = new stdClass();
$this->bank = new stdClass(); $this->bank = new stdClass();
@ -635,18 +652,19 @@ class Conf
unset($this->global->PROJECT_USE_SEARCH_TO_SELECT); unset($this->global->PROJECT_USE_SEARCH_TO_SELECT);
} }
if (!empty($this->productbatch->enabled)) { if (isModEnabled('productbatch')) {
// If module lot/serial enabled, we force the inc/dec mode to STOCK_CALCULATE_ON_SHIPMENT_CLOSE and STOCK_CALCULATE_ON_RECEPTION_CLOSE
$this->global->STOCK_CALCULATE_ON_BILL = 0; $this->global->STOCK_CALCULATE_ON_BILL = 0;
$this->global->STOCK_CALCULATE_ON_VALIDATE_ORDER = 0; $this->global->STOCK_CALCULATE_ON_VALIDATE_ORDER = 0;
if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) $this->global->STOCK_CALCULATE_ON_SHIPMENT = 1;
if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT)) $this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE = 1; if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT)) $this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE = 1;
if (empty($this->global->STOCK_CALCULATE_ON_SHIPMENT_CLOSE)) $this->global->STOCK_CALCULATE_ON_SHIPMENT = 1;
$this->global->STOCK_CALCULATE_ON_SUPPLIER_BILL = 0; $this->global->STOCK_CALCULATE_ON_SUPPLIER_BILL = 0;
$this->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER = 0; $this->global->STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER = 0;
if (empty($this->reception->enabled)) { if (!isModEnabled('reception')) {
$this->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER = 1; $this->global->STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER = 1;
} else { } else {
if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) $this->global->STOCK_CALCULATE_ON_RECEPTION = 1;
if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION)) $this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE = 1; if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION)) $this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE = 1;
if (empty($this->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) $this->global->STOCK_CALCULATE_ON_RECEPTION = 1;
} }
} }

View File

@ -961,9 +961,9 @@ class ExtraFields
$unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key]; $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
$required = $this->attributes[$extrafieldsobjectkey]['required'][$key]; $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
$param = $this->attributes[$extrafieldsobjectkey]['param'][$key]; $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
$perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '1'); $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
$langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key]; $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
$list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1'); $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
$totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key]; $totalizable = $this->attributes[$extrafieldsobjectkey]['totalizable'][$key];
$help = $this->attributes[$extrafieldsobjectkey]['help'][$key]; $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
$hidden = (empty($list) ? 1 : 0); // If empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller) $hidden = (empty($list) ? 1 : 0); // If empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
@ -1597,9 +1597,9 @@ class ExtraFields
$unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key]; $unique = $this->attributes[$extrafieldsobjectkey]['unique'][$key];
$required = $this->attributes[$extrafieldsobjectkey]['required'][$key]; $required = $this->attributes[$extrafieldsobjectkey]['required'][$key];
$param = $this->attributes[$extrafieldsobjectkey]['param'][$key]; $param = $this->attributes[$extrafieldsobjectkey]['param'][$key];
$perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '1'); $perms = dol_eval($this->attributes[$extrafieldsobjectkey]['perms'][$key], 1, 1, '2');
$langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key]; $langfile = $this->attributes[$extrafieldsobjectkey]['langfile'][$key];
$list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '1'); $list = dol_eval($this->attributes[$extrafieldsobjectkey]['list'][$key], 1, 1, '2');
$help = $this->attributes[$extrafieldsobjectkey]['help'][$key]; $help = $this->attributes[$extrafieldsobjectkey]['help'][$key];
$hidden = (empty($list) ? 1 : 0); // If $list empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller) $hidden = (empty($list) ? 1 : 0); // If $list empty, we are sure it is hidden, otherwise we show. If it depends on mode (view/create/edit form or list, this must be filtered by caller)
@ -2097,17 +2097,17 @@ class ExtraFields
$enabled = 1; $enabled = 1;
if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not if (isset($this->attributes[$object->table_element]['enabled'][$key])) { // 'enabled' is often a condition on module enabled or not
$enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '1'); $enabled = dol_eval($this->attributes[$object->table_element]['enabled'][$key], 1, 1, '2');
} }
$visibility = 1; $visibility = 1;
if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility if (isset($this->attributes[$object->table_element]['list'][$key])) { // 'list' is option for visibility
$visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '1')); $visibility = intval(dol_eval($this->attributes[$object->table_element]['list'][$key], 1, 1, '2'));
} }
$perms = 1; $perms = 1;
if (isset($this->attributes[$object->table_element]['perms'][$key])) { if (isset($this->attributes[$object->table_element]['perms'][$key])) {
$perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '1'); $perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1, 1, '2');
} }
if (empty($enabled) if (empty($enabled)
|| ( || (

View File

@ -5087,21 +5087,21 @@ class Form
* print '});'."\n"; * print '});'."\n";
* print '</script>'."\n"; * print '</script>'."\n";
* *
* @param string $page Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated) * @param string $page Url of page to call if confirmation is OK. Can contains parameters (param 'action' and 'confirm' will be reformated)
* @param string $title Title * @param string $title Title
* @param string $question Question * @param string $question Question
* @param string $action Action * @param string $action Action
* @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...')) * @param array|string $formquestion An array with complementary inputs to add into forms: array(array('label'=> ,'type'=> , 'size'=>, 'morecss'=>, 'moreattr'=>'autofocus' or 'style=...'))
* 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss', * 'type' can be 'text', 'password', 'checkbox', 'radio', 'date', 'datetime', 'select', 'multiselect', 'morecss',
* 'other', 'onecolumn' or 'hidden'... * 'other', 'onecolumn' or 'hidden'...
* @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0 * @param int|string $selectedchoice '' or 'no', or 'yes' or '1', 1, '0' or 0
* @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx * @param int|string $useajax 0=No, 1=Yes use Ajax to show the popup, 2=Yes and also submit page with &confirm=no if choice is No, 'xxx'=Yes and preoutput confirm box with div id=dialog-confirm-xxx
* @param int|string $height Force height of box (0 = auto) * @param int|string $height Force height of box (0 = auto)
* @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones. * @param int $width Force width of box ('999' or '90%'). Ignored and forced to 90% on smartphones.
* @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a <form> section. * @param int $disableformtag 1=Disable form tag. Can be used if we are already inside a <form> section.
* @param string $labelbuttonyes Label for Yes * @param string $labelbuttonyes Label for Yes
* @param string $labelbuttonno Label for No * @param string $labelbuttonno Label for No
* @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form * @return string HTML ajax code if a confirm ajax popup is required, Pure HTML code if it's an html form
*/ */
public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No') public function formconfirm($page, $title, $question, $action, $formquestion = '', $selectedchoice = '', $useajax = 0, $height = 0, $width = 500, $disableformtag = 0, $labelbuttonyes = 'Yes', $labelbuttonno = 'No')
{ {

View File

@ -380,7 +380,7 @@ class FormProjets
include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php'; include_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
$comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus); $comboenhancement = ajax_combobox($htmlname, '', 0, $forcefocus);
$out .= $comboenhancement; $out .= $comboenhancement;
$morecss .= ' minwidth200 maxwidth500'; $morecss .= ' minwidth150';
} }
if (empty($option_only)) { if (empty($option_only)) {

View File

@ -360,9 +360,11 @@ class modExpedition extends DolibarrModules
$sql = array( $sql = array(
"DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'shipping' AND entity = ".((int) $conf->entity), "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'shipping' AND entity = ".((int) $conf->entity),
"INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','shipping',".((int) $conf->entity).")", "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."', 'shipping', ".((int) $conf->entity).")",
"DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[3][2])."' AND type = 'delivery' AND entity = ".((int) $conf->entity), "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[3][2])."' AND type = 'delivery' AND entity = ".((int) $conf->entity),
"INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[3][2])."','delivery',".((int) $conf->entity).")", "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[3][2])."', 'delivery', ".((int) $conf->entity).")",
//"DELETE FROM ".MAIN_DB_PREFIX."const WHERE name IN ('STOCK_CALCULATE_ON_BILL', 'STOCK_CALCULATE_ON_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SHIPMENT', 'STOCK_CALCULATE_ON_SHIPMENT_CLOSE') AND entity = ".((int) $conf->entity),
//"INSERT INTO ".MAIN_DB_PREFIX."const (name, value, entity) VALUES ('STOCK_CALCULATE_ON_SHIPMENT_CLOSE', 1, ".((int) $conf->entity).")"
); );
return $this->_init($sql, $options); return $this->_init($sql, $options);

View File

@ -119,7 +119,7 @@ class modMrp extends DolibarrModules
$this->hidden = false; $this->hidden = false;
// List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...)
$this->depends = array('modBom'); $this->depends = array('modBom');
$this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) $this->requiredby = array('modWorkstation'); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...)
$this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...)
$this->langfiles = array("mrp"); $this->langfiles = array("mrp");
$this->phpmin = array(7, 0); // Minimum version of PHP required by module $this->phpmin = array(7, 0); // Minimum version of PHP required by module

View File

@ -282,8 +282,10 @@ class modReception extends DolibarrModules
$sql = array(); $sql = array();
$sql = array( $sql = array(
"DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'reception' AND entity = ".((int) $conf->entity), "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = '".$this->db->escape($this->const[0][2])."' AND type = 'reception' AND entity = ".((int) $conf->entity),
"INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','reception',".((int) $conf->entity).")", "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('".$this->db->escape($this->const[0][2])."','reception',".((int) $conf->entity).")",
//"DELETE FROM ".MAIN_DB_PREFIX."const WHERE name IN ('STOCK_CALCULATE_ON_SUPPLIER_BILL', 'STOCK_CALCULATE_ON_SUPPLIER_VALIDATE_ORDER', 'STOCK_CALCULATE_ON_SUPPLIER_DISPATCH_ORDER', 'STOCK_CALCULATE_ON_RECEPTION', 'STOCK_CALCULATE_ON_RECEPTION_CLOSE') AND entity = ".((int) $conf->entity),
//"INSERT INTO ".MAIN_DB_PREFIX."const (name, value, entity) VALUES ('STOCK_CALCULATE_ON_RECEPTION_CLOSE', 1, ".((int) $conf->entity).")"
); );
return $this->_init($sql, $options); return $this->_init($sql, $options);

View File

@ -61,7 +61,7 @@ class modStockTransfer extends DolibarrModules
// Module description, used if translation string 'ModuleStockTransferDesc' not found (StockTransfer is name of module). // Module description, used if translation string 'ModuleStockTransferDesc' not found (StockTransfer is name of module).
$this->description = $langs->trans("ModuleStockTransferDesc"); $this->description = $langs->trans("ModuleStockTransferDesc");
// Used only if file README.md and README-LL.md not found. // Used only if file README.md and README-LL.md not found.
$this->descriptionlong = "StockTransfer description (Long)"; $this->descriptionlong = "Advanced management of stock transfer orders with generation of stock transfer sheets";
// 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 = 'experimental';
// Url to the file with your last numberversion of this module // Url to the file with your last numberversion of this module

View File

@ -120,7 +120,7 @@ class modWorkstation extends DolibarrModules
// A condition to hide module // A condition to hide module
$this->hidden = false; $this->hidden = false;
// List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...) // List of module class names as string that must be enabled if this module is enabled. Example: array('always1'=>'modModuleToEnable1','always2'=>'modModuleToEnable2', 'FR1'=>'modModuleToEnableFR'...)
$this->depends = array(); $this->depends = array('modMrp');
$this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...) $this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...)
$this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...) $this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...)
$this->langfiles = array("mrp"); $this->langfiles = array("mrp");

View File

@ -74,15 +74,15 @@ if (empty($reshook) && isset($extrafields->attributes[$object->table_element]['l
$enabled = 1; $enabled = 1;
if ($enabled && isset($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra])) { if ($enabled && isset($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra])) {
$enabled = dol_eval($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra], 1); $enabled = dol_eval($extrafields->attributes[$object->table_element]['enabled'][$tmpkeyextra], 1, 1, '2');
} }
if ($enabled && isset($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra])) { if ($enabled && isset($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra])) {
$enabled = dol_eval($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra], 1); $enabled = dol_eval($extrafields->attributes[$object->table_element]['list'][$tmpkeyextra], 1, 1, '2');
} }
$perms = 1; $perms = 1;
if ($perms && isset($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra])) { if ($perms && isset($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra])) {
$perms = dol_eval($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra], 1); $perms = dol_eval($extrafields->attributes[$object->table_element]['perms'][$tmpkeyextra], 1, 1, '2');
} }
//print $tmpkeyextra.'-'.$enabled.'-'.$perms.'<br>'."\n"; //print $tmpkeyextra.'-'.$enabled.'-'.$perms.'<br>'."\n";

View File

@ -134,14 +134,14 @@ if (isset($this->situation_cycle_ref) && $this->situation_cycle_ref) {
if ($usemargins && isModEnabled('margin') && empty($user->socid)) { if ($usemargins && isModEnabled('margin') && empty($user->socid)) {
if (!empty($user->rights->margins->creer)) { if (!empty($user->rights->margins->creer)) {
if ($conf->global->MARGIN_TYPE == "1") { if ($conf->global->MARGIN_TYPE == "1") {
print '<th class="linecolmargin1 margininfos right" style="width: 80px">'.$langs->trans('BuyingPrice').'</th>'; print '<th class="linecolmargin1 margininfos right width75">'.$langs->trans('BuyingPrice').'</th>';
} else { } else {
print '<th class="linecolmargin1 margininfos right" style="width: 80px">'.$langs->trans('CostPrice').'</th>'; print '<th class="linecolmargin1 margininfos right width75">'.$langs->trans('CostPrice').'</th>';
} }
} }
if (!empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) { if (!empty($conf->global->DISPLAY_MARGIN_RATES) && $user->rights->margins->liretous) {
print '<th class="linecolmargin2 margininfos right" style="width: 50px">'.$langs->trans('MarginRate'); print '<th class="linecolmargin2 margininfos right width75">'.$langs->trans('MarginRate');
if ($user->hasRight("propal", "creer")) { if ($user->hasRight("propal", "creer")) {
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?mode=marginforalllines&id='.$object->id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickmarginforalllines opacitymedium paddingleft cursorpointer"').'</a>'; print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?mode=marginforalllines&id='.$object->id.'">'.img_edit($langs->trans("UpdateForAllLines"), 0, 'class="clickmarginforalllines opacitymedium paddingleft cursorpointer"').'</a>';
if (GETPOST('mode', 'aZ09') == 'marginforalllines') { if (GETPOST('mode', 'aZ09') == 'marginforalllines') {
@ -154,7 +154,7 @@ if ($usemargins && isModEnabled('margin') && empty($user->socid)) {
print '</th>'; print '</th>';
} }
if (!empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) { if (!empty($conf->global->DISPLAY_MARK_RATES) && $user->rights->margins->liretous) {
print '<th class="linecolmargin2 margininfos right" style="width: 50px">'.$langs->trans('MarkRate').'</th>'; print '<th class="linecolmargin2 margininfos right width75">'.$langs->trans('MarkRate').'</th>';
} }
} }

View File

@ -865,7 +865,7 @@ class EmailCollector extends CommonObject
/** /**
* overwitePropertiesOfObject * overwitePropertiesOfObject
* *
* @param object $object Current object * @param object $object Current object we will set ->properties
* @param string $actionparam Action parameters * @param string $actionparam Action parameters
* @param string $messagetext Body * @param string $messagetext Body
* @param string $subject Subject * @param string $subject Subject
@ -896,8 +896,13 @@ class EmailCollector extends CommonObject
// Overwrite values with values extracted from source email // Overwrite values with values extracted from source email
// $this->actionparam = 'opportunity_status=123;abc=EXTRACT:BODY:....' // $this->actionparam = 'opportunity_status=123;abc=EXTRACT:BODY:....'
$arrayvaluetouse = dolExplodeIntoArray($actionparam, '(\n\r|\r|\n|;)', '='); $arrayvaluetouse = dolExplodeIntoArray($actionparam, '(\n\r|\r|\n|;)', '=');
$tmp = array();
// Loop on each property set into actionparam
foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) { foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) {
$tmpclass = ''; $tmpproperty = ''; $tmpclass = '';
$tmpproperty = '';
$tmparray = explode('.', $propertytooverwrite); $tmparray = explode('.', $propertytooverwrite);
if (count($tmparray) == 2) { if (count($tmparray) == 2) {
$tmpclass = $tmparray[0]; $tmpclass = $tmparray[0];
@ -952,23 +957,39 @@ class EmailCollector extends CommonObject
if (preg_match('/^options_/', $tmpproperty)) { if (preg_match('/^options_/', $tmpproperty)) {
$object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted);
} else { } else {
$object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); if (property_exists($object, $tmpproperty)) {
$object->$tmpproperty = $this->decodeSMTPSubject($valueextracted);
} else {
$tmp[$tmpproperty] = $this->decodeSMTPSubject($valueextracted);
}
} }
} else { // extract from BODY } else { // extract from BODY
if (preg_match('/^options_/', $tmpproperty)) { if (preg_match('/^options_/', $tmpproperty)) {
$object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted); $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $this->decodeSMTPSubject($valueextracted);
} else { } else {
$object->$tmpproperty = $this->decodeSMTPSubject($valueextracted); if (property_exists($object, $tmpproperty)) {
$object->$tmpproperty = $this->decodeSMTPSubject($valueextracted);
} else {
$tmp[$tmpproperty] = $this->decodeSMTPSubject($valueextracted);
}
} }
} }
if (preg_match('/^options_/', $tmpproperty)) { if (preg_match('/^options_/', $tmpproperty)) {
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->array_options[preg_replace('/^options_/', '', $tmpproperty)], 128)); $operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->array_options[preg_replace('/^options_/', '', $tmpproperty)], 128));
} else { } else {
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->$tmpproperty, 128)); if (property_exists($object, $tmpproperty)) {
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($object->$tmpproperty, 128));
} else {
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> found '.dol_escape_htmltag(dol_trunc($tmp[$tmpproperty], 128));
}
} }
} else { } else {
// Regex not found // Regex not found
$object->$tmpproperty = null; if (property_exists($object, $tmpproperty)) {
$object->$tmpproperty = null;
} else {
$tmp[$tmpproperty] = null;
}
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> not found, so property '.dol_escape_htmltag($tmpproperty).' is set to null.'; $operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/'.dol_escape_htmltag($regexoptions).' into '.strtolower($sourcefield).' -> not found, so property '.dol_escape_htmltag($tmpproperty).' is set to null.';
} }
@ -983,7 +1004,11 @@ class EmailCollector extends CommonObject
if (preg_match('/^options_/', $tmpproperty)) { if (preg_match('/^options_/', $tmpproperty)) {
$valuecurrent = $object->array_options[preg_replace('/^options_/', '', $tmpproperty)]; $valuecurrent = $object->array_options[preg_replace('/^options_/', '', $tmpproperty)];
} else { } else {
$valuecurrent = $object->$tmpproperty; if (property_exists($object, $tmpproperty)) {
$valuecurrent = $object->$tmpproperty;
} else {
$valuecurrent = $tmp[$tmpproperty];
}
} }
if ($regforregex[1] == 'SET' || empty($valuecurrent)) { if ($regforregex[1] == 'SET' || empty($valuecurrent)) {
@ -993,24 +1018,38 @@ class EmailCollector extends CommonObject
$matcharray = array(); $matcharray = array();
preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray); preg_match_all('/__([a-z0-9]+(?:_[a-z0-9]+)?)__/i', $valuetouse, $matcharray);
//var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray); //var_dump($tmpproperty.' - '.$object->$tmpproperty.' - '.$valuetouse); var_dump($matcharray);
if (is_array($matcharray[1])) { // $matcharray[1] is array with list of substitution key found without the __ if (is_array($matcharray[1])) { // $matcharray[1] is an array with the list of substitution key found without the __X__ syntax into the SET entry
foreach ($matcharray[1] as $keytoreplace) { foreach ($matcharray[1] as $keytoreplace) {
if ($keytoreplace && isset($object->$keytoreplace)) { if ($keytoreplace) {
$substitutionarray['__'.$keytoreplace.'__'] = $object->$keytoreplace; if (preg_match('/^options_/', $keytoreplace)) {
$substitutionarray['__'.$keytoreplace.'__'] = $object->array_options[preg_replace('/^options_/', '', $keytoreplace)];
} else {
if (property_exists($object, $keytoreplace)) {
$substitutionarray['__'.$keytoreplace.'__'] = $object->$keytoreplace;
} else {
$substitutionarray['__'.$keytoreplace.'__'] = $tmp[$keytoreplace];
}
}
} }
} }
} }
//var_dump($substitutionarray); //var_dump($substitutionarray);
dol_syslog(var_export($substitutionarray, true)); dol_syslog('substitutionarray='.var_export($substitutionarray, true));
//var_dump($substitutionarray); //var_dump($substitutionarray);
$valuetouse = make_substitutions($valuetouse, $substitutionarray); $valuetouse = make_substitutions($valuetouse, $substitutionarray);
if (preg_match('/^options_/', $tmpproperty)) { if (preg_match('/^options_/', $tmpproperty)) {
$object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse; $object->array_options[preg_replace('/^options_/', '', $tmpproperty)] = $valuetouse;
} else {
$object->$tmpproperty = $valuetouse;
}
$operationslog .= '<br>Set value '.dol_escape_htmltag($valuetouse).' into variable '.dol_escape_htmltag($tmpproperty); $operationslog .= '<br>Set value '.dol_escape_htmltag($valuetouse).' into object->array_options['.dol_escape_htmltag(preg_replace('/^options_/', '', $tmpproperty)).']';
} else {
if (property_exists($object, $tmpproperty)) {
$object->$tmpproperty = $valuetouse;
} else {
$tmp[$tmpproperty] = $valuetouse;
}
$operationslog .= '<br>Set value '.dol_escape_htmltag($valuetouse).' into object->'.dol_escape_htmltag($tmpproperty);
}
} }
} else { } else {
$errorforthisaction++; $errorforthisaction++;
@ -1041,7 +1080,7 @@ class EmailCollector extends CommonObject
require_once DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php'; require_once DOL_DOCUMENT_ROOT.'/includes/webklex/php-imap/vendor/autoload.php';
} }
dol_syslog("EmailCollector::doCollectOneCollector start for id=".$this->id." - ".$this->ref, LOG_DEBUG); dol_syslog("EmailCollector::doCollectOneCollector start for id=".$this->id." - ".$this->ref, LOG_INFO);
$langs->loadLangs(array("project", "companies", "mails", "errors", "ticket", "agenda", "commercial")); $langs->loadLangs(array("project", "companies", "mails", "errors", "ticket", "agenda", "commercial"));
@ -1470,6 +1509,9 @@ class EmailCollector extends CommonObject
try { try {
//var_dump($Query->count()); //var_dump($Query->count());
if ($mode > 0) {
$Query->leaveUnread();
}
$arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder("asc")->get(); $arrayofemail = $Query->limit($this->maxemailpercollect)->setFetchOrder("asc")->get();
//var_dump($arrayofemail); //var_dump($arrayofemail);
} catch (Exception $e) { } catch (Exception $e) {
@ -2016,6 +2058,7 @@ class EmailCollector extends CommonObject
$result = $contactstatic->fetch(0, null, '', $from); $result = $contactstatic->fetch(0, null, '', $from);
if ($result > 0) { if ($result > 0) {
dol_syslog("We found a contact with the email ".$from);
$contactid = $contactstatic->id; $contactid = $contactstatic->id;
$contactfoundby = 'email of contact ('.$from.')'; $contactfoundby = 'email of contact ('.$from.')';
if (empty($thirdpartyid) && $contactstatic->socid > 0) { if (empty($thirdpartyid) && $contactstatic->socid > 0) {
@ -2031,12 +2074,44 @@ class EmailCollector extends CommonObject
if (empty($thirdpartyid)) { // Try to find thirdparty using email if (empty($thirdpartyid)) { // Try to find thirdparty using email
$result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $from); $result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $from);
if ($result > 0) { if ($result > 0) {
dol_syslog("We found a thirdparty with the email ".$from);
$thirdpartyid = $thirdpartystatic->id;;
$thirdpartyfoundby = 'email ('.$from.')'; $thirdpartyfoundby = 'email ('.$from.')';
} }
} }
// Do operations /*
if ($mode < 2) { if ($replyto) {
if (empty($contactid)) { // Try to find contact using email
$result = $contactstatic->fetch(0, null, '', $replyto);
if ($result > 0) {
dol_syslog("We found a contact with the email ".$replyto);
$contactid = $contactstatic->id;
$contactfoundby = 'email of contact ('.$replyto.')';
if (empty($thirdpartyid) && $contactstatic->socid > 0) {
$result = $thirdpartystatic->fetch($contactstatic->socid);
if ($result > 0) {
$thirdpartyid = $thirdpartystatic->id;
$thirdpartyfoundby = 'email of contact ('.$replyto.')';
}
}
}
}
if (empty($thirdpartyid)) { // Try to find thirdparty using email
$result = $thirdpartystatic->fetch(0, '', '', '', '', '', '', '', '', '', $replyto);
if ($result > 0) {
dol_syslog("We found a thirdparty with the email ".$replyto);
$thirdpartyid = $thirdpartystatic->id;;
$thirdpartyfoundby = 'email ('.$replyto.')';
}
}
}
*/
// Do operations (extract variables and creating data)
if ($mode < 2) { // 0=Mode production, 1=Mode test (read IMAP and try SQL update then rollback), 2=Mode test with no SQL updates
foreach ($this->actions as $operation) { foreach ($this->actions as $operation) {
$errorforthisaction = 0; $errorforthisaction = 0;
@ -2047,6 +2122,8 @@ class EmailCollector extends CommonObject
continue; continue;
} }
$operationslog .= '<br>* Process operation '.$operation['type'];
// Make Operation // Make Operation
dol_syslog("Execute action ".$operation['type']." actionparam=".$operation['actionparam'].' thirdpartystatic->id='.$thirdpartystatic->id.' contactstatic->id='.$contactstatic->id.' projectstatic->id='.$projectstatic->id); dol_syslog("Execute action ".$operation['type']." actionparam=".$operation['actionparam'].' thirdpartystatic->id='.$thirdpartystatic->id.' contactstatic->id='.$contactstatic->id.' projectstatic->id='.$projectstatic->id);
dol_syslog("Execute action fk_element_id=".$fk_element_id." fk_element_type=".$fk_element_type); // If a Dolibarr tracker id is found, we should now the id of object dol_syslog("Execute action fk_element_id=".$fk_element_id." fk_element_type=".$fk_element_type); // If a Dolibarr tracker id is found, we should now the id of object
@ -2084,6 +2161,8 @@ class EmailCollector extends CommonObject
$emailtouseforthirdparty = ''; $emailtouseforthirdparty = '';
$namealiastouseforthirdparty = ''; $namealiastouseforthirdparty = '';
$operationslog .= '<br>Loop on each property to set into actionparam';
// $actionparam = 'param=SET:aaa' or 'param=EXTRACT:BODY:....' // $actionparam = 'param=SET:aaa' or 'param=EXTRACT:BODY:....'
$arrayvaluetouse = dolExplodeIntoArray($actionparam, '(\n\r|\r|\n|;)', '='); $arrayvaluetouse = dolExplodeIntoArray($actionparam, '(\n\r|\r|\n|;)', '=');
foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) { foreach ($arrayvaluetouse as $propertytooverwrite => $valueforproperty) {
@ -2115,21 +2194,21 @@ class EmailCollector extends CommonObject
if ($propertytooverwrite == 'id') { if ($propertytooverwrite == 'id') {
$idtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; $idtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found idtouseforthirdparty='.dol_escape_htmltag($idtouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found idtouseforthirdparty='.dol_escape_htmltag($idtouseforthirdparty);
} elseif ($propertytooverwrite == 'email') { } elseif ($propertytooverwrite == 'email') {
$emailtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; $emailtouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found emailtouseforthirdparty='.dol_escape_htmltag($emailtouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found emailtouseforthirdparty='.dol_escape_htmltag($emailtouseforthirdparty);
} elseif ($propertytooverwrite == 'name') { } elseif ($propertytooverwrite == 'name') {
$nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; $nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty);
} elseif ($propertytooverwrite == 'name_alias') { } elseif ($propertytooverwrite == 'name_alias') {
$nametouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null; $namealiastouseforthirdparty = isset($regforval[count($regforval) - 1]) ? trim($regforval[count($regforval) - 1]) : null;
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Found namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty);
} else { } else {
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> We discard this, not used to search existing thirdparty'; $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> We discard this, not used to search existing thirdparty';
} }
} else { } else {
// Regex not found // Regex not found
@ -2138,7 +2217,7 @@ class EmailCollector extends CommonObject
$emailtouseforthirdparty = null; $emailtouseforthirdparty = null;
$namealiastouseforthirdparty = null; $namealiastouseforthirdparty = null;
$operationslog .= '<br>Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Not found'; $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.' Regex /'.dol_escape_htmltag($regexstring).'/ms into '.strtoupper($sourcefield).' -> Not found';
} }
//var_dump($object->$tmpproperty);exit; //var_dump($object->$tmpproperty);exit;
} else { } else {
@ -2154,19 +2233,19 @@ class EmailCollector extends CommonObject
if ($propertytooverwrite == 'id') { if ($propertytooverwrite == 'id') {
$idtouseforthirdparty = $reg[2]; $idtouseforthirdparty = $reg[2];
$operationslog .= '<br>We set property idtouseforthrdparty='.dol_escape_htmltag($idtouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.'We set property idtouseforthrdparty='.dol_escape_htmltag($idtouseforthirdparty);
} elseif ($propertytooverwrite == 'email') { } elseif ($propertytooverwrite == 'email') {
$emailtouseforthirdparty = $reg[2]; $emailtouseforthirdparty = $reg[2];
$operationslog .= '<br>We set property emailtouseforthrdparty='.dol_escape_htmltag($emailtouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.'We set property emailtouseforthrdparty='.dol_escape_htmltag($emailtouseforthirdparty);
} elseif ($propertytooverwrite == 'name') { } elseif ($propertytooverwrite == 'name') {
$nametouseforthirdparty = $reg[2]; $nametouseforthirdparty = $reg[2];
$operationslog .= '<br>We set property nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.'We set property nametouseforthirdparty='.dol_escape_htmltag($nametouseforthirdparty);
} elseif ($propertytooverwrite == 'name_alias') { } elseif ($propertytooverwrite == 'name_alias') {
$namealiastouseforthirdparty = $reg[2]; $namealiastouseforthirdparty = $reg[2];
$operationslog .= '<br>We set property namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty); $operationslog .= '<br>propertytooverwrite='.$propertytooverwrite.'We set property namealiastouseforthirdparty='.dol_escape_htmltag($namealiastouseforthirdparty);
} }
} else { } else {
$errorforactions++; $errorforactions++;
@ -2177,6 +2256,25 @@ class EmailCollector extends CommonObject
} }
if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) { if (!$errorforactions && ($idtouseforthirdparty || $emailtouseforthirdparty || $nametouseforthirdparty || $namealiastouseforthirdparty)) {
// We make another search on thirdparty
$operationslog .= '<br>We have this data to search thirdparty: '.$idtouseforthirdparty.' '.$emailtouseforthirdparty.' '.$nametouseforthirdparty.' '.$namealiastouseforthirdparty;
$tmpobject = new stdClass();
$tmpobject->element == 'generic';
$tmpobject->id = $idtouseforthirdparty;
$tmpobject->name = $nametouseforthirdparty;
$tmpobject->name_alias = $namealiastouseforthirdparty;
$tmpobject->email = $emailtouseforthirdparty;
$this->overwritePropertiesOfObject($tmpobject, $operation['actionparam'], $messagetext, $subject, $header, $operationslog);
$idtouseforthirdparty = $tmpobject->id;
$nametouseforthirdparty = $tmpobject->name;
$namealiastouseforthirdparty = $tmpobject->name_alias;
$emailtouseforthirdparty = $tmpobject->email;
$operationslog .= '<br>We try to search existing thirdparty with '.$idtouseforthirdparty.' '.$emailtouseforthirdparty.' '.$nametouseforthirdparty.' '.$namealiastouseforthirdparty;
$result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty, $namealiastouseforthirdparty); $result = $thirdpartystatic->fetch($idtouseforthirdparty, $nametouseforthirdparty, '', '', '', '', '', '', '', '', $emailtouseforthirdparty, $namealiastouseforthirdparty);
if ($result < 0) { if ($result < 0) {
$errorforactions++; $errorforactions++;
@ -2195,6 +2293,7 @@ class EmailCollector extends CommonObject
dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found. We try to create it."); dol_syslog("Third party with id=".$idtouseforthirdparty." email=".$emailtouseforthirdparty." name=".$nametouseforthirdparty." name_alias=".$namealiastouseforthirdparty." was not found. We try to create it.");
// Create thirdparty // Create thirdparty
$thirdpartystatic = new Societe($db);
$thirdpartystatic->name = $nametouseforthirdparty; $thirdpartystatic->name = $nametouseforthirdparty;
if (!empty($namealiastouseforthirdparty)) { if (!empty($namealiastouseforthirdparty)) {
if ($namealiastouseforthirdparty != $nametouseforthirdparty) { if ($namealiastouseforthirdparty != $nametouseforthirdparty) {
@ -2230,6 +2329,8 @@ class EmailCollector extends CommonObject
} }
} else { } else {
dol_syslog("One and only one existing third party has been found"); dol_syslog("One and only one existing third party has been found");
$operationslog .= '<br>Thirdparty already exists with id = '.dol_escape_htmltag($thirdpartystatic->id);
} }
} }
} }
@ -2726,6 +2827,8 @@ class EmailCollector extends CommonObject
} }
} }
} else { } else {
dol_syslog("Project already exists for msgid = ".dol_escape_htmltag($msgid).", so we do not recreate it.");
$operationslog .= '<br>Project already exists for msgid ='.dol_escape_htmltag($msgid); $operationslog .= '<br>Project already exists for msgid ='.dol_escape_htmltag($msgid);
} }
} elseif ($operation['type'] == 'ticket') { } elseif ($operation['type'] == 'ticket') {
@ -2995,9 +3098,9 @@ class EmailCollector extends CommonObject
// Error for email or not ? // Error for email or not ?
if (!$errorforactions) { if (!$errorforactions) {
if ($targetdir && empty($mode)) { if (!empty($targetdir) && empty($mode)) {
if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) {
dol_syslog("EmailCollector::doCollectOneCollector move message ".$imapemail." to ".$connectstringtarget, LOG_DEBUG); dol_syslog("EmailCollector::doCollectOneCollector move message ".((string) $imapemail)." to ".$connectstringtarget, LOG_DEBUG);
$res = imap_mail_move($connection, $imapemail, $targetdir, 0); $res = imap_mail_move($connection, $imapemail, $targetdir, 0);
if ($res == false) { if ($res == false) {
$errorforemail++; $errorforemail++;
@ -3006,7 +3109,9 @@ class EmailCollector extends CommonObject
dol_syslog(imap_last_error()); dol_syslog(imap_last_error());
} }
} else { } else {
// TODO Move mail using PHP-IMAP // Move mail using PHP-IMAP
dol_syslog("EmailCollector::doCollectOneCollector move message ".($imapemail->getHeader()->get('subject'))." to ".$targetdir, LOG_DEBUG);
$imapemail->move($targetdir);
} }
} else { } else {
if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { if (empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) {
@ -3059,7 +3164,8 @@ class EmailCollector extends CommonObject
if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) { if (!empty($conf->global->MAIN_IMAP_USE_PHPIMAP)) {
$client->disconnect(); $client->disconnect();
} else { } else {
if (empty($mode)) { if (empty($mode) && empty($error)) {
dol_syslog("Expunge", LOG_DEBUG);
imap_expunge($connection); // To validate any move imap_expunge($connection); // To validate any move
} }
imap_close($connection); imap_close($connection);
@ -3088,7 +3194,7 @@ class EmailCollector extends CommonObject
$this->update($user); $this->update($user);
} }
dol_syslog("EmailCollector::doCollectOneCollector end", LOG_DEBUG); dol_syslog("EmailCollector::doCollectOneCollector end", LOG_INFO);
return $error ? -1 : 1; return $error ? -1 : 1;
} }

View File

@ -157,10 +157,21 @@ if (empty($reshook)) {
$upload_dir = $conf->expedition->dir_output.'/sending'; $upload_dir = $conf->expedition->dir_output.'/sending';
include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
// Back to draft
if ($action == 'setdraft' && $user->rights->expedition->creer) {
$object->fetch($id);
$result = $object->setDraft($user, 0);
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
}
// Reopen // Reopen
if ($action == 'reopen' && $user->rights->expedition->creer) { if ($action == 'reopen' && $user->rights->expedition->creer) {
$object->fetch($id); $object->fetch($id);
$result = $object->reOpen(); $result = $object->reOpen();
if ($result < 0) {
setEventMessages($object->error, $object->errors, 'errors');
}
} }
// Set incoterm // Set incoterm
@ -349,6 +360,7 @@ if (empty($reshook)) {
if ($totalqty > 0 && !$error) { // There is at least one thing to ship and no error if ($totalqty > 0 && !$error) { // There is at least one thing to ship and no error
for ($i = 0; $i < $num; $i++) { for ($i = 0; $i < $num; $i++) {
$qty = "qtyl".$i; $qty = "qtyl".$i;
if (!isset($batch_line[$i])) { if (!isset($batch_line[$i])) {
// not batch mode // not batch mode
if (isset($stockLine[$i])) { if (isset($stockLine[$i])) {
@ -400,7 +412,7 @@ if (empty($reshook)) {
} }
if (!$error) { if (!$error) {
$ret = $object->create($user); // This create shipment (like Odoo picking) and lines of shipments. Stock movement will be done when validating shipment. $ret = $object->create($user); // This create shipment (like Odoo picking) and lines of shipments. Stock movement will be done when validating or closing shipment.
if ($ret <= 0) { if ($ret <= 0) {
setEventMessages($object->error, $object->errors, 'errors'); setEventMessages($object->error, $object->errors, 'errors');
$error++; $error++;
@ -1735,6 +1747,11 @@ if ($action == 'create') {
} }
$text = $langs->trans("ConfirmValidateSending", $numref); $text = $langs->trans("ConfirmValidateSending", $numref);
if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
$text .= '<br>'.$langs->trans("StockMovementWillBeRecorded").'.';
} elseif (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
$text .= '<br>'.$langs->trans("StockMovementNotYetRecorded").'.';
}
if (isModEnabled('notification')) { if (isModEnabled('notification')) {
require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php'; require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
@ -1743,7 +1760,7 @@ if ($action == 'create') {
$text .= $notify->confirmMessage('SHIPPING_VALIDATE', $object->socid, $object); $text .= $notify->confirmMessage('SHIPPING_VALIDATE', $object->socid, $object);
} }
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1); $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1, 250);
} }
// Confirm cancelation // Confirm cancelation
if ($action == 'cancel') { if ($action == 'cancel') {
@ -2268,6 +2285,8 @@ if ($action == 'create') {
// Qty in other shipments (with shipment and warehouse used) // Qty in other shipments (with shipment and warehouse used)
if ($origin && $origin_id > 0) { if ($origin && $origin_id > 0) {
print '<td class="linecolqtyinothershipments center nowrap">'; print '<td class="linecolqtyinothershipments center nowrap">';
$htmltooltip = '';
$qtyalreadysent = 0;
foreach ($alreadysent as $key => $val) { foreach ($alreadysent as $key => $val) {
if ($lines[$i]->fk_origin_line == $key) { if ($lines[$i]->fk_origin_line == $key) {
$j = 0; $j = 0;
@ -2278,20 +2297,23 @@ if ($action == 'create') {
$j++; $j++;
if ($j > 1) { if ($j > 1) {
print '<br>'; $htmltooltip .= '<br>';
} }
$shipment_static->fetch($shipmentline_var['shipment_id']); $shipment_static->fetch($shipmentline_var['shipment_id']);
print $shipment_static->getNomUrl(1); $htmltooltip .= $shipment_static->getNomUrl(1, '', 0, 0, 1);
print ' - '.$shipmentline_var['qty_shipped']; $htmltooltip .= ' - '.$shipmentline_var['qty_shipped'];
$htmltext = $langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($shipmentline_var['date_valid'], 'dayhour')); $htmltooltip .= ' - '.$langs->trans("DateValidation").' : '.(empty($shipmentline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
if (isModEnabled('stock') && $shipmentline_var['warehouse'] > 0) { /*if (isModEnabled('stock') && $shipmentline_var['warehouse'] > 0) {
$warehousestatic->fetch($shipmentline_var['warehouse']); $warehousestatic->fetch($shipmentline_var['warehouse']);
$htmltext .= '<br>'.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1); $htmltext .= '<br>'.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
} }*/
print ' '.$form->textwithpicto('', $htmltext, 1); //print ' '.$form->textwithpicto('', $htmltext, 1);
$qtyalreadysent += $shipmentline_var['qty_shipped'];
} }
} }
} }
print $form->textwithpicto($qtyalreadysent, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
print '</td>'; print '</td>';
} }
@ -2390,7 +2412,7 @@ if ($action == 'create') {
if ($detail_entrepot->entrepot_id > 0) { if ($detail_entrepot->entrepot_id > 0) {
$entrepot = new Entrepot($db); $entrepot = new Entrepot($db);
$entrepot->fetch($detail_entrepot->entrepot_id); $entrepot->fetch($detail_entrepot->entrepot_id);
$detail .= $langs->trans("DetailWarehouseFormat", $entrepot->libelle, $detail_entrepot->qty_shipped).'<br>'; $detail .= $langs->trans("DetailWarehouseFormat", $entrepot->label, $detail_entrepot->qty_shipped).'<br>';
} }
} }
print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail); print $form->textwithtooltip(img_picto('', 'object_stock').' '.$langs->trans("DetailWarehouseNumber"), $detail);
@ -2531,13 +2553,20 @@ if ($action == 'create') {
} }
} }
// TODO add alternative status // 0=draft, 1=validated/delivered, 2=closed/delivered
// 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order) // If WORKFLOW_BILL_ON_SHIPMENT: 0=draft, 1=validated, 2=billed (no status delivered)
if ($object->statut == Expedition::STATUS_CLOSED && $user->rights->expedition->creer) { if ($object->statut == Expedition::STATUS_VALIDATED && !getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ? if ($user->hasRight('expedition', 'creer')) {
print dolGetButtonAction('', $langs->trans('ClassifyUnbilled'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?action=setdraft&token='.newToken().'&id='.$object->id, '');
} else { }
print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, ''); }
if ($object->statut == Expedition::STATUS_CLOSED) {
if ($user->hasRight('expedition', 'creer')) {
if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
print dolGetButtonAction('', $langs->trans('ClassifyUnbilled'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, '');
} else {
print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, '');
}
} }
} }

View File

@ -2209,8 +2209,8 @@ class Expedition extends CommonObject
$sql = "SELECT cd.fk_product, cd.subprice,"; $sql = "SELECT cd.fk_product, cd.subprice,";
$sql .= " ed.rowid, ed.qty, ed.fk_entrepot,"; $sql .= " ed.rowid, ed.qty, ed.fk_entrepot,";
$sql .= " e.ref,"; $sql .= " e.ref,";
$sql .= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock"; $sql .= " edb.rowid as edbrowid, edb.eatby, edb.sellby, edb.batch, edb.qty as edbqty, edb.fk_origin_stock,";
$sql .= " ,cd.rowid as cdid, ed.rowid as edid"; $sql .= " cd.rowid as cdid, ed.rowid as edid";
$sql .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd,"; $sql .= " FROM " . MAIN_DB_PREFIX . "commandedet as cd,";
$sql .= " " . MAIN_DB_PREFIX . "expeditiondet as ed"; $sql .= " " . MAIN_DB_PREFIX . "expeditiondet as ed";
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "expeditiondet_batch as edb on edb.fk_expeditiondet = ed.rowid";
@ -2264,8 +2264,8 @@ class Expedition extends CommonObject
// If some stock lines are now 0, we can remove entry into llx_product_stock, but only if there is no child lines into llx_product_batch (detail of batch, because we can imagine // If some stock lines are now 0, we can remove entry into llx_product_stock, but only if there is no child lines into llx_product_batch (detail of batch, because we can imagine
// having a lot1/qty=X and lot2/qty=-X, so 0 but we must not loose repartition of different lot. // having a lot1/qty=X and lot2/qty=-X, so 0 but we must not loose repartition of different lot.
$sql = "DELETE FROM ".MAIN_DB_PREFIX."product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".MAIN_DB_PREFIX."product_batch as pb)"; $sqldelete = "DELETE FROM ".MAIN_DB_PREFIX."product_stock WHERE reel = 0 AND rowid NOT IN (SELECT fk_product_stock FROM ".MAIN_DB_PREFIX."product_batch as pb)";
$resql = $this->db->query($sql); $resqldelete = $this->db->query($sqldelete);
// We do not test error, it can fails if there is child in batch details // We do not test error, it can fails if there is child in batch details
} }
} else { } else {
@ -2318,6 +2318,23 @@ class Expedition extends CommonObject
} }
} }
/**
* Set draft status
*
* @param User $user Object user that modify
* @param int $notrigger 1=Does not execute triggers, 0=Execute triggers
* @return int <0 if KO, >0 if OK
*/
public function setDraft($user, $notrigger = 0)
{
// Protection
if ($this->statut <= self::STATUS_DRAFT) {
return 0;
}
return $this->setStatusCommon($user, self::STATUS_DRAFT, $notrigger, 'SHIPMENT_UNVALIDATE');
}
/** /**
* Classify the shipping as validated/opened * Classify the shipping as validated/opened
* *
@ -2338,7 +2355,7 @@ class Expedition extends CommonObject
$oldbilled = $this->billed; $oldbilled = $this->billed;
$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=1'; $sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut = 1';
$sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0'; $sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0';
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
@ -2388,7 +2405,7 @@ class Expedition extends CommonObject
// line without batch detail // line without batch detail
// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
$result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $numref)); $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $this->ref));
if ($result < 0) { if ($result < 0) {
$this->error = $mouvS->error; $this->error = $mouvS->error;
$this->errors = $mouvS->errors; $this->errors = $mouvS->errors;
@ -2399,7 +2416,7 @@ class Expedition extends CommonObject
// line with batch detail // line with batch detail
// We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record // We decrement stock of product (and sub-products) -> update table llx_product_stock (key of this table is fk_product+fk_entrepot) and add a movement record
$result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $numref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock); $result = $mouvS->livraison($user, $obj->fk_product, $obj->fk_entrepot, -$qty, $obj->subprice, $langs->trans("ShipmentUnClassifyCloseddInDolibarr", $this->ref), '', $this->db->jdate($obj->eatby), $this->db->jdate($obj->sellby), $obj->batch, $obj->fk_origin_stock);
if ($result < 0) { if ($result < 0) {
$this->error = $mouvS->error; $this->error = $mouvS->error;
$this->errors = $mouvS->errors; $this->errors = $mouvS->errors;

View File

@ -773,7 +773,7 @@ if ($id > 0 || !empty($ref)) {
$toBeShippedTotal += $toBeShipped[$objp->fk_product]; $toBeShippedTotal += $toBeShipped[$objp->fk_product];
print $toBeShipped[$objp->fk_product]; print $toBeShipped[$objp->fk_product];
} else { } else {
print '0 ('.$langs->trans("Service").')'; print '0 <span class="opacitymedium">('.$langs->trans("Service").')</span>';
} }
print ($objp->unit_order ? ' '.$objp->unit_order : '').'</td>'; print ($objp->unit_order ? ' '.$objp->unit_order : '').'</td>';

View File

@ -2031,6 +2031,7 @@ if ($action == 'create') {
print '<input type="hidden" name="id" value="'.$object->id.'">'; print '<input type="hidden" name="id" value="'.$object->id.'">';
print '<input type="hidden" name="fk_expensereport" value="'.$object->id.'" />'; print '<input type="hidden" name="fk_expensereport" value="'.$object->id.'" />';
print '<input type="hidden" name="backtopage" value="'.$backtopage.'">'; print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
print '<input type="hidden" name="page_y" value="">';
print '<div class="div-table-responsive-no-min">'; print '<div class="div-table-responsive-no-min">';
print '<table id="tablelines" class="noborder centpercent">'; print '<table id="tablelines" class="noborder centpercent">';
@ -2049,7 +2050,7 @@ if ($action == 'create') {
if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) { if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) {
print '<td class="center linecolcarcategory">'.$langs->trans('CarCategory').'</td>'; print '<td class="center linecolcarcategory">'.$langs->trans('CarCategory').'</td>';
} }
print '<td class="center linecoldescription">'.$langs->trans('Description').'</td>'; print '<td class="linecoldescription">'.$langs->trans('Description').'</td>';
print '<td class="right linecolvat">'.$langs->trans('VAT').'</td>'; print '<td class="right linecolvat">'.$langs->trans('VAT').'</td>';
print '<td class="right linecolpriceuht">'.$langs->trans('PriceUHT').'</td>'; print '<td class="right linecolpriceuht">'.$langs->trans('PriceUHT').'</td>';
print '<td class="right linecolpriceuttc">'.$langs->trans('PriceUTTC').'</td>'; print '<td class="right linecolpriceuttc">'.$langs->trans('PriceUTTC').'</td>';
@ -2088,7 +2089,7 @@ if ($action == 'create') {
// Project // Project
if (isModEnabled('project')) { if (isModEnabled('project')) {
print '<td class="center dateproject">'; print '<td class="lineproject">';
if ($line->fk_project > 0) { if ($line->fk_project > 0) {
$projecttmp->id = $line->fk_project; $projecttmp->id = $line->fk_project;
$projecttmp->ref = $line->projet_ref; $projecttmp->ref = $line->projet_ref;
@ -2483,7 +2484,7 @@ if ($action == 'create') {
if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) { if (!empty($conf->global->MAIN_USE_EXPENSE_IK)) {
print '<td>'.$langs->trans('CarCategory').'</td>'; print '<td>'.$langs->trans('CarCategory').'</td>';
} }
print '<td class="right expensereportcreatedescription">'.$langs->trans('Description').'</td>'; print '<td class="expensereportcreatedescription">'.$langs->trans('Description').'</td>';
print '<td class="right expensereportcreatevat">'.$langs->trans('VAT').'</td>'; print '<td class="right expensereportcreatevat">'.$langs->trans('VAT').'</td>';
print '<td class="right expensereportcreatepriceuth">'.$langs->trans('PriceUHT').'</td>'; print '<td class="right expensereportcreatepriceuth">'.$langs->trans('PriceUHT').'</td>';
print '<td class="right expensereportcreatepricettc">'.$langs->trans('PriceUTTC').'</td>'; print '<td class="right expensereportcreatepricettc">'.$langs->trans('PriceUTTC').'</td>';
@ -2562,7 +2563,7 @@ if ($action == 'create') {
} }
print '<td class="center inputbuttons">'; print '<td class="center inputbuttons">';
print $form->buttonsSaveCancel("Add", '', '', 1); print $form->buttonsSaveCancel("Add", '', '', 1, 'reposition');
print '</td>'; print '</td>';
print '</tr>'; print '</tr>';

View File

@ -69,13 +69,15 @@ function addDispatchLine(index, type, mode)
{ {
mode = mode || 'qtymissing' mode = mode || 'qtymissing'
console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode);
var $row0 = $("tr[name='"+type+'_0_'+index+"']"); var $row0 = $("tr[name='"+type+'_0_'+index+"']");
var $dpopt = $row0.find('.hasDatepicker').first().datepicker('option', 'all'); // get current datepicker options to apply the same to the cloned datepickers var $dpopt = $row0.find('.hasDatepicker').first().datepicker('option', 'all'); // get current datepicker options to apply the same to the cloned datepickers
var $row = $row0.clone(true); // clone first batch line to jQuery object var $row = $row0.clone(true); // clone first batch line to jQuery object
var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; // position of line for batch var nbrTrs = $("tr[name^='"+type+"_'][name$='_"+index+"']").length; // position of line for batch
var qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // Qty ordered is same for all rows var qtyOrdered = parseFloat($("#qty_ordered_0_"+index).val()); // Qty ordered is same for all rows
var qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val()); var qty = parseFloat($("#qty_"+(nbrTrs - 1)+"_"+index).val());
console.log("fourn/js/lib_dispatch.js.php Split line type="+type+" index="+index+" mode="+mode+" qtyOrdered="+qtyOrdered+" qty="+qty);
var qtyDispatched; var qtyDispatched;
if (mode === 'lessone') if (mode === 'lessone')
@ -93,9 +95,17 @@ function addDispatchLine(index, type, mode)
} }
console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered); console.log("qtyDispatched="+qtyDispatched+" qtyOrdered="+qtyOrdered);
if (qtyDispatched >= qtyOrdered || qtyOrdered <= 1) { if (qty <= 1) {
window.alert("Remain quantity to dispatch is too low to be split"); window.alert("Remain quantity to dispatch is too low to be split");
} else if (qtyDispatched < qtyOrdered) { } else {
oldlineqty = qtyDispatched;
newlineqty = qtyOrdered - qtyDispatched;
if (newlineqty <= 0) {
newlineqty = qty - 1;
oldlineqty = 1;
$("#qty_"+(nbrTrs - 1)+"_"+index).val(oldlineqty);
}
//replace tr suffix nbr //replace tr suffix nbr
$row.html($row.html().replace(/_0_/g,"_"+nbrTrs+"_")); $row.html($row.html().replace(/_0_/g,"_"+nbrTrs+"_"));
@ -127,7 +137,7 @@ function addDispatchLine(index, type, mode)
/* Suffix of lines are: _ trs.length _ index */ /* Suffix of lines are: _ trs.length _ index */
$("#qty_"+nbrTrs+"_"+index).focus(); $("#qty_"+nbrTrs+"_"+index).focus();
$("#qty_dispatched_0_"+index).val(qtyDispatched); $("#qty_dispatched_0_"+index).val(oldlineqty);
//hide all buttons then show only the last one //hide all buttons then show only the last one
$("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide(); $("tr[name^='"+type+"_'][name$='_"+index+"'] .splitbutton").hide();
@ -138,7 +148,7 @@ function addDispatchLine(index, type, mode)
qty = 1; // keep 1 in old line qty = 1; // keep 1 in old line
$("#qty_"+(nbrTrs-1)+"_"+index).val(qty); $("#qty_"+(nbrTrs-1)+"_"+index).val(qty);
} }
$("#qty_"+nbrTrs+"_"+index).val(qtyOrdered - qtyDispatched); $("#qty_"+nbrTrs+"_"+index).val(newlineqty);
// Store arbitrary data for dispatch qty input field change event // Store arbitrary data for dispatch qty input field change event
$("#qty_"+(nbrTrs-1)+"_"+index).data('qty', qty); $("#qty_"+(nbrTrs-1)+"_"+index).data('qty', qty);
$("#qty_"+(nbrTrs-1)+"_"+index).data('type', type); $("#qty_"+(nbrTrs-1)+"_"+index).data('type', type);

View File

@ -17,6 +17,13 @@ return ComposerAutoloaderInit4da13270269c89a28e472e1f7324e6d1::getLoader();
// Add class/method of PHP8 for compatibility with older versions of PHP // Add class/method of PHP8 for compatibility with older versions of PHP
require_once(__DIR__.'/symfony/polyfill-php80/bootstrap.php'); require_once(__DIR__.'/symfony/polyfill-php80/bootstrap.php');
//'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
//'a4a119a56e50fbb293281d9a48007e0e' => $vendorDir . '/symfony/polyfill-php80/bootstrap.php',
//'60799491728b879e74601d83e38b2cad' => $vendorDir . '/illuminate/collections/helpers.php',
//'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
//'6e3fae29631ef280660b3cdad06f25a8' => $vendorDir . '/symfony/deprecation-contracts/function.php',
require_once(__DIR__.'/illuminate/collections/helpers.php');
spl_autoload_register(function ($class_name) { spl_autoload_register(function ($class_name) {
// Enable this to detect what we need for require_once // Enable this to detect what we need for require_once

View File

@ -573,7 +573,7 @@ Module50Desc=Management of Products
Module51Name=Mass mailings Module51Name=Mass mailings
Module51Desc=Mass paper mailing management Module51Desc=Mass paper mailing management
Module52Name=Stocks Module52Name=Stocks
Module52Desc=Stock management Module52Desc=Stock management (stock movement tracking and inventory)
Module53Name=Services Module53Name=Services
Module53Desc=Management of Services Module53Desc=Management of Services
Module54Name=Contracts/Subscriptions Module54Name=Contracts/Subscriptions

View File

@ -62,7 +62,7 @@ MemberSubscriptionAddedInDolibarr=Subscription %s for member %s added
MemberSubscriptionModifiedInDolibarr=Subscription %s for member %s modified MemberSubscriptionModifiedInDolibarr=Subscription %s for member %s modified
MemberSubscriptionDeletedInDolibarr=Subscription %s for member %s deleted MemberSubscriptionDeletedInDolibarr=Subscription %s for member %s deleted
ShipmentValidatedInDolibarr=Shipment %s validated ShipmentValidatedInDolibarr=Shipment %s validated
ShipmentClassifyClosedInDolibarr=Shipment %s classified billed ShipmentClassifyClosedInDolibarr=Shipment %s classified closed
ShipmentUnClassifyCloseddInDolibarr=Shipment %s classified re-open ShipmentUnClassifyCloseddInDolibarr=Shipment %s classified re-open
ShipmentBackToDraftInDolibarr=Shipment %s go back to draft status ShipmentBackToDraftInDolibarr=Shipment %s go back to draft status
ShipmentDeletedInDolibarr=Shipment %s deleted ShipmentDeletedInDolibarr=Shipment %s deleted

View File

@ -65,8 +65,8 @@ ActionAC_SUP_ORD=Send purchase order by mail
ActionAC_SUP_INV=Send vendor invoice by mail ActionAC_SUP_INV=Send vendor invoice by mail
ActionAC_OTH=Other ActionAC_OTH=Other
ActionAC_OTH_AUTO=Other auto ActionAC_OTH_AUTO=Other auto
ActionAC_MANUAL=Manually inserted events ActionAC_MANUAL=Events inserted manually (by a user)
ActionAC_AUTO=Automatically inserted events ActionAC_AUTO=Events inserted automatically
ActionAC_OTH_AUTOShort=Other ActionAC_OTH_AUTOShort=Other
ActionAC_EVENTORGANIZATION=Event organization events ActionAC_EVENTORGANIZATION=Event organization events
Stats=Sales statistics Stats=Sales statistics

View File

@ -19,7 +19,7 @@ printSellby=Sell-by: %s
printQty=Qty: %d printQty=Qty: %d
printPlannedWarehouse=Warehouse: %s printPlannedWarehouse=Warehouse: %s
AddDispatchBatchLine=Add a line for Shelf Life dispatching AddDispatchBatchLine=Add a line for Shelf Life dispatching
WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic stock decrease is forced to 'Decrease real stocks on shipping validation' and automatic increase mode is forced to 'Increase real stocks on manual dispatching into warehouses' and can't be edited. Other options can be defined as you want. WhenProductBatchModuleOnOptionAreForced=When module Lot/Serial is on, automatic stock decrease is forced to '%s' and automatic increase mode is forced to '%s'. Some choices may be not available. Other options can be defined as you want.
ProductDoesNotUseBatchSerial=This product does not use lot/serial number ProductDoesNotUseBatchSerial=This product does not use lot/serial number
ProductLotSetup=Setup of module lot/serial ProductLotSetup=Setup of module lot/serial
ShowCurrentStockOfLot=Show current stock for couple product/lot ShowCurrentStockOfLot=Show current stock for couple product/lot

View File

@ -318,3 +318,5 @@ StockTransferRightRead=Read stocks transfers
StockTransferRightCreateUpdate=Create/Update stocks transfers StockTransferRightCreateUpdate=Create/Update stocks transfers
StockTransferRightDelete=Delete stocks transfers StockTransferRightDelete=Delete stocks transfers
BatchNotFound=Lot / serial not found for this product BatchNotFound=Lot / serial not found for this product
StockMovementWillBeRecorded=Stock movement will be recorded
StockMovementNotYetRecorded=Stock movement will not be affected by this step

View File

@ -62,7 +62,7 @@ MemberSubscriptionAddedInDolibarr=Cotisation %s pour l'adhérent %s ajoutée
MemberSubscriptionModifiedInDolibarr=Cotisation %s pour l'adhérent %s modifié MemberSubscriptionModifiedInDolibarr=Cotisation %s pour l'adhérent %s modifié
MemberSubscriptionDeletedInDolibarr=Cotisation %s pour l'adhérent %s supprimé MemberSubscriptionDeletedInDolibarr=Cotisation %s pour l'adhérent %s supprimé
ShipmentValidatedInDolibarr=Expédition %s validée ShipmentValidatedInDolibarr=Expédition %s validée
ShipmentClassifyClosedInDolibarr=Expédition %s classée payée ShipmentClassifyClosedInDolibarr=Expédition %s classée close
ShipmentUnClassifyCloseddInDolibarr=Expédition %s réouverte ShipmentUnClassifyCloseddInDolibarr=Expédition %s réouverte
ShipmentBackToDraftInDolibarr=Expédition %s remise au statut brouillon ShipmentBackToDraftInDolibarr=Expédition %s remise au statut brouillon
ShipmentDeletedInDolibarr=Expédition %s supprimée ShipmentDeletedInDolibarr=Expédition %s supprimée

View File

@ -2312,7 +2312,9 @@ function top_menu_user($hideloginname = 0, $urllogout = '')
} }
$dropdownBody .= '<br><b>'.$langs->trans("VATIntraShort").'</b>: <span>'.dol_print_profids(getDolGlobalString("MAIN_INFO_TVAINTRA"), 'VAT').'</span>'; $dropdownBody .= '<br><b>'.$langs->trans("VATIntraShort").'</b>: <span>'.dol_print_profids(getDolGlobalString("MAIN_INFO_TVAINTRA"), 'VAT').'</span>';
$dropdownBody .= '<br><b>'.$langs->trans("Country").'</b>: <span>'.($mysoc->country_code ? $langs->trans("Country".$mysoc->country_code) : '').'</span>'; $dropdownBody .= '<br><b>'.$langs->trans("Country").'</b>: <span>'.($mysoc->country_code ? $langs->trans("Country".$mysoc->country_code) : '').'</span>';
if (isModEnabled('multicurrency')) {
$dropdownBody .= '<br><b>'.$langs->trans("Currency").'</b>: <span>'.$conf->currency.'</span>';
}
$dropdownBody .= '</div>'; $dropdownBody .= '</div>';
$dropdownBody .= '<br>'; $dropdownBody .= '<br>';

View File

@ -871,6 +871,7 @@ class Product extends CommonObject
$langs->load("products"); $langs->load("products");
$error++; $error++;
$this->error = "ErrorProductAlreadyExists"; $this->error = "ErrorProductAlreadyExists";
dol_syslog(get_class($this)."::Create fails, ref ".$this->ref." already exists");
} }
} else { } else {
$error++; $error++;

View File

@ -6,6 +6,7 @@
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr> * Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es> * Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2019 Juanjo Menent <jmenent@2byte.es> * Copyright (C) 2019 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2021 Noé Cendrier <noe.cendrier@altairis.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -37,7 +38,7 @@ require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php'; require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
// Load translation files required by the page // Load translation files required by the page
$langs->loadLangs(array('products', 'stocks', 'productbatch')); $langs->loadLangs(array('products', 'stocks', 'productbatch', 'categories'));
$action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ... $action = GETPOST('action', 'aZ09') ?GETPOST('action', 'aZ09') : 'view'; // The action 'add', 'create', 'edit', 'update', 'view', ...
$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
@ -48,7 +49,7 @@ $mode = GETPOST('mode', 'aZ');
$sref = GETPOST("sref", 'alpha'); $sref = GETPOST("sref", 'alpha');
$snom = GETPOST("snom", 'alpha'); $snom = GETPOST("snom", 'alpha');
$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
$type = GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT; $type = GETPOSTISSET('type') ? GETPOST('type', 'int') : Product::TYPE_PRODUCT;
$search_barcode = GETPOST("search_barcode", 'alpha'); $search_barcode = GETPOST("search_barcode", 'alpha');
$search_warehouse = GETPOST('search_warehouse', 'alpha'); $search_warehouse = GETPOST('search_warehouse', 'alpha');
@ -82,6 +83,7 @@ if (GETPOSTISSET('catid')) {
} else { } else {
$search_categ = GETPOST('search_categ', 'int'); $search_categ = GETPOST('search_categ', 'int');
} }
$search_warehouse_categ = GETPOST('search_warehouse_categ', 'int');
// Fetch optionals attributes and labels // Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element); $extrafields->fetch_name_optionals_label($object->table_element);
@ -173,11 +175,12 @@ if (empty($reshook)) {
$search['eatby_dtend'] = ''; $search['eatby_dtend'] = '';
$sref = ""; $sref = "";
$snom = ""; $snom = "";
$sall = ""; $search_all = "";
$tosell = ""; $tosell = "";
$tobuy = ""; $tobuy = "";
$search_sale = ""; $search_sale = "";
$search_categ = ""; $search_categ = "";
$search_warehouse_categ = "";
$search_toolowstock = ''; $search_toolowstock = '';
$search_subjecttolotserial = ''; $search_subjecttolotserial = '';
$search_batch = ''; $search_batch = '';
@ -255,8 +258,24 @@ if (!empty($search_categ) && $search_categ != '-1') {
} }
$sql .= ")"; $sql .= ")";
} }
if ($sall) { if (!empty($search_warehouse_categ) && $search_warehouse_categ != '-1') {
$sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $sall); $sql .= " AND ";
if ($search_warehouse_categ == -2) {
$sql .= " NOT EXISTS ";
} else {
$sql .= " EXISTS ";
}
$sql .= "(";
$sql .= " SELECT cp.fk_categorie, cp.fk_warehouse";
$sql .= " FROM " . MAIN_DB_PREFIX . "categorie_warehouse as cp";
$sql .= " WHERE cp.fk_warehouse = e.rowid"; // Join for the needed table to filter by categ
if ($search_warehouse_categ > 0) {
$sql .= " AND cp.fk_categorie = " . ((int) $search_warehouse_categ);
}
$sql .= ")";
}
if ($search_all) {
$sql .= natural_search(array('p.ref', 'p.label', 'p.description', 'p.note'), $search_all);
} }
// if the type is not 1, we show all products (type = 0,2,3) // if the type is not 1, we show all products (type = 0,2,3)
if (dol_strlen($type)) { if (dol_strlen($type)) {
@ -402,7 +421,7 @@ $num = $db->num_rows($resql);
$i = 0; $i = 0;
if ($num == 1 && GETPOST('autojumpifoneonly') && ($sall or $snom or $sref)) { if ($num == 1 && GETPOST('autojumpifoneonly') && ($search_all or $snom or $sref)) {
$objp = $db->fetch_object($resql); $objp = $db->fetch_object($resql);
header("Location: card.php?id=$objp->rowid"); header("Location: card.php?id=$objp->rowid");
exit; exit;
@ -443,8 +462,8 @@ foreach ($search as $key => $val) {
if ($optioncss != '') { if ($optioncss != '') {
$param .= '&optioncss='.urlencode($optioncss); $param .= '&optioncss='.urlencode($optioncss);
} }
if ($sall) { if ($search_all) {
$param .= "&sall=".urlencode($sall); $param .= "&search_all=".urlencode($search_all);
} }
if ($tosell) { if ($tosell) {
$param .= "&tosell=".urlencode($tosell); $param .= "&tosell=".urlencode($tosell);
@ -485,6 +504,9 @@ if ($search_sale) {
if (!empty($search_categ) && $search_categ != '-1') { if (!empty($search_categ) && $search_categ != '-1') {
$param .= "&search_categ=".urlencode($search_categ); $param .= "&search_categ=".urlencode($search_categ);
} }
if (!empty($search_warehouse_categ) && $search_warehouse_categ != '-1') {
$param .= "&search_warehouse_categ=".urlencode($search_warehouse_categ);
}
if ($search_stock_physique) { if ($search_stock_physique) {
$param .= '&search_stock_physique=' . urlencode($search_stock_physique); $param .= '&search_stock_physique=' . urlencode($search_stock_physique);
} }
@ -508,7 +530,7 @@ print '<input type="hidden" name="mode" value="'.$mode.'">';
print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit, 0, 0, 1); print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit, 0, 0, 1);
/*
if ($search_categ > 0) { if ($search_categ > 0) {
print "<div id='ways'>"; print "<div id='ways'>";
$c = new Categorie($db); $c = new Categorie($db);
@ -517,17 +539,27 @@ if ($search_categ > 0) {
print " &gt; ".$ways[0]."<br>\n"; print " &gt; ".$ways[0]."<br>\n";
print "</div><br>"; print "</div><br>";
} }
*/
// Filter on categories // Filter on categories
$moreforfilter = ''; $moreforfilter = '';
if (isModEnabled('categorie')) { if (isModEnabled('categorie')) {
$moreforfilter .= '<div class="divsearchfield">'; $moreforfilter .= '<div class="divsearchfield">';
$moreforfilter .= img_picto($langs->trans('Categories'), 'category', 'class="pictofixedwidth"'); $moreforfilter .= img_picto($langs->trans('ProductsCategoriesShort'), 'category', 'class="pictofixedwidth"');
$moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1); $moreforfilter .= $htmlother->select_categories(Categorie::TYPE_PRODUCT, $search_categ, 'search_categ', 1, $langs->trans("ProductsCategoryShort"), 'maxwidth400');
$moreforfilter .= '</div>'; $moreforfilter .= '</div>';
} }
// Filter on warehouse categories
if (isModEnabled('categorie')) {
$moreforfilter .= '<div class="divsearchfield">';
$moreforfilter .= img_picto($langs->trans('StockCategoriesShort'), 'category', 'class="pictofixedwidth"');
$moreforfilter .= $htmlother->select_categories(Categorie::TYPE_WAREHOUSE, $search_warehouse_categ, 'search_warehouse_categ', 1, $langs->trans("StockCategoriesShort"), 'maxwidth400');
$moreforfilter .= '</div>';
}
$moreforfilter.='<label for="search_subjecttolotserial">'.$langs->trans("SubjectToLotSerialOnly").' </label><input type="checkbox" id="search_subjecttolotserial" name="search_subjecttolotserial" value="1"'.($search_subjecttolotserial?' checked':'').'>'; $moreforfilter.='<label for="search_subjecttolotserial">'.$langs->trans("SubjectToLotSerialOnly").' </label><input type="checkbox" id="search_subjecttolotserial" name="search_subjecttolotserial" value="1"'.($search_subjecttolotserial?' checked':'').'>';
if (!empty($moreforfilter)) { if (!empty($moreforfilter)) {
print '<div class="liste_titre liste_titre_bydiv centpercent">'; print '<div class="liste_titre liste_titre_bydiv centpercent">';
print $moreforfilter; print $moreforfilter;

View File

@ -301,7 +301,9 @@ class MouvementStock extends CommonObject
// If not found, we add record // If not found, we add record
$sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM ".$this->db->prefix()."product_lot as pb"; $sql = "SELECT pb.rowid, pb.batch, pb.eatby, pb.sellby FROM ".$this->db->prefix()."product_lot as pb";
$sql .= " WHERE pb.fk_product = ".((int) $fk_product)." AND pb.batch = '".$this->db->escape($batch)."'"; $sql .= " WHERE pb.fk_product = ".((int) $fk_product)." AND pb.batch = '".$this->db->escape($batch)."'";
dol_syslog(get_class($this)."::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG); dol_syslog(get_class($this)."::_create scan serial for this product to check if eatby and sellby match", LOG_DEBUG);
$resql = $this->db->query($sql); $resql = $this->db->query($sql);
if ($resql) { if ($resql) {
$num = $this->db->num_rows($resql); $num = $this->db->num_rows($resql);
@ -560,6 +562,10 @@ class MouvementStock extends CommonObject
if (!$error && isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) { if (!$error && isModEnabled('productbatch') && $product->hasbatch() && !$skip_batch) {
if ($id_product_batch > 0) { if ($id_product_batch > 0) {
$result = $this->createBatch($id_product_batch, $qty); $result = $this->createBatch($id_product_batch, $qty);
if ($result == -2 && $fk_product_stock > 0) { // The entry for this product batch does not exists anymore, bu we already have a llx_product_stock, so we recreate the batch entry in product_batch
$param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch);
$result = $this->createBatch($param_batch, $qty);
}
} else { } else {
$param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch); $param_batch = array('fk_product_stock' =>$fk_product_stock, 'batchnumber'=>$batch);
$result = $this->createBatch($param_batch, $qty); $result = $this->createBatch($param_batch, $qty);
@ -863,10 +869,10 @@ class MouvementStock extends CommonObject
* Create or update batch record (update table llx_product_batch). No check is done here, done by parent. * Create or update batch record (update table llx_product_batch). No check is done here, done by parent.
* *
* @param array|int $dluo Could be either * @param array|int $dluo Could be either
* - int if row id of product_batch table * - int if row id of product_batch table (for update)
* - or complete array('fk_product_stock'=>, 'batchnumber'=>) * - or complete array('fk_product_stock'=>, 'batchnumber'=>)
* @param int $qty Quantity of product with batch number. May be a negative amount. * @param int $qty Quantity of product with batch number. May be a negative amount.
* @return int <0 if KO, else return productbatch id * @return int <0 if KO, -2 if we try to update a product_batchid that does not exist, else return productbatch id
*/ */
private function createBatch($dluo, $qty) private function createBatch($dluo, $qty)
{ {

View File

@ -50,20 +50,23 @@ if (isModEnabled('productbatch')) {
$langs->load("productbatch"); $langs->load("productbatch");
} }
$id = GETPOST('id', 'int');
$ref = GETPOST('ref', 'alpha');
$msid = GETPOST('msid', 'int');
$product_id = GETPOST("product_id", 'int');
$action = GETPOST('action', 'aZ09'); $action = GETPOST('action', 'aZ09');
$massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists) $massaction = GETPOST('massaction', 'alpha'); // The bulk action (combo box choice into lists)
$confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation $confirm = GETPOST('confirm', 'alpha'); // Result of a confirmation
$cancel = GETPOST('cancel', 'alpha'); $cancel = GETPOST('cancel', 'alpha');
$contextpage = GETPOST('contextpage', 'aZ') ?GETPOST('contextpage', 'aZ') : 'movementlist'; $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : str_replace('_', '', basename(dirname(__FILE__)).basename(__FILE__, '.php')); // To manage different context of search
$toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list $toselect = GETPOST('toselect', 'array'); // Array of ids of elements selected into a list
$backtopage = GETPOST("backtopage", "alpha"); $backtopage = GETPOST("backtopage", "alpha");
$optioncss = GETPOST('optioncss', 'aZ'); // Option for the css output (always '' except when 'print')
$mode = GETPOST('mode', 'aZ'); // The output mode ('list', 'kanban', 'hierarchy', 'calendar', ...)
$id = GETPOST('id', 'int');
$ref = GETPOST('ref', 'alpha');
$msid = GETPOST('msid', 'int');
$idproduct = GETPOST('idproduct', 'int'); $idproduct = GETPOST('idproduct', 'int');
$sall = trim((GETPOST('search_all', 'alphanohtml') != '') ?GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml')); $product_id = GETPOST("product_id", 'int');
$search_all = trim((GETPOST('search_all', 'alphanohtml') != '') ? GETPOST('search_all', 'alphanohtml') : GETPOST('sall', 'alphanohtml'));
$search_date_startday = GETPOST('search_date_startday', 'int'); $search_date_startday = GETPOST('search_date_startday', 'int');
$search_date_startmonth = GETPOST('search_date_startmonth', 'int'); $search_date_startmonth = GETPOST('search_date_startmonth', 'int');
$search_date_startyear = GETPOST('search_date_startyear', 'int'); $search_date_startyear = GETPOST('search_date_startyear', 'int');
@ -83,7 +86,7 @@ $search_batch = trim(GETPOST("search_batch"));
$search_qty = trim(GETPOST("search_qty")); $search_qty = trim(GETPOST("search_qty"));
$search_type_mouvement = GETPOST('search_type_mouvement', 'int'); $search_type_mouvement = GETPOST('search_type_mouvement', 'int');
$search_fk_projet=GETPOST("search_fk_projet", 'int'); $search_fk_projet=GETPOST("search_fk_projet", 'int');
$optioncss = GETPOST('optioncss', 'alpha');
$type = GETPOST("type", "int"); $type = GETPOST("type", "int");
// Load variable for pagination // Load variable for pagination
@ -108,15 +111,15 @@ if (!$sortorder) {
$pdluoid = GETPOST('pdluoid', 'int'); $pdluoid = GETPOST('pdluoid', 'int');
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context // Initialize technical objects
$object = new MouvementStock($db); $object = new MouvementStock($db);
$extrafields = new ExtraFields($db); $extrafields = new ExtraFields($db);
$diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id; $diroutputmassaction = $conf->stock->dir_output.'/temp/massgeneration/'.$user->id;
$hookmanager->initHooks(array('movementlist')); $hookmanager->initHooks(array($contextpage)); // Note that conf->hooks_modules contains array of activated contexes
$formfile = new FormFile($db); $formfile = new FormFile($db);
// fetch optionals attributes and labels // Fetch optionals attributes and labels
$extrafields->fetch_name_optionals_label($object->table_element); $extrafields->fetch_name_optionals_label($object->table_element);
$search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_'); $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
@ -224,7 +227,7 @@ if (empty($reshook)) {
$search_batch = ""; $search_batch = "";
$search_qty = ''; $search_qty = '';
$search_fk_projet=0; $search_fk_projet=0;
$sall = ""; $search_all = "";
$toselect = array(); $toselect = array();
$search_array_options = array(); $search_array_options = array();
} }
@ -588,18 +591,21 @@ if ($action == "transfert_stock" && !$cancel) {
* View * View
*/ */
$productlot = new ProductLot($db);
$productstatic = new Product($db);
$warehousestatic = new Entrepot($db);
$movement = new MouvementStock($db);
$userstatic = new User($db);
$form = new Form($db); $form = new Form($db);
$formproduct = new FormProduct($db); $formproduct = new FormProduct($db);
if (!empty($conf->project->enabled)) { if (!empty($conf->project->enabled)) {
$formproject = new FormProjets($db); $formproject = new FormProjets($db);
} }
$productlot = new ProductLot($db);
$productstatic = new Product($db);
$warehousestatic = new Entrepot($db);
$movement = new MouvementStock($db);
$userstatic = new User($db);
$now = dol_now();
// Build and execute select // Build and execute select
// --------------------------------------------------------------------
$sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,"; $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tosell, p.tobuy, p.tobatch, p.fk_product_type as type, p.entity,";
$sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,"; $sql .= " e.ref as warehouse_ref, e.rowid as entrepot_id, e.lieu, e.fk_parent, e.statut,";
$sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,"; $sql .= " m.rowid as mid, m.value as qty, m.datem, m.fk_user_author, m.label, m.inventorycode, m.fk_origin, m.origintype,";
@ -616,7 +622,7 @@ if (!empty($extrafields->attributes[$object->table_element]['label'])) {
} }
// Add fields from hooks // Add fields from hooks
$parameters = array(); $parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListSelect', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint; $sql .= $hookmanager->resPrint;
$sql = preg_replace('/,\s*$/', '', $sql); $sql = preg_replace('/,\s*$/', '', $sql);
@ -697,7 +703,7 @@ if ($search_type_mouvement != '' && $search_type_mouvement != '-1') {
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php';
// Add where from hooks // Add where from hooks
$parameters = array(); $parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListWhere', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
$sql .= $hookmanager->resPrint; $sql .= $hookmanager->resPrint;
// Count total nb of records // Count total nb of records
@ -714,7 +720,7 @@ if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) {
dol_print_error($db); dol_print_error($db);
} }
if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller then paging size (filtering), goto and load page 0 if (($page * $limit) > $nbtotalofrecords) { // if total resultset is smaller than the paging size (filtering), goto and load page 0
$page = 0; $page = 0;
$offset = 0; $offset = 0;
} }
@ -733,6 +739,9 @@ if (!$resql) {
exit; exit;
} }
$num = $db->num_rows($resql);
$product = new Product($db); $product = new Product($db);
$object = new Entrepot($db); $object = new Entrepot($db);
@ -746,8 +755,6 @@ if ($id > 0 || $ref) {
} }
} }
$num = $db->num_rows($resql);
// Output page // Output page
// -------------------------------------------------------------------- // --------------------------------------------------------------------
@ -767,9 +774,11 @@ if ($msid) {
} }
} }
llxHeader('', $title, $help_url);
$arrayofselected = is_array($toselect) ? $toselect : array(); // Output page
// --------------------------------------------------------------------
llxHeader('', $title, $help_url);
/* /*
* Show tab only if we ask a particular warehouse * Show tab only if we ask a particular warehouse
@ -939,7 +948,12 @@ if ((empty($action) || $action == 'list') && $id > 0) {
print '</div><br>'; print '</div><br>';
} }
$arrayofselected = is_array($toselect) ? $toselect : array();
$param = ''; $param = '';
if (!empty($mode)) {
$param .= '&mode='.urlencode($mode);
}
if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) { if (!empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) {
$param .= '&contextpage='.urlencode($contextpage); $param .= '&contextpage='.urlencode($contextpage);
} }
@ -996,6 +1010,10 @@ if ($idproduct > 0) {
} }
// Add $param from extra fields // Add $param from extra fields
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_param.tpl.php';
// Add $param from hooks
$parameters = array();
$reshook = $hookmanager->executeHooks('printFieldListSearchParam', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
$param .= $hookmanager->resPrint;
// List of mass actions available // List of mass actions available
$arrayofmassactions = array(); $arrayofmassactions = array();
@ -1023,10 +1041,15 @@ print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
print '<input type="hidden" name="type" value="'.$type.'">'; print '<input type="hidden" name="type" value="'.$type.'">';
print '<input type="hidden" name="page" value="'.$page.'">'; print '<input type="hidden" name="page" value="'.$page.'">';
print '<input type="hidden" name="contextpage" value="'.$contextpage.'">'; print '<input type="hidden" name="contextpage" value="'.$contextpage.'">';
print '<input type="hidden" name="page_y" value="">';
print '<input type="hidden" name="mode" value="'.$mode.'">';
if ($id > 0) { if ($id > 0) {
print '<input type="hidden" name="id" value="'.$id.'">'; print '<input type="hidden" name="id" value="'.$id.'">';
} }
$newcardbutton = '';
if ($id > 0) { if ($id > 0) {
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1); print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, $massactionbutton, $num, $nbtotalofrecords, 'movement', 0, '', '', $limit, 0, 0, 1);
} else { } else {
@ -1040,17 +1063,20 @@ $objecttmp = new MouvementStock($db);
$trackid = 'mov'.$object->id; $trackid = 'mov'.$object->id;
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php'; include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
if ($sall) { if ($search_all) {
$setupstring = '';
foreach ($fieldstosearchall as $key => $val) { foreach ($fieldstosearchall as $key => $val) {
$fieldstosearchall[$key] = $langs->trans($val); $fieldstosearchall[$key] = $langs->trans($val);
$setupstring .= $key."=".$val.";";
} }
print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $sall).join(', ', $fieldstosearchall).'</div>'; print '<!-- Search done like if STOCK_QUICKSEARCH_ON_FIELDS = '.$setupstring.' -->'."\n";
print '<div class="divsearchfieldfilter">'.$langs->trans("FilterOnInto", $search_all).join(', ', $fieldstosearchall).'</div>'."\n";
} }
$moreforfilter = ''; $moreforfilter = '';
$parameters = array('arrayfields'=>&$arrayfields); $parameters = array('arrayfields'=>&$arrayfields);
$reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldPreListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
if (empty($reshook)) { if (empty($reshook)) {
$moreforfilter .= $hookmanager->resPrint; $moreforfilter .= $hookmanager->resPrint;
} else { } else {
@ -1064,7 +1090,7 @@ if (!empty($moreforfilter)) {
} }
$varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage; $varpage = empty($contextpage) ? $_SERVER["PHP_SELF"] : $contextpage;
$selectedfields = $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields $selectedfields = ($mode != 'kanban' ? $form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage, getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN', '')) : ''); // This also change content of $arrayfields
$selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : ''); $selectedfields .= (count($arrayofmassactions) ? $form->showCheckAddButtons('checkforselect', 1) : '');
print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table print '<div class="div-table-responsive">'; // You can use div-table-responsive-no-min if you dont need reserved height for your table
@ -1073,6 +1099,13 @@ print '<table class="tagtable nobottomiftotal liste'.($moreforfilter ? " listwit
// Fields title search // Fields title search
// -------------------------------------------------------------------- // --------------------------------------------------------------------
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print '<td class="liste_titre center maxwidthsearch">';
$searchpicto = $form->showFilterButtons('left');
print $searchpicto;
print '</td>';
}
if (!empty($arrayfields['m.rowid']['checked'])) { if (!empty($arrayfields['m.rowid']['checked'])) {
// Ref // Ref
print '<td class="liste_titre left">'; print '<td class="liste_titre left">';
@ -1185,7 +1218,7 @@ include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_input.tpl.php';
// Fields from hook // Fields from hook
$parameters = array('arrayfields'=>$arrayfields); $parameters = array('arrayfields'=>$arrayfields);
$reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListOption', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint; print $hookmanager->resPrint;
// Date creation // Date creation
if (!empty($arrayfields['m.datec']['checked'])) { if (!empty($arrayfields['m.datec']['checked'])) {
@ -1198,16 +1231,25 @@ if (!empty($arrayfields['m.tms']['checked'])) {
print '</td>'; print '</td>';
} }
// Action column // Action column
print '<td class="liste_titre maxwidthsearch">'; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
$searchpicto = $form->showFilterButtons(); print '<td class="liste_titre center maxwidthsearch">';
print $searchpicto; $searchpicto = $form->showFilterButtons();
print '</td>'; print $searchpicto;
print '</td>';
}
print '</tr>'."\n"; print '</tr>'."\n";
$totalarray = array();
$totalarray['nbfield'] = 0;
// Fields title label // Fields title label
// -------------------------------------------------------------------- // --------------------------------------------------------------------
print '<tr class="liste_titre">'; print '<tr class="liste_titre">';
// Action column
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
if (!empty($arrayfields['m.rowid']['checked'])) { if (!empty($arrayfields['m.rowid']['checked'])) {
print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder); print_liste_field_titre($arrayfields['m.rowid']['label'], $_SERVER["PHP_SELF"], 'm.rowid', '', $param, '', $sortfield, $sortorder);
} }
@ -1262,8 +1304,8 @@ if (!empty($arrayfields['m.price']['checked'])) {
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_title.tpl.php';
// Hook fields // Hook fields
$parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder); $parameters = array('arrayfields'=>$arrayfields, 'param'=>$param, 'sortfield'=>$sortfield, 'sortorder'=>$sortorder, 'totalarray'=>&$totalarray);
$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint; print $hookmanager->resPrint;
if (!empty($arrayfields['m.datec']['checked'])) { if (!empty($arrayfields['m.datec']['checked'])) {
print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap '); print_liste_field_titre($arrayfields['p.datec']['label'], $_SERVER["PHP_SELF"], "p.datec", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
@ -1272,7 +1314,10 @@ if (!empty($arrayfields['m.tms']['checked'])) {
print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap '); print_liste_field_titre($arrayfields['p.tms']['label'], $_SERVER["PHP_SELF"], "p.tms", "", $param, '', $sortfield, $sortorder, 'center nowrap ');
} }
// Action column // Action column
print_liste_field_titre($selectedfields, $_SERVER["PHP_SELF"], "", '', '', '', $sortfield, $sortorder, 'center maxwidthsearch '); if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print getTitleFieldOfList($selectedfields, 0, $_SERVER["PHP_SELF"], '', '', '', '', $sortfield, $sortorder, 'center maxwidthsearch ')."\n";
$totalarray['nbfield']++;
}
print '</tr>'."\n"; print '</tr>'."\n";
@ -1282,9 +1327,11 @@ $arrayofuniqueproduct = array();
// Loop on record // Loop on record
// -------------------------------------------------------------------- // --------------------------------------------------------------------
$i = 0; $i = 0;
$savnbfield = $totalarray['nbfield'];
$totalarray = array(); $totalarray = array();
$totalarray['nbfield'] = 0; $totalarray['nbfield'] = 0;
while ($i < ($limit ? min($num, $limit) : $num)) { $imaxinloop = ($limit ? min($num, $limit) : $num);
while ($i < $imaxinloop) {
$obj = $db->fetch_object($resql); $obj = $db->fetch_object($resql);
if (empty($obj)) { if (empty($obj)) {
break; // Should not happen break; // Should not happen
@ -1346,139 +1393,193 @@ while ($i < ($limit ? min($num, $limit) : $num)) {
$origin = ''; $origin = '';
} }
print '<tr class="oddeven">'; if ($mode == 'kanban') {
// Id movement if ($i == 0) {
if (!empty($arrayfields['m.rowid']['checked'])) { print '<tr><td colspan="'.$savnbfield.'">';
print '<td class="nowraponall">'; print '<div class="box-flex-container kanban">';
print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
print $obj->mid;
print '</td>'; // This is primary not movement id
}
if (!empty($arrayfields['m.datem']['checked'])) {
// Date
print '<td class="nowraponall center">'.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').'</td>';
}
if (!empty($arrayfields['p.ref']['checked'])) {
// Product ref
print '<td class="nowraponall">';
print $productstatic->getNomUrl(1, 'stock', 16);
print "</td>\n";
}
if (!empty($arrayfields['p.label']['checked'])) {
// Product label
print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($productstatic->label).'">';
print $productstatic->label;
print "</td>\n";
}
if (!empty($arrayfields['m.batch']['checked'])) {
print '<td class="center nowraponall">';
if ($productlot->id > 0) {
print $productlot->getNomUrl(1);
} else {
print $productlot->batch; // the id may not be defined if movement was entered when lot was not saved or if lot was removed after movement.
} }
print '</td>'; // Output Kanban
} if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
if (!empty($arrayfields['pl.eatby']['checked'])) { $selected = 0;
print '<td class="center">'.dol_print_date($obj->eatby, 'day').'</td>'; if (in_array($object->id, $arrayofselected)) {
} $selected = 1;
if (!empty($arrayfields['pl.sellby']['checked'])) { }
print '<td class="center">'.dol_print_date($obj->sellby, 'day').'</td>';
}
// Warehouse
if (!empty($arrayfields['e.ref']['checked'])) {
print '<td class="tdoverflowmax100">';
print $warehousestatic->getNomUrl(1);
print "</td>\n";
}
// Author
if (!empty($arrayfields['m.fk_user_author']['checked'])) {
print '<td class="tdoverflowmax100">';
print $userstatic->getNomUrl(-1);
print "</td>\n";
}
if (!empty($arrayfields['m.inventorycode']['checked'])) {
// Inventory code
print '<td><a href="'.$_SERVER["PHP_SELF"].'?search_inventorycode='.urlencode('^'.$obj->inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.'</a></td>';
}
if (!empty($arrayfields['m.label']['checked'])) {
// Label of movement
print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($obj->label).'">'.$obj->label.'</td>';
}
if (!empty($arrayfields['origin']['checked'])) {
// Origin of movement
print '<td class="nowraponall">'.$origin.'</td>';
}
if (!empty($arrayfields['m.fk_projet']['checked'])) {
// fk_project
print '<td>';
if ($obj->fk_project != 0) {
print $movement->get_origin($obj->fk_project, 'project');
} }
print '</td>'; print $object->getKanbanView('');
} if ($i == ($imaxinloop - 1)) {
if (!empty($arrayfields['m.type_mouvement']['checked'])) { print '</div>';
// Type of movement print '</td></tr>';
print '<td class="center">';
print $movement->getTypeMovement();
print '</td>';
}
if (!empty($arrayfields['m.value']['checked'])) {
// Qty
print '<td class="right">';
if ($obj->qty > 0) {
print '<span class="stockmovemententry">';
print '+';
print $obj->qty;
print '</span>';
} else {
print '<span class="stockmovementexit">';
print $obj->qty;
print '</span>';
} }
print '</td>'; } else {
} // Show here line of result
if (!empty($arrayfields['m.price']['checked'])) { $j = 0;
// Price print '<tr data-rowid="'.$object->id.'" class="oddeven">';
print '<td class="right">'; // Action column
if ($obj->price != 0) { if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
print price($obj->price); print '<td class="nowrap center">';
if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
$selected = 0;
if (in_array($obj->mid, $arrayofselected)) {
$selected = 1;
}
print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
}
// Id movement
if (!empty($arrayfields['m.rowid']['checked'])) {
print '<td class="nowraponall">';
print img_picto($langs->trans("StockMovement"), 'movement', 'class="pictofixedwidth"');
print $obj->mid;
print '</td>'; // This is primary not movement id
}
if (!empty($arrayfields['m.datem']['checked'])) {
// Date
print '<td class="nowraponall center">'.dol_print_date($db->jdate($obj->datem), 'dayhour', 'tzuserrel').'</td>';
}
if (!empty($arrayfields['p.ref']['checked'])) {
// Product ref
print '<td class="nowraponall">';
print $productstatic->getNomUrl(1, 'stock', 16);
print "</td>\n";
}
if (!empty($arrayfields['p.label']['checked'])) {
// Product label
print '<td class="tdoverflowmax150" title="'.dol_escape_htmltag($productstatic->label).'">';
print $productstatic->label;
print "</td>\n";
}
if (!empty($arrayfields['m.batch']['checked'])) {
print '<td class="center nowraponall">';
if ($productlot->id > 0) {
print $productlot->getNomUrl(1);
} else {
print $productlot->batch; // the id may not be defined if movement was entered when lot was not saved or if lot was removed after movement.
}
print '</td>';
}
if (!empty($arrayfields['pl.eatby']['checked'])) {
print '<td class="center">'.dol_print_date($obj->eatby, 'day').'</td>';
}
if (!empty($arrayfields['pl.sellby']['checked'])) {
print '<td class="center">'.dol_print_date($obj->sellby, 'day').'</td>';
}
// Warehouse
if (!empty($arrayfields['e.ref']['checked'])) {
print '<td class="tdoverflowmax100">';
print $warehousestatic->getNomUrl(1);
print "</td>\n";
}
// Author
if (!empty($arrayfields['m.fk_user_author']['checked'])) {
print '<td class="tdoverflowmax100">';
print $userstatic->getNomUrl(-1);
print "</td>\n";
}
if (!empty($arrayfields['m.inventorycode']['checked'])) {
// Inventory code
print '<td><a href="'.$_SERVER["PHP_SELF"].'?search_inventorycode='.urlencode('^'.$obj->inventorycode.'$').'&search_type_mouvement='.urlencode($obj->type_mouvement).'">'.$obj->inventorycode.'</a></td>';
}
if (!empty($arrayfields['m.label']['checked'])) {
// Label of movement
print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($obj->label).'">'.$obj->label.'</td>';
}
if (!empty($arrayfields['origin']['checked'])) {
// Origin of movement
print '<td class="nowraponall">'.$origin.'</td>';
}
if (!empty($arrayfields['m.fk_projet']['checked'])) {
// fk_project
print '<td>';
if ($obj->fk_project != 0) {
print $movement->get_origin($obj->fk_project, 'project');
}
print '</td>';
}
if (!empty($arrayfields['m.type_mouvement']['checked'])) {
// Type of movement
print '<td class="center">';
print $movement->getTypeMovement();
print '</td>';
}
if (!empty($arrayfields['m.value']['checked'])) {
// Qty
print '<td class="right">';
if ($obj->qty > 0) {
print '<span class="stockmovemententry">';
print '+';
print $obj->qty;
print '</span>';
} else {
print '<span class="stockmovementexit">';
print $obj->qty;
print '</span>';
}
print '</td>';
}
if (!empty($arrayfields['m.price']['checked'])) {
// Price
print '<td class="right">';
if ($obj->price != 0) {
print price($obj->price);
}
print '</td>';
} }
print '</td>';
}
// Extra fields // Extra fields
$object = $movement; $object = $movement;
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php'; include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_print_fields.tpl.php';
// Fields from hook // Fields from hook
$parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray); $parameters = array('arrayfields'=>$arrayfields, 'object'=>$object, 'obj'=>$obj, 'i'=>$i, 'totalarray'=>&$totalarray);
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object); // Note that $action and $object may have been modified by hook $reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print $hookmanager->resPrint; print $hookmanager->resPrint;
// Action column // Action column
print '<td class="nowrap center">'; if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined print '<td class="nowrap center">';
$selected = 0; if ($massactionbutton || $massaction) { // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
if (in_array($obj->mid, $arrayofselected)) { $selected = 0;
$selected = 1; if (in_array($obj->mid, $arrayofselected)) {
$selected = 1;
}
print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
} }
print '<input id="cb'.$obj->mid.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$obj->mid.'"'.($selected ? ' checked="checked"' : '').'>';
}
print '</td>';
if (!$i) {
$totalarray['nbfield']++;
}
print '</tr>'."\n"; print '</tr>'."\n";
}
$i++; $i++;
} }
// If no record found
if ($num == 0) {
$colspan = 1;
foreach ($arrayfields as $key => $val) {
if (!empty($val['checked'])) {
$colspan++;
}
}
print '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
}
$db->free($resql); $db->free($resql);
print "</table>"; $parameters = array('arrayfields'=>$arrayfields, 'sql'=>$sql);
print '</div>'; $reshook = $hookmanager->executeHooks('printFieldListFooter', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
print "</form>"; print $hookmanager->resPrint;
print '</table>'."\n";
print '</div>'."\n";
print '</form>'."\n";
// Add number of product when there is a filter on period // Add number of product when there is a filter on period
if (count($arrayofuniqueproduct) == 1 && !empty($year) && is_numeric($year)) { if (count($arrayofuniqueproduct) == 1 && !empty($year) && is_numeric($year)) {
@ -1527,7 +1628,7 @@ if (in_array('builddoc', $arrayofmassactions) && ($nbtotalofrecords === '' || $n
$genallowed = $permissiontoread; $genallowed = $permissiontoread;
$delallowed = $permissiontoadd; $delallowed = $permissiontoadd;
print $formfile->showdocuments('massfilesarea_mymodule', '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty); print $formfile->showdocuments('massfilesarea_'.$object->module, '', $filedir, $urlsource, 0, $delallowed, '', 1, 1, 0, 48, 1, $param, $title, '', '', '', null, $hidegeneratedfilelistifempty);
} }
// End of page // End of page

View File

@ -1159,11 +1159,14 @@ if ($action == 'create' && $user->rights->projet->creer) {
print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0); print $form->selectDate($object->date_start ? $object->date_start : -1, 'projectstart', 0, 0, 0, '', 1, 0);
print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> '; print ' <span class="opacitymedium"> '.$langs->trans("to").' </span> ';
print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0); print $form->selectDate($object->date_end ? $object->date_end : -1, 'projectend', 0, 0, 0, '', 1, 0);
print ' &nbsp; &nbsp; <input type="checkbox" class="valignmiddle" id="reportdate" name="reportdate" value="yes" '; $object->getLinesArray(null, 0);
if ($comefromclone) { if (!empty($object->usage_task) && !empty($object->lines)) {
print ' checked '; print ' <span id="divreportdate" class="hidden">&nbsp; &nbsp; <input type="checkbox" class="valignmiddle" id="reportdate" name="reportdate" value="yes" ';
if ($comefromclone) {
print 'checked ';
}
print '/><label for="reportdate" class="valignmiddle opacitymedium">'.$langs->trans("ProjectReportDate").'</label></span>';
} }
print '/><label for="reportdate" class="opacitymedium">'.$langs->trans("ProjectReportDate").'</label>';
print '</td></tr>'; print '</td></tr>';
if (isModEnabled('eventorganization')) { if (isModEnabled('eventorganization')) {
@ -1385,6 +1388,11 @@ if ($action == 'create' && $user->rights->projet->creer) {
jQuery("#usage_task").prop("checked", true); jQuery("#usage_task").prop("checked", true);
} }
}); });
jQuery("#projectstart").change(function() {
console.log("We modify the start date");
jQuery("#divreportdate").show();
});
}); });
</script>'; </script>';

View File

@ -291,7 +291,7 @@ class Project extends CommonObject
'date_close' =>array('type'=>'datetime', 'label'=>'DateClosing', 'enabled'=>1, 'visible'=>0, 'position'=>105), 'date_close' =>array('type'=>'datetime', 'label'=>'DateClosing', 'enabled'=>1, 'visible'=>0, 'position'=>105),
'fk_user_close' =>array('type'=>'integer', 'label'=>'UserClosing', 'enabled'=>1, 'visible'=>0, 'position'=>110), 'fk_user_close' =>array('type'=>'integer', 'label'=>'UserClosing', 'enabled'=>1, 'visible'=>0, 'position'=>110),
'opp_amount' =>array('type'=>'double(24,8)', 'label'=>'OpportunityAmountShort', 'enabled'=>1, 'visible'=>'getDolGlobalString("PROJECT_USE_OPPORTUNITIES")', 'position'=>115), 'opp_amount' =>array('type'=>'double(24,8)', 'label'=>'OpportunityAmountShort', 'enabled'=>1, 'visible'=>'getDolGlobalString("PROJECT_USE_OPPORTUNITIES")', 'position'=>115),
'budget_amount' =>array('type'=>'double(24,8)', 'label'=>'Budget', 'enabled'=>1, 'visible'=>1, 'position'=>119), 'budget_amount' =>array('type'=>'double(24,8)', 'label'=>'Budget', 'enabled'=>1, 'visible'=>-1, 'position'=>119),
'usage_bill_time' =>array('type'=>'integer', 'label'=>'UsageBillTimeShort', 'enabled'=>1, 'visible'=>-1, 'position'=>130), 'usage_bill_time' =>array('type'=>'integer', 'label'=>'UsageBillTimeShort', 'enabled'=>1, 'visible'=>-1, 'position'=>130),
'usage_opportunity' =>array('type'=>'integer', 'label'=>'UsageOpportunity', 'enabled'=>1, 'visible'=>-1, 'position'=>135), 'usage_opportunity' =>array('type'=>'integer', 'label'=>'UsageOpportunity', 'enabled'=>1, 'visible'=>-1, 'position'=>135),
'usage_task' =>array('type'=>'integer', 'label'=>'UsageTasks', 'enabled'=>1, 'visible'=>-1, 'position'=>140), 'usage_task' =>array('type'=>'integer', 'label'=>'UsageTasks', 'enabled'=>1, 'visible'=>-1, 'position'=>140),
@ -2344,11 +2344,11 @@ class Project extends CommonObject
/** /**
* Create an array of tasks of current project * Create an array of tasks of current project
* *
* @param User $user Object user we want project allowed to * @param User $user Object user we want project allowed to
* @param int $loadRoleMode 1= will test Roles on task; 0 used in delete project action * @param int $loadRoleMode 1= will test Roles on task; 0 used in delete project action
* @return int >0 if OK, <0 if KO * @return int >0 if OK, <0 if KO
*/ */
public function getLinesArray($user, $loadRoleMode = 1) public function getLinesArray($user, $loadRoleMode = 1)
{ {

View File

@ -1858,8 +1858,8 @@ while ($i < $imaxinloop) {
} }
// Email MsgID // Email MsgID
if (!empty($arrayfields['p.email_msgid']['checked'])) { if (!empty($arrayfields['p.email_msgid']['checked'])) {
print '<td class="center">'; print '<td class="tdoverflowmax125" title="'.dol_escape_htmltag($obj->email_msgid).'">';
print $obj->email_msgid; print dol_escape_htmltag($obj->email_msgid);
print '</td>'; print '</td>';
if (!$i) $totalarray['nbfield']++; if (!$i) $totalarray['nbfield']++;
} }

View File

@ -1797,7 +1797,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
if ($projectstatic->public) { if ($projectstatic->public) {
$contactsofproject = array(); $contactsofproject = array();
} }
print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'maxwidth250'); print $form->select_dolusers((GETPOST('userid', 'int') ? GETPOST('userid', 'int') : $userid), 'userid', 0, '', 0, '', $contactsofproject, 0, 0, 0, '', 0, $langs->trans("ResourceNotAssignedToProject"), 'maxwidth200');
} else { } else {
if ($nboftasks) { if ($nboftasks) {
print img_error($langs->trans('FirstAddRessourceToAllocateTime')).' '.$langs->trans('FirstAddRessourceToAllocateTime'); print img_error($langs->trans('FirstAddRessourceToAllocateTime')).' '.$langs->trans('FirstAddRessourceToAllocateTime');
@ -1830,8 +1830,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '</td>'; print '</td>';
if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) { if ($conf->service->enabled && $projectstatic->thirdparty->id > 0 && $projectstatic->usage_bill_time) {
print '<td class="nowrap">'; print '<td class="nowraponall">';
print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); print img_picto('', 'product');
print $form->select_produits('', 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 1, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth150', 0, '', null, 1);
print '</td>'; print '</td>';
} }
} }
@ -1843,7 +1844,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '<td class="center">'; print '<td class="center">';
$form->buttonsSaveCancel(); $form->buttonsSaveCancel();
print '<input type="submit" name="save" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-add" value="'.$langs->trans("Add").'">'; print '<input type="submit" name="save" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-add reposition" value="'.$langs->trans("Add").'">';
print '<input type="submit" name="cancel" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">'; print '<input type="submit" name="cancel" class="button buttongen marginleftonly margintoponlyshort marginbottomonlyshort button-cancel" value="'.$langs->trans("Cancel").'">';
print '</td></tr>'; print '</td></tr>';
@ -2149,7 +2150,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
// Thirdparty // Thirdparty
if (!empty($arrayfields['p.fk_soc']['checked'])) { if (!empty($arrayfields['p.fk_soc']['checked'])) {
print '<td class="nowrap tdoverflowmax150">'; print '<td class="tdoverflowmax125">';
if ($task_time->fk_soc > 0) { if ($task_time->fk_soc > 0) {
if (empty($conf->cache['thridparty'][$task_time->fk_soc])) { if (empty($conf->cache['thridparty'][$task_time->fk_soc])) {
$tmpsociete = new Societe($db); $tmpsociete = new Societe($db);
@ -2331,9 +2332,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
} }
} }
//Product // Product
if (!empty($arrayfields['t.fk_product']['checked'])) { if (!empty($arrayfields['t.fk_product']['checked'])) {
print '<td class="nowraponall">'; print '<td class="nowraponall tdoverflowmax125">';
if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) { if ($action == 'editline' && $_GET['lineid'] == $task_time->rowid) {
$form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500'); $form->select_produits($task_time->fk_product, 'fk_product', '1', 0, $projectstatic->thirdparty->price_level, 1, 2, '', 0, array(), $projectstatic->thirdparty->id, 'None', 0, 'maxwidth500');
} elseif (!empty($task_time->fk_product)) { } elseif (!empty($task_time->fk_product)) {
@ -2432,9 +2433,9 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '<td class="center nowraponall">'; print '<td class="center nowraponall">';
if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) { if (($action == 'editline' || $action == 'splitline') && GETPOST('lineid', 'int') == $task_time->rowid) {
print '<input type="hidden" name="lineid" value="'.GETPOST('lineid', 'int').'">'; print '<input type="hidden" name="lineid" value="'.GETPOST('lineid', 'int').'">';
print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-save" name="save" value="'.$langs->trans("Save").'">'; print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-save small" name="save" value="'.$langs->trans("Save").'">';
print ' '; print ' ';
print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-cancel" name="cancel" value="'.$langs->trans("Cancel").'">'; print '<input type="submit" class="button buttongen margintoponlyshort marginbottomonlyshort button-cancel small" name="cancel" value="'.$langs->trans("Cancel").'">';
} elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks } elseif ($user->hasRight('projet', 'time') || $user->hasRight('projet', 'all', 'creer')) { // Read project and enter time consumed on assigned tasks
if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) { if (in_array($task_time->fk_user, $childids) || $user->hasRight('projet', 'all', 'creer')) {
if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) { if (getDolGlobalString('MAIN_FEATURES_LEVEL') >= 2) {
@ -2474,6 +2475,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
// Add line to split // Add line to split
if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
print '<!-- first line -->';
print '<tr class="oddeven">'; print '<tr class="oddeven">';
// Date // Date
@ -2491,6 +2493,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '</td>'; print '</td>';
} }
// Thirdparty
if (!empty($arrayfields['p.fk_soc']['checked'])) {
print '<td class="nowrap">';
print '</td>';
}
// Thirdparty alias
if (!empty($arrayfields['s.name_alias']['checked'])) {
print '<td class="nowrap">';
print '</td>';
}
// Project ref // Project ref
if (!empty($allprojectforuser)) { if (!empty($allprojectforuser)) {
if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
@ -2522,7 +2536,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
// User // User
if (!empty($arrayfields['author']['checked'])) { if (!empty($arrayfields['author']['checked'])) {
print '<td>'; print '<td class="nowraponall">';
if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
if (empty($object->id)) { if (empty($object->id)) {
$object->fetch($id); $object->fetch($id);
@ -2573,6 +2587,12 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '</td>'; print '</td>';
} }
// Product
if (!empty($arrayfields['t.fk_product']['checked'])) {
print '<td class="nowraponall tdoverflowmax125">';
print '</td>';
}
// Value spent // Value spent
if (!empty($arrayfields['value']['checked'])) { if (!empty($arrayfields['value']['checked'])) {
print '<td class="right">'; print '<td class="right">';
@ -2612,7 +2632,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
// Line for second dispatching // Line for second dispatching
print '<tr class="oddeven">'; print '<!-- second line --><tr class="oddeven">';
// Date // Date
if (!empty($arrayfields['t.element_date']['checked'])) { if (!empty($arrayfields['t.element_date']['checked'])) {
@ -2629,6 +2649,18 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '</td>'; print '</td>';
} }
// Thirdparty
if (!empty($arrayfields['p.fk_soc']['checked'])) {
print '<td class="nowrap">';
print '</td>';
}
// Thirdparty alias
if (!empty($arrayfields['s.name_alias']['checked'])) {
print '<td class="nowrap">';
print '</td>';
}
// Project ref // Project ref
if (!empty($allprojectforuser)) { if (!empty($allprojectforuser)) {
if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
@ -2653,14 +2685,14 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
if (!empty($arrayfields['t.element_label']['checked'])) { if (!empty($arrayfields['t.element_label']['checked'])) {
if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task if ((empty($id) && empty($ref)) || !empty($projectidforalltimes)) { // Not a dedicated task
print '<td class="nowrap">'; print '<td class="nowrap">';
print $task_time->label; print dol_escape_htmltag($task_time->label);
print '</td>'; print '</td>';
} }
} }
// User // User
if (!empty($arrayfields['author']['checked'])) { if (!empty($arrayfields['author']['checked'])) {
print '<td>'; print '<td class="nowraponall">';
if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) { if ($action == 'splitline' && GETPOST('lineid', 'int') == $task_time->rowid) {
if (empty($object->id)) { if (empty($object->id)) {
$object->fetch($id); $object->fetch($id);
@ -2711,6 +2743,12 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser
print '</td>'; print '</td>';
} }
// Product
if (!empty($arrayfields['t.fk_product']['checked'])) {
print '<td class="nowraponall tdoverflowmax125">';
print '</td>';
}
// Value spent // Value spent
if (!empty($arrayfields['value']['checked'])) { if (!empty($arrayfields['value']['checked'])) {
print '<td class="right">'; print '<td class="right">';

View File

@ -24,7 +24,7 @@
* \remarks To run this script as CLI: phpunit filename.php * \remarks To run this script as CLI: phpunit filename.php
*/ */
print "PHP Version: ".phpversion()."\n"; print "PHP Version: ".phpversion()."\n";
print "Memory: ". ini_get('memory_limit')."\n"; print "Memory limit: ". ini_get('memory_limit')."\n";
global $conf,$user,$langs,$db; global $conf,$user,$langs,$db;
//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver //define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver

View File

@ -259,11 +259,12 @@ class CategorieTest extends PHPUnit\Framework\TestCase
$langs=$this->savlangs; $langs=$this->savlangs;
$db=$this->savdb; $db=$this->savdb;
$localobject->note='New note after update'; $localobject->note_private ='New note after update';
$result=$localobject->update($user); $result=$localobject->update($user);
print __METHOD__." id=".$localobject->id." result=".$result."\n"; print __METHOD__." id=".$localobject->id." result=".$result."\n";
$this->assertGreaterThan(0, $result); $this->assertGreaterThan(0, $result);
return $localobject; return $localobject;
} }
@ -288,8 +289,6 @@ class CategorieTest extends PHPUnit\Framework\TestCase
print __METHOD__." id=".$localobject->id." result=".$result."\n"; print __METHOD__." id=".$localobject->id." result=".$result."\n";
$this->assertLessThan($result, 0); $this->assertLessThan($result, 0);
*/ */
$localobject2=new Categorie($db);
$localobject2->initAsSpecimen();
$retarray=$localobject->liste_photos('/'); $retarray=$localobject->liste_photos('/');
print __METHOD__." retarray size=".count($retarray)."\n"; print __METHOD__." retarray size=".count($retarray)."\n";

View File

@ -146,41 +146,44 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase
// We create a product for tests // We create a product for tests
$product0=new Product($db); $product0=new Product($db);
$product0->initAsSpecimen(); $product0->initAsSpecimen();
$product0->ref.=' 0'; $product0->ref.=' phpunit 0';
$product0->label.=' 0'; $product0->label.=' phpunit 0';
$product0->status_batch = 1; $product0->status_batch = 1;
$product0id=$product0->create($user); $product0id=$product0->create($user);
print __METHOD__." product0id=".$product0id."\n";
$this->assertGreaterThan(0, $product0id, 'Failed to create product');
$product1=new Product($db); $product1=new Product($db);
$product1->initAsSpecimen(); $product1->initAsSpecimen();
$product1->ref.=' 1'; $product1->ref.=' phpunit 1';
$product1->label.=' 1'; $product1->label.=' phpunit 1';
$product1id=$product1->create($user); $product1id=$product1->create($user);
$product2=new Product($db); $product2=new Product($db);
$product2->initAsSpecimen(); $product2->initAsSpecimen();
$product2->ref.=' 2'; $product2->ref.=' phpunit 2';
$product2->label.=' 2'; $product2->label.=' phpunit 2';
$product2id=$product2->create($user); $product2id=$product2->create($user);
// We create a product for tests // We create a product for tests
$warehouse0=new Entrepot($db); $warehouse0=new Entrepot($db);
$warehouse0->initAsSpecimen(); $warehouse0->initAsSpecimen();
$warehouse0->label.=' 0'; $warehouse0->label.=' phpunit 0';
$warehouse0->description.=' 0'; $warehouse0->description.=' phpunit 0';
$warehouse0->statut = 0; $warehouse0->statut = 0;
$warehouse0id=$warehouse0->create($user); $warehouse0id=$warehouse0->create($user);
$warehouse1=new Entrepot($db); $warehouse1=new Entrepot($db);
$warehouse1->initAsSpecimen(); $warehouse1->initAsSpecimen();
$warehouse1->label.=' 1'; $warehouse1->label.=' phpunit 1';
$warehouse1->description.=' 1'; $warehouse1->description.=' phpunit 1';
$warehouse1id=$warehouse1->create($user); $warehouse1id=$warehouse1->create($user);
$warehouse2=new Entrepot($db); $warehouse2=new Entrepot($db);
$warehouse2->initAsSpecimen(); $warehouse2->initAsSpecimen();
$warehouse2->label.=' 2'; $warehouse2->label.=' phpunit 2';
$warehouse2->description.=' 2'; $warehouse2->description.=' phpunit 2';
$warehouse2id=$warehouse2->create($user); $warehouse2id=$warehouse2->create($user);
$localobject=new MouvementStock($this->savdb); $localobject=new MouvementStock($this->savdb);
@ -188,10 +191,10 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase
$datetest1 = dol_mktime(0, 0, 0, 1, 1, 2000); $datetest1 = dol_mktime(0, 0, 0, 1, 1, 2000);
$datetest2 = dol_mktime(0, 0, 0, 1, 2, 2000); $datetest2 = dol_mktime(0, 0, 0, 1, 2, 2000);
// Create an input movement movement (type = 3) with value for eatby date and a lot // Create an input movement movement (type = 3) with value for eatby date and a lot $datetest1
$result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberA', '', 0, 'Inventory Code Test with batch'); $result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberA', '', 0, 'Inventory Code Test with batch');
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertGreaterThan(0, $result, 'Failed to create a movement with a lot number of product with status_batch=1'); $this->assertGreaterThan(0, $result, 'Failed to create a movement with a lot number '.$datetest1.' for product id='.$product0id.' with status_batch=1');
$result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberB', '', 0, 'Inventory Code Test with batch'); $result=$localobject->reception($user, $product0id, $warehouse0id, 5, 999, 'Movement for unit test with batch', $datetest1, $datetest1, 'anotyetuselotnumberB', '', 0, 'Inventory Code Test with batch');
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
@ -250,12 +253,12 @@ class MouvementStockTest extends PHPUnit\Framework\TestCase
// Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8 // Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8
$result=$localobject->_create($user, $product1id, $warehouse2id, 1, 0, 0, 'Input from transfer wh 2', 'Transfert X 2'); $result=$localobject->_create($user, $product1id, $warehouse2id, 1, 0, 0, 'Input from transfer wh 2', 'Transfert X 2');
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertGreaterThan(0, $result); $this->assertGreaterThan(0, $result, 'Test create A');
// Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8 // Create an output movement (type = 1) of price 9.7 -> should update PMP to 9.9/9.7 = 9.8
$result=$localobject->_create($user, $product1id, $warehouse2id, -2, 1, 0, 'Output from transfer wh 2', 'Transfert Y 2'); $result=$localobject->_create($user, $product1id, $warehouse2id, -2, 1, 0, 'Output from transfer wh 2', 'Transfert Y 2');
print __METHOD__." result=".$result."\n"; print __METHOD__." result=".$result."\n";
$this->assertGreaterThan(0, $result); $this->assertGreaterThan(0, $result, 'Test create B');
return $localobject; return $localobject;
} }