NEW : adds visual indicators on the Sales Order card (commande/card.php) (#37460)

* This PR adds visual indicators on the Sales Order card (commande/card.php) to quickly identify if an order or its lines are shippable based on current stock levels. This feature mirrors the existing functionality found in the Orders List, bringing valuable logistics information directly into the Order Card context.

Key Features:
Global Shippable Status: Adds a "shippable" icon (Truck) next to the "Planned delivery date" field.

Logic: Checks if all products in the order are in stock.

Condition: Visible only if Stock and Shipment modules are enabled, a delivery date is set, and the order is validated.

Visual: Green icon if fully shippable, Red/Warning if stock is insufficient. Includes a detailed tooltip.

Per-Line Shippable Status: Adds a new "Shippable" column in the product lines table.

Logic: Compares real stock vs. remaining quantity to ship for each line.

Visual: Displays a green/red status bullet (standard Dolibarr status icons) directly in the line.

Implementation: Done by updating objectline_title.tpl.php and objectline_view.tpl.php with specific checks for the commande element.

New Configuration Option: Added a hidden option ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD to disable this feature if needed (configurable in Home > Setup > Other Setup or via module settings).

Backend Optimization: Added a new method getShippableInfos() in commande.class.php to centralize the stock check logic (optimized with stock caching to avoid N+1 query issues).

Technical Details:
Modified Files:

commande/card.php: Integration of the global icon next to the date.

commande/class/commande.class.php: Added getShippableInfos() method.

core/tpl/objectline_title.tpl.php: Added "Shippable" column header (conditional for Orders).

core/tpl/objectline_view.tpl.php: Added "Shippable" column cell content (conditional for Orders).

Performance: Logic uses static caching for product stock to minimize database impact when rendering large orders.

* missed element

* img_picto

* phan add

* load_stock and global $i

* phan

* ci retour

* change icon
change phan directive

* phan

* Fight against optionflation

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

* Change condition for displaying shippable icon

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

* Change condition for displaying shippable status icon

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

* Update card.php

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

* Update shippable status condition in template

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

* Update shippable status condition logic

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>

---------

Signed-off-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: jpb <jean-pascal.boudet@atm-consulting>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
boudet jean pascal 2026-03-12 14:42:31 +01:00 committed by GitHub
parent b02f1a4ebf
commit a4b8cb7008
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 240 additions and 103 deletions

View file

@ -3117,6 +3117,20 @@ if ($action == 'create' && $usercancreate) {
print ' ' . img_picto($langs->trans("Late") . ' : ' . $object->showDelay(), "warning");
}
}
// --- SHIPPABLE icon ---
if (isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && !empty($object->delivery_date)) {
$shippableInfos = $object->getShippableInfos();
if (!empty($shippableInfos['has_product'])) {
print ' ';
print $form->textwithtooltip('', $shippableInfos['textinfo'], 2, 1, $shippableInfos['texticon'], '', 2);
if (!empty($shippableInfos['warning'])) {
print ' ';
print $form->textwithtooltip('', $langs->trans("NotEnoughForAllOrders"), 2, 1, img_picto('', 'error', '', 0, 0, 0, '', '2'), '', 2);
}
}
}
print '</td>';
print '</tr>';

View file

