diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 7ad0a8ed4bc..d0089e6f1e7 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3500,6 +3500,7 @@ class Facture extends CommonInvoice return -2; } } else { + $this->errors[]='status of invoice must be Draft to allow use of ->addline()'; dol_syslog(get_class($this)."::addline status of invoice must be Draft to allow use of ->addline()", LOG_ERR); return -3; } diff --git a/htdocs/langs/en_US/projects.lang b/htdocs/langs/en_US/projects.lang index 1e0ed42d3e3..645171e8ac7 100644 --- a/htdocs/langs/en_US/projects.lang +++ b/htdocs/langs/en_US/projects.lang @@ -259,7 +259,7 @@ TimeSpentInvoiced=Time spent billed TimeSpentForIntervention=Time spent TimeSpentForInvoice=Time spent OneLinePerUser=One line per user -ServiceToUseOnLines=Service to use on lines +ServiceToUseOnLines=Service to use on lines by default InvoiceGeneratedFromTimeSpent=Invoice %s has been generated from time spent on project InterventionGeneratedFromTimeSpent=Intervention %s has been generated from time spent on project ProjectBillTimeDescription=Check if you enter timesheet on tasks of project AND you plan to generate invoice(s) from the timesheet to bill the customer of the project (do not check if you plan to create invoice that is not based on entered timesheets). Note: To generate invoice, go on tab 'Time spent' of the project and select lines to include. @@ -276,6 +276,7 @@ NewInter=New intervention OneLinePerTask=One line per task OneLinePerPeriod=One line per period OneLinePerTimeSpentLine=One line for each time spent declaration +OneLinePerTimeSpentLineProduct=One line for each time spent declaration with product defined AddDetailDateAndDuration=With date and duration into line description RefTaskParent=Ref. Parent Task ProfitIsCalculatedWith=Profit is calculated using diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 365b5e90916..fb42b6887f2 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -6058,6 +6058,43 @@ class Product extends CommonObject dol_print_error($this->db); } } + + + /** + * Return the duration in Hours of a service base on duration fields + * @return int -1 KO, >= 0 is the duration in hours + */ + public function getProductDurationHours() + { + global $langs; + + if (empty($this->duration_value)) { + $this->errors[]='ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice'; + return -1; + } + + if ($this->duration_unit == 'i') { + $prodDurationHours = 1. / 60; + } + if ($this->duration_unit == 'h') { + $prodDurationHours = 1.; + } + if ($this->duration_unit == 'd') { + $prodDurationHours = 24.; + } + if ($this->duration_unit == 'w') { + $prodDurationHours = 24. * 7; + } + if ($this->duration_unit == 'm') { + $prodDurationHours = 24. * 30; + } + if ($this->duration_unit == 'y') { + $prodDurationHours = 24. * 365; + } + $prodDurationHours *= $this->duration_value; + + return $prodDurationHours; + } } diff --git a/htdocs/projet/tasks/time.php b/htdocs/projet/tasks/time.php index 34333b91632..b201feef622 100644 --- a/htdocs/projet/tasks/time.php +++ b/htdocs/projet/tasks/time.php @@ -392,36 +392,21 @@ if ($action == 'confirm_generateinvoice') { $generateinvoicemode = GETPOST('generateinvoicemode', 'string'); $invoiceToUse = GETPOST('invoiceid', 'int'); - $prodDurationHours = 1.0; + $prodDurationHoursBase = 1.0; if ($idprod > 0) { $tmpproduct->fetch($idprod); + if ($result<0) { + $error++; + setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors'); + } - if (empty($tmpproduct->duration_value)) { + $prodDurationHoursBase=$tmpproduct->getProductDurationHours(); + if ($prodDurationHoursBase<0) { $error++; $langs->load("errors"); - setEventMessages($langs->trans("ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice"), null, 'errors'); + setEventMessages(null, $tmpproduct->errors, 'errors'); } - if ($tmpproduct->duration_unit == 'i') { - $prodDurationHours = 1. / 60; - } - if ($tmpproduct->duration_unit == 'h') { - $prodDurationHours = 1.; - } - if ($tmpproduct->duration_unit == 'd') { - $prodDurationHours = 24.; - } - if ($tmpproduct->duration_unit == 'w') { - $prodDurationHours = 24. * 7; - } - if ($tmpproduct->duration_unit == 'm') { - $prodDurationHours = 24. * 30; - } - if ($tmpproduct->duration_unit == 'y') { - $prodDurationHours = 24. * 365; - } - $prodDurationHours *= $tmpproduct->duration_value; - $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0); $pu_ht = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht']; @@ -429,7 +414,7 @@ if ($action == 'confirm_generateinvoice') { $localtax1 = $dataforprice['localtax1']; $localtax2 = $dataforprice['localtax2']; } else { - $prodDurationHours = 1; + $prodDurationHoursBase = 1; $pu_ht = 0; $txtva = get_default_tva($mysoc, $projectstatic->thirdparty); @@ -476,7 +461,7 @@ if ($action == 'confirm_generateinvoice') { } // Add lines - $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username).' : '.$qtyhourtext, $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); + $lineid = $tmpinvoice->addline($langs->trans("TimeSpentForInvoice", $username).' : '.$qtyhourtext, $pu_ht, round($qtyhour / $prodDurationHoursBase, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); // Update lineid into line of timespent $sql = 'UPDATE '.MAIN_DB_PREFIX.'projet_task_time SET invoice_line_id = '.((int) $lineid).', invoice_id = '.((int) $tmpinvoice->id); @@ -488,8 +473,9 @@ if ($action == 'confirm_generateinvoice') { break; } } - } elseif ($generateinvoicemode == 'onelineperperiod') { // One line for each time spent line + } elseif ($generateinvoicemode == 'onelineperperiod' || $generateinvoicemode == 'onelineperperiodproduct') { // One line for each time spent line $arrayoftasks = array(); + $product_data_cache = array(); $withdetail=GETPOST('detail_time_duration', 'alpha'); foreach ($toselect as $key => $value) { // Get userid, timepent @@ -519,6 +505,7 @@ if ($action == 'confirm_generateinvoice') { $arrayoftasks[$object->timespent_id]['note'] .= ' - '.$langs->trans("Duration").': '.convertSecondToTime($object->timespent_duration, 'all', $conf->global->MAIN_DURATION_OF_WORKDAY); } $arrayoftasks[$object->timespent_id]['user'] = $object->timespent_fk_user; + $arrayoftasks[$object->timespent_id]['fk_product'] = $object->timespent_fk_product; } foreach ($arrayoftasks as $timespent_id => $value) { @@ -534,7 +521,50 @@ if ($action == 'confirm_generateinvoice') { } // Add lines - $lineid = $tmpinvoice->addline($value['note'], $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0)); + $prodDurationHours = $prodDurationHoursBase; + $idprodline=$idprod; + $pu_htline = $pu_ht; + $txtvaline = $txtva; + $localtax1line = $localtax1; + $localtax2line = $localtax2; + + + if ($generateinvoicemode == 'onelineperperiodproduct' && !empty($value['fk_product']) && $value['fk_product']!==$idprod) { + if (!array_key_exists($value['fk_product'], $product_data_cache)) { + $result = $tmpproduct->fetch($value['fk_product']); + if ($result < 0) { + $error++; + setEventMessages($tmpproduct->error, $tmpproduct->errors, 'errors'); + } + $prodDurationHours = $tmpproduct->getProductDurationHours(); + if ($prodDurationHours < 0) { + $error++; + $langs->load("errors"); + setEventMessages(null, $tmpproduct->errors, 'errors'); + } + + $dataforprice = $tmpproduct->getSellPrice($mysoc, $projectstatic->thirdparty, 0); + + $pu_htline = empty($dataforprice['pu_ht']) ? 0 : $dataforprice['pu_ht']; + $txtvaline = $dataforprice['tva_tx']; + $localtax1line = $dataforprice['localtax1']; + $localtax2line = $dataforprice['localtax2']; + + $product_data_cache[$value['fk_product']] = array('duration'=>$prodDurationHours,'dataforprice'=>$dataforprice); + } else { + $prodDurationHours = $product_data_cache[$value['fk_product']]['duration']; + $pu_htline = empty($product_data_cache[$value['fk_product']]['dataforprice']['pu_ht']) ? 0 : $product_data_cache[$value['fk_product']]['dataforprice']['pu_ht']; + $txtvaline = $product_data_cache[$value['fk_product']]['dataforprice']['tva_tx']; + $localtax1line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax1']; + $localtax2line = $product_data_cache[$value['fk_product']]['dataforprice']['localtax2']; + } + $idprodline=$value['fk_product']; + } + $lineid = $tmpinvoice->addline($value['note'], $pu_htline, round($qtyhour / $prodDurationHours, 2), $txtvaline, $localtax1line, $localtax2line, ($idprodline > 0 ? $idprodline : 0)); + if ($lineid<0) { + $error++; + setEventMessages(null, $tmpinvoice->errors, 'errors'); + } //var_dump($lineid);exit; // Update lineid into line of timespent @@ -1178,6 +1208,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0 || $allprojectforuser 'onelineperuser'=>'OneLinePerUser', 'onelinepertask'=>'OneLinePerTask', 'onelineperperiod'=>'OneLinePerTimeSpentLine', + 'onelineperperiodproduct'=>'OneLinePerTimeSpentLineProduct', ); print $form->selectarray('generateinvoicemode', $tmparray, 'onelineperuser', 0, 0, 0, '', 1); print "\n".'