diff --git a/htdocs/accountancy/admin/account.php b/htdocs/accountancy/admin/account.php index 95ba62de0c5..cb3255f981d 100644 --- a/htdocs/accountancy/admin/account.php +++ b/htdocs/accountancy/admin/account.php @@ -256,10 +256,8 @@ if ($resql) { print ''; print ' '; print ''; - - print ''; - print ' '; - print ''; + $searchpitco=$form->showFilterAndCheckAddButtons($massactionbutton?1:0, 'checkforselect', 1); + print $searchpitco; print ''; print ''; diff --git a/htdocs/accountancy/admin/defaultaccounts.php b/htdocs/accountancy/admin/defaultaccounts.php index a66217ebbee..6854c8a45ff 100644 --- a/htdocs/accountancy/admin/defaultaccounts.php +++ b/htdocs/accountancy/admin/defaultaccounts.php @@ -138,7 +138,7 @@ foreach ( $list_account as $key ) { $label = $langs->trans($key); print '' . $label . ''; // Value - print ''; + print ''; // Do not force align=right, or it align also the content of the select box print $formaccountancy->select_account($conf->global->$key, $key, 1, '', 1, 1); print ''; print ''; diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 495fb2a1304..5de8be91d20 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -40,6 +40,7 @@ $langs->load("companies"); $langs->load("compta"); $langs->load("main"); $langs->load("accountancy"); +$langs->load("products"); // Security check if (empty($conf->accounting->enabled)) { @@ -61,6 +62,10 @@ $changeaccount_sell = GETPOST('changeaccount_sell', 'array'); $search_ref = GETPOST('search_ref', 'alpha'); $search_label = GETPOST('search_label', 'alpha'); $search_desc = GETPOST('search_desc', 'alpha'); +$search_current_account = GETPOST('search_current_account', 'alpha'); +$search_current_account_valid = GETPOST('search_current_account_valid', 'alpha'); +if ($search_current_account_valid == '') $search_current_account_valid='withoutvalidaccount'; + $accounting_product_mode = GETPOST('accounting_product_mode', 'alpha'); $btn_changeaccount = GETPOST('changeaccount'); $btn_changetype = GETPOST('changetype'); @@ -85,12 +90,21 @@ $arrayfields=array(); * Actions */ +if (GETPOST('cancel')) { $action='list'; $massaction=''; } +if (! GETPOST('confirmmassaction') && $massaction != 'presend' && $massaction != 'confirm_presend') { $massaction=''; } + +$parameters=array(); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + // Purge search criteria if (GETPOST("button_removefilter_x") || GETPOST("button_removefilter.x") || GETPOST("button_removefilter")) // All test are required to be compatible with all browsers { $search_ref = ''; $search_label = ''; $search_desc = ''; + $search_current_account = ''; + $search_current_account_valid = '-1'; } // Sales or Purchase mode ? @@ -189,23 +203,38 @@ $aacompta_prodsell = (! empty($conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT) ? llxHeader('', $langs->trans("ProductsBinding")); -$pcgver = $conf->global->CHARTOFACCOUNTS; +$pcgverid = $conf->global->CHARTOFACCOUNTS; +$pcgvercode = dol_getIdFromCode($db, $pcgverid, 'accounting_system', 'rowid', 'pcg_version'); +if (empty($pcgvercode)) $pcgvercode=$pcgverid; -$sql = "SELECT p.rowid, p.ref, p.label, p.description , p.accountancy_code_sell, p.accountancy_code_buy, p.tms, p.fk_product_type as product_type"; -$sql .= " FROM " . MAIN_DB_PREFIX . "product as p"; -$sql .= " WHERE ("; -if ($accounting_product_mode == 'ACCOUNTANCY_BUY' ? ' checked' : '') { - $sql .= " p.accountancy_code_buy ='' OR p.accountancy_code_buy IS NULL"; - $sql .= " OR (p.accountancy_code_buy IS NOT NULL AND p.accountancy_code_buy != '' AND p.accountancy_code_buy NOT IN - (SELECT aa.account_number FROM " . MAIN_DB_PREFIX . "accounting_account as aa , " . MAIN_DB_PREFIX . "accounting_system as asy WHERE fk_pcg_version = asy.pcg_version AND asy.rowid = " . $pcgver . "))"; -} else { - $sql .= " p.accountancy_code_sell ='' OR p.accountancy_code_sell IS NULL "; - $sql .= " OR (p.accountancy_code_sell IS NOT NULL AND p.accountancy_code_sell != '' AND p.accountancy_code_sell NOT IN - (SELECT aa.account_number FROM " . MAIN_DB_PREFIX . "accounting_account as aa , " . MAIN_DB_PREFIX . "accounting_system as asy WHERE fk_pcg_version = asy.pcg_version AND asy.rowid = " . $pcgver . "))"; +$sql = "SELECT p.rowid, p.ref, p.label, p.description, p.tosell, p.tobuy, p.accountancy_code_sell, p.accountancy_code_buy, p.tms, p.fk_product_type as product_type,"; +$sql.= " aa.rowid as aaid"; +$sql.= " FROM " . MAIN_DB_PREFIX . "product as p"; +$sql.= " LEFT JOIN ".MAIN_DB_PREFIX."accounting_account as aa ON"; +if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { + $sql.=" p.accountancy_code_buy = aa.account_number AND aa.fk_pcg_version = '" . $pcgvercode . "'"; } -$sql .= ")"; -if (! empty($conf->multicompany->enabled)) { - $sql.= ' AND p.entity IN ('.getEntity('product', 1).')'; +else +{ + $sql.=" p.accountancy_code_sell = aa.account_number AND aa.fk_pcg_version = '" . $pcgvercode . "'"; +} +$sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; +if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { + if (strlen(trim($search_current_account))) { + $sql .= natural_search("p.accountancy_code_buy",$search_current_account); + } +} else { + if (strlen(trim($search_current_account))) { + $sql .= natural_search("p.accountancy_code_sell",$search_current_account); + } +} +if ($search_current_account_valid == 'withoutvalidaccount') +{ + $sql .= " AND aa.account_number IS NULL"; +} +if ($search_current_account_valid == 'withvalidaccount') +{ + $sql .= " AND aa.account_number IS NOT NULL"; } // Add search filter like if (strlen(trim($search_ref))) { @@ -218,6 +247,7 @@ if (strlen(trim($search_desc))) { $sql .= natural_search("p.description",$search_desc); } $sql .= $db->order($sortfield, $sortorder); + $nbtotalofrecords = 0; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) { @@ -236,9 +266,11 @@ if ($result) $param=''; if (! empty($contextpage) && $contextpage != $_SERVER["PHP_SELF"]) $param.='&contextpage='.$contextpage; if ($limit > 0 && $limit != $conf->liste_limit) $param.='&limit='.$limit; - if ($search_ref > 0) $param.="&search_desc=".urlencode($search_ref); - if ($search_label > 0) $param.="&search_desc=".urlencode($search_label); - if ($search_desc > 0) $param.="&search_desc=".urlencode($search_desc); + if ($search_ref > 0) $param.="&search_desc=".urlencode($search_ref); + if ($search_label > 0) $param.="&search_desc=".urlencode($search_label); + if ($search_desc > 0) $param.="&search_desc=".urlencode($search_desc); + if ($search_current_account > 0) $param.="&search_current_account=".urlencode($search_current_account); + if ($search_current_account_valid && $search_current_account_valid != '-1') $param.="&search_current_account_valid=".urlencode($search_current_account_valid); print '
'; if ($optioncss != '') print ''; @@ -260,11 +292,10 @@ if ($result) print '' . $langs->trans('Options') . '' . $langs->trans('Description') . ''; print "\n"; print ' ' . $langs->trans('OptionModeProductSell') . ''; - print '' . nl2br($langs->trans('OptionModeProductSellDesc')); + print ''.$langs->trans('OptionModeProductSellDesc'); print "\n"; print ' ' . $langs->trans('OptionModeProductBuy') . ''; - print '' . nl2br($langs->trans('OptionModeProductBuyDesc')) . "\n"; - + print ''.$langs->trans('OptionModeProductBuyDesc')."\n"; print "\n"; print '
'; @@ -277,7 +308,7 @@ if ($result) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - $texte=$langs->trans("ListOfProductsWithoutAccountingAccount"); + $texte=$langs->trans("ListOfProductsServices"); print_barre_liste($texte, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, '', 0, '', '', $limit); print ''; @@ -285,37 +316,54 @@ if ($result) print_liste_field_titre($langs->trans("Ref"), $_SERVER["PHP_SELF"], "p.ref", "", $param, '', $sortfield, $sortorder); print_liste_field_titre($langs->trans("Label"), $_SERVER["PHP_SELF"], "p.label", "", $param, '', $sortfield, $sortorder); if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print_liste_field_titre($langs->trans("Description"), $_SERVER["PHP_SELF"], "p.description", "", $param, '', $sortfield, $sortorder); - /* - if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { - print_liste_field_titre($langs->trans("Accountancy_code_buy")); - } else { - print_liste_field_titre($langs->trans("Accountancy_code_sell")); - } - */ - print_liste_field_titre($langs->trans("AccountAccounting")); - //print_liste_field_titre($langs->trans("Modify") . '
/ ', '', '', '', '', 'align="center"'); + print_liste_field_titre($langs->trans("OnSell"), $_SERVER["PHP_SELF"], "p.tosell", "", $param, 'align="center"', $sortfield, $sortorder); + print_liste_field_titre($langs->trans("OnBuy"), $_SERVER["PHP_SELF"], "p.tobuy", "", $param, 'align="center"', $sortfield, $sortorder); + if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { + $fieldtosortaccount="p.accountancy_code_buy"; + } + else $fieldtosortaccount="p.accountancy_code_sell"; + print_liste_field_titre($langs->trans("CurrentDedicatedAccountingAccount"), $_SERVER["PHP_SELF"], $fieldtosortaccount, "", $param, '', $sortfield, $sortorder); + print_liste_field_titre($langs->trans("AssignDedicatedAccountingAccount")); print_liste_field_titre('', '', '', '', '', 'align="center"'); print ''; print ''; - print ''; - print ''; - print ''; - if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print ''; + print ''; + print ''; + if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) print ''; + // On sell + print ''; + // On buy + print ''; + // Current account + print ''; + print ''; print ''; print ''; - $var = true; + $product_static = new Product($db); + $var = true; + $i=0; while ($i < min($num,$limit)) { $obj = $db->fetch_object($result); - $var = ! $var; - - $compta_prodsell = $obj->accountancy_code_sell; + + // Ref produit as link + $product_static->ref = $obj->ref; + $product_static->id = $obj->rowid; + $product_static->type = $obj->product_type; + $product_static->label = $obj->label; + $product_static->description = $obj->description; + $product_static->status = $obj->tosell; + $product_static->status_buy = $obj->tobuy; if ($obj->product_type == 0) { $compta_prodsell = (! empty($conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_SOLD_ACCOUNT : $langs->trans("CodeNotDef")); @@ -325,8 +373,6 @@ if ($result) $compta_prodsell_id = $aarowid_servsell; } - $compta_prodbuy = $obj->accountancy_code_buy; - if ($obj->product_type == 0) { $compta_prodbuy = (! empty($conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT) ? $conf->global->ACCOUNTING_PRODUCT_BUY_ACCOUNT : $langs->trans("CodeNotDef")); $compta_prodbuy_id = $aarowid_prodbuy; @@ -335,30 +381,15 @@ if ($result) $compta_prodbuy_id = $aarowid_servbuy; } - $product_static = new Product($db); - - print ''; - - print ""; - + $var = ! $var; print ''; - // Ref produit as link - $product_static->ref = $obj->ref; - $product_static->id = $obj->rowid; - $product_static->type = $obj->type; - $product_static->label = $obj->label; - $product_static->description = $obj->description; - print ''; print ''; - + if (! empty($conf->global->ACCOUNTANCY_SHOW_PROD_DESC)) { // TODO ADJUST DESCRIPTION SIZE @@ -368,24 +399,43 @@ if ($result) print ''; } - // Accounting account buy + print ''; + + print ''; + + // Current accounting account + print ''; - // TODO: replace by select - // print ''; - // TODO: we shoul set a user defined value to adjust user square / wide screen size - // $trunclenghform = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50; + print length_accountg($obj->accountancy_code_buy); + if ($obj->accountancy_code_buy && empty($obj->aaid)) print ' '.img_warning($langs->trans("ValueNotIntoChartOfAccount")); + } + else + { + print length_accountg($obj->accountancy_code_sell); + if ($obj->accountancy_code_sell && empty($obj->aaid)) print ' '.img_warning($langs->trans("ValueNotIntoChartOfAccount")); + } + print ''; + + // Dedicated account + $defaultvalue=''; + if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { + // Accounting account buy print ''; } else { // Accounting account sell - // print ''; - // TODO: replace by select - // TODO: we shoul set a user defined value to adjust user square / wide screen size - // $trunclenghform = defined('ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT') ? ACCOUNTING_LENGTH_DESCRIPTION_ACCOUNT : 50; print ''; } @@ -397,7 +447,34 @@ if ($result) } print '
 '; + print ''; + $listofvals=array('withoutvalidaccount'=>$langs->trans("WithoutValidAccount"), 'withvalidaccount'=>$langs->trans("WithValidAccount")); + print ' '.$langs->trans("or").' '.$form->selectarray('search_current_account_valid', $listofvals, $search_current_account_valid, 1); + print ' '; $searchpitco=$form->showFilterAndCheckAddButtons(1, 'checkforselect', 1); print $searchpitco; print '
'; - if ($product_static->id) - print $product_static->getNomUrl(1); - else - print '- '; + print $product_static->getNomUrl(1); print ''.$obj->label.'' . nl2br(dol_trunc($obj->description, $trunclengh)) . ''.$product_static->getLibStatut(3, 0).''.$product_static->getLibStatut(3, 1).''; if ($accounting_product_mode == 'ACCOUNTANCY_BUY') { - // print '' . $obj->accountancy_code_buy . '' . $compta_prodbuy . ''; - print $form->select_account($compta_prodbuy_id, 'codeventil_' . $product_static->id, 1); + //$defaultvalue=GETPOST('codeventil_' . $product_static->id,'alpha'); This is id and we need a code + if (empty($defaultvalue)) $defaultvalue=$compta_prodbuy; + $codesell=length_accountg($obj->accountancy_code_buy); + if (! empty($obj->aaid)) $defaultvalue = ''; // Do not suggest default new value is code is already valid + print $form->select_account($defaultvalue, 'codeventil_' . $product_static->id, 1, array(), 1); print '' . $obj->accountancy_code_sell . ''; - print $form->select_account($compta_prodsell_id, 'codeventil_' . $product_static->id, 1); + //$defaultvalue=GETPOST('codeventil_' . $product_static->id,'alpha'); This is id and we need a code + if (empty($defaultvalue)) $defaultvalue=$compta_prodsell; + $codesell=length_accountg($obj->accountancy_code_sell); + //var_dump($defaultvalue.' - '.$codesell.' - '.$compta_prodsell); + if (! empty($obj->aaid)) $defaultvalue = ''; // Do not suggest default new value is code is already valid + print $form->select_account($defaultvalue, 'codeventil_' . $product_static->id, 1, array(), 1); print '
'; - print '
'; + // Example : Adding jquery code + print ''; + + + print '
'; print '
'; diff --git a/htdocs/accountancy/class/html.formventilation.class.php b/htdocs/accountancy/class/html.formventilation.class.php index ac72df44e21..fab9e81031d 100644 --- a/htdocs/accountancy/class/html.formventilation.class.php +++ b/htdocs/accountancy/class/html.formventilation.class.php @@ -65,7 +65,7 @@ class FormVentilation extends Form /** * Return list of accounts with label by chart of accounts * - * @param string $selectid Preselected chart of accounts + * @param string $selectid Preselected id or code of accounting accounts (depends on $select_in) * @param string $htmlname Name of field in html form * @param int $showempty Add an empty field * @param array $event Event options @@ -99,26 +99,28 @@ class FormVentilation extends Form $out = ajax_combobox($htmlname, $event); + // TODO Add $options in cache so next call will not execute the request + $selected = 0; $options = array(); - $selected = null; - - while ($obj = $this->db->fetch_object($resql)) { + while ($obj = $this->db->fetch_object($resql)) + { $label = length_accountg($obj->account_number) . ' - ' . $obj->label; $label = dol_trunc($label, $trunclength); $select_value_in = $obj->rowid; $select_value_out = $obj->rowid; + // Try to guess if we have found default value if ($select_in == 1) { $select_value_in = $obj->account_number; } if ($select_out == 1) { $select_value_out = $obj->account_number; } - // Remember guy's we store in database llx_facturedet the rowid of accounting_account and not the account_number // Because same account_number can be share between different accounting_system and do have the same meaning - if (($selectid != '') && $selectid == $select_value_in) { + if ($selectid != '' && $selectid == $select_value_in) { + //var_dump("Found ".$selectid." ".$select_value_in); $selected = $select_value_out; } @@ -127,6 +129,7 @@ class FormVentilation extends Form $out .= Form::selectarray($htmlname, $options, $selected, $showempty, 0, 0, '', 0, 0, 0, '', $morecss, 1); $this->db->free($resql); + return $out; } diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index d7414a46835..e00a8a825b8 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5197,7 +5197,7 @@ function dol_osencode($str) * Store also Code-Id into a cache to speed up next request on same key. * * @param DoliDB $db Database handler - * @param string $key Code to get Id + * @param string $key Code or Id to get Id or Code * @param string $tablename Table name without prefix * @param string $fieldkey Field for code * @param string $fieldid Field for id diff --git a/htdocs/langs/en_US/accountancy.lang b/htdocs/langs/en_US/accountancy.lang index d24ec11a502..9a94bf5d5c5 100644 --- a/htdocs/langs/en_US/accountancy.lang +++ b/htdocs/langs/en_US/accountancy.lang @@ -16,6 +16,8 @@ Journaux=Journals JournalFinancial=Financial journals BackToChartofaccounts=Return chart of accounts Chartofaccounts=Chart of accounts +CurrentDedicatedAccountingAccount=Current dedicated account +AssignDedicatedAccountingAccount=New account to assign AccountancyArea=Accountancy area AccountancyAreaDescIntro=Usage of the accountancy module is done in several step: @@ -207,11 +209,15 @@ DefaultBindingDesc=This page can be used to set a default account to use to link Options=Options OptionModeProductSell=Mode sales OptionModeProductBuy=Mode purchases -OptionModeProductSellDesc=Show all products with no accounting account defined for sales. -OptionModeProductBuyDesc=Show all products with no accounting account defined for purchases. +OptionModeProductSellDesc=Show all products with accounting account for sales. +OptionModeProductBuyDesc=Show all products with accounting account for purchases. CleanFixHistory=Remove accountancy code from lines that not exists into charts of account CleanHistory=Reset all bindings for selected year +WithoutValidAccount=Without valid dedicated account +WithValidAccount=With valid dedicated account +ValueNotIntoChartOfAccount=This value of accounting account does not exist into chart of account + ## Dictionary Range=Range of accounting account Calculated=Calculated diff --git a/htdocs/langs/en_US/products.lang b/htdocs/langs/en_US/products.lang index 27b64a4399d..9bea19a30a2 100644 --- a/htdocs/langs/en_US/products.lang +++ b/htdocs/langs/en_US/products.lang @@ -101,6 +101,7 @@ KeywordFilter=Keyword filter CategoryFilter=Category filter ProductToAddSearch=Search product to add NoMatchFound=No match found +ListOfProductsServices=List of products/services ProductAssociationList=List of products/services that are component of this virtual product/package ProductParentList=List of virtual products/services with this product as a component ErrorAssociationIsFatherOfThis=One of selected product is parent with current product diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 7e3f337ed3b..4755e5e5405 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -3159,17 +3159,21 @@ class Product extends CommonObject if (! empty($this->label)) $label .= '
' . $langs->trans('ProductLabel') . ': ' . $this->label; - $tmptext=''; - if ($this->weight) $tmptext.="
".$langs->trans("Weight").': '.$this->weight.' '.measuring_units_string($this->weight_units,"weight"); - if ($this->length) $tmptext.="
".$langs->trans("Length").': '.$this->length.' '.measuring_units_string($this->length_units,'length'); - if ($this->surface) $tmptext.="
".$langs->trans("Surface").': '.$this->surface.' '.measuring_units_string($this->surface_units,'surface'); - if ($this->volume) $tmptext.="
".$langs->trans("Volume").': '.$this->volume.' '.measuring_units_string($this->volume_units,'volume'); - if ($tmptext) $label .= $tmptext; - if (! empty($conf->productbatch->enabled)) + if ($this->type == Product::TYPE_PRODUCT) { - $tmptext.="
".$langs->trans("ManageLotSerial").': '.$this->getLibStatut(0,2); + if ($this->weight) $label.="
".$langs->trans("Weight").': '.$this->weight.' '.measuring_units_string($this->weight_units,"weight"); + if ($this->length) $label.="
".$langs->trans("Length").': '.$this->length.' '.measuring_units_string($this->length_units,'length'); + if ($this->surface) $label.="
".$langs->trans("Surface").': '.$this->surface.' '.measuring_units_string($this->surface_units,'surface'); + if ($this->volume) $label.="
".$langs->trans("Volume").': '.$this->volume.' '.measuring_units_string($this->volume_units,'volume'); + if (! empty($conf->productbatch->enabled)) + { + $label.="
".$langs->trans("ManageLotSerial").': '.$this->getLibStatut(0,2); + } + } + if ($this->type == Product::TYPE_SERVICE) + { + // } - $label.=$tmptext; if (! empty($this->entity)) $label .= '
' . $this->show_photos($conf->product->multidir_output[$this->entity],1,1,0,0,0,80);