@ -4320,4 +4320,164 @@ class Commande extends CommonOrder
{
return $this->setSignedStatusCommon($user, $status, $notrigger, $triggercode);
}
/**
* Compute shippable status and tooltip/icon for the order.
*
* @param array<mixed> $options Extra options (reserved for future use)
* @return array<string,mixed> Array with keys: has_product, shippable, texticon, textinfo, warning
* /
*/
public function getShippableInfos(array $options = array()) : array
{
global $conf, $langs;
$langs->loadLangs(array('orders', 'sendings', 'stocks', 'products'));
$result = array(
'has_product' => false,
'shippable' => false,
'texticon' => '',
'textinfo' => '',
'warning' => false,
);
// Requested naming for statuses
if ($this->status == self::STATUS_DRAFT || $this->status == self::STATUS_CLOSED) {
return $result;
}
$genericCommande = $this;
$genericProduct = new Product($this->db);
$productstatcache = array();
$productstatcachevirtual = array();
$genericCommande->getLinesArray(); // Load array ->lines
$genericCommande->loadExpeditions(); // Load array ->expeditions
$notshippable = 0;
$has_reliquat = 0;
$warning = 0;
$textinfo = '';
$textwarning = '';
$nbprod = 0;
$genericProduct = new Product($this->db);
$numlines = count($genericCommande->lines);
for ($lig = 0; $lig < $numlines; $lig++) {
$orderLine = $genericCommande->lines[$lig]; // @phan-var-force OrderLine $orderLine
if (isset($genericCommande->expeditions[$orderLine->id])) {
$reliquat = $orderLine->qty - $genericCommande->expeditions[$orderLine->id];
} else {
$reliquat = $orderLine->qty;
}
if ($orderLine->product_type == 0 && $orderLine->fk_product > 0) { // product, not service
$nbprod = 1;
if (empty($productstatcache[$orderLine->fk_product])) {
$genericProduct->fetch($orderLine->fk_product);
$genericProduct->load_stock('nobatch,warehouseopen'); // loadvirtualstock included
$productstatcache[$orderLine->fk_product]['stockreel'] = $genericProduct->stock_reel;
$productstatcachevirtual[$orderLine->fk_product]['stockreel'] = $genericProduct->stock_theorique;
}
$genericProduct->stock_reel = $productstatcache[$orderLine->fk_product]['stockreel'];
$genericProduct->stock_theorique = $productstatcachevirtual[$orderLine->fk_product]['stockreel'];
if ($reliquat > 0) {
$has_reliquat = 1;
if (!getDolGlobalString('SHIPPABLE_ORDER_ICON_IN_LIST')) {
$textinfo .= $reliquat . ' x ' . $orderLine->product_ref . '&nbsp;' . dol_trunc($orderLine->product_label, 20);
$textinfo .= ' - ' . $langs->trans("Stock") . ': <span class="' . ($genericProduct->stock_reel >= $reliquat ? 'ok' : 'error') . '">' . $genericProduct->stock_reel . '</span>';
$textinfo .= ' - ' . $langs->trans("VirtualStock") . ': <span class="' . ($genericProduct->stock_theorique >= $reliquat ? 'ok' : 'error') . '">' . $genericProduct->stock_theorique . '</span>';
if ($reliquat != $orderLine->qty) {
$textinfo .= ' <span class="opacitymedium">' . $langs->trans("QtyInOtherShipments") . ' ' . ($orderLine->qty - $reliquat) . '</span>';
}
$textinfo .= '<br>';
} else {
// BUGGED CODE (kept for backward compatibility and hidden conf)
$stockorder = 0;
$stockordersupplier = 0;
if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT') || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
if (isModEnabled('order')) {
if (empty($productstatcache[$orderLine->fk_product]['statsordercustomer'])) {
$genericProduct->fetch($orderLine->fk_product);
$genericProduct->load_stats_commande(0, '1,2');
$productstatcache[$orderLine->fk_product]['statsordercustomer'] = $genericProduct->stats_commande['qty'];
}
$genericProduct->stats_commande['qty'] = $productstatcache[$orderLine->fk_product]['statsordercustomer'];
$stockorder = $genericProduct->stats_commande['qty'];
if (isModEnabled('supplier_order')) {
if (empty($productstatcache[$orderLine->fk_product]['statsordersupplier'])) {
$genericProduct->load_stats_commande_fournisseur(0, '3');
$productstatcache[$orderLine->fk_product]['statsordersupplier'] = $genericProduct->stats_commande_fournisseur['qty'];
}
$genericProduct->stats_commande_fournisseur['qty'] = $productstatcache[$orderLine->fk_product]['statsordersupplier'];
$stockordersupplier = $genericProduct->stats_commande_fournisseur['qty'];
}
}
}
$textinfo .= $reliquat . ' x ' . $orderLine->ref . '&nbsp;' . dol_trunc($orderLine->product_label, 20);
$textinfo .= ' ' . $langs->trans("Available") . '&nbsp;&nbsp;' . $genericProduct->stock_reel . '..' . $stockorder;
if ($stockorder && $genericProduct->stock_reel < ($genericProduct->stock_reel - $stockorder + $reliquat)) {
$warning++;
$textwarning .= '<span class="warning">' . $langs->trans("Available") . '&nbsp;&nbsp;' . $genericProduct->stock_reel . '..' . $stockorder . '</span>';
} else {
if ($reliquat > $genericProduct->stock_reel) {
$textinfo .= ' <span class="warning">' . $langs->trans("Available") . '&nbsp;&nbsp;' . $genericProduct->stock_reel . '</span>';
} else {
$textinfo .= ' <span class="ok">' . $langs->trans("Available") . '&nbsp;&nbsp;' . $genericProduct->stock_reel . '</span>';
}
}
if (isModEnabled('supplier_order')) {
$textinfo .= '&nbsp;' . $langs->trans("SupplierOrder") . '&nbsp;&nbsp;' . $stockordersupplier;
}
if ($reliquat != $orderLine->qty) {
$textinfo .= ' <span class="opacitymedium">' . $langs->trans("QtyInOtherShipments") . ' ' . ($orderLine->qty - $reliquat) . '</span>';
}
$textinfo .= '<br>';
}
if ($reliquat > $genericProduct->stock_reel) {
$notshippable++;
}
}
}
}
if ($nbprod) {
if (!$has_reliquat) {
$texticon = img_picto('', 'statut5', '', 0, 0, 0, '', 'paddingleft');
$textinfo = $texticon . ' ' . $langs->trans("Shipped");
$result['shippable'] = true;
} elseif ($notshippable) {
$texticon = img_picto('', 'dolly', '', 0, 0, 0, '', 'error paddingleft');
$textinfo = $texticon . ' ' . $langs->trans("NonShippable") . '<br>' . $textinfo;
$result['shippable'] = false;
} else {
$texticon = img_picto('', 'dolly', '', 0, 0, 0, '', 'green paddingleft');
$textinfo = $texticon . ' ' . $langs->trans("Shippable") . '<br>' . $textinfo;
$result['shippable'] = true;
}
$result['has_product'] = true;
$result['texticon'] = $texticon;
$result['textinfo'] = $textinfo;
$result['warning'] = !empty($warning);
}
return $result;
}
}

