Better help on mass invoicing from orders
This commit is contained in:
parent
d1860b87f8
commit
75e5d80eb6
@ -209,224 +209,6 @@ if (empty($reshook))
|
|||||||
$uploaddir = $conf->commande->dir_output;
|
$uploaddir = $conf->commande->dir_output;
|
||||||
$trigger_name='ORDER_SENTBYMAIL';
|
$trigger_name='ORDER_SENTBYMAIL';
|
||||||
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
|
include DOL_DOCUMENT_ROOT.'/core/actions_massactions.inc.php';
|
||||||
|
|
||||||
// TODO Move this into mass action include
|
|
||||||
if ($massaction == 'confirm_createbills') {
|
|
||||||
|
|
||||||
$orders = GETPOST('toselect','array');
|
|
||||||
$createbills_onebythird = GETPOST('createbills_onebythird', 'int');
|
|
||||||
$validate_invoices = GETPOST('valdate_invoices', 'int');
|
|
||||||
|
|
||||||
$TFact = array();
|
|
||||||
$TFactThird = array();
|
|
||||||
|
|
||||||
$nb_bills_created = 0;
|
|
||||||
|
|
||||||
$db->begin();
|
|
||||||
|
|
||||||
foreach($orders as $id_order)
|
|
||||||
{
|
|
||||||
$cmd = new Commande($db);
|
|
||||||
if ($cmd->fetch($id_order) <= 0) continue;
|
|
||||||
|
|
||||||
$object = new Facture($db);
|
|
||||||
if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) $object = $TFactThird[$cmd->socid]; // If option "one bill per third" is set, we use already created order.
|
|
||||||
else {
|
|
||||||
|
|
||||||
$object->socid = $cmd->socid;
|
|
||||||
$object->type = Facture::TYPE_STANDARD;
|
|
||||||
$object->cond_reglement_id = $cmd->cond_reglement_id;
|
|
||||||
$object->mode_reglement_id = $cmd->mode_reglement_id;
|
|
||||||
$object->fk_project = $cmd->fk_project;
|
|
||||||
|
|
||||||
$datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
|
|
||||||
if (empty($datefacture))
|
|
||||||
{
|
|
||||||
$datefacture = dol_mktime(date("h"), date("M"), 0, date("m"), date("d"), date("Y"));
|
|
||||||
}
|
|
||||||
|
|
||||||
$object->date = $datefacture;
|
|
||||||
$object->origin = 'commande';
|
|
||||||
$object->origin_id = $id_order;
|
|
||||||
|
|
||||||
$res = $object->create($user);
|
|
||||||
|
|
||||||
if($res > 0) $nb_bills_created++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($object->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.= ", '".$object->origin."'";
|
|
||||||
$sql.= ", ".$object->id;
|
|
||||||
$sql.= ", '".$object->element."'";
|
|
||||||
$sql.= ")";
|
|
||||||
|
|
||||||
if (! $db->query($sql))
|
|
||||||
{
|
|
||||||
$error++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $error)
|
|
||||||
{
|
|
||||||
$lines = $cmd->lines;
|
|
||||||
if (empty($lines) && method_exists($cmd, 'fetch_lines'))
|
|
||||||
{
|
|
||||||
$cmd->fetch_lines();
|
|
||||||
$lines = $cmd->lines;
|
|
||||||
}
|
|
||||||
|
|
||||||
$fk_parent_line=0;
|
|
||||||
$num=count($lines);
|
|
||||||
|
|
||||||
for ($i=0;$i<$num;$i++)
|
|
||||||
{
|
|
||||||
$desc=($lines[$i]->desc?$lines[$i]->desc:$lines[$i]->libelle);
|
|
||||||
if ($lines[$i]->subprice < 0)
|
|
||||||
{
|
|
||||||
// Negative line, we create a discount line
|
|
||||||
$discount = new DiscountAbsolute($db);
|
|
||||||
$discount->fk_soc=$object->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);
|
|
||||||
$discount->tva_tx=$lines[$i]->tva_tx;
|
|
||||||
$discount->fk_user=$user->id;
|
|
||||||
$discount->description=$desc;
|
|
||||||
$discountid=$discount->create($user);
|
|
||||||
if ($discountid > 0)
|
|
||||||
{
|
|
||||||
$result=$object->insert_discount($discountid);
|
|
||||||
//$result=$discount->link_to_invoice($lineid,$id);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
setEventMessages($discount->error, $discount->errors, 'errors');
|
|
||||||
$error++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Positive line
|
|
||||||
$product_type=($lines[$i]->product_type?$lines[$i]->product_type:0);
|
|
||||||
// Date start
|
|
||||||
$date_start=false;
|
|
||||||
if ($lines[$i]->date_debut_prevue) $date_start=$lines[$i]->date_debut_prevue;
|
|
||||||
if ($lines[$i]->date_debut_reel) $date_start=$lines[$i]->date_debut_reel;
|
|
||||||
if ($lines[$i]->date_start) $date_start=$lines[$i]->date_start;
|
|
||||||
//Date end
|
|
||||||
$date_end=false;
|
|
||||||
if ($lines[$i]->date_fin_prevue) $date_end=$lines[$i]->date_fin_prevue;
|
|
||||||
if ($lines[$i]->date_fin_reel) $date_end=$lines[$i]->date_fin_reel;
|
|
||||||
if ($lines[$i]->date_end) $date_end=$lines[$i]->date_end;
|
|
||||||
// Reset fk_parent_line for no child products and special product
|
|
||||||
if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9)
|
|
||||||
{
|
|
||||||
$fk_parent_line = 0;
|
|
||||||
}
|
|
||||||
$result = $object->addline(
|
|
||||||
$desc,
|
|
||||||
$lines[$i]->subprice,
|
|
||||||
$lines[$i]->qty,
|
|
||||||
$lines[$i]->tva_tx,
|
|
||||||
$lines[$i]->localtax1_tx,
|
|
||||||
$lines[$i]->localtax2_tx,
|
|
||||||
$lines[$i]->fk_product,
|
|
||||||
$lines[$i]->remise_percent,
|
|
||||||
$date_start,
|
|
||||||
$date_end,
|
|
||||||
0,
|
|
||||||
$lines[$i]->info_bits,
|
|
||||||
$lines[$i]->fk_remise_except,
|
|
||||||
'HT',
|
|
||||||
0,
|
|
||||||
$product_type,
|
|
||||||
$ii,
|
|
||||||
$lines[$i]->special_code,
|
|
||||||
$object->origin,
|
|
||||||
$lines[$i]->rowid,
|
|
||||||
$fk_parent_line,
|
|
||||||
$lines[$i]->fk_fournprice,
|
|
||||||
$lines[$i]->pa_ht,
|
|
||||||
$lines[$i]->label
|
|
||||||
);
|
|
||||||
if ($result > 0)
|
|
||||||
{
|
|
||||||
$lineid=$result;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$lineid=0;
|
|
||||||
$error++;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Defined the new fk_parent_line
|
|
||||||
if ($result > 0 && $lines[$i]->product_type == 9)
|
|
||||||
{
|
|
||||||
$fk_parent_line = $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module.
|
|
||||||
|
|
||||||
if(!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) $TFactThird[$cmd->socid] = $object;
|
|
||||||
else $TFact[$object->id] = $object;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build doc with all invoices
|
|
||||||
$TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird;
|
|
||||||
$toselect = array();
|
|
||||||
|
|
||||||
if (! $error && $validate_invoices)
|
|
||||||
{
|
|
||||||
$massaction = $action = 'builddoc';
|
|
||||||
foreach($TAllFact as &$object)
|
|
||||||
{
|
|
||||||
$result = $object->validate($user);
|
|
||||||
if ($result <= 0)
|
|
||||||
{
|
|
||||||
$error++;
|
|
||||||
setEventMessages($object->error, $object->errors, 'errors');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$id = $object->id; // For builddoc action
|
|
||||||
|
|
||||||
// Fac builddoc
|
|
||||||
$donotredirect = 1;
|
|
||||||
$upload_dir = $conf->facture->dir_output;
|
|
||||||
$permissioncreate=$user->rights->facture->creer;
|
|
||||||
include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
$massaction = $action = 'confirm_createbills';
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $error)
|
|
||||||
{
|
|
||||||
$db->commit();
|
|
||||||
setEventMessage($langs->trans('BillCreated', $nb_bills_created));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$db->rollback();
|
|
||||||
$action='create';
|
|
||||||
$_GET["origin"]=$_POST["origin"];
|
|
||||||
$_GET["originid"]=$_POST["originid"];
|
|
||||||
setEventMessages($object->error, $object->errors, 'errors');
|
|
||||||
$error++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -682,7 +464,7 @@ if ($resql)
|
|||||||
|
|
||||||
print '<table class="noborder" width="100%" >';
|
print '<table class="noborder" width="100%" >';
|
||||||
print '<tr>';
|
print '<tr>';
|
||||||
print '<td class="titlefieldmiddle">';
|
print '<td class="titlefield">';
|
||||||
print $langs->trans('DateInvoice');
|
print $langs->trans('DateInvoice');
|
||||||
print '</td>';
|
print '</td>';
|
||||||
print '<td>';
|
print '<td>';
|
||||||
@ -711,6 +493,8 @@ if ($resql)
|
|||||||
{
|
{
|
||||||
print $form->selectyesno('valdate_invoices', 0, 1);
|
print $form->selectyesno('valdate_invoices', 0, 1);
|
||||||
}
|
}
|
||||||
|
if (! empty($conf->global->WORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER)) print ' <span class="opacitymedium">'.$langs->trans("IfValidateInvoiceIsNoOrderStayUnbilled").'</span>';
|
||||||
|
else print ' <span class="opacitymedium">'.$langs->trans("OptionToSetOrderBilledNotEnabled").'</span>';
|
||||||
print '</td>';
|
print '</td>';
|
||||||
print '</tr>';
|
print '</tr>';
|
||||||
print '</table>';
|
print '</table>';
|
||||||
|
|||||||
@ -481,6 +481,223 @@ if (! $error && $massaction == 'confirm_presend')
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($massaction == 'confirm_createbills')
|
||||||
|
{
|
||||||
|
$orders = GETPOST('toselect','array');
|
||||||
|
$createbills_onebythird = GETPOST('createbills_onebythird', 'int');
|
||||||
|
$validate_invoices = GETPOST('valdate_invoices', 'int');
|
||||||
|
|
||||||
|
$TFact = array();
|
||||||
|
$TFactThird = array();
|
||||||
|
|
||||||
|
$nb_bills_created = 0;
|
||||||
|
|
||||||
|
$db->begin();
|
||||||
|
|
||||||
|
foreach($orders as $id_order)
|
||||||
|
{
|
||||||
|
$cmd = new Commande($db);
|
||||||
|
if ($cmd->fetch($id_order) <= 0) continue;
|
||||||
|
|
||||||
|
$object = new Facture($db);
|
||||||
|
if (!empty($createbills_onebythird) && !empty($TFactThird[$cmd->socid])) $object = $TFactThird[$cmd->socid]; // If option "one bill per third" is set, we use already created order.
|
||||||
|
else {
|
||||||
|
|
||||||
|
$object->socid = $cmd->socid;
|
||||||
|
$object->type = Facture::TYPE_STANDARD;
|
||||||
|
$object->cond_reglement_id = $cmd->cond_reglement_id;
|
||||||
|
$object->mode_reglement_id = $cmd->mode_reglement_id;
|
||||||
|
$object->fk_project = $cmd->fk_project;
|
||||||
|
|
||||||
|
$datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
|
||||||
|
if (empty($datefacture))
|
||||||
|
{
|
||||||
|
$datefacture = dol_mktime(date("h"), date("M"), 0, date("m"), date("d"), date("Y"));
|
||||||
|
}
|
||||||
|
|
||||||
|
$object->date = $datefacture;
|
||||||
|
$object->origin = 'commande';
|
||||||
|
$object->origin_id = $id_order;
|
||||||
|
|
||||||
|
$res = $object->create($user);
|
||||||
|
|
||||||
|
if($res > 0) $nb_bills_created++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($object->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.= ", '".$object->origin."'";
|
||||||
|
$sql.= ", ".$object->id;
|
||||||
|
$sql.= ", '".$object->element."'";
|
||||||
|
$sql.= ")";
|
||||||
|
|
||||||
|
if (! $db->query($sql))
|
||||||
|
{
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $error)
|
||||||
|
{
|
||||||
|
$lines = $cmd->lines;
|
||||||
|
if (empty($lines) && method_exists($cmd, 'fetch_lines'))
|
||||||
|
{
|
||||||
|
$cmd->fetch_lines();
|
||||||
|
$lines = $cmd->lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fk_parent_line=0;
|
||||||
|
$num=count($lines);
|
||||||
|
|
||||||
|
for ($i=0;$i<$num;$i++)
|
||||||
|
{
|
||||||
|
$desc=($lines[$i]->desc?$lines[$i]->desc:$lines[$i]->libelle);
|
||||||
|
if ($lines[$i]->subprice < 0)
|
||||||
|
{
|
||||||
|
// Negative line, we create a discount line
|
||||||
|
$discount = new DiscountAbsolute($db);
|
||||||
|
$discount->fk_soc=$object->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);
|
||||||
|
$discount->tva_tx=$lines[$i]->tva_tx;
|
||||||
|
$discount->fk_user=$user->id;
|
||||||
|
$discount->description=$desc;
|
||||||
|
$discountid=$discount->create($user);
|
||||||
|
if ($discountid > 0)
|
||||||
|
{
|
||||||
|
$result=$object->insert_discount($discountid);
|
||||||
|
//$result=$discount->link_to_invoice($lineid,$id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setEventMessages($discount->error, $discount->errors, 'errors');
|
||||||
|
$error++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Positive line
|
||||||
|
$product_type=($lines[$i]->product_type?$lines[$i]->product_type:0);
|
||||||
|
// Date start
|
||||||
|
$date_start=false;
|
||||||
|
if ($lines[$i]->date_debut_prevue) $date_start=$lines[$i]->date_debut_prevue;
|
||||||
|
if ($lines[$i]->date_debut_reel) $date_start=$lines[$i]->date_debut_reel;
|
||||||
|
if ($lines[$i]->date_start) $date_start=$lines[$i]->date_start;
|
||||||
|
//Date end
|
||||||
|
$date_end=false;
|
||||||
|
if ($lines[$i]->date_fin_prevue) $date_end=$lines[$i]->date_fin_prevue;
|
||||||
|
if ($lines[$i]->date_fin_reel) $date_end=$lines[$i]->date_fin_reel;
|
||||||
|
if ($lines[$i]->date_end) $date_end=$lines[$i]->date_end;
|
||||||
|
// Reset fk_parent_line for no child products and special product
|
||||||
|
if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9)
|
||||||
|
{
|
||||||
|
$fk_parent_line = 0;
|
||||||
|
}
|
||||||
|
$result = $object->addline(
|
||||||
|
$desc,
|
||||||
|
$lines[$i]->subprice,
|
||||||
|
$lines[$i]->qty,
|
||||||
|
$lines[$i]->tva_tx,
|
||||||
|
$lines[$i]->localtax1_tx,
|
||||||
|
$lines[$i]->localtax2_tx,
|
||||||
|
$lines[$i]->fk_product,
|
||||||
|
$lines[$i]->remise_percent,
|
||||||
|
$date_start,
|
||||||
|
$date_end,
|
||||||
|
0,
|
||||||
|
$lines[$i]->info_bits,
|
||||||
|
$lines[$i]->fk_remise_except,
|
||||||
|
'HT',
|
||||||
|
0,
|
||||||
|
$product_type,
|
||||||
|
$ii,
|
||||||
|
$lines[$i]->special_code,
|
||||||
|
$object->origin,
|
||||||
|
$lines[$i]->rowid,
|
||||||
|
$fk_parent_line,
|
||||||
|
$lines[$i]->fk_fournprice,
|
||||||
|
$lines[$i]->pa_ht,
|
||||||
|
$lines[$i]->label
|
||||||
|
);
|
||||||
|
if ($result > 0)
|
||||||
|
{
|
||||||
|
$lineid=$result;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$lineid=0;
|
||||||
|
$error++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Defined the new fk_parent_line
|
||||||
|
if ($result > 0 && $lines[$i]->product_type == 9)
|
||||||
|
{
|
||||||
|
$fk_parent_line = $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//$cmd->classifyBilled($user); // Disabled. This behavior must be set or not using the workflow module.
|
||||||
|
|
||||||
|
if(!empty($createbills_onebythird) && empty($TFactThird[$cmd->socid])) $TFactThird[$cmd->socid] = $object;
|
||||||
|
else $TFact[$object->id] = $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build doc with all invoices
|
||||||
|
$TAllFact = empty($createbills_onebythird) ? $TFact : $TFactThird;
|
||||||
|
$toselect = array();
|
||||||
|
|
||||||
|
if (! $error && $validate_invoices)
|
||||||
|
{
|
||||||
|
$massaction = $action = 'builddoc';
|
||||||
|
foreach($TAllFact as &$object)
|
||||||
|
{
|
||||||
|
$result = $object->validate($user);
|
||||||
|
if ($result <= 0)
|
||||||
|
{
|
||||||
|
$error++;
|
||||||
|
setEventMessages($object->error, $object->errors, 'errors');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = $object->id; // For builddoc action
|
||||||
|
|
||||||
|
// Fac builddoc
|
||||||
|
$donotredirect = 1;
|
||||||
|
$upload_dir = $conf->facture->dir_output;
|
||||||
|
$permissioncreate=$user->rights->facture->creer;
|
||||||
|
include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
|
||||||
|
}
|
||||||
|
|
||||||
|
$massaction = $action = 'confirm_createbills';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! $error)
|
||||||
|
{
|
||||||
|
$db->commit();
|
||||||
|
setEventMessage($langs->trans('BillCreated', $nb_bills_created));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$db->rollback();
|
||||||
|
$action='create';
|
||||||
|
$_GET["origin"]=$_POST["origin"];
|
||||||
|
$_GET["originid"]=$_POST["originid"];
|
||||||
|
setEventMessages($object->error, $object->errors, 'errors');
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_search'))
|
if (! $error && $massaction == "builddoc" && $permtoread && ! GETPOST('button_search'))
|
||||||
{
|
{
|
||||||
if (empty($diroutputmassaction))
|
if (empty($diroutputmassaction))
|
||||||
|
|||||||
@ -152,5 +152,7 @@ OrderCreated=Your orders have been created
|
|||||||
OrderFail=An error happened during your orders creation
|
OrderFail=An error happened during your orders creation
|
||||||
CreateOrders=Create orders
|
CreateOrders=Create orders
|
||||||
ToBillSeveralOrderSelectCustomer=To create an invoice for several orders, click first onto customer, then choose "%s".
|
ToBillSeveralOrderSelectCustomer=To create an invoice for several orders, click first onto customer, then choose "%s".
|
||||||
|
OptionToSetOrderBilledNotEnabled=Option (from module Workflow) to set order to 'Billed' automatically when invoice is validated is off, so you will have to set status of order to 'Billed' manually.
|
||||||
|
IfValidateInvoiceIsNoOrderStayUnbilled=If invoice validation is 'No', the order will remain to status 'Unbilled' until the invoice is validated.
|
||||||
CloseReceivedSupplierOrdersAutomatically=Close order to "%s" automatically if all products are received.
|
CloseReceivedSupplierOrdersAutomatically=Close order to "%s" automatically if all products are received.
|
||||||
SetShippingMode=Set shipping mode
|
SetShippingMode=Set shipping mode
|
||||||
Loading…
Reference in New Issue
Block a user