This commit is contained in:
Laurent Destailleur 2021-08-25 14:53:14 +02:00
parent d022b3b0a1
commit 65629711d0
4 changed files with 124 additions and 80 deletions

View File

@ -631,6 +631,8 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
$createbills_onebythird = GETPOST('createbills_onebythird', 'int'); $createbills_onebythird = GETPOST('createbills_onebythird', 'int');
$validate_invoices = GETPOST('validate_invoices', 'int'); $validate_invoices = GETPOST('validate_invoices', 'int');
$errors = array();
$TFact = array(); $TFact = array();
$TFactThird = array(); $TFactThird = array();
@ -645,18 +647,19 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
if ($cmd->fetch($id_order) <= 0) { if ($cmd->fetch($id_order) <= 0) {
continue; continue;
} }
$cmd->fetch_thirdparty();
$objecttmp = new Facture($db); $objecttmp = new Facture($db);
if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) { if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) {
$objecttmp = $TFactThird[$cmd->socid]; // If option "one bill per third" is set, we use already created order. // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it.
$objecttmp = $TFactThird[$cmd->socid];
} else { } else {
// Load extrafields of order // If we want one invoice per order or if there is no first invoice yet for this thirdparty.
$cmd->fetch_optionals();
$objecttmp->socid = $cmd->socid; $objecttmp->socid = $cmd->socid;
$objecttmp->type = $objecttmp::TYPE_STANDARD; $objecttmp->type = $objecttmp::TYPE_STANDARD;
$objecttmp->cond_reglement_id = $cmd->cond_reglement_id; $objecttmp->cond_reglement_id = ($cmd->cond_reglement_id || $cmd->thirdparty->cond_reglement_id);
$objecttmp->mode_reglement_id = $cmd->mode_reglement_id; $objecttmp->mode_reglement_id = ($cmd->mode_reglement_id || $cmd->thirdparty->mode_reglement_id);
$objecttmp->fk_project = $cmd->fk_project; $objecttmp->fk_project = $cmd->fk_project;
$objecttmp->multicurrency_code = $cmd->multicurrency_code; $objecttmp->multicurrency_code = $cmd->multicurrency_code;
if (empty($createbills_onebythird)) { if (empty($createbills_onebythird)) {
@ -680,23 +683,20 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
$nb_bills_created++; $nb_bills_created++;
$lastref = $objecttmp->ref; $lastref = $objecttmp->ref;
$lastid = $objecttmp->id; $lastid = $objecttmp->id;
$TFactThird[$cmd->socid] = $objecttmp;
} else {
$langs->load("errors");
$errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->error);
$error++;
} }
} }
if ($objecttmp->id > 0) { if ($objecttmp->id > 0) {
$sql = "INSERT INTO ".MAIN_DB_PREFIX."element_element ("; $res = $objecttmp->add_object_linked($objecttmp->origin, $id_order);
$sql .= "fk_source";
$sql .= ", sourcetype";
$sql .= ", fk_target";
$sql .= ", targettype";
$sql .= ") VALUES (";
$sql .= $id_order;
$sql .= ", '".$db->escape($objecttmp->origin)."'";
$sql .= ", ".$objecttmp->id;
$sql .= ", '".$db->escape($objecttmp->element)."'";
$sql .= ")";
if (!$db->query($sql)) { if ($res == 0) {
$errors[] = $objecttmp->error;
$error++; $error++;
} }
@ -845,7 +845,6 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
} }
$id = $objecttmp->id; // For builddoc action $id = $objecttmp->id; // For builddoc action
$object = $objecttmp;
// Builddoc // Builddoc
$donotredirect = 1; $donotredirect = 1;
@ -949,6 +948,7 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
exit; exit;
} else { } else {
$db->rollback(); $db->rollback();
$action = 'create'; $action = 'create';
$_GET["origin"] = $_POST["origin"]; $_GET["origin"] = $_POST["origin"];
$_GET["originid"] = $_POST["originid"]; $_GET["originid"] = $_POST["originid"];

View File

@ -3611,9 +3611,9 @@ abstract class CommonObject
$sql .= ", fk_target"; $sql .= ", fk_target";
$sql .= ", targettype"; $sql .= ", targettype";
$sql .= ") VALUES ("; $sql .= ") VALUES (";
$sql .= $origin_id; $sql .= ((int) $origin_id);
$sql .= ", '" . $this->db->escape($origin) . "'"; $sql .= ", '" . $this->db->escape($origin) . "'";
$sql .= ", " . $this->id; $sql .= ", " . ((int) $this->id);
$sql .= ", '" . $this->db->escape($this->element) . "'"; $sql .= ", '" . $this->db->escape($this->element) . "'";
$sql .= ")"; $sql .= ")";

View File

@ -151,6 +151,7 @@ PDFEdisonDescription=A simple order model
PDFProformaDescription=A complete Proforma invoice template PDFProformaDescription=A complete Proforma invoice template
CreateInvoiceForThisCustomer=Bill orders CreateInvoiceForThisCustomer=Bill orders
CreateInvoiceForThisSupplier=Bill orders CreateInvoiceForThisSupplier=Bill orders
CreateInvoiceForThisReceptions=Bill receptions
NoOrdersToInvoice=No orders billable NoOrdersToInvoice=No orders billable
CloseProcessedOrdersAutomatically=Classify "Processed" all selected orders. CloseProcessedOrdersAutomatically=Classify "Processed" all selected orders.
OrderCreation=Order creation OrderCreation=Order creation

View File

@ -171,88 +171,103 @@ if (empty($reshook)) {
$createbills_onebythird = GETPOST('createbills_onebythird', 'int'); $createbills_onebythird = GETPOST('createbills_onebythird', 'int');
$validate_invoices = GETPOST('validate_invoices', 'int'); $validate_invoices = GETPOST('validate_invoices', 'int');
$errors = array();
$TFact = array(); $TFact = array();
$TFactThird = array(); $TFactThird = array();
$nb_bills_created = 0; $nb_bills_created = 0;
$lastid= 0;
$lastref = '';
$db->begin(); $db->begin();
$errors = array();
foreach ($receptions as $id_reception) { foreach ($receptions as $id_reception) {
$rcp = new Reception($db); $rcp = new Reception($db);
// On ne facture que les réceptions validées // We only invoice reception that are validated
if ($rcp->fetch($id_reception) <= 0 || $rcp->statut != 1) { if ($rcp->fetch($id_reception) <= 0 || $rcp->statut != $rcp::STATUS_VALIDATED) {
$errors[] = $langs->trans('StatusOfRefMustBe', $rcp->ref, $langs->transnoentities("StatusSupplierOrderValidatedShort")); $errors[] = $langs->trans('StatusOfRefMustBe', $rcp->ref, $langs->transnoentities("StatusSupplierOrderValidatedShort"));
$error++; $error++;
continue; continue;
} }
$object = new FactureFournisseur($db); $objecttmp = new FactureFournisseur($db);
if (!empty($createbills_onebythird) && !empty($TFactThird[$rcp->socid])) { if (!empty($createbills_onebythird) && !empty($TFactThird[$rcp->socid])) {
$object = $TFactThird[$rcp->socid]; // If option "one bill per third" is set, we use already created reception. // If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it.
if (empty($object->rowid) && $object->id != null) { $objecttmp = $TFactThird[$rcp->socid];
$object->rowid = $object->id;
}
if (!empty($object->rowid)) {
$object->fetchObjectLinked();
}
$rcp->fetchObjectLinked();
if (count($rcp->linkedObjectsIds['reception']) > 0) { // Add all links of this new reception to the existing invoice
foreach ($rcp->linkedObjectsIds['reception'] as $key => $value) { $objecttmp->fetchObjectLinked();
if (empty($object->linkedObjectsIds['reception']) || !in_array($value, $object->linkedObjectsIds['reception'])) { //Dont try to link if already linked $rcp->fetchObjectLinked();
$object->add_object_linked('reception', $value); // add supplier order linked object if (count($rcp->linkedObjectsIds['order_supplier']) > 0) {
foreach ($rcp->linkedObjectsIds['order_supplier'] as $key => $value) {
if (empty($objecttmp->linkedObjectsIds['order_supplier']) || !in_array($value, $objecttmp->linkedObjectsIds['order_supplier'])) { //Dont try to link if already linked
$objecttmp->add_object_linked('order_supplier', $value); // add supplier order linked object
} }
} }
} }
} else { } else {
$object->socid = $rcp->socid; // If we want one invoice per reception or if there is no first invoice yet for this thirdparty.
$object->type = FactureFournisseur::TYPE_STANDARD; $objecttmp->socid = $rcp->socid;
$object->cond_reglement_id = $rcp->thirdparty->cond_reglement_supplier_id; $objecttmp->type = $objecttmp::TYPE_STANDARD;
$object->mode_reglement_id = $rcp->thirdparty->mode_reglement_supplier_id; $objecttmp->cond_reglement_id = $rcp->cond_reglement_id || $rcp->thirdparty->cond_reglement_supplier_id;
$object->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0; $objecttmp->mode_reglement_id = $rcp->mode_reglement_id || $rcp->thirdparty->mode_reglement_supplier_id;
$object->remise_percent = !empty($rcp->thirdparty->remise_percent) ? $rcp->thirdparty->remise_percent : 0;
$object->remise_absolue = !empty($rcp->thirdparty->remise_absolue) ? $rcp->thirdparty->remise_absolue : 0;
$object->fk_project = $rcp->fk_project; $objecttmp->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0;
$object->ref_supplier = $rcp->ref_supplier; $objecttmp->remise_percent = !empty($rcp->thirdparty->remise_percent) ? $rcp->thirdparty->remise_percent : 0;
$objecttmp->remise_absolue = !empty($rcp->thirdparty->remise_absolue) ? $rcp->thirdparty->remise_absolue : 0;
$datefacture = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')); $objecttmp->fk_project = $rcp->fk_project;
//$objecttmp->multicurrency_code = $rcp->multicurrency_code;
if (empty($createbills_onebythird)) {
$objecttmp->ref_supplier = $rcp->ref;
} else {
// Set a unique value for the invoice for the n reception
$objecttmp->ref_supplier = $langs->trans("Reception").' '.dol_print_date(dol_now(), 'dayhourlog').'-'.$rcp->socid;
}
$datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
if (empty($datefacture)) { if (empty($datefacture)) {
$datefacture = dol_mktime(date("h"), date("M"), 0, date("m"), date("d"), date("Y")); $datefacture = dol_now();
} }
$object->date = $datefacture; $objecttmp->date = $datefacture;
$object->origin = 'reception'; $objecttmp->origin = 'reception';
$object->origin_id = $id_reception; $objecttmp->origin_id = $id_reception;
$objecttmp->array_options = $rcp->array_options; // Copy extrafields
// Set $objecttmp->linked_objects with all links order_supplier existing on reception, so same links will be added to the generated supplier invoice
$rcp->fetchObjectLinked(); $rcp->fetchObjectLinked();
if (count($rcp->linkedObjectsIds['reception']) > 0) { if (count($rcp->linkedObjectsIds['order_supplier']) > 0) {
foreach ($rcp->linkedObjectsIds['reception'] as $key => $value) { foreach ($rcp->linkedObjectsIds['order_supplier'] as $key => $value) {
$object->linked_objects['reception'] = $value; $objecttmp->linked_objects['order_supplier'] = $value;
} }
} }
$res = $object->create($user); $res = $objecttmp->create($user); // This should create the supplier invoice + links into $objecttmp->linked_objects + add a link to ->origin_id
//var_dump($object->error);exit;
//var_dump($objecttmp->error);exit;
if ($res > 0) { if ($res > 0) {
$nb_bills_created++; $nb_bills_created++;
$object->id = $res; $lastref = $objecttmp->ref;
$lastid = $objecttmp->id;
$TFactThird[$rcp->socid] = $objecttmp;
} else { } else {
$errors[] = $rcp->ref.' : '.$langs->trans($object->error); $langs->load("errors");
$errors[] = $rcp->ref.' : '.$langs->trans($objecttmp->error);
$error++; $error++;
} }
} }
if ($object->id > 0) { if ($objecttmp->id > 0) {
if (!empty($createbills_onebythird) && !empty($TFactThird[$rcp->socid])) { //cause function create already add object linked for facturefournisseur $res = $objecttmp->add_object_linked($objecttmp->origin, $id_reception);
$res = $object->add_object_linked($object->origin, $id_reception);
if ($res == 0) { if ($res == 0) {
$errors[] = $object->error; $errors[] = $objecttmp->error;
$error++; $error++;
} }
}
if (!$error) { if (!$error) {
$lines = $rcp->lines; $lines = $rcp->lines;
@ -266,10 +281,15 @@ if (empty($reshook)) {
for ($i = 0; $i < $num; $i++) { for ($i = 0; $i < $num; $i++) {
$desc = ($lines[$i]->desc ? $lines[$i]->desc : $lines[$i]->libelle); $desc = ($lines[$i]->desc ? $lines[$i]->desc : $lines[$i]->libelle);
// If we build one invoice for several reception, we must put the ref of reception on the invoice line
if (!empty($createbills_onebythird)) {
$desc = dol_concatdesc($desc, $langs->trans("Reception").' '.$rcp->ref.' - '.dol_print_date($rcp->date, 'day'));
}
if ($lines[$i]->subprice < 0) { if ($lines[$i]->subprice < 0) {
// Negative line, we create a discount line // Negative line, we create a discount line
$discount = new DiscountAbsolute($db); $discount = new DiscountAbsolute($db);
$discount->fk_soc = $object->socid; $discount->fk_soc = $objecttmp->socid;
$discount->amount_ht = abs($lines[$i]->total_ht); $discount->amount_ht = abs($lines[$i]->total_ht);
$discount->amount_tva = abs($lines[$i]->total_tva); $discount->amount_tva = abs($lines[$i]->total_tva);
$discount->amount_ttc = abs($lines[$i]->total_ttc); $discount->amount_ttc = abs($lines[$i]->total_ttc);
@ -278,7 +298,7 @@ if (empty($reshook)) {
$discount->description = $desc; $discount->description = $desc;
$discountid = $discount->create($user); $discountid = $discount->create($user);
if ($discountid > 0) { if ($discountid > 0) {
$result = $object->insert_discount($discountid); $result = $objecttmp->insert_discount($discountid);
//$result=$discount->link_to_invoice($lineid,$id); //$result=$discount->link_to_invoice($lineid,$id);
} else { } else {
setEventMessages($discount->error, $discount->errors, 'errors'); setEventMessages($discount->error, $discount->errors, 'errors');
@ -314,7 +334,16 @@ if (empty($reshook)) {
if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
$fk_parent_line = 0; $fk_parent_line = 0;
} }
$result = $object->addline(
// Extrafields
if (method_exists($lines[$i], 'fetch_optionals')) {
$lines[$i]->fetch_optionals();
$array_options = $lines[$i]->array_options;
}
$objecttmp->context['createfromclone'];
$result = $objecttmp->addline(
$desc, $desc,
$lines[$i]->subprice, $lines[$i]->subprice,
$lines[$i]->tva_tx, $lines[$i]->tva_tx,
@ -359,9 +388,9 @@ if (empty($reshook)) {
//$rcp->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module. //$rcp->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module.
if (!empty($createbills_onebythird) && empty($TFactThird[$rcp->socid])) { if (!empty($createbills_onebythird) && empty($TFactThird[$rcp->socid])) {
$TFactThird[$rcp->socid] = $object; $TFactThird[$rcp->socid] = $objecttmp;
} else { } else {
$TFact[$object->id] = $object; $TFact[$objecttmp->id] = $objecttmp;
} }
} }
@ -371,21 +400,27 @@ if (empty($reshook)) {
if (!$error && $validate_invoices) { if (!$error && $validate_invoices) {
$massaction = $action = 'builddoc'; $massaction = $action = 'builddoc';
foreach ($TAllFact as &$object) { foreach ($TAllFact as &$objecttmp) {
$result = $object->validate($user); $result = $objecttmp->validate($user);
if ($result <= 0) { if ($result <= 0) {
$error++; $error++;
setEventMessages($object->error, $object->errors, 'errors'); setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
break; break;
} }
$id = $object->id; // For builddoc action $id = $objecttmp->id; // For builddoc action
$object =$objecttmp;
// Fac builddoc // Fac builddoc
$donotredirect = 1; $donotredirect = 1;
$upload_dir = $conf->fournisseur->facture->dir_output; $upload_dir = $conf->fournisseur->facture->dir_output;
$permissiontoadd = ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer); $permissiontoadd = ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer);
// Call action to build doc
$savobject = $object;
$object = $objecttmp;
include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php'; include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
$object = $savobject;
} }
$massaction = $action = 'confirm_createbills'; $massaction = $action = 'confirm_createbills';
@ -393,9 +428,17 @@ if (empty($reshook)) {
if (!$error) { if (!$error) {
$db->commit(); $db->commit();
setEventMessage($langs->trans('BillCreated', $nb_bills_created));
if ($nb_bills_created == 1) {
$texttoshow = $langs->trans('BillXCreated', '{s1}');
$texttoshow = str_replace('{s1}', '<a href="'.DOL_URL_ROOT.'/fourn/facture/card.php?id='.urlencode($lastid).'">'.$lastref.'</a>', $texttoshow);
setEventMessages($texttoshow, null, 'mesgs');
} else {
setEventMessages($langs->trans('BillCreated', $nb_bills_created), null, 'mesgs');
}
} else { } else {
$db->rollback(); $db->rollback();
$action = 'create'; $action = 'create';
$_GET["origin"] = $_POST["origin"]; $_GET["origin"] = $_POST["origin"];
$_GET["originid"] = $_POST["originid"]; $_GET["originid"] = $_POST["originid"];
@ -597,7 +640,7 @@ $arrayofmassactions = array(
); );
if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) { if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) {
$arrayofmassactions['createbills'] = $langs->trans("CreateInvoiceForThisSupplier"); $arrayofmassactions['createbills'] = $langs->trans("CreateInvoiceForThisReceptions");
} }
if ($massaction == 'createbills') { if ($massaction == 'createbills') {
$arrayofmassactions = array(); $arrayofmassactions = array();
@ -656,7 +699,7 @@ if ($massaction == 'createbills') {
print '<br>'; print '<br>';
print '<div class="center">'; print '<div class="center">';
print '<input type="submit" class="button" id="createbills" name="createbills" value="'.$langs->trans('CreateInvoiceForThisSupplier').'"> '; print '<input type="submit" class="button" id="createbills" name="createbills" value="'.$langs->trans('CreateInvoiceForThisReceptions').'"> ';
print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">'; print '<input type="submit" class="button button-cancel" id="cancel" name="cancel" value="'.$langs->trans("Cancel").'">';
print '</div>'; print '</div>';
print '<br>'; print '<br>';