NEW billing on shipment+reception. Can be done before or after delivery.

This commit is contained in:
Laurent Destailleur 2023-09-03 21:38:11 +02:00
parent 3675ec0b42
commit 3343a47244
15 changed files with 138 additions and 87 deletions

View file

@ -19,7 +19,8 @@ WARNING:
Following changes may create regressions for some external modules, but were necessary to make Dolibarr better:
* The property ->brouillon has been removed from all classes. It was not reliable and was a duplicate of ->status == self::STATUS_DRAFT.
* The method get_substitutionarray_shipment_lines() has been removed. Use the generic get_substitutionarray_lines() instead.
* Recheck setup of your module workflow to see if you need to enable the new setting to have shipment set to billed automatically
when an invoice from a shipment is validated (and if your process is to make invoice on shipment and not on order).
***** ChangeLog for 18.0.1 compared to 18.0.0 *****

View file

@ -153,20 +153,40 @@ $workflowcodes = array(
),
// Automatic classification shipping
/* Replaced by next option
'WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE' => array(
'family' => 'classify_shipping',
'position' => 90,
'enabled' => isModEnabled("expedition") && isModEnabled("facture"),
'picto' => 'shipment',
'deprecated' => 1
),
*/
'WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE' => array(
'family' => 'classify_shipping',
'position' => 91,
'enabled' => isModEnabled("expedition") && isModEnabled("facture") && getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0',
'picto' => 'shipment'
),
// Automatic classification reception
'WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE'=>array(
/*
'WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE'=>array(
'family'=>'classify_reception',
'position'=>95,
'enabled'=>(isModEnabled("reception") && (isModEnabled("supplier_order") || isModEnabled("supplier_invoice"))),
'picto'=>'reception'
),
*/
'WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE' => array(
'family' => 'classify_reception',
'position' => 91,
'enabled' => isModEnabled("reception") && isModEnabled("supplier_invoice") && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0',
'picto' => 'shipment'
),
'separator2'=>array('family'=>'separator', 'position'=>400, 'enabled' => (isModEnabled('ticket') && isModEnabled('contract'))),
@ -284,6 +304,9 @@ foreach ($workflowcodes as $key => $params) {
if (!empty($params['warning'])) {
print ' '.img_warning($langs->transnoentitiesnoconv($params['warning']));
}
if (!empty($params['deprecated'])) {
print ' '.img_warning($langs->transnoentitiesnoconv("Deprecated"));
}
print '</td>';

View file

@ -2954,14 +2954,14 @@ if ($action == 'create' && $usercancreate) {
// Note: Even if module invoice is not enabled, we should be able to use button "Classified billed"
if ($object->statut > Commande::STATUS_DRAFT && !$object->billed && $object->total_ttc >= 0) {
if (isModEnabled('facture') && $user->hasRight('facture', 'creer') && empty($conf->global->WORKFLOW_DISABLE_CREATE_INVOICE_FROM_ORDER)) {
print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;token='.newToken().'&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&amp;token='.newToken().'&amp;origin='.urlencode($object->element).'&amp;originid='.$object->id.'&amp;socid='.$object->socid, '');
}
if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifybilled&amp;token='.newToken().'&amp;id='.$object->id, '');
}
}
if ($object->statut > Commande::STATUS_DRAFT && $object->billed) {
if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
if ($usercancreate && $object->statut >= Commande::STATUS_VALIDATED && empty($conf->global->WORKFLOW_DISABLE_CLASSIFY_BILLED_FROM_ORDER) && !getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')) {
print dolGetButtonAction('', $langs->trans('ClassifyUnBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifyunbilled&amp;token='.newToken().'&amp;id='.$object->id, '');
}
}

View file

@ -3729,14 +3729,6 @@ class Commande extends CommonOrder
$labelTooltip .= ' - '.$langs->transnoentitiesnoconv("DateDeliveryPlanned").dol_print_date($this->delivery_date, 'day').$billedtext;
}
$statusType = 'status4';
} elseif ($status == self::STATUS_CLOSED && (!$billed && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
$labelStatus = $langs->transnoentitiesnoconv('StatusOrderToBill'); // translated into Delivered
$labelStatusShort = $langs->transnoentitiesnoconv('StatusOrderToBillShort'); // translated into Delivered
$statusType = 'status4';
} elseif ($status == self::STATUS_CLOSED && ($billed && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
$labelStatus = $langs->transnoentitiesnoconv('StatusOrderProcessed').$billedtext;
$labelStatusShort = $langs->transnoentitiesnoconv('StatusOrderProcessedShort').$billedtext;
$statusType = 'status6';
} elseif ($status == self::STATUS_CLOSED && (!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
$labelStatus = $langs->transnoentitiesnoconv('StatusOrderDelivered');
$labelStatusShort = $langs->transnoentitiesnoconv('StatusOrderDeliveredShort');

View file

@ -206,7 +206,7 @@ $arrayfields = array(
'c.note_public'=>array('label'=>'NotePublic', 'checked'=>0, 'enabled'=>(!getDolGlobalInt('MAIN_LIST_HIDE_PUBLIC_NOTES')), 'position'=>135),
'c.note_private'=>array('label'=>'NotePrivate', 'checked'=>0, 'enabled'=>(!getDolGlobalInt('MAIN_LIST_HIDE_PRIVATE_NOTES')), 'position'=>140),
'shippable'=>array('label'=>"Shippable", 'checked'=>1,'enabled'=>(isModEnabled("expedition")), 'position'=>990),
'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)), 'position'=>995),
'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position'=>995),
'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999),
'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000)
);

View file

@ -213,7 +213,7 @@ $arrayfields = array(
'c.note_public'=>array('label'=>'NotePublic', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PUBLIC_NOTES)), 'position'=>135),
'c.note_private'=>array('label'=>'NotePrivate', 'checked'=>0, 'enabled'=>(empty($conf->global->MAIN_LIST_ALLOW_PRIVATE_NOTES)), 'position'=>140),
'shippable'=>array('label'=>"Shippable", 'checked'=>1,'enabled'=>(isModEnabled('expedition')), 'position'=>990),
'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)), 'position'=>995),
'c.facture'=>array('label'=>"Billed", 'checked'=>1, 'enabled'=>(!getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT')), 'position'=>995),
'c.import_key' =>array('type'=>'varchar(14)', 'label'=>'ImportId', 'enabled'=>1, 'visible'=>-2, 'position'=>999),
'c.fk_statut'=>array('label'=>"Status", 'checked'=>1, 'position'=>1000)
);

View file

@ -298,10 +298,7 @@ function getCustomerOrderPieChart($socid = 0)
if ($status == Commande::STATUS_SHIPMENTONPROCESS) {
$colorseries[$status] = $badgeStatus4;
}
if ($status == Commande::STATUS_CLOSED && empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) {
$colorseries[$status] = $badgeStatus6;
}
if ($status == Commande::STATUS_CLOSED && (!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))) {
if ($status == Commande::STATUS_CLOSED) {
$colorseries[$status] = $badgeStatus6;
}
if ($status == Commande::STATUS_CANCELED) {

View file

@ -189,6 +189,7 @@ class InterfaceWorkflowManager extends DolibarrTriggers
}
}
// Set shipment to "Closed" if WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE is set (deprecated, WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE instead))
if (isModEnabled("expedition") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE)) {
$object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
if (!empty($object->linkedObjects)) {
@ -210,6 +211,27 @@ class InterfaceWorkflowManager extends DolibarrTriggers
}
}
if (isModEnabled("expedition") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE)) {
$object->fetchObjectLinked('', 'shipping', $object->id, $object->element);
if (!empty($object->linkedObjects)) {
$totalonlinkedelements = 0;
foreach ($object->linkedObjects['shipping'] as $element) {
if ($element->statut == Expedition::STATUS_VALIDATED || $element->statut == Expedition::STATUS_CLOSED) {
$totalonlinkedelements += $element->total_ht;
}
}
dol_syslog("Amount of linked shipment = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
if ($totalonlinkedelements == $object->total_ht) {
foreach ($object->linkedObjects['shipping'] as $element) {
$ret = $element->setBilled();
if ($ret < 0) {
return $ret;
}
}
}
}
}
return $ret;
}
@ -262,8 +284,32 @@ class InterfaceWorkflowManager extends DolibarrTriggers
}
}
// Then set reception to "Billed" if WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE is set
if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE)) {
// Set reception to "Closed" if WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE is set (deprecated, WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE instead))
/*
if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE)) {
$object->fetchObjectLinked('', 'reception', $object->id, $object->element);
if (!empty($object->linkedObjects)) {
$totalonlinkedelements = 0;
foreach ($object->linkedObjects['reception'] as $element) {
if ($element->statut == Reception::STATUS_VALIDATED || $element->statut == Reception::STATUS_CLOSED) {
$totalonlinkedelements += $element->total_ht;
}
}
dol_syslog("Amount of linked reception = ".$totalonlinkedelements.", of invoice = ".$object->total_ht.", egality is ".($totalonlinkedelements == $object->total_ht), LOG_DEBUG);
if ($totalonlinkedelements == $object->total_ht) {
foreach ($object->linkedObjects['reception'] as $element) {
$ret = $element->setClosed();
if ($ret < 0) {
return $ret;
}
}
}
}
}
*/
// Then set reception to "Billed" if WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE is set
if (isModEnabled("reception") && !empty($conf->workflow->enabled) && !empty($conf->global->WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE)) {
$object->fetchObjectLinked('', 'reception', $object->id, $object->element);
if (!empty($object->linkedObjects)) {
$totalonlinkedelements = 0;

View file

@ -2573,7 +2573,6 @@ if ($action == 'create') {
}
// 0=draft, 1=validated/delivered, 2=closed/delivered
// If WORKFLOW_BILL_ON_SHIPMENT: 0=draft, 1=validated, 2=billed (no status delivered)
if ($object->statut == Expedition::STATUS_VALIDATED && !getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
if ($user->hasRight('expedition', 'creer')) {
print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"].'?action=setdraft&token='.newToken().'&id='.$object->id, '');
@ -2581,11 +2580,7 @@ if ($action == 'create') {
}
if ($object->statut == Expedition::STATUS_CLOSED) {
if ($user->hasRight('expedition', 'creer')) {
if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
print dolGetButtonAction('', $langs->trans('ClassifyUnbilled'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, '');
} else {
print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, '');
}
print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"].'?action=reopen&token='.newToken().'&id='.$object->id, '');
}
}
@ -2603,9 +2598,9 @@ if ($action == 'create') {
// Create bill
if (isModEnabled('facture') && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED)) {
if ($user->hasRight('facture', 'creer')) {
// TODO show button only if (!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT))
// If we do that, we must also make this option official.
print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, '');
if (getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0') {
print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT.'/compta/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid, '');
}
}
}
@ -2614,28 +2609,26 @@ if ($action == 'create') {
if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && ($object->statut == Expedition::STATUS_VALIDATED || $object->statut == Expedition::STATUS_CLOSED) && $user->rights->expedition->delivery->creer && empty($object->linkedObjectsIds['delivery'])) {
print dolGetButtonAction('', $langs->trans('CreateDeliveryOrder'), 'default', $_SERVER["PHP_SELF"].'?action=create_delivery&token='.newToken().'&id='.$object->id, '');
}
// Close
// Set Billed and Closed
if ($object->statut == Expedition::STATUS_VALIDATED) {
if ($user->rights->expedition->creer && $object->statut > 0 && !$object->billed) {
$label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received
// Label here should be "Close" or "ClassifyBilled" if we decided to make bill on shipments instead of orders
if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
$label = "ClassifyBilled";
$paramaction = 'classifybilled';
if ($user->hasRight('expedition', 'creer') && $object->statut > 0) {
if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0') {
print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"].'?action=classifybilled&token='.newToken().'&id='.$object->id, '');
}
print dolGetButtonAction('', $langs->trans($label), 'default', $_SERVER["PHP_SELF"].'?action='. $paramaction .'&token='.newToken().'&id='.$object->id, '');
print dolGetButtonAction('', $langs->trans("Close"), 'default', $_SERVER["PHP_SELF"].'?action='. $paramaction .'&token='.newToken().'&id='.$object->id, '');
}
}
// Cancel
if ($object->statut == Expedition::STATUS_VALIDATED) {
if ($user->rights->expedition->supprimer) {
if ($user->hasRight('expedition', 'creer')) {
print dolGetButtonAction('', $langs->trans('Cancel'), 'danger', $_SERVER["PHP_SELF"].'?action=cancel&token='.newToken().'&id='.$object->id.'&mode=init#formmailbeforetitle', '');
}
}
// Delete
if ($user->rights->expedition->supprimer) {
if ($user->hasRight('expedition', 'supprimer')) {
print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"].'?action=delete&token='.newToken().'&id='.$object->id, '');
}
}

View file

@ -2108,13 +2108,13 @@ class Expedition extends CommonObject
}
/**
* Classify the shipping as closed.
* Classify the shipping as closed (this record also the stock movement)
*
* @return int <0 if KO, >0 if OK
*/
public function setClosed()
{
global $conf, $langs, $user;
global $conf, $user;
$error = 0;
@ -2280,7 +2280,7 @@ class Expedition extends CommonObject
}
/**
* Classify the shipping as invoiced (used when WORKFLOW_BILL_ON_SHIPMENT is on)
* Classify the shipping as invoiced (used for exemple by trigger when WORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE is on)
*
* @return int <0 if ko, >0 if ok
*/
@ -2291,17 +2291,17 @@ class Expedition extends CommonObject
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET fk_statut=2, billed=1'; // TODO Update only billed
$sql = 'UPDATE '.MAIN_DB_PREFIX.'expedition SET billed = 1';
$sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0';
$resql = $this->db->query($sql);
if ($resql) {
$this->statut = self::STATUS_CLOSED;
$this->billed = 1;
// Call trigger
$result = $this->call_trigger('SHIPPING_BILLED', $user);
if ($result < 0) {
$this->billed = 0;
$error++;
}
} else {
@ -2313,8 +2313,6 @@ class Expedition extends CommonObject
$this->db->commit();
return 1;
} else {
$this->statut = self::STATUS_VALIDATED;
$this->billed = 0;
$this->db->rollback();
return -1;
}

View file

@ -144,7 +144,7 @@ $arrayfields = array(
'e.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
'l.ref'=>array('label'=>$langs->trans("DeliveryRef"), 'checked'=>1, 'enabled'=>(getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') ? 1 : 0)),
'l.date_delivery'=>array('label'=>$langs->trans("DateReceived"), 'checked'=>1, 'enabled'=>(getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') ? 1 : 0)),
'e.billed'=>array('label'=>$langs->trans("Billed"), 'checked'=>1, 'position'=>1000, 'enabled'=>(!empty($conf->global->WORKFLOW_BILL_ON_SHIPMENT)))
'e.billed'=>array('label'=>$langs->trans("Billed"), 'checked'=>1, 'position'=>1000, 'enabled'=>'getDolGlobalConst("WORKFLOW_BILL_ON_SHIPMENT") !== "0"')
);
// Extra fields

View file

@ -9,11 +9,11 @@ descWORKFLOW_CONTRACT_AUTOCREATE_INVOICE=Automatically create a customer invoice
descWORKFLOW_ORDER_AUTOCREATE_INVOICE=Automatically create a customer invoice after a sales order is closed (the new invoice will have same amount as the order)
descWORKFLOW_TICKET_CREATE_INTERVENTION=On ticket creation, automatically create an intervention.
# Autoclassify customer proposal or order
descWORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL=Classify linked source proposal as billed when sales order is set to billed (and if the amount of the order is the same as the total amount of the signed linked proposal)
descWORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL=Classify linked source proposal as billed when customer invoice is validated (and if the amount of the invoice is the same as the total amount of the signed linked proposal)
descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER=Classify linked source sales order as billed when customer invoice is validated (and if the amount of the invoice is the same as the total amount of the linked order)
descWORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER=Classify linked source sales order as billed when customer invoice is set to paid (and if the amount of the invoice is the same as the total amount of the linked order)
descWORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING=Classify linked source sales order as shipped when a shipment is validated (and if the quantity shipped by all shipments is the same as in the order to update)
descWORKFLOW_ORDER_CLASSIFY_BILLED_PROPAL=Classify linked source proposals as billed when a sales order is set to billed (and if the amount of the order is the same as the total amount of the signed linked proposal)
descWORKFLOW_INVOICE_CLASSIFY_BILLED_PROPAL=Classify linked source proposals as billed when a customer invoice is validated (and if the amount of the invoice is the same as the total amount of the signed linked proposal)
descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_ORDER=Classify linked source sales order as billed when a customer invoice is validated (and if the amount of the invoice is the same as the total amount of the linked order)
descWORKFLOW_INVOICE_CLASSIFY_BILLED_ORDER=Classify linked source sales orders as billed when a customer invoice is set to paid (and if the amount of the invoice is the same as the total amount of the linked order)
descWORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING=Classify linked source sales orders as shipped when a shipment is validated (and if the quantity shipped by all shipments is the same as in the order to update)
descWORKFLOW_ORDER_CLASSIFY_SHIPPED_SHIPPING_CLOSED=Classify linked source sales order as shipped when a shipment is closed (and if the quantity shipped by all shipments is the same as in the order to update)
# Autoclassify purchase proposal
descWORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL=Classify linked source vendor proposal as billed when vendor invoice is validated (and if the amount of the invoice is the same as the total amount of the linked proposal)
@ -21,8 +21,12 @@ descWORKFLOW_ORDER_CLASSIFY_BILLED_SUPPLIER_PROPOSAL=Classify linked source vend
descWORKFLOW_INVOICE_AMOUNT_CLASSIFY_BILLED_SUPPLIER_ORDER=Classify linked source purchase order as billed when vendor invoice is validated (and if the amount of the invoice is the same as the total amount of the linked order)
descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION=Classify linked source purchase order as received when a reception is validated (and if the quantity received by all receptions is the same as in the purchase order to update)
descWORKFLOW_ORDER_CLASSIFY_RECEIVED_RECEPTION_CLOSED=Classify linked source purchase order as received when a reception is closed (and if the quantity received by all rceptions is the same as in the purchase order to update)
# Autoclassify purchase invoice
descWORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE=Classify receptions to "billed" when a linked purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions)
# Autoclassify shipment
descWORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE=Classify linked source shipment as closed when a customer invoice is validated (and if the amount of the invoice is the same as the total amount of the linked shipments)
descWORKFLOW_SHIPPING_CLASSIFY_BILLED_INVOICE=Classify linked source shipment as billed when a customer invoice is validated (and if the amount of the invoice is the same as the total amount of the linked shipments)
# Autoclassify receptions
descWORKFLOW_RECEPTION_CLASSIFY_CLOSED_INVOICE=Classify linked source receptions as billed when a purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions)
descWORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE=Classify linked source receptions as billed when a purchase invoice is validated (and if the amount of the invoice is the same as the total amount of the linked receptions)
# Automatically link ticket to contract
descWORKFLOW_TICKET_LINK_CONTRACT=When creating a ticket, link available contracts of matching thirdparty
descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search among those of parents companies
@ -30,7 +34,5 @@ descWORKFLOW_TICKET_USE_PARENT_COMPANY_CONTRACTS=When linking contracts, search
descWORKFLOW_TICKET_CLOSE_INTERVENTION=Close all interventions linked to the ticket when a ticket is closed
AutomaticCreation=Automatic creation
AutomaticClassification=Automatic classification
# Autoclassify shipment
descWORKFLOW_SHIPPING_CLASSIFY_CLOSED_INVOICE=Classify linked source shipment as closed when customer invoice is validated (and if the amount of the invoice is the same as the total amount of the linked shipments)
AutomaticClosing=Automatic closing
AutomaticLinking=Automatic linking

View file

@ -2133,11 +2133,7 @@ if ($action == 'create') {
// TODO add alternative status
// 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
if ($object->statut == Reception::STATUS_CLOSED && $user->rights->reception->creer) {
if (isModEnabled('facture') && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ClassifyUnbilled").'</a>';
} else {
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
}
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
}
// Send
@ -2154,27 +2150,24 @@ if ($action == 'create') {
// Create bill
if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED)) {
if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
// TODO show button only if (!empty($conf->global->WORKFLOW_BILL_ON_RECEPTION))
// If we do that, we must also make this option official.
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
}
}
// Close
if ($object->statut == Reception::STATUS_VALIDATED) {
if ($user->rights->reception->creer && $object->statut > 0 && !$object->billed) {
$label = "Close"; $paramaction = 'classifyclosed'; // = Transferred/Received
// Label here should be "Close" or "ClassifyBilled" if we decided to make bill on receptions instead of orders
if (isModEnabled("supplier_order") && !empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)) { // Quand l'option est on, il faut avoir le bouton en plus et non en remplacement du Close ?
$label = "ClassifyBilled";
$paramaction = 'classifybilled';
if (getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&amp;origin='.$object->element.'&amp;originid='.$object->id.'&amp;socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
}
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action='.$paramaction.'&token='.newToken().'">'.$langs->trans($label).'</a>';
}
}
if ($user->rights->reception->supprimer) {
// Set Billed and Closed
if ($object->statut == Reception::STATUS_VALIDATED) {
if ($user->hasRight('reception', 'creer') && $object->statut > 0) {
if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans('ClassifyBilled').'</a>';
}
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyclosed&token='.newToken().'">'.$langs->trans("Close").'</a>';
}
}
if ($user->hasRight('reception', 'supprimer')) {
print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
}
}

View file

@ -370,7 +370,7 @@ class Reception extends CommonObject
return -1;
}
$sql = "SELECT e.rowid, e.entity, e.ref, e.fk_soc as socid, e.date_creation, e.ref_supplier, e.ref_ext, e.fk_user_author, e.fk_statut";
$sql = "SELECT e.rowid, e.entity, e.ref, e.fk_soc as socid, e.date_creation, e.ref_supplier, e.ref_ext, e.fk_user_author, e.fk_statut as status";
$sql .= ", e.weight, e.weight_units, e.size, e.size_units, e.width, e.height";
$sql .= ", e.date_reception as date_reception, e.model_pdf, e.date_delivery";
$sql .= ", e.fk_shipping_method, e.tracking_number";
@ -404,7 +404,8 @@ class Reception extends CommonObject
$this->socid = $obj->socid;
$this->ref_supplier = $obj->ref_supplier;
$this->ref_ext = $obj->ref_ext;
$this->statut = $obj->fk_statut;
$this->statut = $obj->status;
$this->status = $obj->status;
$this->user_author_id = $obj->fk_user_author;
$this->date_creation = $this->db->jdate($obj->date_creation);
$this->date = $this->db->jdate($obj->date_reception); // TODO deprecated
@ -1530,9 +1531,14 @@ class Reception extends CommonObject
$error = 0;
// Protection. This avoid to move stock later when we should not
if ($this->statut == self::STATUS_CLOSED) {
return 0;
}
$this->db->begin();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET fk_statut='.self::STATUS_CLOSED;
$sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET fk_statut = '.self::STATUS_CLOSED;
$sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0';
$resql = $this->db->query($sql);
@ -1562,7 +1568,7 @@ class Reception extends CommonObject
}
$this->statut = self::STATUS_CLOSED;
$this->status = self::STATUS_CLOSED;
// If stock increment is done on closing
if (!$error && isModEnabled('stock') && !empty($conf->global->STOCK_CALCULATE_ON_RECEPTION_CLOSE)) {
@ -1653,7 +1659,7 @@ class Reception extends CommonObject
}
/**
* Classify the reception as invoiced (used when WORKFLOW_EXPEDITION_CLASSIFY_CLOSED_INVOICE is on)
* Classify the reception as invoiced (used for exemple by trigger when WORKFLOW_RECEPTION_CLASSIFY_BILLED_INVOICE is on)
*
* @return int <0 if ko, >0 if ok
*/
@ -1666,17 +1672,17 @@ class Reception extends CommonObject
$this->setClosed();
$sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET billed=1';
$sql = 'UPDATE '.MAIN_DB_PREFIX.'reception SET billed=1';
$sql .= " WHERE rowid = ".((int) $this->id).' AND fk_statut > 0';
$resql = $this->db->query($sql);
if ($resql) {
$this->statut = 2;
$this->billed = 1;
// Call trigger
$result = $this->call_trigger('RECEPTION_BILLED', $user);
if ($result < 0) {
$this->billed = 0;
$error++;
}
} else {

View file

@ -129,7 +129,7 @@ $arrayfields = array(
'e.datec'=>array('label'=>$langs->trans("DateCreation"), 'checked'=>0, 'position'=>500),
'e.tms'=>array('label'=>$langs->trans("DateModificationShort"), 'checked'=>0, 'position'=>500),
'e.fk_statut'=>array('label'=>$langs->trans("Status"), 'checked'=>1, 'position'=>1000),
'e.billed'=>array('label'=>$langs->trans("Billed"), 'checked'=>1, 'position'=>1000, 'enabled'=>(!empty($conf->global->WORKFLOW_BILL_ON_RECEPTION)))
'e.billed'=>array('label'=>$langs->trans("Billed"), 'checked'=>1, 'position'=>1000, 'enabled'=>'getDolGlobalConst("WORKFLOW_BILL_ON_RECEPTION") !== "0"')
);
// Extra fields