NEW: Add a new method for margin calculation. Added margin on "cost
price" to margin on WAP price and margin on "best supplier price".
This commit is contained in:
parent
381eea0dbf
commit
d396612a7c
@ -4192,9 +4192,10 @@ abstract class CommonObject
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* define buy price if not defined
|
* Get buy price to use for margin calculation. This function is called when buy price is unknown.
|
||||||
* set buy price = sell price if ForceBuyingPriceIfNull configured,
|
* set buy price = sell price if ForceBuyingPriceIfNull configured,
|
||||||
* else if calculation MARGIN_TYPE = 'pmp' and pmp is calculated, set pmp as buyprice
|
* else if calculation MARGIN_TYPE = 'costprice' and costprice is defined, use costprice as buyprice
|
||||||
|
* else if calculation MARGIN_TYPE = 'pmp' and pmp is calculated, use pmp as buyprice
|
||||||
* else set min buy price as buy price
|
* else set min buy price as buy price
|
||||||
*
|
*
|
||||||
* @param float $unitPrice product unit price
|
* @param float $unitPrice product unit price
|
||||||
@ -4209,16 +4210,16 @@ abstract class CommonObject
|
|||||||
|
|
||||||
$buyPrice = 0;
|
$buyPrice = 0;
|
||||||
|
|
||||||
if (($unitPrice > 0) && (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 1))
|
if (($unitPrice > 0) && (isset($conf->global->ForceBuyingPriceIfNull) && $conf->global->ForceBuyingPriceIfNull == 1)) // In most cases, test here is false
|
||||||
{
|
{
|
||||||
$buyPrice = $unitPrice * (1 - $discountPercent / 100);
|
$buyPrice = $unitPrice * (1 - $discountPercent / 100);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Get PMP
|
// Get cost price for margin calculation
|
||||||
if (! empty($fk_product))
|
if (! empty($fk_product))
|
||||||
{
|
{
|
||||||
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp')
|
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'costprice')
|
||||||
{
|
{
|
||||||
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||||
$product = new Product($this->db);
|
$product = new Product($this->db);
|
||||||
@ -4228,13 +4229,32 @@ abstract class CommonObject
|
|||||||
$this->errors[] = 'ErrorProductIdDoesNotExists';
|
$this->errors[] = 'ErrorProductIdDoesNotExists';
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (($product->pmp > 0))
|
if ($product->cost_price > 0)
|
||||||
|
{
|
||||||
|
$buyPrice = $product->cost_price;
|
||||||
|
}
|
||||||
|
else if ($product->pmp > 0)
|
||||||
{
|
{
|
||||||
$buyPrice = $product->pmp;
|
$buyPrice = $product->pmp;
|
||||||
}
|
}
|
||||||
// TODO add option to set PMP of product
|
|
||||||
}
|
}
|
||||||
else if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '1')
|
else if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp')
|
||||||
|
{
|
||||||
|
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
||||||
|
$product = new Product($this->db);
|
||||||
|
$result = $product->fetch($fk_product);
|
||||||
|
if ($result <= 0)
|
||||||
|
{
|
||||||
|
$this->errors[] = 'ErrorProductIdDoesNotExists';
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if ($product->pmp > 0)
|
||||||
|
{
|
||||||
|
$buyPrice = $product->pmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($buyPrice) && isset($conf->global->MARGIN_TYPE) && in_array($conf->global->MARGIN_TYPE, array('1','pmp','costprice')))
|
||||||
{
|
{
|
||||||
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
|
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.product.class.php';
|
||||||
$productFournisseur = new ProductFournisseur($this->db);
|
$productFournisseur = new ProductFournisseur($this->db);
|
||||||
|
|||||||
@ -521,30 +521,56 @@ jQuery(document).ready(function() {
|
|||||||
var defaultkey = '';
|
var defaultkey = '';
|
||||||
var defaultprice = '';
|
var defaultprice = '';
|
||||||
var bestpricefound = 0;
|
var bestpricefound = 0;
|
||||||
|
|
||||||
|
var bestpriceid = 0; var bestpricevalue = 0;
|
||||||
|
var pmppriceid = 0; var pmppricevalue = 0;
|
||||||
|
var costpriceid = 0; var costpricevalue = 0;
|
||||||
|
|
||||||
|
/* setup of margin calculation */
|
||||||
|
var defaultbuyprice = '<?php
|
||||||
|
if (isset($conf->global->MARGIN_TYPE))
|
||||||
|
{
|
||||||
|
if ($conf->global->MARGIN_TYPE == '1') print 'bestsupplierprice';
|
||||||
|
if ($conf->global->MARGIN_TYPE == 'pmp') print 'pmp';
|
||||||
|
if ($conf->global->MARGIN_TYPE == 'costprice') print 'costprice';
|
||||||
|
} ?>';
|
||||||
|
console.log("defaultbuyprice="+defaultbuyprice);
|
||||||
|
|
||||||
var i = 0;
|
var i = 0;
|
||||||
$(data).each(function() {
|
$(data).each(function() {
|
||||||
if (this.id != 'pmpprice')
|
if (this.id != 'pmpprice' && this.id != 'costprice')
|
||||||
{
|
{
|
||||||
i++;
|
i++;
|
||||||
this.price = parseFloat(this.price);//fix this.price >0
|
this.price = parseFloat(this.price); // to fix when this.price >0
|
||||||
|
|
||||||
// If margin is calculated on best supplier price, we set it by defaut (but only if value is not 0)
|
// If margin is calculated on best supplier price, we set it by defaut (but only if value is not 0)
|
||||||
var defaultbuyprice = '<?php echo ((isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '1')?'bestsupplierprice':''); ?>'; // We set here default value to use
|
console.log("id="+this.id+"-price="+this.price+"-"+(this.price > 0));
|
||||||
console.log(this.id+" "+this.price+" "+defaultbuyprice+" "+(this.price > 0));
|
if (bestpricefound == 0 && this.price > 0) { defaultkey = this.id; defaultprice = this.price; bestpriceid = this.id; bestpricevalue = this.price; bestpricefound=1; } // bestpricefound is used to take the first price > 0
|
||||||
if (bestpricefound == 0 && this.price > 0 && 'bestsupplierprice' == defaultbuyprice) { defaultkey = this.id; defaultprice = this.price; bestpricefound=1; } // bestpricefound is used to take the first price > 0
|
|
||||||
}
|
}
|
||||||
if (this.id == 'pmpprice')
|
if (this.id == 'pmpprice')
|
||||||
{
|
{
|
||||||
// If margin is calculated on PMP, we set it by defaut (but only if value is not 0)
|
// If margin is calculated on PMP, we set it by defaut (but only if value is not 0)
|
||||||
var defaultbuyprice = '<?php echo ((isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp')?'pmp':''); ?>';
|
console.log("id="+this.id+"-price="+this.price);
|
||||||
console.log(this.id+" "+this.price+" "+defaultbuyprice);
|
if ('pmp' == defaultbuyprice || 'costprice' == defaultbuyprice)
|
||||||
if (this.price > 0 && 'pmp' == defaultbuyprice) { defaultkey = this.id; defaultprice = this.price; }
|
{
|
||||||
|
if (this.price > 0) { defaultkey = this.id; defaultprice = this.price; pmppriceid = this.id; pmppricevalue = this.price;
|
||||||
|
console.log("pmppricevalue="+pmppricevalue); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.id == 'costprice')
|
||||||
|
{
|
||||||
|
// If margin is calculated on Cost price, we set it by defaut (but only if value is not 0)
|
||||||
|
console.log("id="+this.id+"-price="+this.price+"-pmppricevalue="+pmppricevalue);
|
||||||
|
if ('costprice' == defaultbuyprice)
|
||||||
|
{
|
||||||
|
if (this.price > 0) { defaultkey = this.id; defaultprice = this.price; costpriceid = this.id; costpricevalue = this.price; }
|
||||||
|
else if (pmppricevalue > 0) { defaultkey = pmppriceid; defaultprice = pmppricevalue; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
options += '<option value="'+this.id+'" price="'+this.price+'">'+this.label+'</option>';
|
options += '<option value="'+this.id+'" price="'+this.price+'">'+this.label+'</option>';
|
||||||
});
|
});
|
||||||
options += '<option value="inputprice" price="'+defaultprice+'"><?php echo $langs->trans("InputPrice"); ?></option>';
|
options += '<option value="inputprice" price="'+defaultprice+'"><?php echo $langs->trans("InputPrice"); ?></option>';
|
||||||
|
|
||||||
console.log("defaultkey="+defaultkey);
|
console.log("finally selected defaultkey="+defaultkey+" defaultprice="+defaultprice);
|
||||||
|
|
||||||
$("#fournprice_predef").html(options).show();
|
$("#fournprice_predef").html(options).show();
|
||||||
if (defaultkey != '')
|
if (defaultkey != '')
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
/* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
||||||
* Copyright (C) 2015 Francis Appels <francis.appels@z-application.com>
|
* Copyright (C) 2015 Francis Appels <francis.appels@z-application.com>
|
||||||
|
* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -18,7 +19,7 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* \file /htdocs/fourn/ajax/getSupplierPrices.php
|
* \file /htdocs/fourn/ajax/getSupplierPrices.php
|
||||||
* \brief File to return an Ajax response to get a supplier prices
|
* \brief File to return an Ajax response to get list of possible prices for margin calculation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal
|
if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Disables token renewal
|
||||||
@ -36,6 +37,8 @@ $idprod=GETPOST('idprod','int');
|
|||||||
$prices = array();
|
$prices = array();
|
||||||
|
|
||||||
$langs->load('stocks');
|
$langs->load('stocks');
|
||||||
|
$langs->load('margins');
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* View
|
* View
|
||||||
@ -92,6 +95,10 @@ if ($idprod > 0)
|
|||||||
// Add price for pmp
|
// Add price for pmp
|
||||||
$price=$producttmp->pmp;
|
$price=$producttmp->pmp;
|
||||||
$prices[] = array("id" => 'pmpprice', "price" => price2num($price), "label" => $langs->trans("PMPValueShort").': '.price($price,0,$langs,0,0,-1,$conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price,0,$langs,0,0,-1,$conf->currency)); // For price field, we must use price2num(), for label or title, price()
|
$prices[] = array("id" => 'pmpprice', "price" => price2num($price), "label" => $langs->trans("PMPValueShort").': '.price($price,0,$langs,0,0,-1,$conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price,0,$langs,0,0,-1,$conf->currency)); // For price field, we must use price2num(), for label or title, price()
|
||||||
|
|
||||||
|
// Add price for costprice
|
||||||
|
$price=$producttmp->cost_price;
|
||||||
|
$prices[] = array("id" => 'costprice', "price" => price2num($price), "label" => $langs->trans("CostPrice").': '.price($price,0,$langs,0,0,-1,$conf->currency), "title" => $langs->trans("PMPValueShort").': '.price($price,0,$langs,0,0,-1,$conf->currency)); // For price field, we must use price2num(), for label or title, price()
|
||||||
}
|
}
|
||||||
|
|
||||||
echo json_encode($prices);
|
echo json_encode($prices);
|
||||||
|
|||||||
@ -35,8 +35,9 @@ MargeBrute=Raw margin
|
|||||||
MargeNette=Net margin
|
MargeNette=Net margin
|
||||||
MargeType1=Margin on Best supplier price
|
MargeType1=Margin on Best supplier price
|
||||||
MargeType2=Margin on Weighted Average Price (WAP)
|
MargeType2=Margin on Weighted Average Price (WAP)
|
||||||
MARGIN_TYPE_DETAILS=Raw margin : Selling price - Buying price<br/>Net margin : Selling price - Cost price
|
MargeType3=Margin on Cost Price
|
||||||
MarginTypeDesc=Margin on best buying price : Selling price - Best supplier price defined on product card<br/>Margin on Weighted Average Price (WAP) : Selling price - Product Weighted Average Price (WAP) or best supplier price if WAP not yet defined
|
MARGIN_TYPE_DETAILS=Raw margin : Selling price - Buying price<br>Net margin : Selling price - Cost price
|
||||||
|
MarginTypeDesc=* Margin on best buying price = Selling price - Best supplier price defined on product card<br>* Margin on Weighted Average Price (WAP) = Selling price - Product Weighted Average Price (WAP) or best supplier price if WAP not yet defined<br>* Margin on Cost price = Selling price - Cost price defined on product card or WAP if cost price not defined, or best supplier price if WAP not yet defined
|
||||||
CostPrice=Cost price
|
CostPrice=Cost price
|
||||||
BuyingCost=Cost price
|
BuyingCost=Cost price
|
||||||
UnitCharges=Unit charges
|
UnitCharges=Unit charges
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
/* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
/* Copyright (C) 2012 Christophe Battarel <christophe.battarel@altairis.fr>
|
||||||
|
* Copyright (C) 2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -145,20 +146,15 @@ if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '1')
|
|||||||
print '/> ';
|
print '/> ';
|
||||||
print $langs->trans('MargeType1');
|
print $langs->trans('MargeType1');
|
||||||
print '<br>';
|
print '<br>';
|
||||||
/*print $langs->trans('MargeNette');
|
print ' <input type="radio" name="MARGIN_TYPE" value="pmp" ';
|
||||||
print ' <input type="radio" name="MARGIN_TYPE" value="2" ';
|
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp') print 'checked ';
|
||||||
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '2')
|
print '/> ';
|
||||||
print 'checked ';
|
print $langs->trans('MargeType2');
|
||||||
print '/>';*/
|
print '<br>';
|
||||||
// TODO Check that PMP is available when stock module is not enabled. If not, make this choice greyed when stock module disabled.
|
print ' <input type="radio" name="MARGIN_TYPE" value="costprice" ';
|
||||||
//if (! empty($conf->stock->enabled))
|
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'costprice') print 'checked ';
|
||||||
//{
|
print '/> ';
|
||||||
print ' <input type="radio" name="MARGIN_TYPE" value="pmp" ';
|
print $langs->trans('MargeType3');
|
||||||
if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp')
|
|
||||||
print 'checked ';
|
|
||||||
print '/> ';
|
|
||||||
print $langs->trans('MargeType2');
|
|
||||||
//}
|
|
||||||
print '</td>';
|
print '</td>';
|
||||||
print '<td>';
|
print '<td>';
|
||||||
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'" class="button">';
|
print '<input type="submit" class="button" value="'.$langs->trans("Modify").'" class="button">';
|
||||||
|
|||||||
@ -106,6 +106,8 @@ class Product extends CommonObject
|
|||||||
|
|
||||||
//! Stock
|
//! Stock
|
||||||
var $stock_reel;
|
var $stock_reel;
|
||||||
|
//! Cost price
|
||||||
|
var $cost_price;
|
||||||
//! Average price value for product entry into stock (PMP)
|
//! Average price value for product entry into stock (PMP)
|
||||||
var $pmp;
|
var $pmp;
|
||||||
//! Stock alert
|
//! Stock alert
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user