diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000000..186b20a051d --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,5 @@ +# These are supported funding model platforms + +open_collective: dolibarr +custom: https://wiki.dolibarr.org/index.php/Subscribe +# github: [eldy] \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE/bug_report.md similarity index 78% rename from .github/ISSUE_TEMPLATE.md rename to .github/ISSUE_TEMPLATE/bug_report.md index a105eed20ea..432f30f2332 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,8 +1,16 @@ +--- +name: Bug report +about: Create a report to help us fix something that is broken +title: '' +labels: Bug +assignees: '' + +--- + # Instructions *This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.* *Please:* -- *only keep the "Bug" or "Feature Request" section* -- *replace the bracket enclosed texts with meaningful informations* +- *replace the bracket enclosed texts with meaningful information* - *remove any unused sub-section* @@ -25,17 +33,3 @@ ## [Attached files](https://help.github.com/articles/issue-attachments) (Screenshots, screencasts, dolibarr.log, debugging informations…) [*Files*] - - - -# Feature Request -[*Short description*] - -## Use case -[*Verbose description*] - -## Suggested implementation -[*Verbose description*] - -## Suggested steps -[*List of tasks to achieve goal*] diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000000..32e2deff2c1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,27 @@ +--- +name: Feature request +about: Suggest a new idea for this project +title: '' +labels: Feature request +assignees: '' + +--- + +# Instructions +*This is a template to help you report good issues. You may use [Github Markdown](https://help.github.com/articles/getting-started-with-writing-and-formatting-on-github/) syntax to format your issue report.* +*Please:* +- *replace the bracket enclosed texts with meaningful information* +- *remove any unused sub-section* + + +# Feature Request +[*Short description*] + +## Use case +[*Verbose description*] + +## Suggested implementation +[*Verbose description*] + +## Suggested steps +[*List of tasks to achieve goal*] diff --git a/.travis.yml b/.travis.yml index 1521035578b..7c1552bb2a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -293,12 +293,12 @@ script: echo - | - echo "Checking coding style" + echo "Checking coding style (excluding Pull Requests builds)" # Ensure we catch errors set -e # Exclusions are defined in the ruleset.xml file #phpcs -s -n -p -d memory_limit=-1 --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 . - phpcs -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true . + if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then phpcs -s -p -d memory_limit=-1 --extensions=php --colors --tab-width=4 --standard=dev/setup/codesniffer/ruleset.xml --encoding=utf-8 --runtime-set ignore_warnings_on_exit true .; fi set +e echo diff --git a/README.md b/README.md index 5d4de0af909..8100cabddbe 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # DOLIBARR ERP & CRM ![Downloads per day](https://img.shields.io/sourceforge/dw/dolibarr.svg) -[![Reviewed by Hound](https://img.shields.io/badge/Reviewed_by-Hound-8E64B0.svg)](https://houndci.com) |7|8|9|10|develop| |----------|----------|----------|----------|----------| @@ -138,7 +137,7 @@ See the [ChangeLog](https://github.com/Dolibarr/dolibarr/blob/develop/ChangeLog) - Multi-company by adding of an external module. - Very user friendly and easy to use. - Highly customizable: enable only the modules you need, add user personalized fields, choose your skin, several menu managers (can be used by internal users as a back-office with a particular menu, or by external users as a front-office with another one) -- Works with PHP 5.3+ and MariaDB 5.0.3+, MySQL 5.0.3+ or PostgreSQL 8.1.4+ (See requirements on the [Wiki](https://wiki.dolibarr.org/index.php/Prerequisite)) +- Works with PHP 5.5+ and MariaDB 5.0.3+, MySQL 5.0.3+ or PostgreSQL 8.1.4+ (See requirements on the [Wiki](https://wiki.dolibarr.org/index.php/Prerequisite)) - Compatible with all Cloud solutions that match MySQL, PHP or PostgreSQL prerequisites. - APIs. - An easy to understand, maintain and develop code (PHP with no heavy framework; trigger and hook architecture) diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 3a39632d783..0d3980318a4 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -121,10 +121,12 @@ class AdherentType extends CommonObject $this->db->begin(); $sql = "INSERT INTO ".MAIN_DB_PREFIX."adherent_type ("; - $sql.= "libelle"; + $sql.= " morphy"; + $sql.= ", libelle"; $sql.= ", entity"; $sql.= ") VALUES ("; - $sql.= "'".$this->db->escape($this->label)."'"; + $sql.= "'".$this->db->escape($this->morphy)."'"; + $sql.= ", '".$this->db->escape($this->label)."'"; $sql.= ", ".$conf->entity; $sql.= ")"; diff --git a/htdocs/admin/system/perf.php b/htdocs/admin/system/perf.php index fbf6fa3bb14..e17756391f1 100644 --- a/htdocs/admin/system/perf.php +++ b/htdocs/admin/system/perf.php @@ -522,9 +522,9 @@ if ($resql) $nb=$obj->nb; if ($nb > $limitforoptim) { - if (empty($conf->global->THIRDPARTY_DONOTSEARCH_ANYWHERE)) + if (empty($conf->global->COMPANY_DONOTSEARCH_ANYWHERE)) { - print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseSearchOptim", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'THIRDPARTY_DONOTSEARCH_ANYWHERE'); + print img_picto('', 'warning.png').' '.$langs->trans("YouHaveXObjectUseSearchOptim", $nb, $langs->transnoentitiesnoconv("ThirdParties"), 'COMPANY_DONOTSEARCH_ANYWHERE'); } else { diff --git a/htdocs/admin/tools/dolibarr_export.php b/htdocs/admin/tools/dolibarr_export.php index c06314daa9a..e07e7999414 100644 --- a/htdocs/admin/tools/dolibarr_export.php +++ b/htdocs/admin/tools/dolibarr_export.php @@ -50,14 +50,23 @@ if (! $user->admin) if ($action == 'delete') { - $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); - $ret=dol_delete_file($file, 1); - if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); - else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); - $action=''; + if (preg_match('/^backup\//', GETPOST('urlfile', 'alpha'))) + { + $file=$conf->admin->dir_output.'/backup/'.basename(GETPOST('urlfile', 'alpha')); + $ret=dol_delete_file($file, 1); + if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); + else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); + } + else + { + $file=$conf->admin->dir_output.'/documents/'.basename(GETPOST('urlfile', 'alpha')); + $ret=dol_delete_file($file, 1); + if ($ret) setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs'); + else setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors'); + } + $action=''; } - /* * View */ diff --git a/htdocs/commande/card.php b/htdocs/commande/card.php index a44054cdfd0..031d2c95235 100644 --- a/htdocs/commande/card.php +++ b/htdocs/commande/card.php @@ -240,6 +240,7 @@ if (empty($reshook)) { $datecommande = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $datelivraison = dol_mktime(12, 0, 0, GETPOST('liv_month'), GETPOST('liv_day'), GETPOST('liv_year')); + $selectedLines = GETPOST('toselect', 'array'); if ($datecommande == '') { setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentities('Date')), null, 'errors'); @@ -346,6 +347,8 @@ if (empty($reshook)) for($i = 0; $i < $num; $i ++) { + if(!in_array($lines[$i]->id, $selectedLines)) continue; // Skip unselected lines + $label = (! empty($lines[$i]->label) ? $lines[$i]->label : ''); $desc = (! empty($lines[$i]->desc) ? $lines[$i]->desc : ''); $product_type = (! empty($lines[$i]->product_type) ? $lines[$i]->product_type : 0); @@ -1758,6 +1761,15 @@ if ($action == 'create' && $usercancreate) $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); print $hookmanager->resPrint; if (empty($reshook)) { + if (! empty($conf->global->THIRDPARTY_PROPAGATE_EXTRAFIELDS_TO_ORDER)) { + // copy from thirdparty + $tpExtrafields = new Extrafields($db); + $tpExtrafieldLabels = $tpExtrafields->fetch_name_optionals_label($soc->table_element); + if ($soc->fetch_optionals() > 0) { + $object->array_options = array_merge($object->array_options, $soc->array_options); + } + }; + print $object->showOptionals($extrafields, 'edit'); } @@ -1872,8 +1884,6 @@ if ($action == 'create' && $usercancreate) print ''; print ''; - print ''; - // Show origin lines if (! empty($origin) && ! empty($originid) && is_object($objectsrc)) { $title = $langs->trans('ProductsAndServices'); @@ -1881,10 +1891,12 @@ if ($action == 'create' && $usercancreate) print ''; - $objectsrc->printOriginLinesList(); + $objectsrc->printOriginLinesList('', $selectedLines); print '
'; } + + print ''; } else { // Mode view $now = dol_now(); diff --git a/htdocs/commande/class/commande.class.php b/htdocs/commande/class/commande.class.php index de93ff778c4..02ea14142fc 100644 --- a/htdocs/commande/class/commande.class.php +++ b/htdocs/commande/class/commande.class.php @@ -365,7 +365,7 @@ class Commande extends CommonOrder // Validate $sql = "UPDATE ".MAIN_DB_PREFIX."commande"; - $sql.= " SET ref = '".$num."',"; + $sql.= " SET ref = '".$this->db->escape($num)."',"; $sql.= " fk_statut = ".self::STATUS_VALIDATED.","; $sql.= " date_valid='".$this->db->idate($now)."',"; $sql.= " fk_user_valid = ".$user->id; diff --git a/htdocs/compta/bank/various_payment/card.php b/htdocs/compta/bank/various_payment/card.php index 67f1e2909fc..aac8f603054 100644 --- a/htdocs/compta/bank/various_payment/card.php +++ b/htdocs/compta/bank/various_payment/card.php @@ -544,16 +544,16 @@ if ($id) { if (! empty($user->rights->banque->modifier)) { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } else { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } } else { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } print ""; diff --git a/htdocs/compta/facture/list.php b/htdocs/compta/facture/list.php index 71e0de738fa..dd3f2add4ba 100644 --- a/htdocs/compta/facture/list.php +++ b/htdocs/compta/facture/list.php @@ -615,7 +615,7 @@ if ($resql) $massactionbutton=$form->selectMassAction('', $arrayofmassactions); $newcardbutton=''; - if($user->rights->facture->creer) + if($user->rights->facture->creer && $contextpage != 'poslist') { $newcardbutton.= dolGetButtonTitle($langs->trans('NewBill'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/compta/facture/card.php?action=create'); } @@ -697,7 +697,7 @@ if ($resql) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields - if ($massactionbutton) $selectedfields.=$form->showCheckAddButtons('checkforselect', 1); + if ($massactionbutton && $contextpage != 'poslist') $selectedfields.=$form->showCheckAddButtons('checkforselect', 1); print '
'; print ''."\n"; @@ -1094,7 +1094,14 @@ if ($resql) if (! empty($arrayfields['s.nom']['checked'])) { print ''; if (! $i) $totalarray['nbfield']++; } @@ -1261,7 +1268,7 @@ if ($resql) // Action column print ''; print ''; print ''; - print ''; + + $parameters=array(); + $reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $facture, $action); // Note that $action and $object may have been modified by hook + + print ''; print "\n"; $total=0; @@ -745,7 +749,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie print ""; $parameters=array(); - $reshook=$hookmanager->executeHooks('printFieldListTitle', $parameters, $objp, $action); // Note that $action and $object may have been modified by hook + $reshook=$hookmanager->executeHooks('printFieldListValue', $parameters, $objp, $action); // Note that $action and $object may have been modified by hook // Warning print ''; } +if (! empty($arrayfields['p.jabberid']['checked'])) +{ + print ''; +} if (! empty($arrayfields['p.twitter']['checked'])) { print ''; print ''; @@ -4203,8 +4204,9 @@ abstract class CommonObject { print ''; } - print ''; - + print ''; + print ''; + print ''; $var = true; $i = 0; @@ -4223,7 +4225,7 @@ abstract class CommonObject } else { - $this->printOriginLine($line, $var, $restrictlist); + $this->printOriginLine($line, $var, $restrictlist, '/core/tpl', $selectedLines); } $i++; @@ -4241,9 +4243,10 @@ abstract class CommonObject * @param string $var Var * @param string $restrictlist ''=All lines, 'services'=Restrict to services only (strike line if not) * @param string $defaulttpldir Directory where to find the template + * @param array $selectedLines Array of lines id for selected lines * @return void */ - public function printOriginLine($line, $var, $restrictlist = '', $defaulttpldir = '/core/tpl') + public function printOriginLine($line, $var, $restrictlist = '', $defaulttpldir = '/core/tpl', $selectedLines = array()) { global $langs, $conf; @@ -4267,6 +4270,8 @@ abstract class CommonObject if ($line->date_fin_reel) $date_end=$line->date_fin_reel; } + $this->tpl['id'] = $line->id; + $this->tpl['label'] = ''; if (! empty($line->fk_parent_line)) $this->tpl['label'].= img_picto('', 'rightarrow'); diff --git a/htdocs/core/class/discount.class.php b/htdocs/core/class/discount.class.php index 678cfe446a0..5cf7e8cdb7a 100644 --- a/htdocs/core/class/discount.class.php +++ b/htdocs/core/class/discount.class.php @@ -629,6 +629,49 @@ class DiscountAbsolute return -1; } } + /** + * Return amount (with tax) of all converted amount for this credit note + * + * @param CommonInvoice $invoice Object invoice + * @param int $multicurrency Return multicurrency_amount instead of amount + * @return int <0 if KO, Sum of credit notes and deposits amount otherwise + */ + public function getSumFromThisCreditNotesNotUsed($invoice, $multicurrency = 0) + { + dol_syslog(get_class($this)."::getSumCreditNotesUsed", LOG_DEBUG); + + if ($invoice->element == 'facture' || $invoice->element == 'invoice') + { + $sql = 'SELECT sum(rc.amount_ttc) as amount, sum(rc.multicurrency_amount_ttc) as multicurrency_amount'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'societe_remise_except as rc'; + $sql.= ' WHERE rc.fk_facture IS NULL AND rc.fk_facture_source = '.$invoice->id; + } + elseif ($invoice->element == 'invoice_supplier') + { + $sql = 'SELECT sum(rc.amount_ttc) as amount, sum(rc.multicurrency_amount_ttc) as multicurrency_amount'; + $sql.= ' FROM '.MAIN_DB_PREFIX.'societe_remise_except as rc'; + $sql.= ' WHERE rc.fk_invoice_supplier IS NULL AND rc.fk_invoice_supplier_source = '.$invoice->id; + } + else + { + $this->error=get_class($this)."::getSumCreditNotesUsed was called with a bad object as a first parameter"; + dol_print_error($this->error); + return -1; + } + + $resql=$this->db->query($sql); + if ($resql) + { + $obj = $this->db->fetch_object($resql); + if ($multicurrency) return $obj->multicurrency_amount; + else return $obj->amount; + } + else + { + $this->error = $this->db->lasterror(); + return -1; + } + } /** * Return clickable ref of object (with picto or not) diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 3a69d8e6d42..5ee969a73a0 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -1887,10 +1887,10 @@ class Form * @param int $forcecombo Force to use combo box * @param string $morecss Add more css on select * @param int $hidepriceinlabel 1=Hide prices in label - * @param string $warehouseStatus warehouse status filter, following comma separated filter options can be used - * 'warehouseopen' = select products from open warehouses, - * 'warehouseclosed' = select products from closed warehouses, - * 'warehouseinternal' = select products from warehouses for internal correct/transfer only + * @param string $warehouseStatus Warehouse status filter to count the quantity in stock. Following comma separated filter options can be used + * 'warehouseopen' = count products from open warehouses, + * 'warehouseclosed' = count products from closed warehouses, + * 'warehouseinternal' = count products from warehouses for internal correct/transfer only * @param array $selected_combinations Selected combinations. Format: array([attrid] => attrval, [...]) * @return void */ @@ -2042,10 +2042,10 @@ class Form * @param int $forcecombo Force to use combo box * @param string $morecss Add more css on select * @param int $hidepriceinlabel 1=Hide prices in label - * @param string $warehouseStatus warehouse status filter, following comma separated filter options can be used - * 'warehouseopen' = select products from open warehouses, - * 'warehouseclosed' = select products from closed warehouses, - * 'warehouseinternal' = select products from warehouses for internal correct/transfer only + * @param string $warehouseStatus Warehouse status filter to group/count stock. Following comma separated filter options can be used. + * 'warehouseopen' = count products from open warehouses, + * 'warehouseclosed' = count products from closed warehouses, + * 'warehouseinternal' = count products from warehouses for internal correct/transfer only * @return array Array of keys for json */ public function select_produits_list($selected = '', $htmlname = 'productid', $filtertype = '', $limit = 20, $price_level = 0, $filterkey = '', $status = 1, $finished = 2, $outputmode = 0, $socid = 0, $showempty = '1', $forcecombo = 0, $morecss = '', $hidepriceinlabel = 0, $warehouseStatus = '') @@ -2075,7 +2075,14 @@ class Form } $selectFields = " p.rowid, p.label, p.ref, p.description, p.barcode, p.fk_product_type, p.price, p.price_ttc, p.price_base_type, p.tva_tx, p.duration, p.fk_price_expression"; - (count($warehouseStatusArray)) ? $selectFieldsGrouped = ", sum(ps.reel) as stock" : $selectFieldsGrouped = ", p.stock"; + if (count($warehouseStatusArray)) + { + $selectFieldsGrouped = ", sum(".$db->ifsql("e.statut IS NULL", "0", "ps.reel").") as stock"; // e.statut is null if there is no record in stock + } + else + { + $selectFieldsGrouped = ", p.stock"; + } $sql = "SELECT "; $sql.= $selectFields . $selectFieldsGrouped; @@ -2126,7 +2133,8 @@ class Form if (count($warehouseStatusArray)) { $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps on ps.fk_product = p.rowid"; - $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid"; + $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot as e on ps.fk_entrepot = e.rowid AND e.entity IN (".getEntity('stock').")"; + $sql.= ' AND e.statut IN ('.$this->db->escape(implode(',', $warehouseStatusArray)).')'; // Return line if product is inside the selected stock. If not, an empty line will be returned so we will count 0. } // include search in supplier ref @@ -2154,10 +2162,6 @@ class Form } $sql.= ' WHERE p.entity IN ('.getEntity('product').')'; - if (count($warehouseStatusArray)) - { - $sql.= ' AND (p.fk_product_type = 1 OR e.statut IN ('.$this->db->escape(implode(',', $warehouseStatusArray)).'))'; - } if (!empty($conf->global->PRODUIT_ATTRIBUTES_HIDECHILD)) { $sql .= " AND pac.rowid IS NULL"; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index f267e572ee4..6ee6007088b 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -5671,7 +5671,7 @@ function dol_string_is_good_iso($s) $ok=1; for($scursor=0;$scursor<$len;$scursor++) { - $ordchar=ord($s{$scursor}); + $ordchar=ord($s[$scursor]); //print $scursor.'-'.$ordchar.'
'; if ($ordchar < 32 && $ordchar != 13 && $ordchar != 10) { $ok=0; break; } if ($ordchar > 126 && $ordchar < 160) { $ok=0; break; } diff --git a/htdocs/core/lib/json.lib.php b/htdocs/core/lib/json.lib.php index 4a8f61915b5..423607fb819 100644 --- a/htdocs/core/lib/json.lib.php +++ b/htdocs/core/lib/json.lib.php @@ -119,7 +119,7 @@ function _val($val) */ for ($c = 0; $c < $strlen_var; ++$c) { - $ord_var_c = ord($val{$c}); + $ord_var_c = ord($val[$c]); switch (true) { case $ord_var_c == 0x08: @@ -142,18 +142,18 @@ function _val($val) case $ord_var_c == 0x2F: case $ord_var_c == 0x5C: // double quote, slash, slosh - $ascii .= '\\'.$val{$c}; + $ascii .= '\\'.$val[$c]; break; case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)): // characters U-00000000 - U-0000007F (same as ASCII) - $ascii .= $val{$c}; + $ascii .= $val[$c]; break; case (($ord_var_c & 0xE0) == 0xC0): // characters U-00000080 - U-000007FF, mask 110XXXXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($val{$c + 1})); + $char = pack('C*', $ord_var_c, ord($val[$c + 1])); $c += 1; $utf16 = utf82utf16($char); $ascii .= sprintf('\u%04s', bin2hex($utf16)); @@ -162,7 +162,7 @@ function _val($val) case (($ord_var_c & 0xF0) == 0xE0): // characters U-00000800 - U-0000FFFF, mask 1110XXXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2})); + $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2])); $c += 2; $utf16 = utf82utf16($char); $ascii .= sprintf('\u%04s', bin2hex($utf16)); @@ -171,7 +171,7 @@ function _val($val) case (($ord_var_c & 0xF8) == 0xF0): // characters U-00010000 - U-001FFFFF, mask 11110XXX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3})); + $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]), ord($val[$c + 3])); $c += 3; $utf16 = utf82utf16($char); $ascii .= sprintf('\u%04s', bin2hex($utf16)); @@ -180,7 +180,7 @@ function _val($val) case (($ord_var_c & 0xFC) == 0xF8): // characters U-00200000 - U-03FFFFFF, mask 111110XX // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3}), ord($val{$c + 4})); + $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]), ord($val[$c + 3]), ord($val[$c + 4])); $c += 4; $utf16 = utf82utf16($char); $ascii .= sprintf('\u%04s', bin2hex($utf16)); @@ -189,7 +189,7 @@ function _val($val) case (($ord_var_c & 0xFE) == 0xFC): // characters U-04000000 - U-7FFFFFFF, mask 1111110X // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 - $char = pack('C*', $ord_var_c, ord($val{$c + 1}), ord($val{$c + 2}), ord($val{$c + 3}), ord($val{$c + 4}), ord($val{$c + 5})); + $char = pack('C*', $ord_var_c, ord($val[$c + 1]), ord($val[$c + 2]), ord($val[$c + 3]), ord($val[$c + 4]), ord($val[$c + 5])); $c += 5; $utf16 = utf82utf16($char); $ascii .= sprintf('\u%04s', bin2hex($utf16)); diff --git a/htdocs/core/modules/modAdherent.class.php b/htdocs/core/modules/modAdherent.class.php index 827928af6b6..300f071de1e 100644 --- a/htdocs/core/modules/modAdherent.class.php +++ b/htdocs/core/modules/modAdherent.class.php @@ -181,7 +181,10 @@ class modAdherent extends DolibarrModules // Boxes //------- - $this->boxes = array(0=>array('file'=>'box_members.php','enabledbydefaulton'=>'Home')); + $this->boxes = array( + 0=>array('file'=>'box_members.php','enabledbydefaulton'=>'Home'), + 2=>array('file'=>'box_birthdays_members.php','enabledbydefaulton'=>'Home') + ); // Permissions //------------ diff --git a/htdocs/core/modules/oauth/stripelive_oauthcallback.php b/htdocs/core/modules/oauth/stripelive_oauthcallback.php index cf2c2418092..a32223105b9 100644 --- a/htdocs/core/modules/oauth/stripelive_oauthcallback.php +++ b/htdocs/core/modules/oauth/stripelive_oauthcallback.php @@ -17,7 +17,7 @@ */ /** - * \file htdocs/core/modules/oauth/stripe_oauthcallback.php + * \file htdocs/core/modules/oauth/stripelive_oauthcallback.php * \ingroup oauth * \brief Page to get oauth callback */ @@ -45,7 +45,7 @@ $backtourl = GETPOST('backtourl', 'alpha'); $uriFactory = new \OAuth\Common\Http\Uri\UriFactory(); //$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); //$currentUri->setQuery(''); -$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/stripe_oauthcallback.php'); +$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/stripelive_oauthcallback.php'); /** @@ -65,7 +65,7 @@ $storage = new DoliStorage($db, $conf); // Setup the credentials for the requests $credentials = new Credentials( - $conf->global->OAUTH_STRIPE_TEST_ID, + $conf->global->OAUTH_STRIPE_LIVE_ID, $conf->global->STRIPE_LIVE_SECRET_KEY, $currentUri->getAbsoluteUri() ); diff --git a/htdocs/core/modules/oauth/stripetest_oauthcallback.php b/htdocs/core/modules/oauth/stripetest_oauthcallback.php index eb7463749ae..55b532f231c 100644 --- a/htdocs/core/modules/oauth/stripetest_oauthcallback.php +++ b/htdocs/core/modules/oauth/stripetest_oauthcallback.php @@ -17,7 +17,7 @@ */ /** - * \file htdocs/core/modules/oauth/stripe_oauthcallback.php + * \file htdocs/core/modules/oauth/stripetest_oauthcallback.php * \ingroup oauth * \brief Page to get oauth callback */ @@ -45,7 +45,7 @@ $backtourl = GETPOST('backtourl', 'alpha'); $uriFactory = new \OAuth\Common\Http\Uri\UriFactory(); //$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER); //$currentUri->setQuery(''); -$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/stripe_oauthcallback.php'); +$currentUri = $uriFactory->createFromAbsolute($urlwithroot.'/core/modules/oauth/stripetest_oauthcallback.php'); /** diff --git a/htdocs/core/tpl/contacts.tpl.php b/htdocs/core/tpl/contacts.tpl.php index 3830e2bc31a..1f7d403b575 100644 --- a/htdocs/core/tpl/contacts.tpl.php +++ b/htdocs/core/tpl/contacts.tpl.php @@ -69,7 +69,7 @@ $userstatic=new User($db); if ($permission) { ?> -
trans("Nature"); ?>
+
trans("NatureOfContact"); ?>
trans("ThirdParty"); ?>
trans("Users").'/'.$langs->trans("Contacts"); ?>
trans("ContactType"); ?>
@@ -149,7 +149,7 @@ if ($permission) { ?> -
trans("Nature"); ?>
+
trans("NatureOfContact"); ?>
trans("ThirdParty"); ?>
trans("Users").'/'.$langs->trans("Contacts"); ?>
trans("ContactType"); ?>
diff --git a/htdocs/core/tpl/originproductline.tpl.php b/htdocs/core/tpl/originproductline.tpl.php index 2f0accd6306..e29ea678282 100644 --- a/htdocs/core/tpl/originproductline.tpl.php +++ b/htdocs/core/tpl/originproductline.tpl.php @@ -40,6 +40,10 @@ if($conf->global->PRODUCT_USE_UNITS) print ''; print ''; + +$selected=1; +if (!empty($selectedLines) && !in_array($this->tpl['id'], $selectedLines)) $selected=0; +print ''; print ''."\n"; ?> diff --git a/htdocs/fourn/class/fournisseur.facture.class.php b/htdocs/fourn/class/fournisseur.facture.class.php index b1c623bb0f0..a3e6666f412 100644 --- a/htdocs/fourn/class/fournisseur.facture.class.php +++ b/htdocs/fourn/class/fournisseur.facture.class.php @@ -2680,6 +2680,27 @@ class FactureFournisseur extends CommonInvoice return ($this->statut == self::STATUS_VALIDATED) && ($this->date_echeance < ($now - $conf->facture->fournisseur->warning_delay)); } + + /** + * Is credit note used + * + * @return bool + */ + public function isCreditNoteUsed() + { + global $db; + + $isUsed = false; + + $sql = "SELECT fk_invoice_supplier FROM ".MAIN_DB_PREFIX."societe_remise_except WHERE fk_invoice_supplier_source=".$this->id; + $resql = $db->query($sql); + if(!empty($resql)){ + $obj = $db->fetch_object($resql); + if(!empty($obj->fk_invoice_supplier))$isUsed=true; + } + + return $isUsed; + } } diff --git a/htdocs/fourn/facture/list.php b/htdocs/fourn/facture/list.php index b18af4c3f19..c8a5ab2fec7 100644 --- a/htdocs/fourn/facture/list.php +++ b/htdocs/fourn/facture/list.php @@ -1,6 +1,6 @@ - * Copyright (C) 2004-2016 Laurent Destailleur + * Copyright (C) 2004-2019 Laurent Destailleur * Copyright (C) 2005-2013 Regis Houssin * Copyright (C) 2013-2019 Philippe Grand * Copyright (C) 2013 Florian Henry @@ -588,14 +588,14 @@ if ($resql) if (! empty($arrayfields['f.ref']['checked'])) { print ''; } // Ref supplier if (! empty($arrayfields['f.ref_supplier']['checked'])) { print ''; } // Type @@ -622,7 +622,7 @@ if ($resql) if (! empty($arrayfields['f.label']['checked'])) { print ''; } // Date invoice @@ -647,17 +647,17 @@ if ($resql) // Project if (! empty($arrayfields['p.ref']['checked'])) { - print ''; + print ''; } // Thirpdarty if (! empty($arrayfields['s.nom']['checked'])) { - print ''; + print ''; } // Town - if (! empty($arrayfields['s.town']['checked'])) print ''; + if (! empty($arrayfields['s.town']['checked'])) print ''; // Zip - if (! empty($arrayfields['s.zip']['checked'])) print ''; + if (! empty($arrayfields['s.zip']['checked'])) print ''; // State if (! empty($arrayfields['state.nom']['checked'])) { @@ -688,35 +688,35 @@ if ($resql) } if (! empty($arrayfields['f.total_ht']['checked'])) { - // Amount + // Amount without tax print ''; } if (! empty($arrayfields['f.total_vat']['checked'])) { - // Amount + // Amount vat print ''; } if (! empty($arrayfields['f.total_localtax1']['checked'])) { - // Amount + // Amount tax 1 print ''; } if (! empty($arrayfields['f.total_localtax2']['checked'])) { - // Amount + // Amount tax 2 print ''; } if (! empty($arrayfields['f.total_ttc']['checked'])) { - // Amount + // Amount inc tac print ''; @@ -776,7 +776,7 @@ if ($resql) if (! empty($arrayfields['p.ref']['checked'])) print_liste_field_titre($arrayfields['p.ref']['label'], $_SERVER['PHP_SELF'], "p.ref", '', $param, '', $sortfield, $sortorder); if (! empty($arrayfields['s.nom']['checked'])) print_liste_field_titre($arrayfields['s.nom']['label'], $_SERVER['PHP_SELF'], 's.nom', '', $param, '', $sortfield, $sortorder); if (! empty($arrayfields['s.town']['checked'])) print_liste_field_titre($arrayfields['s.town']['label'], $_SERVER["PHP_SELF"], 's.town', '', $param, '', $sortfield, $sortorder); - if (! empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder); + if (! empty($arrayfields['s.zip']['checked'])) print_liste_field_titre($arrayfields['s.zip']['label'], $_SERVER["PHP_SELF"], 's.zip', '', $param, '', $sortfield, $sortorder, 'center '); if (! empty($arrayfields['state.nom']['checked'])) print_liste_field_titre($arrayfields['state.nom']['label'], $_SERVER["PHP_SELF"], "state.nom", "", $param, '', $sortfield, $sortorder); if (! empty($arrayfields['country.code_iso']['checked'])) print_liste_field_titre($arrayfields['country.code_iso']['label'], $_SERVER["PHP_SELF"], "country.code_iso", "", $param, '', $sortfield, $sortorder, 'center '); if (! empty($arrayfields['typent.code']['checked'])) print_liste_field_titre($arrayfields['typent.code']['label'], $_SERVER["PHP_SELF"], "typent.code", "", $param, '', $sortfield, $sortorder, 'center '); @@ -820,6 +820,7 @@ if ($resql) $facturestatic->date_echeance = $db->jdate($obj->datelimite); $facturestatic->statut = $obj->fk_statut; + $thirdparty->id=$obj->socid; $thirdparty->name=$obj->name; $thirdparty->client=$obj->client; @@ -837,6 +838,14 @@ if ($resql) $totalpay = $paiement + $totalcreditnotes + $totaldeposits; $remaintopay = $obj->total_ttc - $totalpay; + //If invoice has been converted and the conversion has been used, we dont have remain to pay on invoice + if($facturestatic->type == FactureFournisseur::TYPE_CREDIT_NOTE) { + + if($facturestatic->isCreditNoteUsed()){ + $remaintopay=-$facturestatic->getSumFromThisCreditNotesNotUsed(); + } + } + print ''; if (! empty($arrayfields['f.ref']['checked'])) { @@ -944,7 +953,7 @@ if ($resql) // Zip if (! empty($arrayfields['s.zip']['checked'])) { - print ''; if (! $i) $totalarray['nbfield']++; diff --git a/htdocs/install/inc.php b/htdocs/install/inc.php index 2e7099d84b8..c8dc7fd4382 100644 --- a/htdocs/install/inc.php +++ b/htdocs/install/inc.php @@ -258,9 +258,6 @@ $langs = new Translate('..', $conf); if (GETPOST('lang', 'aZ09')) $langs->setDefaultLang(GETPOST('lang', 'aZ09')); else $langs->setDefaultLang('auto'); -$bc[false]=' class="bg1"'; -$bc[true]=' class="bg2"'; - /** * Load conf file (file must exists) diff --git a/htdocs/langs/en_US/cashdesk.lang b/htdocs/langs/en_US/cashdesk.lang index 628de17efcc..33ea50dfb0f 100644 --- a/htdocs/langs/en_US/cashdesk.lang +++ b/htdocs/langs/en_US/cashdesk.lang @@ -62,6 +62,7 @@ TicketVatGrouped=Group VAT by rate in tickets AutoPrintTickets=Automatically print tickets EnableBarOrRestaurantFeatures=Enable features for Bar or Restaurant ConfirmDeletionOfThisPOSSale=Do your confirm the deletion of this current sale ? +ConfirmDiscardOfThisPOSSale=Do you want to discard this current sale ? History=History ValidateAndClose=Validate and close Terminal=Terminal @@ -72,3 +73,5 @@ BasicPhoneLayout=Use basic layout for phones SetupOfTerminalNotComplete=Setup of terminal %s is not complete DirectPayment=Direct payment DirectPaymentButton=Direct cash payment button +InvoiceIsAlreadyValidated=Invoice is already validated +NoLinesToBill=No lines to bill diff --git a/htdocs/langs/en_US/companies.lang b/htdocs/langs/en_US/companies.lang index 616b565496a..dccd53c597a 100644 --- a/htdocs/langs/en_US/companies.lang +++ b/htdocs/langs/en_US/companies.lang @@ -54,6 +54,7 @@ Firstname=First name PostOrFunction=Job position UserTitle=Title NatureOfThirdParty=Nature of Third party +NatureOfContact=Nature of Contact Address=Address State=State/Province StateShort=State diff --git a/htdocs/loan/card.php b/htdocs/loan/card.php index e826e86ea57..2ba29aef106 100644 --- a/htdocs/loan/card.php +++ b/htdocs/loan/card.php @@ -179,11 +179,12 @@ if (empty($reshook)) } else { - $object->datestart = $datestart; - $object->dateend = $dateend; - $object->capital = $capital; - $object->nbterm = GETPOST("nbterm", 'int'); - $object->rate = price2num(GETPOST("rate", 'alpha')); + $object->datestart = $datestart; + $object->dateend = $dateend; + $object->capital = $capital; + $object->nbterm = GETPOST("nbterm", 'int'); + $object->rate = price2num(GETPOST("rate", 'alpha')); + $object->insurance_amount = price2num(GETPOST('insurance_amount', 'int')); $accountancy_account_capital = GETPOST('accountancy_account_capital'); $accountancy_account_insurance = GETPOST('accountancy_account_insurance'); @@ -793,25 +794,25 @@ if ($id > 0) { // print ''.$langs->trans('CreateCalcSchedule').''; - print ''.$langs->trans("Modify").''; + print '
'.$langs->trans("Modify").'
'; } // Emit payment if ($object->paid == 0 && ((price2num($object->capital) > 0 && round($staytopay) < 0) || (price2num($object->capital) > 0 && round($staytopay) > 0)) && $user->rights->loan->write) { - print ''.$langs->trans("DoPayment").''; + print '
'.$langs->trans("DoPayment").'
'; } // Classify 'paid' if ($object->paid == 0 && round($staytopay) <=0 && $user->rights->loan->write) { - print ''.$langs->trans("ClassifyPaid").''; + print '
'.$langs->trans("ClassifyPaid").'
'; } // Delete if ($object->paid == 0 && $user->rights->loan->delete) { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } print ""; diff --git a/htdocs/product/stock/class/entrepot.class.php b/htdocs/product/stock/class/entrepot.class.php index e857166e392..18d17f9acf0 100644 --- a/htdocs/product/stock/class/entrepot.class.php +++ b/htdocs/product/stock/class/entrepot.class.php @@ -686,6 +686,8 @@ class Entrepot extends CommonObject $label.= '
' . $langs->trans('Ref') . ': ' . (empty($this->ref)?(empty($this->label)?$this->libelle:$this->label):$this->ref); if (! empty($this->lieu)) $label.= '
' . $langs->trans('LocationSummary').': '.$this->lieu; + if (isset($this->statut)) + $label.= '
' . $langs->trans("Status").": ".$this->getLibStatut(5); $url = DOL_URL_ROOT.'/product/stock/card.php?id='.$this->id; diff --git a/htdocs/product/stock/list.php b/htdocs/product/stock/list.php index 8e19242d1c1..9426d2041b0 100644 --- a/htdocs/product/stock/list.php +++ b/htdocs/product/stock/list.php @@ -104,13 +104,19 @@ $form=new Form($db); $warehouse=new Entrepot($db); $sql = "SELECT e.rowid, e.ref, e.statut, e.lieu, e.address, e.zip, e.town, e.fk_pays, e.fk_parent,"; -$sql.= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue, SUM(ps.reel) as stockqty"; +$sql.= " SUM(p.pmp * ps.reel) as estimatedvalue, SUM(p.price * ps.reel) as sellvalue, SUM(ps.reel) as stockqty,"; // Add fields from extrafields -foreach ($extrafields->attribute_label as $key => $val) $sql.=($extrafields->attribute_type[$key] != 'separate' ? ", ef.".$key.' as options_'.$key : ''); +if (! empty($extrafields->attributes[$object->table_element]['label'])) + foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) $sql.=($extrafields->attributes[$object->table_element]['type'][$key] != 'separate' ? "ef.".$key.' as options_'.$key.', ' : ''); +// Add fields from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListSelect', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; +$sql=preg_replace('/, $/', '', $sql); $sql.= " FROM ".MAIN_DB_PREFIX."entrepot as e"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product_stock as ps ON e.rowid = ps.fk_entrepot"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON ps.fk_product = p.rowid"; -if (is_array($extrafields->attribute_label) && count($extrafields->attribute_label)) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."entrepot_extrafields as ef on (e.rowid = ef.fk_object)"; +if (is_array($extrafields->attributes[$object->table_element]['label']) && count($extrafields->attributes[$object->table_element]['label'])) $sql.= " LEFT JOIN ".MAIN_DB_PREFIX.$object->table_element."_extrafields as ef on (e.rowid = ef.fk_object)"; $sql.= " WHERE e.entity IN (".getEntity('stock').")"; if ($search_ref) $sql.= natural_search("e.ref", $search_ref); // ref if ($search_label) $sql.= natural_search("e.lieu", $search_label); // label @@ -118,6 +124,10 @@ if ($search_status != '' && $search_status >= 0) $sql.= " AND e.statut = ".$sear if ($sall) $sql .= natural_search(array_keys($fieldstosearchall), $sall); // Add where from extra fields include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_list_search_sql.tpl.php'; +// Add where from hooks +$parameters=array(); +$reshook=$hookmanager->executeHooks('printFieldListWhere', $parameters, $object); // Note that $action and $object may have been modified by hook +$sql.=$hookmanager->resPrint; $sql.= " GROUP BY e.rowid, e.ref, e.statut, e.lieu, e.address, e.zip, e.town, e.fk_pays, e.fk_parent"; $totalnboflines=0; $result=$db->query($sql); @@ -241,6 +251,7 @@ if ($result) $warehouse->label = $obj->ref; $warehouse->lieu = $obj->lieu; $warehouse->fk_parent = $obj->fk_parent; + $warehouse->statut = $obj->statut; print ''; print ''; diff --git a/htdocs/product/stock/movement_list.php b/htdocs/product/stock/movement_list.php index f62b732cf7e..149804ee966 100644 --- a/htdocs/product/stock/movement_list.php +++ b/htdocs/product/stock/movement_list.php @@ -420,7 +420,7 @@ $formproduct=new FormProduct($db); if (!empty($conf->projet->enabled)) $formproject=new FormProjets($db); $sql = "SELECT p.rowid, p.ref as product_ref, p.label as produit, p.tobatch, p.fk_product_type as type, p.entity,"; -$sql.= " e.ref as stock, e.rowid as entrepot_id, e.lieu,"; +$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.batch, m.price,"; $sql.= " m.type_mouvement,"; @@ -988,8 +988,12 @@ if ($resql) $productlot->sellby= $objp->sellby; $warehousestatic->id=$objp->entrepot_id; - $warehousestatic->libelle=$objp->stock; + $warehousestatic->ref=$objp->warehouse_ref; + $warehousestatic->libelle=$objp->warehouse_ref; + $warehousestatic->label=$objp->warehouse_ref; $warehousestatic->lieu=$objp->lieu; + $warehousestatic->fk_parent = $objp->fk_parent; + $warehousestatic->statut = $objp->statut; $arrayofuniqueproduct[$objp->rowid]=$objp->produit; if(!empty($objp->fk_origin)) { diff --git a/htdocs/product/stock/product.php b/htdocs/product/stock/product.php index 2c0515d309c..41c9b151865 100644 --- a/htdocs/product/stock/product.php +++ b/htdocs/product/stock/product.php @@ -827,7 +827,7 @@ if (! $variants) { print ''; } - $sql = "SELECT e.rowid, e.ref as label, e.lieu, ps.reel, ps.rowid as product_stock_id, p.pmp"; + $sql = "SELECT e.rowid, e.ref, e.lieu, e.fk_parent, e.statut, ps.reel, ps.rowid as product_stock_id, p.pmp"; $sql .= " FROM " . MAIN_DB_PREFIX . "entrepot as e,"; $sql .= " " . MAIN_DB_PREFIX . "product_stock as ps"; $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON p.rowid = ps.fk_product"; @@ -851,9 +851,15 @@ if (! $variants) { $var = false; while ($i < $num) { $obj = $db->fetch_object($resql); + $entrepotstatic->id = $obj->rowid; - $entrepotstatic->libelle = $obj->label; + $entrepotstatic->ref = $obj->ref; + $entrepotstatic->libelle = $obj->ref; + $entrepotstatic->label = $obj->ref; $entrepotstatic->lieu = $obj->lieu; + $entrepotstatic->fk_parent = $obj->fk_parent; + $entrepotstatic->statut = $obj->statut; + $stock_real = price2num($obj->reel, 'MS'); print ''; print ''; diff --git a/htdocs/projet/index.php b/htdocs/projet/index.php index 14d9fa2e483..f29ce739b30 100644 --- a/htdocs/projet/index.php +++ b/htdocs/projet/index.php @@ -266,7 +266,7 @@ $sql = "SELECT COUNT(p.rowid) as nb, SUM(p.opp_amount)"; $sql.= ", s.nom as name, s.rowid as socid"; $sql.= " FROM ".MAIN_DB_PREFIX."projet as p"; $sql.= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s on p.fk_soc = s.rowid"; -$sql.= " WHERE p.entity IN (".getEntity('project', $conf->entity).")"; +$sql.= " WHERE p.entity IN (".getEntity('project').")"; $sql.= " AND p.fk_statut = 1"; if ($mine || empty($user->rights->projet->all->lire)) $sql.= " AND p.rowid IN (".$projectsListId.")"; // If we have this test true, it also means projectset is not 2 if ($socid) $sql.= " AND (p.fk_soc IS NULL OR p.fk_soc = 0 OR p.fk_soc = ".$socid.")"; diff --git a/htdocs/salaries/card.php b/htdocs/salaries/card.php index 5028dae747e..31dcd83db91 100644 --- a/htdocs/salaries/card.php +++ b/htdocs/salaries/card.php @@ -482,16 +482,16 @@ if ($id) { if (! empty($user->rights->salaries->delete)) { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } else { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } } else { - print ''.$langs->trans("Delete").''; + print '
'.$langs->trans("Delete").'
'; } print ""; } diff --git a/htdocs/societe/class/societe.class.php b/htdocs/societe/class/societe.class.php index 01770e1bee1..374cebb8583 100644 --- a/htdocs/societe/class/societe.class.php +++ b/htdocs/societe/class/societe.class.php @@ -3884,7 +3884,7 @@ class Societe extends CommonObject $alreadypayed=price2num($paiement + $creditnotes + $deposits,'MT'); $remaintopay=price2num($invoice->total_ttc - $paiement - $creditnotes - $deposits,'MT'); */ - if ($mode == 'supplier') $sql = "SELECT rowid, total_ht as total_ht, total_ttc, paye, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; + if ($mode == 'supplier') $sql = "SELECT rowid, total_ht as total_ht, total_ttc, paye, type, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; else $sql = "SELECT rowid, total as total_ht, total_ttc, paye, fk_statut, close_code FROM ".MAIN_DB_PREFIX.$table." as f"; $sql .= " WHERE fk_soc = ". $this->id; if ($mode == 'supplier') { @@ -3911,7 +3911,11 @@ class Societe extends CommonObject $tmpobject=new Facture($this->db); } while($obj=$this->db->fetch_object($resql)) { - $tmpobject->id=$obj->rowid; + $tmpobject->id=$obj->rowid; + + + + if ($obj->fk_statut != 0 // Not a draft && ! ($obj->fk_statut == 3 && $obj->close_code == 'replaced') // Not a replaced invoice ) @@ -3928,8 +3932,12 @@ class Societe extends CommonObject $paiement = $tmpobject->getSommePaiement(); $creditnotes = $tmpobject->getSumCreditNotesUsed(); $deposits = $tmpobject->getSumDepositsUsed(); + $outstandingOpened+=$obj->total_ttc - $paiement - $creditnotes - $deposits; } + + //if credit note is converted but not used + if($mode == 'supplier' && $obj->type == FactureFournisseur::TYPE_CREDIT_NOTE && $tmpobject->isCreditNoteUsed())$outstandingOpened-=$tmpobject->getSumFromThisCreditNotesNotUsed(); } return array('opened'=>$outstandingOpened, 'total_ht'=>$outstandingTotal, 'total_ttc'=>$outstandingTotalIncTax); // 'opened' is 'incl taxes' } diff --git a/htdocs/societe/list.php b/htdocs/societe/list.php index 2ab86d454f0..f69c92da51a 100644 --- a/htdocs/societe/list.php +++ b/htdocs/societe/list.php @@ -199,7 +199,7 @@ $arrayfields=array( 's.idprof5'=>array('label'=>"ProfId5Short", 'checked'=>$checkedprofid5), 's.idprof6'=>array('label'=>"ProfId6Short", 'checked'=>$checkedprofid6), 's.tva_intra'=>array('label'=>"VATIntraShort", 'checked'=>0), - 'customerorsupplier'=>array('label'=>'Nature', 'checked'=>1), + 'customerorsupplier'=>array('label'=>'NatureOfThirdParty', 'checked'=>1), 's.fk_prospectlevel'=>array('label'=>"ProspectLevelShort", 'checked'=>$checkprospectlevel), 's.fk_stcomm'=>array('label'=>"StatusProsp", 'checked'=>$checkstcomm), 's2.nom'=>array('label'=>'ParentCompany', 'checked'=>0), @@ -670,7 +670,7 @@ if ($moreforfilter) $varpage=empty($contextpage)?$_SERVER["PHP_SELF"]:$contextpage; $selectedfields=$form->multiSelectArrayWithCheckbox('selectedfields', $arrayfields, $varpage); // This also change content of $arrayfields -if ($massactionbutton) $selectedfields.=$form->showCheckAddButtons('checkforselect', 1); +if ($massactionbutton && $contextpage != 'poslist') $selectedfields.=$form->showCheckAddButtons('checkforselect', 1); if (empty($arrayfields['customerorsupplier']['checked'])) print ''; @@ -1288,7 +1288,7 @@ while ($i < min($num, $limit)) // Action column print ''; + $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); + if (! in_array($cpt->currency, $arrayzerounitcurrency)) $amount = $cpt->amount / 100; + else $amount = $cpt->amount; + print ''; } } @@ -1267,7 +1327,10 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' { foreach ($balance->pending as $cpt) { - print ''; + $arrayzerounitcurrency=array('BIF', 'CLP', 'DJF', 'GNF', 'JPY', 'KMF', 'KRW', 'MGA', 'PYG', 'RWF', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'); + if (! in_array($cpt->currency, $arrayzerounitcurrency)) $amount = $cpt->amount / 100; + else $amount = $cpt->amount; + print ''; } } print '
'; - print $thirdpartystatic->getNomUrl(1, 'customer'); + if ($contextpage == 'poslist') + { + print $thirdpartystatic->name; + } + else + { + print $thirdpartystatic->getNomUrl(1, 'customer'); + } print ''; - if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + if (($massactionbutton || $massaction) && $contextpage != 'poslist') // 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->id, $arrayofselected)) $selected=1; diff --git a/htdocs/compta/paiement.php b/htdocs/compta/paiement.php index 30c31109224..e8fceebb03c 100644 --- a/htdocs/compta/paiement.php +++ b/htdocs/compta/paiement.php @@ -539,7 +539,7 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie $sql = 'SELECT f.rowid as facid, f.ref, f.total_ttc, f.multicurrency_code, f.multicurrency_total_ttc, f.type,'; $sql.= ' f.datef as df, f.fk_soc as socid, f.date_lim_reglement as dlr'; $sql.= ' FROM '.MAIN_DB_PREFIX.'facture as f'; - $sql.= ' WHERE f.entity IN ('.getEntity('invoice', $conf->entity).')'; + $sql.= ' WHERE f.entity IN ('.getEntity('facture').')'; $sql.= ' AND (f.fk_soc = '.$facture->socid; // Can pay invoices of all child of parent company if(!empty($conf->global->FACTURE_PAYMENTS_ON_DIFFERENT_THIRDPARTIES_BILLS) && !empty($facture->thirdparty->parent)) { @@ -597,7 +597,11 @@ if ($action == 'create' || $action == 'confirm_paiement' || $action == 'add_paie print ''.$alreadypayedlabel.''.$remaindertopay.''.$langs->trans('PaymentAmount').'  
'; diff --git a/htdocs/compta/sociales/card.php b/htdocs/compta/sociales/card.php index 0318efb7e1a..9e68e6e79a3 100644 --- a/htdocs/compta/sociales/card.php +++ b/htdocs/compta/sociales/card.php @@ -710,37 +710,37 @@ if ($id > 0) // Reopen if ($object->paye && $user->rights->tax->charges->creer) { - print "id&action=reopen\">".$langs->trans("ReOpen").""; + print ""; } // Edit if ($object->paye == 0 && $user->rights->tax->charges->creer) { - print "id&action=edit\">".$langs->trans("Modify").""; + print ""; } // Emit payment if ($object->paye == 0 && ((price2num($object->amount) < 0 && price2num($resteapayer, 'MT') < 0) || (price2num($object->amount) > 0 && price2num($resteapayer, 'MT') > 0)) && $user->rights->tax->charges->creer) { - print "id&action=create\">".$langs->trans("DoPayment").""; + print ""; } // Classify 'paid' if ($object->paye == 0 && round($resteapayer) <=0 && $user->rights->tax->charges->creer) { - print "id&action=paid\">".$langs->trans("ClassifyPaid").""; + print ""; } // Clone if ($user->rights->tax->charges->creer) { - print "id&action=clone\">".$langs->trans("ToClone").""; + print ""; } // Delete if ($user->rights->tax->charges->supprimer) { - print "id&action=delete\">".$langs->trans("Delete").""; + print ""; } print ""; diff --git a/htdocs/compta/sociales/class/chargesociales.class.php b/htdocs/compta/sociales/class/chargesociales.class.php index 4fd157de9e6..c3914ae79db 100644 --- a/htdocs/compta/sociales/class/chargesociales.class.php +++ b/htdocs/compta/sociales/class/chargesociales.class.php @@ -317,7 +317,7 @@ class ChargeSociales extends CommonObject $sql.= ", date_ech='".$this->db->idate($this->date_ech)."'"; $sql.= ", periode='".$this->db->idate($this->periode)."'"; $sql.= ", amount='".price2num($this->amount, 'MT')."'"; - $sql.= ", fk_projet=".($this->fk_project > 0 ? $this->fk_project : null); + $sql.= ", fk_projet=".($this->fk_project>0?$this->db->escape($this->fk_project):"NULL"); $sql.= ", fk_user_modif=".$user->id; $sql.= " WHERE rowid=".$this->id; diff --git a/htdocs/compta/tva/card.php b/htdocs/compta/tva/card.php index be738b374cf..759ed75df5e 100644 --- a/htdocs/compta/tva/card.php +++ b/htdocs/compta/tva/card.php @@ -385,16 +385,16 @@ if ($id) { if (! empty($user->rights->tax->charges->supprimer)) { - print ''.$langs->trans("Delete").''; + print ''; } else { - print ''.$langs->trans("Delete").''; + print ''; } } else { - print ''.$langs->trans("Delete").''; + print ''; } print ""; } diff --git a/htdocs/contact/list.php b/htdocs/contact/list.php index fa26c5ed30b..b0db8b0affb 100644 --- a/htdocs/contact/list.php +++ b/htdocs/contact/list.php @@ -165,8 +165,8 @@ $arrayfields=array( 'p.fax'=>array('label'=>"Fax", 'checked'=>0), 'p.email'=>array('label'=>"EMail", 'checked'=>1), 'p.no_email'=>array('label'=>"No_Email", 'checked'=>0, 'enabled'=>(! empty($conf->mailing->enabled))), - 'p.jabberid'=>array('label'=>"Jabber", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), 'p.skype'=>array('label'=>"Skype", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), + 'p.jabberid'=>array('label'=>"Jabber", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), 'p.twitter'=>array('label'=>"Twitter", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), 'p.facebook'=>array('label'=>"Facebook", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), 'p.linkedin'=>array('label'=>"LinkedIn", 'checked'=>1, 'enabled'=>(! empty($conf->socialnetworks->enabled))), @@ -427,7 +427,7 @@ if ($search_societe != '') $param.='&search_societe='.urlencode($search_soci if ($search_zip != '') $param.='&search_zip='.urlencode($search_zip); if ($search_town != '') $param.='&search_town='.urlencode($search_town); if ($search_country != '') $param.= "&search_country=".urlencode($search_country); -if ($search_job != '') $param.='&search_job='.urlencode($search_job); +if ($search_poste != '') $param.='&search_poste='.urlencode($search_poste); if ($search_phone_pro != '') $param.='&search_phone_pro='.urlencode($search_phone_pro); if ($search_phone_perso != '') $param.='&search_phone_perso='.urlencode($search_phone_perso); if ($search_phone_mobile != '') $param.='&search_phone_mobile='.urlencode($search_phone_mobile); @@ -629,6 +629,12 @@ if (! empty($arrayfields['p.skype']['checked'])) print ''; print ''; + print ''; + print ''; @@ -720,6 +726,7 @@ if (! empty($arrayfields['p.fax']['checked'])) print_liste_field if (! empty($arrayfields['p.email']['checked'])) print_liste_field_titre($arrayfields['p.email']['label'], $_SERVER["PHP_SELF"], "p.email", $begin, $param, '', $sortfield, $sortorder); if (! empty($arrayfields['p.no_email']['checked'])) print_liste_field_titre($arrayfields['p.no_email']['label'], $_SERVER["PHP_SELF"], "p.no_email", $begin, $param, '', $sortfield, $sortorder, 'center '); if (! empty($arrayfields['p.skype']['checked'])) print_liste_field_titre($arrayfields['p.skype']['label'], $_SERVER["PHP_SELF"], "p.skype", $begin, $param, '', $sortfield, $sortorder); +if (! empty($arrayfields['p.jabberid']['checked'])) print_liste_field_titre($arrayfields['p.jabberid']['label'], $_SERVER["PHP_SELF"], "p.jabberid", $begin, $param, '', $sortfield, $sortorder); if (! empty($arrayfields['p.twitter']['checked'])) print_liste_field_titre($arrayfields['p.twitter']['label'], $_SERVER["PHP_SELF"], "p.twitter", $begin, $param, '', $sortfield, $sortorder); if (! empty($arrayfields['p.facebook']['checked'])) print_liste_field_titre($arrayfields['p.facebook']['label'], $_SERVER["PHP_SELF"], "p.facebook", $begin, $param, '', $sortfield, $sortorder); if (! empty($arrayfields['p.linkedin']['checked'])) print_liste_field_titre($arrayfields['p.linkedin']['label'], $_SERVER["PHP_SELF"], "p.linkedin", $begin, $param, '', $sortfield, $sortorder); diff --git a/htdocs/core/boxes/box_birthdays_members.php b/htdocs/core/boxes/box_birthdays_members.php new file mode 100644 index 00000000000..6a36bc01ae4 --- /dev/null +++ b/htdocs/core/boxes/box_birthdays_members.php @@ -0,0 +1,163 @@ + + * Copyright (C) 2004-2010 Laurent Destailleur + * Copyright (C) 2005-2009 Regis Houssin + * Copyright (C) 2015 Frederic France + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/core/boxes/box_adherent_birthdays.php + * \ingroup member + * \brief Box for member birthdays + */ + +include_once DOL_DOCUMENT_ROOT.'/core/boxes/modules_boxes.php'; + + +/** + * Class to manage the box to show user birthdays + */ +class box_birthdays_members extends ModeleBoxes +{ + public $boxcode="birthdays_members"; + public $boximg="object_user"; + public $boxlabel="BoxBirthdaysMembers"; + public $depends = array("adherent"); + + /** + * @var DoliDB Database handler. + */ + public $db; + + public $enabled = 1; + + public $info_box_head = array(); + public $info_box_contents = array(); + + + /** + * Constructor + * + * @param DoliDB $db Database handler + * @param string $param More parameters + */ + public function __construct($db, $param = '') + { + global $conf, $user; + + $this->db = $db; + + $this->hidden = ! ($user->rights->adherent->lire && empty($user->socid)); + } + + /** + * Load data for box to show them later + * + * @param int $max Maximum number of records to load + * @return void + */ + public function loadBox($max = 20) + { + global $user, $langs, $db, $conf; + $langs->load("boxes"); + + $this->max=$max; + + include_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; + $memberstatic=new Adherent($db); + + $this->info_box_head = array('text' => $langs->trans("BoxTitleMemberNextBirthdays")); + + if ($user->rights->adherent->lire) + { + $sql = "SELECT u.rowid, u.firstname, u.lastname"; + $sql.= ", u.birth"; + $sql.= " FROM ".MAIN_DB_PREFIX."adherent as u"; + $sql.= " WHERE u.entity IN (".getEntity('adherent').")"; + $sql.= " AND u.statut = 1"; + $sql.= " AND date_format(u.birth, '%m-%d') >= date_format(curdate(), '%m-%d')"; + $sql.= " ORDER BY date_format(u.birth, '%m-%d') ASC"; + $sql.= $db->plimit($max, 0); + + dol_syslog(get_class($this)."::loadBox", LOG_DEBUG); + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + + $line = 0; + while ($line < $num) + { + $objp = $db->fetch_object($result); + $memberstatic->id = $objp->rowid; + $memberstatic->firstname = $objp->firstname; + $memberstatic->lastname = $objp->lastname; + $memberstatic->email = $objp->email; + $dateb=$db->jdate($objp->birth); + $age = date('Y', dol_now()) - date('Y', $dateb); + + $this->info_box_contents[$line][] = array( + 'td' => '', + 'text' => $memberstatic->getNomUrl(1), + 'asis' => 1, + ); + + $this->info_box_contents[$line][] = array( + 'td' => 'class="right"', + 'text' => dol_print_date($dateb, "day") . ' - ' . $age . ' ' . $langs->trans('DurationYears') + ); + + /*$this->info_box_contents[$line][] = array( + 'td' => 'class="right" width="18"', + 'text' => $memberstatic->LibStatut($objp->status, 3) + );*/ + + $line++; + } + + if ($num==0) $this->info_box_contents[$line][0] = array('td' => 'class="center"','text'=>$langs->trans("NoRecordedUsers")); + + $db->free($result); + } + else { + $this->info_box_contents[0][0] = array( + 'td' => '', + 'maxlength'=>500, + 'text' => ($db->error().' sql='.$sql) + ); + } + } + else { + $this->info_box_contents[0][0] = array( + 'td' => 'class="nohover opacitymedium left"', + 'text' => $langs->trans("ReadPermissionNotAllowed") + ); + } + } + + /** + * Method to show box + * + * @param array $head Array with properties of box title + * @param array $contents Array with properties of box lines + * @param int $nooutput No print, only return string + * @return string + */ + public function showBox($head = null, $contents = null, $nooutput = 0) + { + return parent::showBox($this->info_box_head, $this->info_box_contents, $nooutput); + } +} diff --git a/htdocs/core/class/commoninvoice.class.php b/htdocs/core/class/commoninvoice.class.php index 9dd49ea8864..259014cf691 100644 --- a/htdocs/core/class/commoninvoice.class.php +++ b/htdocs/core/class/commoninvoice.class.php @@ -195,6 +195,29 @@ abstract class CommonInvoice extends CommonObject } } + /** + * Return amount (with tax) of all converted amount for this credit note + * + * @param int $multicurrency Return multicurrency_amount instead of amount + * @return int <0 if KO, Sum of credit notes and deposits amount otherwise + */ + public function getSumFromThisCreditNotesNotUsed($multicurrency = 0) + { + require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php'; + + $discountstatic=new DiscountAbsolute($this->db); + $result=$discountstatic->getSumFromThisCreditNotesNotUsed($this, $multicurrency); + if ($result >= 0) + { + return $result; + } + else + { + $this->error=$discountstatic->error; + return -1; + } + } + /** * Renvoie tableau des ids de facture avoir issus de la facture * diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 458c6a2563b..c57148124be 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4186,11 +4186,12 @@ abstract class CommonObject * But for the moment we don't know if it's possible, so we keep the method available on overloaded objects. * * @param string $restrictlist ''=All lines, 'services'=Restrict to services only + * @param array $selectedLines Array of lines id for selected lines * @return void */ - public function printOriginLinesList($restrictlist = '') + public function printOriginLinesList($restrictlist = '', $selectedLines = array()) { - global $langs, $hookmanager, $conf; + global $langs, $hookmanager, $conf, $form; print '
'.$langs->trans('Ref').''.$langs->trans('Unit').''.$langs->trans('ReductionShort').'
'.$langs->trans('ReductionShort').''.$form->showCheckAddButtons('checkforselect', 1).'
'.$langs->trans($this->tpl['unit']).''.$this->tpl['remise_percent'].'
'; - print ''; + print ''; print ''; - print ''; + print ''; print ''; - print ''; + print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print ''; print '
'; + print ''; print $obj->zip; print '
' . $warehouse->getNomUrl(1) . '
' . $entrepotstatic->getNomUrl(1) . ''; - if ($massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined + if (($massactionbutton || $massaction) && $contextpage != 'poslist') // 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->rowid, $arrayofselected)) $selected=1; diff --git a/htdocs/societe/paymentmodes.php b/htdocs/societe/paymentmodes.php index 9310ede87c5..e20b76b1349 100644 --- a/htdocs/societe/paymentmodes.php +++ b/htdocs/societe/paymentmodes.php @@ -600,6 +600,63 @@ if (empty($reshook)) $db->rollback(); } } + + if ($action == 'setkey_account_supplier') + { + $error = 0; + + $newsup = GETPOST('key_account_supplier', 'alpha'); + + $db->begin(); + + if (empty($newsup)) { + $sql = "DELETE FROM ".MAIN_DB_PREFIX."oauth_token WHERE fk_soc = ".$object->id." AND service = '".$service."' AND entity = ".$conf->entity; + } else { + try { + $stripesup = \Stripe\Account::retrieve($db->escape(GETPOST('key_account_supplier', 'alpha'))); + $tokenstring['stripe_user_id'] = $stripesup->id; + $tokenstring['type'] = $stripesup->type; + $sql = "UPDATE ".MAIN_DB_PREFIX."oauth_token"; + $sql.= " SET tokenstring = '".dol_json_encode($tokenstring)."'"; + $sql.= " WHERE fk_soc = ".$object->id." AND service = '".$service."' AND entity = ".$conf->entity; // Keep = here for entity. Only 1 record must be modified ! + } + catch(Exception $e) + { + $error++; + setEventMessages($e->getMessage(), null, 'errors'); + } + } + + $resql = $db->query($sql); + $num = $db->num_rows($resql); + if (empty($num) && !empty($newsup)) + { + try { + $stripesup = \Stripe\Account::retrieve($db->escape(GETPOST('key_account_supplier', 'alpha'))); + $tokenstring['stripe_user_id'] = $stripesup->id; + $tokenstring['type'] = $stripesup->type; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."oauth_token (service, fk_soc, entity, tokenstring)"; + $sql .= " VALUES ('".$service."', ".$object->id.", ".$conf->entity.", '".dol_json_encode($tokenstring)."')"; + } + catch(Exception $e) + { + $error++; + setEventMessages($e->getMessage(), null, 'errors'); + } + $resql = $db->query($sql); + } + + if (! $error) + { + $stripesupplieracc = $newsup; + $db->commit(); + } + else + { + $db->rollback(); + } + } + if ($action == 'setlocalassourcedefault') // Set as default when payment mode defined locally (and may be also remotely) { try { @@ -845,7 +902,7 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' print $form->editfieldkey("StripeConnectAccount", 'key_account_supplier', $stripesupplieracc, $object, $permissiontowrite, 'string', '', 0, 2, 'socid'); print ''; print $form->editfieldval("StripeConnectAccount", 'key_account_supplier', $stripesupplieracc, $object, $permissiontowrite, 'string', '', null, null, '', 2, '', 'socid'); - if (! empty($conf->stripe->enabled) && $stripesupplieracc && $action != 'editkey_account') + if (! empty($conf->stripe->enabled) && $stripesupplieracc && $action != 'editkey_account_supplier') { $connect=''; @@ -1259,7 +1316,10 @@ if ($socid && $action != 'edit' && $action != 'create' && $action != 'editcard' { foreach ($balance->available as $cpt) { - print '
'.$langs->trans("Available").''.price($cpt->amount, 0, '', 1, - 1, - 1, strtoupper($cpt->currency)).' '.$langs->trans("Currency".strtoupper($cpt->currency)).'
'.$langs->trans("Available").''.price(amount, 0, '', 1, - 1, - 1, strtoupper($cpt->currency)).' '.$langs->trans("Currency".strtoupper($cpt->currency)).'
'.$langs->trans("Pending").''.price($cpt->amount, 0, '', 1, - 1, - 1, strtoupper($cpt->currency)).' '.$langs->trans("Currency".strtoupper($cpt->currency)).'
'.$langs->trans("Pending").''.price($amount, 0, '', 1, - 1, - 1, strtoupper($cpt->currency)).' '.$langs->trans("Currency".strtoupper($cpt->currency)).'
'; diff --git a/htdocs/stripe/class/stripe.class.php b/htdocs/stripe/class/stripe.class.php index 5dda24a763e..cf683671c5d 100644 --- a/htdocs/stripe/class/stripe.class.php +++ b/htdocs/stripe/class/stripe.class.php @@ -92,7 +92,7 @@ class Stripe extends CommonObject if ($fk_soc > 0) { $sql.= " AND fk_soc = ".$fk_soc; } - else { + else { $sql.= " AND fk_soc IS NULL"; } $sql.= " AND fk_user IS NULL AND fk_adherent IS NULL"; diff --git a/htdocs/takepos/admin/setup.php b/htdocs/takepos/admin/setup.php index 6d33b8a19c2..23e6eb05c48 100644 --- a/htdocs/takepos/admin/setup.php +++ b/htdocs/takepos/admin/setup.php @@ -80,6 +80,7 @@ if (GETPOST('action', 'alpha') == 'set') $res = dolibarr_set_const($db, "TAKEPOS_NUMPAD", GETPOST('TAKEPOS_NUMPAD', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_NUM_TERMINALS", GETPOST('TAKEPOS_NUM_TERMINALS', 'alpha'), 'chaine', 0, '', $conf->entity); $res = dolibarr_set_const($db, "TAKEPOS_DIRECT_PAYMENT", GETPOST('TAKEPOS_DIRECT_PAYMENT', 'int'), 'int', 0, '', $conf->entity); + $res = dolibarr_set_const($db, "TAKEPOS_EMAIL_TEMPLATE_INVOICE", GETPOST('TAKEPOS_EMAIL_TEMPLATE_INVOICE', 'alpha'), 'chaine', 0, '', $conf->entity); if ($conf->global->TAKEPOS_ORDER_NOTES==1) { @@ -231,6 +232,30 @@ print ''; print $form->selectyesno("TAKEPOS_DIRECT_PAYMENT", $conf->global->TAKEPOS_DIRECT_PAYMENT, 1); print "\n"; +// Email template for send invoice +print ''; +print $langs->trans('EmailTemplate'); +print ''; +include_once DOL_DOCUMENT_ROOT.'/core/class/html.formmail.class.php'; +$formmail = new FormMail($db); +$nboftemplates = $formmail->fetchAllEMailTemplate('facture_send', $user, null, -1); // We set lang=null to get in priority record with no lang +//$arraydefaultmessage = $formmail->getEMailTemplate($db, $tmp[1], $user, null, 0, 1, ''); +$arrayofmessagename=array(); +if (is_array($formmail->lines_model)) +{ + foreach($formmail->lines_model as $modelmail) + { + //var_dump($modelmail); + $moreonlabel=''; + if (! empty($arrayofmessagename[$modelmail->label])) $moreonlabel=' ('.$langs->trans("SeveralLangugeVariatFound").')'; + $arrayofmessagename[$modelmail->label]=$langs->trans(preg_replace('/\(|\)/', '', $modelmail->label)).$moreonlabel; + } +} +//var_dump($arraydefaultmessage); +//var_dump($arrayofmessagename); +print $form->selectarray('TAKEPOS_EMAIL_TEMPLATE_INVOICE', $arrayofmessagename, $conf->global->TAKEPOS_EMAIL_TEMPLATE_INVOICE, 'None', 1, 0, '', 0, 0, 0, '', '', 1); +print "\n"; + $substitutionarray=pdf_getSubstitutionArray($langs, null, null, 2); $substitutionarray['__(AnyTranslationKey)__']=$langs->trans("Translation"); $htmltext = ''.$langs->trans("AvailableVariables").':
'; diff --git a/htdocs/takepos/invoice.php b/htdocs/takepos/invoice.php index 17805a6b060..0f0498bc8a8 100644 --- a/htdocs/takepos/invoice.php +++ b/htdocs/takepos/invoice.php @@ -37,7 +37,7 @@ require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php'; require_once DOL_DOCUMENT_ROOT . '/core/class/html.form.class.php'; -$langs->loadLangs(array("bills", "cashdesk")); +$langs->loadLangs(array("companies", "commercial", "bills", "cashdesk")); $id = GETPOST('id', 'int'); $action = GETPOST('action', 'alpha'); @@ -161,9 +161,22 @@ if ($action == 'valid' && $user->rights->facture->creer) $invoice->update($user); } - if (! empty($conf->stock->enabled) && $conf->global->{'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]} != "1") + $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; + if ($invoice->statut != Facture::STATUS_DRAFT) { - $invoice->validate($user, '', $conf->global->{'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]}); + dol_syslog("Sale already validated"); + dol_htmloutput_errors($langs->trans("InvoiceIsAlreadyValidated", "TakePos"), null, 1); + } + elseif (count($invoice->lines)==0) + { + dol_syslog("Sale without lines"); + dol_htmloutput_errors($langs->trans("NoLinesToBill", "TakePos"), null, 1); + } + elseif (! empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") + { + $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; + dol_syslog("Validate invoice with stock change into warehouse id ".$constantforkey); + $invoice->validate($user, '', $conf->global->$constantforkey); } else { @@ -175,7 +188,7 @@ if ($action == 'valid' && $user->rights->facture->creer) $payment->datepaye = $now; $payment->fk_account = $bankaccount; $payment->amounts[$invoice->id] = $amountofpayment; - + // If user has not used change control, add total invoice payment if ($amountofpayment == 0) $payment->amounts[$invoice->id] = $invoice->total_ttc; @@ -287,12 +300,28 @@ if ($action == "deleteline") { } if ($action == "delete") { - if ($placeid > 0) { //If invoice exists + // $placeid is the invoice id (it differs from place) and is defined if the place is set and the ref of invoice is '(PROV-POS'.$_SESSION["takeposterminal"].'-'.$place.')', so the fetch at begining of page works. + if ($placeid > 0) { $result = $invoice->fetch($placeid); - if ($result > 0) + + if ($result > 0 && $invoice->statut == Facture::STATUS_DRAFT) { - $sql = "DELETE FROM " . MAIN_DB_PREFIX . "facturedet where fk_facture='".$placeid."'"; - $resql = $db->query($sql); + $db->begin(); + + // We delete the lines + $sql = "DELETE FROM " . MAIN_DB_PREFIX . "facturedet_extrafields where fk_object = ".$placeid; + $resql1 = $db->query($sql); + $sql = "DELETE FROM " . MAIN_DB_PREFIX . "facturedet where fk_facture = ".$placeid; + $resql2 = $db->query($sql); + + if ($resql1 && $resql2) + { + $db->commit(); + } + else + { + $db->rollback(); + } $invoice->fetch($placeid); } @@ -395,7 +424,7 @@ if ($action=="valid" || $action=="history") } else { - if ($invoice->paye) $sectionwithinvoicelink.=''.$langs->trans("Payed").''; + if ($invoice->paye) $sectionwithinvoicelink.=''.$langs->trans("Paid").''; else $sectionwithinvoicelink.=$langs->trans('BillShortStatusValidated'); } $sectionwithinvoicelink.=''; @@ -541,7 +570,7 @@ if ($_SESSION["basiclayout"]!=1) { print '' . $langs->trans('ReductionShort') . ''; print '' . $langs->trans('Qty') . ''; - print '' . $langs->trans('TotalHTShort') . ''; + print '' . $langs->trans('TotalTTCShort') . ''; } print "\n"; @@ -567,7 +596,7 @@ if ($_SESSION["basiclayout"]==1) $htmlforlines.= '
'; print $htmlforlines; } - + if ($mobilepage=="products") { require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; @@ -591,7 +620,7 @@ if ($_SESSION["basiclayout"]==1) $htmlforlines.= ''; print $htmlforlines; } - + if ($mobilepage=="places") { $sql="SELECT rowid, entity, label, leftpos, toppos, floor FROM ".MAIN_DB_PREFIX."takepos_floor_tables"; @@ -689,9 +718,52 @@ if ($invoice->socid != $conf->global->{'CASHDESK_ID_THIRDPARTY'.$_SESSION["takep $soc = new Societe($db); if ($invoice->socid > 0) $soc->fetch($invoice->socid); else $soc->fetch($conf->global->{'CASHDESK_ID_THIRDPARTY'.$_SESSION["takeposterminal"]}); - print '

'; + print '

'; print $langs->trans("Customer").': '.$soc->name; + + $constantforkey = 'CASHDESK_NO_DECREASE_STOCK'.$_SESSION["takeposterminal"]; + if (! empty($conf->stock->enabled) && $conf->global->$constantforkey != "1") + { + $constantforkey = 'CASHDESK_ID_WAREHOUSE'.$_SESSION["takeposterminal"]; + $warehouse = new Entrepot($db); + $warehouse->fetch($conf->global->$constantforkey); + print '
'.$langs->trans("Warehouse").': '.$warehouse->ref; + } print '

'; + + // Module Adherent + if (! empty($conf->adherent->enabled)) + { + require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent.class.php'; + $langs->load("members"); + print '

'; + print $langs->trans("Member").': '; + $adh=new Adherent($db); + $result=$adh->fetch('', '', $invoice->socid); + if ($result > 0) + { + $adh->ref=$adh->getFullName($langs); + print $adh->getFullName($langs); + print '
'.$langs->trans("Type").': '.$adh->type; + if ($adh->datefin) + { + print '
'.$langs->trans("SubscriptionEndDate").': '.dol_print_date($adh->datefin, 'day'); + if ($adh->hasDelay()) { + print " ".img_warning($langs->trans("Late")); + } + } + else + { + print $langs->trans("SubscriptionNotReceived"); + if ($adh->statut > 0) print " ".img_warning($langs->trans("Late")); // displays delay Pictogram only if not a draft and not terminated + } + } + else + { + print ''.$langs->trans("ThirdpartyNotLinkedToMember").''; + } + print '

'; + } } if ($action == "search") diff --git a/htdocs/takepos/takepos.php b/htdocs/takepos/takepos.php index 4dc481a98cf..46cbdd595d9 100644 --- a/htdocs/takepos/takepos.php +++ b/htdocs/takepos/takepos.php @@ -398,8 +398,9 @@ function Refresh() { } function New() { - console.log("New"); - var r = confirm('trans("ConfirmDeletionOfThisPOSSale"); ?>'); + // If we go here,it means $conf->global->TAKEPOS_BAR_RESTAURANT is not defined + console.log("New with place = , js place="+place); + var r = confirm(' 0 ? $langs->trans("ConfirmDeletionOfThisPOSSale") : $langs->trans("ConfirmDiscardOfThisPOSSale")); ?>'); if (r == true) { $("#poslines").load("invoice.php?action=delete&place="+place, function() { //$('#poslines').scrollTop($('#poslines')[0].scrollHeight); @@ -664,7 +665,7 @@ if (empty($conf->global->TAKEPOS_BAR_RESTAURANT)) else { // BAR RESTAURANT specific menu - $menus[$r++]=array('title'=>'
'.$langs->trans("Floors").'
', 'action'=>'Floors();'); + $menus[$r++]=array('title'=>'
'.$langs->trans("Place").'
', 'action'=>'Floors();'); } $menus[$r++]=array('title'=>'
'.$langs->trans("Customer").'
', 'action'=>'Customer();'); diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index ee7ec9375d6..37abbc9a2bd 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -75,7 +75,7 @@ class AllTests public static function suite() { - $suite = new PHPUnit_Framework_TestSuite('PHPUnit Framework'); + $suite = new PHPUnit\Framework\TestSuite('PHPUnit Framework'); //require_once dirname(__FILE__).'/CoreTest.php'; //$suite->addTestSuite('CoreTest'); @@ -239,6 +239,8 @@ class AllTests require_once dirname(__FILE__).'/FormAdminTest.php'; $suite->addTestSuite('FormAdminTest'); + require_once dirname(__FILE__).'/FormTest.php'; + $suite->addTestSuite('FormTest'); require_once dirname(__FILE__).'/ModulesTest.php'; // At end because it's the longer $suite->addTestSuite('ModulesTest'); diff --git a/test/phpunit/FormAdminTest.php b/test/phpunit/FormAdminTest.php index 20c22a76cd8..b58b43b368b 100644 --- a/test/phpunit/FormAdminTest.php +++ b/test/phpunit/FormAdminTest.php @@ -119,7 +119,7 @@ class FormAdminTest extends PHPUnit\Framework\TestCase } /** - * testFactureCreate + * testSelectPaperFormat * * @return int */ diff --git a/test/phpunit/FormTest.php b/test/phpunit/FormTest.php new file mode 100644 index 00000000000..69594325b20 --- /dev/null +++ b/test/phpunit/FormTest.php @@ -0,0 +1,149 @@ + + * + * 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 + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file test/phpunit/FormTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/class/html.form.class.php'; + +if (empty($user->id)) +{ + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class FormTest extends PHPUnit\Framework\TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return FactureTest + */ + public function __construct() + { + parent::__construct(); + + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + // Static methods + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + + // tear down after class + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + } + + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + /** + * testSelectProduitsList + * + * @return int + */ + public function testSelectProduitsList() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new Form($this->savdb); + $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1); + + $this->assertEquals(count($result), 5); + print __METHOD__." result=".$result."\n"; + + $conf->global->ENTREPOT_EXTRA_STATUS = 1; + + // Exclude stock in warehouseinternal + $result=$localobject->select_produits_list('', 'productid', '', 5, 0, '', 1, 2, 1, 0, '1', 0, '', 0, 'warehouseclosed,warehouseopen'); + $this->assertEquals(count($result), 5); + print __METHOD__." result=".$result."\n"; + + return $result; + } +} diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 5b2b65c9e50..2a7734716eb 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -1260,4 +1260,25 @@ class FunctionsLibTest extends PHPUnit\Framework\TestCase return true; } + + /** + * testDolStringIsGoodIso + * + * @return boolean + */ + public function testDolStringIsGoodIso() + { + global $conf, $langs; + + $chaine='This is an ISO string'; + $result = dol_string_is_good_iso($chaine); + $this->assertEquals($result, 1); + + $chaine='This is a not ISO string '.chr(0); + $result = dol_string_is_good_iso($chaine); + $this->assertEquals($result, 0); + + return true; + } + }