forked from Wavyzz/dolibarr
Merge branch '14.0' of git@github.com:Dolibarr/dolibarr.git into develop
This commit is contained in:
21
ChangeLog
21
ChangeLog
@@ -2,6 +2,27 @@
|
|||||||
English Dolibarr ChangeLog
|
English Dolibarr ChangeLog
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
***** ChangeLog for 13.0.4 compared to 13.0.2 *****
|
||||||
|
|
||||||
|
FIX: Allow disabling of a module (not a dangerous action) even if there is problem with token (due to bugged modules).
|
||||||
|
FIX: 13.0 - fatal - missing inclusion of ajax.lib.php for calling `ajax_autocompleter()`
|
||||||
|
FIX: #17919 pictures in docs.
|
||||||
|
FIX: #18006
|
||||||
|
FIX: Accountancy - if we define a date start, automatic binding try to continue to solve old binding
|
||||||
|
FIX: Accoutancy Limit date payment not registered on purchases operations
|
||||||
|
FIX: Can't edit replacement invoice
|
||||||
|
FIX: deposit can create credit note in payment conf
|
||||||
|
FIX: division by zero on create
|
||||||
|
FIX: holiday: balances not updated correctly with pgsql because of case sensitivity field
|
||||||
|
FIX: holiday: status filter parameter has been renamed but not in links it was used
|
||||||
|
FIX: List and Create Companies Left Menus
|
||||||
|
FIX: method exists
|
||||||
|
FIX: need to add payment sum to getlibstatus function in object linked block
|
||||||
|
FIX: permission to close a proposal when using advanced permissions
|
||||||
|
FIX: Problem of z-index with popup and top menu
|
||||||
|
FIX: same thing on supplier orders
|
||||||
|
FIX: Status of invoice when making a replacement invoice
|
||||||
|
FIX: update contact birthday alert
|
||||||
|
|
||||||
***** ChangeLog for 14.0.0 compared to 13.0.0 *****
|
***** ChangeLog for 14.0.0 compared to 13.0.0 *****
|
||||||
|
|
||||||
|
|||||||
@@ -272,8 +272,10 @@ class HookManager
|
|||||||
$parameters['currentcontext'] = $context;
|
$parameters['currentcontext'] = $context;
|
||||||
// Hooks that must return int (hooks with type 'addreplace')
|
// Hooks that must return int (hooks with type 'addreplace')
|
||||||
if ($hooktype == 'addreplace') {
|
if ($hooktype == 'addreplace') {
|
||||||
$resaction += $actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example)
|
$resactiontmp = $actionclassinstance->$method($parameters, $object, $action, $this); // $object and $action can be changed by method ($object->id during creation for example or $action to go back to other action for example)
|
||||||
if ($resaction < 0 || !empty($actionclassinstance->error) || (!empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) {
|
$resaction += $resactiontmp;
|
||||||
|
|
||||||
|
if ($resactiontmp < 0 || !empty($actionclassinstance->error) || (!empty($actionclassinstance->errors) && count($actionclassinstance->errors) > 0)) {
|
||||||
$error++;
|
$error++;
|
||||||
$this->error = $actionclassinstance->error;
|
$this->error = $actionclassinstance->error;
|
||||||
$this->errors = array_merge($this->errors, (array) $actionclassinstance->errors);
|
$this->errors = array_merge($this->errors, (array) $actionclassinstance->errors);
|
||||||
@@ -281,13 +283,22 @@ class HookManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($actionclassinstance->results) && is_array($actionclassinstance->results)) {
|
if (isset($actionclassinstance->results) && is_array($actionclassinstance->results)) {
|
||||||
$this->resArray = array_merge($this->resArray, $actionclassinstance->results);
|
if ($resactiontmp > 0) {
|
||||||
|
$this->resArray = $actionclassinstance->results;
|
||||||
|
} else {
|
||||||
|
$this->resArray = array_merge($this->resArray, $actionclassinstance->results);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!empty($actionclassinstance->resprints)) {
|
if (!empty($actionclassinstance->resprints)) {
|
||||||
$this->resPrint .= $actionclassinstance->resprints;
|
if ($resactiontmp > 0) {
|
||||||
|
$this->resPrint = $actionclassinstance->resprints;
|
||||||
|
} else {
|
||||||
|
$this->resPrint .= $actionclassinstance->resprints;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
// Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...)
|
// Generic hooks that return a string or array (printLeftBlock, formAddObjectLine, formBuilddocOptions, ...)
|
||||||
|
else {
|
||||||
// TODO. this test should be done into the method of hook by returning nothing
|
// TODO. this test should be done into the method of hook by returning nothing
|
||||||
if (is_array($parameters) && !empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) {
|
if (is_array($parameters) && !empty($parameters['special_code']) && $parameters['special_code'] > 3 && $parameters['special_code'] != $actionclassinstance->module_number) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -1899,7 +1899,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = '', $noprin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Status
|
// Status
|
||||||
$out .= '<td class="nowrap center">'.$actionstatic->LibStatut($histo[$key]['percent'], 3, 0, $histo[$key]['datestart']).'</td>';
|
$out .= '<td class="nowrap center">'.$actionstatic->LibStatut($histo[$key]['percent'], 2, 0, $histo[$key]['datestart']).'</td>';
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
$out .= '<td></td>';
|
$out .= '<td></td>';
|
||||||
|
|||||||
@@ -8487,8 +8487,10 @@ function complete_head_from_modules($conf, $langs, $object, &$head, &$h, $type,
|
|||||||
if (!empty($hookmanager)) {
|
if (!empty($hookmanager)) {
|
||||||
$parameters = array('object' => $object, 'mode' => $mode, 'head' => &$head);
|
$parameters = array('object' => $object, 'mode' => $mode, 'head' => &$head);
|
||||||
$reshook = $hookmanager->executeHooks('completeTabsHead', $parameters);
|
$reshook = $hookmanager->executeHooks('completeTabsHead', $parameters);
|
||||||
if ($reshook > 0) {
|
if ($reshook > 0) { // Hook ask to replace completely the array
|
||||||
$head = $hookmanager->resArray;
|
$head = $hookmanager->resArray;
|
||||||
|
} else { // Hook
|
||||||
|
$head = array_merge($head, $hookmanager->resArray);
|
||||||
}
|
}
|
||||||
$h = count($head);
|
$h = count($head);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -367,7 +367,7 @@ ALTER TABLE llx_actioncomm_reminder ADD UNIQUE uk_actioncomm_reminder_unique (fk
|
|||||||
|
|
||||||
ALTER TABLE llx_actioncomm_reminder ADD INDEX idx_actioncomm_reminder_status (status);
|
ALTER TABLE llx_actioncomm_reminder ADD INDEX idx_actioncomm_reminder_status (status);
|
||||||
|
|
||||||
|
ALTER TABLE llx_inventorydet ADD COLUMN fk_warehouse integer DEFAULT 0;
|
||||||
ALTER TABLE llx_inventorydet ADD UNIQUE uk_inventorydet(fk_inventory, fk_warehouse, fk_product, batch);
|
ALTER TABLE llx_inventorydet ADD UNIQUE uk_inventorydet(fk_inventory, fk_warehouse, fk_product, batch);
|
||||||
|
|
||||||
ALTER TABLE llx_commandedet ADD COLUMN ref_ext varchar(255) AFTER label;
|
ALTER TABLE llx_commandedet ADD COLUMN ref_ext varchar(255) AFTER label;
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ create table llx_facture
|
|||||||
fk_incoterms integer, -- for incoterms
|
fk_incoterms integer, -- for incoterms
|
||||||
location_incoterms varchar(255), -- for incoterms
|
location_incoterms varchar(255), -- for incoterms
|
||||||
|
|
||||||
fk_mode_transport integer, -- for intracomm report
|
fk_transport_mode integer, -- for intracomm report
|
||||||
|
|
||||||
situation_cycle_ref smallint, -- situation cycle reference
|
situation_cycle_ref smallint, -- situation cycle reference
|
||||||
situation_counter smallint, -- situation counter
|
situation_counter smallint, -- situation counter
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ create table llx_facture_fourn
|
|||||||
fk_incoterms integer, -- for incoterms
|
fk_incoterms integer, -- for incoterms
|
||||||
location_incoterms varchar(255), -- for incoterms
|
location_incoterms varchar(255), -- for incoterms
|
||||||
|
|
||||||
fk_mode_transport integer, -- for intracomm report
|
fk_transport_mode integer, -- for intracomm report
|
||||||
|
|
||||||
model_pdf varchar(255),
|
model_pdf varchar(255),
|
||||||
last_main_doc varchar(255), -- relative filepath+filename of last main generated document
|
last_main_doc varchar(255), -- relative filepath+filename of last main generated document
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ ErrorAnAmountWithoutTaxIsRequired=Error, amount is mandatory
|
|||||||
ErrorAPercentIsRequired=Error, please fill in the percentage correctly
|
ErrorAPercentIsRequired=Error, please fill in the percentage correctly
|
||||||
ErrorYouMustFirstSetupYourChartOfAccount=You must first setup your chart of account
|
ErrorYouMustFirstSetupYourChartOfAccount=You must first setup your chart of account
|
||||||
ErrorFailedToFindEmailTemplate=Failed to find template with code name %s
|
ErrorFailedToFindEmailTemplate=Failed to find template with code name %s
|
||||||
|
ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice=Duration not defined on service. No way to calculate the hourly price.
|
||||||
|
|
||||||
# Warnings
|
# Warnings
|
||||||
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.
|
WarningParamUploadMaxFileSizeHigherThanPostMaxSize=Your PHP parameter upload_max_filesize (%s) is higher than PHP parameter post_max_size (%s). This is not a consistent setup.
|
||||||
|
|||||||
@@ -1234,7 +1234,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
|
|||||||
if ($type == 1) {
|
if ($type == 1) {
|
||||||
print '<tr><td>'.$langs->trans("Duration").'</td><td>';
|
print '<tr><td>'.$langs->trans("Duration").'</td><td>';
|
||||||
print '<input name="duration_value" size="4" value="'.GETPOST('duration_value', 'int').'">';
|
print '<input name="duration_value" size="4" value="'.GETPOST('duration_value', 'int').'">';
|
||||||
print $formproduct->selectMeasuringUnits("duration_unit", "time", GETPOST('duration_value', 'alpha'), 0, 1);
|
print $formproduct->selectMeasuringUnits("duration_unit", "time", (GETPOSTISSET('duration_value') ? GETPOSTISSET('duration_value', 'alpha') : 'h'), 0, 1);
|
||||||
print '</td></tr>';
|
print '</td></tr>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -414,7 +414,7 @@ class FormProduct
|
|||||||
dol_print_error($db);
|
dol_print_error($db);
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
$return .= '<select class="flat'.($morecss ? ' '.$morecss : '').'" name="'.$name.'">';
|
$return .= '<select class="flat'.($morecss ? ' '.$morecss : '').'" name="'.$name.'" id="'.$name.'">';
|
||||||
if ($adddefault || $adddefault === '') {
|
if ($adddefault || $adddefault === '') {
|
||||||
$return .= '<option value="0">'.($adddefault ? $langs->trans("Default") : '').'</option>';
|
$return .= '<option value="0">'.($adddefault ? $langs->trans("Default") : '').'</option>';
|
||||||
}
|
}
|
||||||
@@ -447,6 +447,8 @@ class FormProduct
|
|||||||
$return .= '</select>';
|
$return .= '</select>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$return .= ajax_combobox($name);
|
||||||
|
|
||||||
return $return;
|
return $return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,6 +116,7 @@ class Task extends CommonObject
|
|||||||
public $timespent_datehour; // More accurate start date (same than timespent_date but includes hours, minutes and seconds)
|
public $timespent_datehour; // More accurate start date (same than timespent_date but includes hours, minutes and seconds)
|
||||||
public $timespent_withhour; // 1 = we entered also start hours for timesheet line
|
public $timespent_withhour; // 1 = we entered also start hours for timesheet line
|
||||||
public $timespent_fk_user;
|
public $timespent_fk_user;
|
||||||
|
public $timespent_thm;
|
||||||
public $timespent_note;
|
public $timespent_note;
|
||||||
|
|
||||||
public $comments = array();
|
public $comments = array();
|
||||||
@@ -1224,6 +1225,7 @@ class Task extends CommonObject
|
|||||||
$ret = -2;
|
$ret = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update hourly rate of this time spent entry
|
||||||
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time";
|
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time";
|
||||||
$sql .= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".((int) $this->timespent_fk_user).")"; // set average hour rate of user
|
$sql .= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".((int) $this->timespent_fk_user).")"; // set average hour rate of user
|
||||||
$sql .= " WHERE rowid = ".((int) $tasktime_id);
|
$sql .= " WHERE rowid = ".((int) $tasktime_id);
|
||||||
@@ -1437,6 +1439,7 @@ class Task extends CommonObject
|
|||||||
$sql .= " ptt.task_duration,";
|
$sql .= " ptt.task_duration,";
|
||||||
$sql .= " ptt.fk_user,";
|
$sql .= " ptt.fk_user,";
|
||||||
$sql .= " ptt.note,";
|
$sql .= " ptt.note,";
|
||||||
|
$sql .= " ptt.thm,";
|
||||||
$sql .= " pt.rowid as task_id,";
|
$sql .= " pt.rowid as task_id,";
|
||||||
$sql .= " pt.ref as task_ref,";
|
$sql .= " pt.ref as task_ref,";
|
||||||
$sql .= " pt.label as task_label,";
|
$sql .= " pt.label as task_label,";
|
||||||
@@ -1447,7 +1450,7 @@ class Task extends CommonObject
|
|||||||
$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as ptt, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."projet as p";
|
$sql .= " FROM ".MAIN_DB_PREFIX."projet_task_time as ptt, ".MAIN_DB_PREFIX."projet_task as pt, ".MAIN_DB_PREFIX."projet as p";
|
||||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."societe as s ON p.fk_soc = s.rowid";
|
||||||
$sql .= " WHERE ptt.fk_task = pt.rowid AND pt.fk_projet = p.rowid";
|
$sql .= " WHERE ptt.fk_task = pt.rowid AND pt.fk_projet = p.rowid";
|
||||||
$sql .= " AND ptt.fk_user = ".$userobj->id;
|
$sql .= " AND ptt.fk_user = ".((int) $userobj->id);
|
||||||
$sql .= " AND pt.entity IN (".getEntity('project').")";
|
$sql .= " AND pt.entity IN (".getEntity('project').")";
|
||||||
if ($morewherefilter) {
|
if ($morewherefilter) {
|
||||||
$sql .= $morewherefilter;
|
$sql .= $morewherefilter;
|
||||||
@@ -1483,6 +1486,7 @@ class Task extends CommonObject
|
|||||||
$newobj->timespent_withhour = $obj->task_date_withhour;
|
$newobj->timespent_withhour = $obj->task_date_withhour;
|
||||||
$newobj->timespent_duration = $obj->task_duration;
|
$newobj->timespent_duration = $obj->task_duration;
|
||||||
$newobj->timespent_fk_user = $obj->fk_user;
|
$newobj->timespent_fk_user = $obj->fk_user;
|
||||||
|
$newobj->timespent_thm = $obj->thm; // hourly rate
|
||||||
$newobj->timespent_note = $obj->note;
|
$newobj->timespent_note = $obj->note;
|
||||||
|
|
||||||
$arrayres[] = $newobj;
|
$arrayres[] = $newobj;
|
||||||
@@ -1575,10 +1579,12 @@ class Task extends CommonObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($ret == 1 && ($this->timespent_old_duration != $this->timespent_duration)) {
|
if ($ret == 1 && ($this->timespent_old_duration != $this->timespent_duration)) {
|
||||||
$newDuration = $this->timespent_duration - $this->timespent_old_duration;
|
// Recalculate amount of time spent for task and update denormalized field
|
||||||
|
|
||||||
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
|
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
|
||||||
$sql .= " SET duration_effective = (SELECT SUM(task_duration) FROM ".MAIN_DB_PREFIX."projet_task_time as ptt where ptt.fk_task = ".((int) $this->id).")";
|
$sql .= " SET duration_effective = (SELECT SUM(task_duration) FROM ".MAIN_DB_PREFIX."projet_task_time as ptt where ptt.fk_task = ".((int) $this->id).")";
|
||||||
|
if (isset($this->progress)) {
|
||||||
|
$sql .= ", progress = ".((float) $this->progress); // Do not overwrite value if not provided
|
||||||
|
}
|
||||||
$sql .= " WHERE rowid = ".((int) $this->id);
|
$sql .= " WHERE rowid = ".((int) $this->id);
|
||||||
|
|
||||||
dol_syslog(get_class($this)."::updateTimeSpent", LOG_DEBUG);
|
dol_syslog(get_class($this)."::updateTimeSpent", LOG_DEBUG);
|
||||||
@@ -1587,6 +1593,17 @@ class Task extends CommonObject
|
|||||||
$this->db->rollback();
|
$this->db->rollback();
|
||||||
$ret = -2;
|
$ret = -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update hourly rate of this time spent entry, but only if it was not set initialy
|
||||||
|
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task_time";
|
||||||
|
$sql .= " SET thm = (SELECT thm FROM ".MAIN_DB_PREFIX."user WHERE rowid = ".((int) $this->timespent_fk_user).")"; // set average hour rate of user
|
||||||
|
$sql .= " WHERE (thm IS NULL OR thm = 0) AND rowid = ".((int) $this->timespent_id);
|
||||||
|
|
||||||
|
dol_syslog(get_class($this)."::addTimeSpent", LOG_DEBUG);
|
||||||
|
if (!$this->db->query($sql)) {
|
||||||
|
$this->error = $this->db->lasterror();
|
||||||
|
$ret = -2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ret >= 0) {
|
if ($ret >= 0) {
|
||||||
|
|||||||
@@ -262,10 +262,10 @@ if (($action == 'updateline' || $action == 'updatesplitline') && !$cancel && $us
|
|||||||
$object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
|
$object->timespent_duration = GETPOSTINT("new_durationhour") * 60 * 60; // We store duration in seconds
|
||||||
$object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
|
$object->timespent_duration += (GETPOSTINT("new_durationmin") ? GETPOSTINT('new_durationmin') : 0) * 60; // We store duration in seconds
|
||||||
if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
|
if (GETPOST("timelinehour") != '' && GETPOST("timelinehour") >= 0) { // If hour was entered
|
||||||
$object->timespent_date = dol_mktime(GETPOST("timelinehour"), GETPOST("timelinemin"), 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
|
$object->timespent_date = dol_mktime(GETPOST("timelinehour", 'int'), GETPOST("timelinemin", 'int'), 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int'));
|
||||||
$object->timespent_withhour = 1;
|
$object->timespent_withhour = 1;
|
||||||
} else {
|
} else {
|
||||||
$object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth"), GETPOST("timelineday"), GETPOST("timelineyear"));
|
$object->timespent_date = dol_mktime(12, 0, 0, GETPOST("timelinemonth", 'int'), GETPOST("timelineday", 'int'), GETPOST("timelineyear", 'int'));
|
||||||
}
|
}
|
||||||
$object->timespent_fk_user = GETPOST("userid_line", 'int');
|
$object->timespent_fk_user = GETPOST("userid_line", 'int');
|
||||||
|
|
||||||
@@ -354,6 +354,13 @@ if ($action == 'confirm_generateinvoice') {
|
|||||||
$prodDurationHours = 1.0;
|
$prodDurationHours = 1.0;
|
||||||
if ($idprod > 0) {
|
if ($idprod > 0) {
|
||||||
$tmpproduct->fetch($idprod);
|
$tmpproduct->fetch($idprod);
|
||||||
|
|
||||||
|
if (empty($tmpproduct->duration_value)) {
|
||||||
|
$error++;
|
||||||
|
$langs->load("errors");
|
||||||
|
setEventMessages($langs->trans("ErrorDurationForServiceNotDefinedCantCalculateHourlyPrice"), null, 'errors');
|
||||||
|
}
|
||||||
|
|
||||||
if ($tmpproduct->duration_unit == 'i') {
|
if ($tmpproduct->duration_unit == 'i') {
|
||||||
$prodDurationHours = 1. / 60;
|
$prodDurationHours = 1. / 60;
|
||||||
}
|
}
|
||||||
@@ -381,6 +388,8 @@ if ($action == 'confirm_generateinvoice') {
|
|||||||
$localtax1 = $dataforprice['localtax1'];
|
$localtax1 = $dataforprice['localtax1'];
|
||||||
$localtax2 = $dataforprice['localtax2'];
|
$localtax2 = $dataforprice['localtax2'];
|
||||||
} else {
|
} else {
|
||||||
|
$prodDurationHours = 1;
|
||||||
|
|
||||||
$pu_ht = 0;
|
$pu_ht = 0;
|
||||||
$txtva = get_default_tva($mysoc, $projectstatic->thirdparty);
|
$txtva = get_default_tva($mysoc, $projectstatic->thirdparty);
|
||||||
$localtax1 = get_default_localtax($mysoc, $projectstatic->thirdparty, 1);
|
$localtax1 = get_default_localtax($mysoc, $projectstatic->thirdparty, 1);
|
||||||
@@ -483,14 +492,14 @@ if ($action == 'confirm_generateinvoice') {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elseif ($generateinvoicemode == 'onelinepertask') {
|
} elseif ($generateinvoicemode == 'onelinepertask') { // One line for each different task
|
||||||
$arrayoftasks = array();
|
$arrayoftasks = array();
|
||||||
foreach ($toselect as $key => $value) {
|
foreach ($toselect as $key => $value) {
|
||||||
// Get userid, timepent
|
// Get userid, timepent
|
||||||
$object->fetchTimeSpent($value);
|
$object->fetchTimeSpent($value); // Call method to get list of timespent for a timespent line id (We use the utiliy method found into Task object)
|
||||||
// $object->id is the task id
|
// $object->id is now the task id
|
||||||
$arrayoftasks[$object->id]['timespent'] += $object->timespent_duration;
|
$arrayoftasks[$object->id]['timespent'] += $object->timespent_duration;
|
||||||
$arrayoftasks[$object->id]['totalvaluetodivideby3600'] += $object->timespent_duration * $object->timespent_thm;
|
$arrayoftasks[$object->id]['totalvaluetodivideby3600'] += ($object->timespent_duration * $object->timespent_thm);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($arrayoftasks as $task_id => $value) {
|
foreach ($arrayoftasks as $task_id => $value) {
|
||||||
@@ -500,24 +509,46 @@ if ($action == 'confirm_generateinvoice') {
|
|||||||
$qtyhour = $value['timespent'] / 3600;
|
$qtyhour = $value['timespent'] / 3600;
|
||||||
$qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
|
$qtyhourtext = convertSecondToTime($value['timespent'], 'all', $conf->global->MAIN_DURATION_OF_WORKDAY);
|
||||||
|
|
||||||
// If no unit price known
|
if ($idprod > 0) {
|
||||||
if (empty($pu_ht)) {
|
// If a product is defined, we msut use the $prodDurationHours and $pu_ht of product (already set previously).
|
||||||
$pu_ht = price2num($value['totalvaluetodivideby3600'] / 3600, 'MU');
|
$pu_ht_for_task = $pu_ht;
|
||||||
|
// If we want to reuse the value of timespent (so use same price than cost price)
|
||||||
|
if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) {
|
||||||
|
$pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours;
|
||||||
|
}
|
||||||
|
$pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU') * $prodDurationHours;
|
||||||
|
} else {
|
||||||
|
// If not product used, we use the hour unit for duration and unit price.
|
||||||
|
$pu_ht_for_task = 0;
|
||||||
|
// If we want to reuse the value of timespent (so use same price than cost price)
|
||||||
|
if (!empty($conf->global->PROJECT_TIME_SPENT_INTO_INVOICE_USE_VALUE)) {
|
||||||
|
$pu_ht_for_task = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU');
|
||||||
|
}
|
||||||
|
$pa_ht = price2num($value['totalvaluetodivideby3600'] / $value['timespent'], 'MU');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add lines
|
// Add lines
|
||||||
|
$date_start = '';
|
||||||
|
$date_end = '';
|
||||||
$lineName = $ftask->ref.' - '.$ftask->label;
|
$lineName = $ftask->ref.' - '.$ftask->label;
|
||||||
$lineid = $tmpinvoice->addline($lineName, $pu_ht, round($qtyhour / $prodDurationHours, 2), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0));
|
$lineid = $tmpinvoice->addline($lineName, $pu_ht_for_task, price2num($qtyhour / $prodDurationHours, 'MS'), $txtva, $localtax1, $localtax2, ($idprod > 0 ? $idprod : 0), 0, $date_start, $date_end, 0, 0, '', 'HT', 0, 1, -1, 0, '', 0, 0, null, $pa_ht);
|
||||||
|
if ($lineid < 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);
|
|
||||||
$sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).')';
|
|
||||||
$result = $db->query($sql);
|
|
||||||
if (!$result) {
|
|
||||||
$error++;
|
$error++;
|
||||||
setEventMessages($db->lasterror(), null, 'errors');
|
setEventMessages($tmpinvoice->error, $tmpinvoice->errors, 'errors');
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!$error) {
|
||||||
|
// 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);
|
||||||
|
$sql .= ' WHERE rowid IN ('.$db->sanitize(join(',', $toselect)).')';
|
||||||
|
$result = $db->query($sql);
|
||||||
|
if (!$result) {
|
||||||
|
$error++;
|
||||||
|
setEventMessages($db->lasterror(), null, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1042,7 +1073,7 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
|
|||||||
print '<input type="hidden" name="massaction" value="confirm_createbills">';
|
print '<input type="hidden" name="massaction" value="confirm_createbills">';
|
||||||
|
|
||||||
if ($projectstatic->thirdparty->id > 0) {
|
if ($projectstatic->thirdparty->id > 0) {
|
||||||
print '<table class="noborder" width="100%" >';
|
print '<table class="noborder centerpercent">';
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
print '<td class="titlefield">';
|
print '<td class="titlefield">';
|
||||||
print $langs->trans('DateInvoice');
|
print $langs->trans('DateInvoice');
|
||||||
@@ -1464,11 +1495,11 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
print '<tr class="oddeven">';
|
|
||||||
|
|
||||||
$date1 = $db->jdate($task_time->task_date);
|
$date1 = $db->jdate($task_time->task_date);
|
||||||
$date2 = $db->jdate($task_time->task_datehour);
|
$date2 = $db->jdate($task_time->task_datehour);
|
||||||
|
|
||||||
|
print '<tr class="oddeven">';
|
||||||
|
|
||||||
// Date
|
// Date
|
||||||
if (!empty($arrayfields['t.task_date']['checked'])) {
|
if (!empty($arrayfields['t.task_date']['checked'])) {
|
||||||
print '<td class="nowrap">';
|
print '<td class="nowrap">';
|
||||||
@@ -1592,9 +1623,13 @@ if (($id > 0 || !empty($ref)) || $projectidforalltimes > 0) {
|
|||||||
|
|
||||||
// Value spent
|
// Value spent
|
||||||
if (!empty($arrayfields['value']['checked'])) {
|
if (!empty($arrayfields['value']['checked'])) {
|
||||||
|
$langs->load("salaries");
|
||||||
|
|
||||||
print '<td class="nowraponall right">';
|
print '<td class="nowraponall right">';
|
||||||
$value = price2num($task_time->thm * $task_time->task_duration / 3600, 'MT', 1);
|
$value = price2num($task_time->thm * $task_time->task_duration / 3600, 'MT', 1);
|
||||||
|
print '<span class="amount" title="'.$langs->trans("THM").': '.price($task_time->thm).'">';
|
||||||
print price($value, 1, $langs, 1, -1, -1, $conf->currency);
|
print price($value, 1, $langs, 1, -1, -1, $conf->currency);
|
||||||
|
print '</span>';
|
||||||
print '</td>';
|
print '</td>';
|
||||||
if (!$i) {
|
if (!$i) {
|
||||||
$totalarray['nbfield']++;
|
$totalarray['nbfield']++;
|
||||||
|
|||||||
Reference in New Issue
Block a user