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');
$validate_invoices = GETPOST('validate_invoices', 'int');
$errors = array();
$TFact = array();
$TFactThird = array();
@ -645,18 +647,19 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
if ($cmd->fetch($id_order) <= 0) {
continue;
}
$cmd->fetch_thirdparty();
$objecttmp = new Facture($db);
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 {
// Load extrafields of order
$cmd->fetch_optionals();
// If we want one invoice per order or if there is no first invoice yet for this thirdparty.
$objecttmp->socid = $cmd->socid;
$objecttmp->type = $objecttmp::TYPE_STANDARD;
$objecttmp->cond_reglement_id = $cmd->cond_reglement_id;
$objecttmp->mode_reglement_id = $cmd->mode_reglement_id;
$objecttmp->cond_reglement_id = ($cmd->cond_reglement_id || $cmd->thirdparty->cond_reglement_id);
$objecttmp->mode_reglement_id = ($cmd->mode_reglement_id || $cmd->thirdparty->mode_reglement_id);
$objecttmp->fk_project = $cmd->fk_project;
$objecttmp->multicurrency_code = $cmd->multicurrency_code;
if (empty($createbills_onebythird)) {
@ -680,23 +683,20 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
$nb_bills_created++;
$lastref = $objecttmp->ref;
$lastid = $objecttmp->id;
$TFactThird[$cmd->socid] = $objecttmp;
} else {
$langs->load("errors");
$errors[] = $cmd->ref.' : '.$langs->trans($objecttmp->error);
$error++;
}
}
if ($objecttmp->id > 0) {
$sql = "INSERT INTO ".MAIN_DB_PREFIX."element_element (";
$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 .= ")";
$res = $objecttmp->add_object_linked($objecttmp->origin, $id_order);
if (!$db->query($sql)) {
if ($res == 0) {
$errors[] = $objecttmp->error;
$error++;
}
@ -845,7 +845,6 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
}
$id = $objecttmp->id; // For builddoc action
$object = $objecttmp;
// Builddoc
$donotredirect = 1;
@ -854,7 +853,7 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
// Call action to build doc
$savobject = $object;
$object = $objecttmp;
$object = $objecttmp;
include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
$object = $savobject;
}
@ -949,6 +948,7 @@ if ($massaction == 'confirm_createbills') { // Create bills from orders.
exit;
} else {
$db->rollback();
$action = 'create';
$_GET["origin"] = $_POST["origin"];
$_GET["originid"] = $_POST["originid"];

View File

@ -3577,7 +3577,7 @@ abstract class CommonObject
* @param string $origin Linked element type
* @param int $origin_id Linked element id
* @param User $f_user User that create
* @param int $notrigger 1=Does not execute triggers, 0= execute triggers
* @param int $notrigger 1=Does not execute triggers, 0=execute triggers
* @return int <=0 if KO, >0 if OK
* @see fetchObjectLinked(), updateObjectLinked(), deleteObjectLinked()
*/
@ -3611,9 +3611,9 @@ abstract class CommonObject
$sql .= ", fk_target";
$sql .= ", targettype";
$sql .= ") VALUES (";
$sql .= $origin_id;
$sql .= ((int) $origin_id);
$sql .= ", '" . $this->db->escape($origin) . "'";
$sql .= ", " . $this->id;
$sql .= ", " . ((int) $this->id);
$sql .= ", '" . $this->db->escape($this->element) . "'";
$sql .= ")";

View File

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

View File

@ -171,87 +171,102 @@ if (empty($reshook)) {
$createbills_onebythird = GETPOST('createbills_onebythird', 'int');
$validate_invoices = GETPOST('validate_invoices', 'int');
$errors = array();
$TFact = array();
$TFactThird = array();
$nb_bills_created = 0;
$lastid= 0;
$lastref = '';
$db->begin();
$errors = array();
foreach ($receptions as $id_reception) {
$rcp = new Reception($db);
// On ne facture que les réceptions validées
if ($rcp->fetch($id_reception) <= 0 || $rcp->statut != 1) {
// We only invoice reception that are validated
if ($rcp->fetch($id_reception) <= 0 || $rcp->statut != $rcp::STATUS_VALIDATED) {
$errors[] = $langs->trans('StatusOfRefMustBe', $rcp->ref, $langs->transnoentities("StatusSupplierOrderValidatedShort"));
$error++;
continue;
}
$object = new FactureFournisseur($db);
$objecttmp = new FactureFournisseur($db);
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 (empty($object->rowid) && $object->id != null) {
$object->rowid = $object->id;
}
if (!empty($object->rowid)) {
$object->fetchObjectLinked();
}
$rcp->fetchObjectLinked();
// If option "one bill per third" is set, and an invoice for this thirdparty was already created, we re-use it.
$objecttmp = $TFactThird[$rcp->socid];
if (count($rcp->linkedObjectsIds['reception']) > 0) {
foreach ($rcp->linkedObjectsIds['reception'] as $key => $value) {
if (empty($object->linkedObjectsIds['reception']) || !in_array($value, $object->linkedObjectsIds['reception'])) { //Dont try to link if already linked
$object->add_object_linked('reception', $value); // add supplier order linked object
// Add all links of this new reception to the existing invoice
$objecttmp->fetchObjectLinked();
$rcp->fetchObjectLinked();
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 {
$object->socid = $rcp->socid;
$object->type = FactureFournisseur::TYPE_STANDARD;
$object->cond_reglement_id = $rcp->thirdparty->cond_reglement_supplier_id;
$object->mode_reglement_id = $rcp->thirdparty->mode_reglement_supplier_id;
$object->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0;
$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;
// If we want one invoice per reception or if there is no first invoice yet for this thirdparty.
$objecttmp->socid = $rcp->socid;
$objecttmp->type = $objecttmp::TYPE_STANDARD;
$objecttmp->cond_reglement_id = $rcp->cond_reglement_id || $rcp->thirdparty->cond_reglement_supplier_id;
$objecttmp->mode_reglement_id = $rcp->mode_reglement_id || $rcp->thirdparty->mode_reglement_supplier_id;
$object->fk_project = $rcp->fk_project;
$object->ref_supplier = $rcp->ref_supplier;
$objecttmp->fk_account = !empty($rcp->thirdparty->fk_account) ? $rcp->thirdparty->fk_account : 0;
$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'));
if (empty($datefacture)) {
$datefacture = dol_mktime(date("h"), date("M"), 0, date("m"), date("d"), date("Y"));
$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;
}
$object->date = $datefacture;
$object->origin = 'reception';
$object->origin_id = $id_reception;
$datefacture = dol_mktime(12, 0, 0, GETPOST('remonth', 'int'), GETPOST('reday', 'int'), GETPOST('reyear', 'int'));
if (empty($datefacture)) {
$datefacture = dol_now();
}
$objecttmp->date = $datefacture;
$objecttmp->origin = '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();
if (count($rcp->linkedObjectsIds['reception']) > 0) {
foreach ($rcp->linkedObjectsIds['reception'] as $key => $value) {
$object->linked_objects['reception'] = $value;
if (count($rcp->linkedObjectsIds['order_supplier']) > 0) {
foreach ($rcp->linkedObjectsIds['order_supplier'] as $key => $value) {
$objecttmp->linked_objects['order_supplier'] = $value;
}
}
$res = $object->create($user);
//var_dump($object->error);exit;
$res = $objecttmp->create($user); // This should create the supplier invoice + links into $objecttmp->linked_objects + add a link to ->origin_id
//var_dump($objecttmp->error);exit;
if ($res > 0) {
$nb_bills_created++;
$object->id = $res;
$lastref = $objecttmp->ref;
$lastid = $objecttmp->id;
$TFactThird[$rcp->socid] = $objecttmp;
} else {
$errors[] = $rcp->ref.' : '.$langs->trans($object->error);
$langs->load("errors");
$errors[] = $rcp->ref.' : '.$langs->trans($objecttmp->error);
$error++;
}
}
if ($object->id > 0) {
if (!empty($createbills_onebythird) && !empty($TFactThird[$rcp->socid])) { //cause function create already add object linked for facturefournisseur
$res = $object->add_object_linked($object->origin, $id_reception);
if ($objecttmp->id > 0) {
$res = $objecttmp->add_object_linked($objecttmp->origin, $id_reception);
if ($res == 0) {
$errors[] = $object->error;
$error++;
}
if ($res == 0) {
$errors[] = $objecttmp->error;
$error++;
}
if (!$error) {
@ -266,10 +281,15 @@ if (empty($reshook)) {
for ($i = 0; $i < $num; $i++) {
$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) {
// Negative line, we create a discount line
$discount = new DiscountAbsolute($db);
$discount->fk_soc = $object->socid;
$discount->fk_soc = $objecttmp->socid;
$discount->amount_ht = abs($lines[$i]->total_ht);
$discount->amount_tva = abs($lines[$i]->total_tva);
$discount->amount_ttc = abs($lines[$i]->total_ttc);
@ -278,7 +298,7 @@ if (empty($reshook)) {
$discount->description = $desc;
$discountid = $discount->create($user);
if ($discountid > 0) {
$result = $object->insert_discount($discountid);
$result = $objecttmp->insert_discount($discountid);
//$result=$discount->link_to_invoice($lineid,$id);
} else {
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) {
$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,
$lines[$i]->subprice,
$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.
if (!empty($createbills_onebythird) && empty($TFactThird[$rcp->socid])) {
$TFactThird[$rcp->socid] = $object;
$TFactThird[$rcp->socid] = $objecttmp;
} else {
$TFact[$object->id] = $object;
$TFact[$objecttmp->id] = $objecttmp;
}
}
@ -371,21 +400,27 @@ if (empty($reshook)) {
if (!$error && $validate_invoices) {
$massaction = $action = 'builddoc';
foreach ($TAllFact as &$object) {
$result = $object->validate($user);
foreach ($TAllFact as &$objecttmp) {
$result = $objecttmp->validate($user);
if ($result <= 0) {
$error++;
setEventMessages($object->error, $object->errors, 'errors');
setEventMessages($objecttmp->error, $objecttmp->errors, 'errors');
break;
}
$id = $object->id; // For builddoc action
$id = $objecttmp->id; // For builddoc action
$object =$objecttmp;
// Fac builddoc
$donotredirect = 1;
$upload_dir = $conf->fournisseur->facture->dir_output;
$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';
$object = $savobject;
}
$massaction = $action = 'confirm_createbills';
@ -393,9 +428,17 @@ if (empty($reshook)) {
if (!$error) {
$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 {
$db->rollback();
$action = 'create';
$_GET["origin"] = $_POST["origin"];
$_GET["originid"] = $_POST["originid"];
@ -597,7 +640,7 @@ $arrayofmassactions = array(
);
if ($user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer) {
$arrayofmassactions['createbills'] = $langs->trans("CreateInvoiceForThisSupplier");
$arrayofmassactions['createbills'] = $langs->trans("CreateInvoiceForThisReceptions");
}
if ($massaction == 'createbills') {
$arrayofmassactions = array();
@ -656,7 +699,7 @@ if ($massaction == 'createbills') {
print '<br>';
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 '</div>';
print '<br>';