View file

@ -2999,108 +2999,22 @@ while ($i < $imaxinloop) {
if (!empty($arrayfields['shippable']['checked'])) {
print '<td class="center">';
if (!empty($show_shippable_command) && isModEnabled('stock')) {
$text_icon = '';
if (($obj->fk_statut > $generic_commande::STATUS_DRAFT) && ($obj->fk_statut < $generic_commande::STATUS_CLOSED)) {
$generic_commande->getLinesArray(); // Load array ->lines
$generic_commande->loadExpeditions(); // Load array ->expeditions
$commande = new Commande($db);
$commande->id = (int) $obj->rowid;
$commande->status = (int) $obj->fk_statut;
$commande->statut = (int) $obj->fk_statut;
$numlines = count($generic_commande->lines); // Loop on each line of order
for ($lig = 0; $lig < $numlines; $lig++) {
$orderLine = $generic_commande->lines[$lig];
'@phan-var-force OrderLine $orderLine';
if (isset($generic_commande->expeditions[$orderLine->id])) {
$reliquat = $orderLine->qty - $generic_commande->expeditions[$orderLine->id];
} else {
$reliquat = $orderLine->qty;
}
if ($orderLine->product_type == 0 && $orderLine->fk_product > 0) { // If line is a product and not a service
$nbprod++; // order contains real products
$generic_product->id = $orderLine->fk_product;
$shippableInfos = $commande->getShippableInfos();
// Get local and virtual stock and store it into cache
if (empty($productstat_cache[$orderLine->fk_product])) {
$generic_product->load_stock('nobatch,warehouseopen'); // ->load_virtual_stock() is already included into load_stock()
$productstat_cache[$orderLine->fk_product]['stock_reel'] = $generic_product->stock_reel;
$productstat_cachevirtual[$orderLine->fk_product]['stock_reel'] = $generic_product->stock_theorique;
} else {
$generic_product->stock_reel = $productstat_cache[$orderLine->fk_product]['stock_reel'];
// @phan-suppress-next-line PhanTypeInvalidDimOffset
$generic_product->stock_theorique = $productstat_cachevirtual[$orderLine->fk_product]['stock_reel'];
}
if ($reliquat > $generic_product->stock_reel) {
$notshippable++;
}
if (!getDolGlobalString('SHIPPABLE_ORDER_ICON_IN_LIST')) { // Default code. Default should be this case.
$text_info .= $reliquat.' x '.$orderLine->product_ref.'&nbsp;'.dol_trunc($orderLine->product_label, 20);
$text_info .= ' - '.$langs->trans("Stock").': <span class="'.($generic_product->stock_reel > 0 ? 'ok' : 'error').'">'.$generic_product->stock_reel.'</span>';
$text_info .= ' - '.$langs->trans("VirtualStock").': <span class="'.($generic_product->stock_theorique > 0 ? 'ok' : 'error').'">'.$generic_product->stock_theorique.'</span>';
$text_info .= ($reliquat != $orderLine->qty ? ' <span class="opacitymedium">('.$langs->trans("QtyInOtherShipments").' '.($orderLine->qty - $reliquat).')</span>' : '');
$text_info .= '<br>';
} else { // BUGGED CODE.
// DOES NOT TAKE INTO ACCOUNT MANUFACTURING. THIS CODE SHOULD BE USELESS. PREVIOUS CODE SEEMS COMPLETE.
// COUNT STOCK WHEN WE SHOULD ALREADY HAVE VALUE
// Detailed virtual stock, looks bugged, incomplete and need heavy load.
// stock order and stock order_supplier
$stock_order = 0;
$stock_order_supplier = 0;
if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT') || getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) { // What about other options ?
if (isModEnabled('order')) {
if (empty($productstat_cache[$orderLine->fk_product]['stats_order_customer'])) {
$generic_product->load_stats_commande(0, '1,2');
$productstat_cache[$orderLine->fk_product]['stats_order_customer'] = $generic_product->stats_commande['qty'];
} else {
// @phan-suppress-next-line PhanTypeInvalidDimOffset
$generic_product->stats_commande['qty'] = $productstat_cache[$orderLine->fk_product]['stats_order_customer'];
}
$stock_order = $generic_product->stats_commande['qty'];
}
if (isModEnabled("supplier_order")) {
if (empty($productstat_cache[$orderLine->fk_product]['stats_order_supplier'])) {
$generic_product->load_stats_commande_fournisseur(0, '3');
$productstat_cache[$orderLine->fk_product]['stats_order_supplier'] = $generic_product->stats_commande_fournisseur['qty'];
} else {
// @phan-suppress-next-line PhanTypeInvalidDimOffset
$generic_product->stats_commande_fournisseur['qty'] = $productstat_cache[$orderLine->fk_product]['stats_order_supplier'];
}
$stock_order_supplier = $generic_product->stats_commande_fournisseur['qty'];
}
}
$text_info .= $reliquat.' x '.$orderLine->ref.'&nbsp;'.dol_trunc($orderLine->product_label, 20);
$text_stock_reel = $generic_product->stock_reel.'/'.$stock_order;
if ($stock_order > $generic_product->stock_reel && !($generic_product->stock_reel < $orderLine->qty)) {
$warning++;
$text_warning .= '<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
}
if ($reliquat > $generic_product->stock_reel) {
$text_info .= '<span class="warning">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
} else {
$text_info .= '<span class="ok">'.$langs->trans('Available').'&nbsp;:&nbsp;'.$text_stock_reel.'</span>';
}
if (isModEnabled("supplier_order")) {
$text_info .= '&nbsp;'.$langs->trans('SupplierOrder').'&nbsp;:&nbsp;'.$stock_order_supplier;
}
$text_info .= ($reliquat != $orderLine->qty ? ' <span class="opacitymedium">('.$langs->trans("QtyInOtherShipments").' '.($orderLine->qty - $reliquat).')</span>' : '');
$text_info .= '<br>';
}
}
}
if ($notshippable == 0) {
$text_icon = img_picto('', 'dolly', '', 0, 0, 0, '', 'green paddingleft');
$text_info = $text_icon.' '.$langs->trans('Shippable').'<br>'.$text_info;
} else {
$text_icon = img_picto('', 'dolly', '', 0, 0, 0, '', 'error paddingleft');
$text_info = $text_icon.' '.$langs->trans('NonShippable').'<br>'.$text_info;
}
}
if ($nbprod) { // If there is at least one product to ship, we show the shippable icon
print '<a href="'.DOL_URL_ROOT.'/expedition/shipment.php?id='.((int) $obj->rowid).'">';
print $form->textwithtooltip('', $text_info, 2, 1, $text_icon, '', 2);
if ($shippableInfos['has_product']) {
print '<a href="'.DOL_URL_ROOT.'/expedition/shipment.php?id='.(int) $obj->rowid.'">';
print $form->textwithtooltip('', $shippableInfos['textinfo'], 2, 1, $shippableInfos['texticon'], '', 2);
print '</a>';
}
if ($warning) { // Always false in default mode
print $form->textwithtooltip('', $langs->trans('NotEnoughForAllOrders').'<br>'.$text_warning, 2, 1, img_picto('', 'error'), '', 2);
if (!empty($shippableInfos['warning'])) {
// On ne remonte plus le détail textwarning, mais on garde l’icône d’avertissement
print $form->textwithtooltip('', $langs->trans("NotEnoughForAllOrders"), 2, 1, img_picto('', 'error', '', 0, 0, 0, '', '2'), '', 2);
}
}
}
print '</td>';

View file

@ -58,7 +58,6 @@ if (empty($object) || !is_object($object)) {
print "Error, template page can't be called as URL";
exit(1);
}
'
@phan-var-force Propal|Contrat|Commande|Facture|Expedition|Delivery|CommandeFournisseur|FactureFournisseur|SupplierProposal $object
@phan-var-force PropaleLigne|ContratLigne|CommonObjectLine|CommonInvoiceLine|CommonOrderLine|ExpeditionLigne|DeliveryLine|FactureFournisseurLigneRec|SupplierInvoiceLine|SupplierProposalLine $line
@ -117,7 +116,7 @@ $coldisplay = 0;
?>
<tr class="oddeven tredited">
<?php if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) { ?>
<td class="linecolnum center"><?php $coldisplay++; ?><?php echo($i + 1); ?></td>
<td class="linecolnum center"><?php $coldisplay++; ?><?php /* @phan-suppress-current-line PhanUndeclaredGlobalVariable */ echo($i + 1); ?></td>
<?php }
$coldisplay++;
@ -303,7 +302,14 @@ $coldisplay++;
&nbsp;
<?php } ?>
</td>
<?php
// Shippable Status (Empty cell for edit mode to keep column alignment)
if ($object->element == 'commande' && isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && ($object->status > 0 && $object->status < 3)) {
print '<td class="linecolstock center">';
print '&nbsp;';
print '</td>';
}
?>
<?php
if (getDolGlobalString('PRODUCT_USE_UNITS')) {
$unit_type = false;
@ -414,7 +420,9 @@ $coldisplay++;
$prefillDates = false;
$date_start_prefill = 0;
$date_end_prefill = 0;
// @phan-suppress-next-line PhanUndeclaredGlobalVariable
if (getDolGlobalString('MAIN_FILL_SERVICE_DATES_FROM_LAST_SERVICE_LINE') && !empty($object->lines) && $i > 0) {
// @phan-suppress-next-line PhanUndeclaredGlobalVariable
for ($j = $i - 1; $j >= 0; $j--) {
$lastline = $object->lines[$j];
if ($lastline->product_type == Product::TYPE_SERVICE && (!empty($lastline->date_start) || !empty($lastline->date_end))) {

View file

@ -137,6 +137,11 @@ if (isModEnabled("multicurrency") && $this->multicurrency_code && $this->multicu
// Qty
print '<th class="linecolqty right">'.$langs->trans('Qty').'</th>';
//ShippableStatus
if ($object->element == 'commande' && isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && ($object->status > 0 && $object->status < 3)) {
print '<th class="linecolstock center" style="width: 30px;">'.$langs->trans("ShippableStatus").'</th>';
}
// Unit
if (getDolGlobalString('PRODUCT_USE_UNITS')) {
print '<th class="linecoluseunit left">'.$langs->trans('Unit').'</th>';

View file

@ -83,7 +83,7 @@ if (defined('SUBTOTALS_SPECIAL_CODE') && $line->special_code == SUBTOTALS_SPECIA
return require DOL_DOCUMENT_ROOT.'/core/tpl/subtotal_view.tpl.php';
}
global $mysoc;
global $mysoc, $db;
global $forceall, $senderissupplier, $inputalsopricewithtax, $outputalsopricetotalwithtax;
$usemargins = 0;
@ -462,7 +462,40 @@ if ((($line->info_bits & 2) != 2) && $line->special_code != 3) {
print '&nbsp;';
}
print '</td>';
//Shippable Status
if ($object->element == 'commande' && isModEnabled('stock') && isModEnabled('shipping') && !getDolGlobalString('ORDER_DISABLE_SHIPPABLE_ICON_ON_CARD') && ($object->status > 0 && $object->status < 3)) {
$coldisplay++;
print '<td class="linecolstock center">';
if ($line->fk_product > 0 && $line->product_type == 0) {
static $productstatcache = array();
if (empty($productstatcache[$line->fk_product])) {
$prod = new Product($this->db);
$prod->fetch($line->fk_product);
$prod->load_stock('nobatch,warehouseopen');
$productstatcache[$line->fk_product]['stockreel'] = $prod->stock_reel;
}
$stock = $productstatcache[$line->fk_product]['stockreel'];
$reliquat = $line->qty;
if (!empty($object->expeditions[$line->id])) {
$reliquat -= $object->expeditions[$line->id];
}
if ($reliquat > 0) {
if ($stock >= $reliquat) {
print img_picto($langs->trans("Stock").': '.$stock, 'dolly', '', 0, 0, 0, '', 'green');
} else {
print img_picto($langs->trans("Stock").': '.$stock, 'dolly', '', 0, 0, 0, '', 'error');
}
} else {
print img_picto($langs->trans("Shipped"), 'statut5');
}
} else {
print '&nbsp;';
}
print '</td>';
}
if (getDolGlobalString('PRODUCT_USE_UNITS')) {
print '<td class="linecoluseunit nowrap left">';
$label = $line->getLabelOfUnit('short', $langs);

View file

@ -1551,6 +1551,7 @@ InvoiceOptionCategoryOfOperationsYes1=Yes, below the address block
InvoiceOptionCategoryOfOperationsYes2=Yes, in the lower left-hand corner
InvoiceClassifyBilledSupplierOrderWithoutInvoice=Disallow the classification of an order as billed without invoice.
InvoiceClassifyBilledSupplierOrderWithoutInvoiceHelp=An order can be classified as billed by default. If this conf is set to true, it will be not.
EnableShippableIconOnCard=Enable shippable icon on order card
##### Supplier Orders #####
SupplierOrderClassifyBilledWithoutInvoice=Disallow the classification of a purchase order as billed without invoice.
SupplierOrderClassifyBilledWithoutInvoiceHelp=A supplier order can be classified as billed by default. If this conf is set to true, it will be not.

View file

@ -398,6 +398,8 @@ PriceUHT=U.P. (net)
PriceUHTCurrency=U.P (net) (currency)
PriceUTTC=U.P. (inc. tax)
PriceUTTCCurrency=U.P (inc. tax) (currency)
ShippableStatus=Shippable
Shipped=Shipped
Amount=Amount
Amounts=Amounts
AmountInvoice=Invoice amount