From d396612a7cfd941e91fd151f6145d536890707a8 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 13 Jan 2016 12:48:59 +0100 Subject: [PATCH] NEW: Add a new method for margin calculation. Added margin on "cost price" to margin on WAP price and margin on "best supplier price". --- htdocs/core/class/commonobject.class.php | 38 ++++++++++++++----- htdocs/core/tpl/objectline_create.tpl.php | 46 ++++++++++++++++++----- htdocs/fourn/ajax/getSupplierPrices.php | 11 +++++- htdocs/langs/en_US/margins.lang | 5 ++- htdocs/margin/admin/margin.php | 24 +++++------- htdocs/product/class/product.class.php | 2 + 6 files changed, 89 insertions(+), 37 deletions(-) diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index 2929b66e80c..7570b89d9f9 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -4191,10 +4191,11 @@ abstract class CommonObject return true; } - /** - * 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, - * 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 * * @param float $unitPrice product unit price @@ -4209,16 +4210,16 @@ abstract class CommonObject $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); } else { - // Get PMP + // Get cost price for margin calculation 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'; $product = new Product($this->db); @@ -4228,13 +4229,32 @@ abstract class CommonObject $this->errors[] = 'ErrorProductIdDoesNotExists'; return -1; } - if (($product->pmp > 0)) + if ($product->cost_price > 0) + { + $buyPrice = $product->cost_price; + } + else if ($product->pmp > 0) { $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'; $productFournisseur = new ProductFournisseur($this->db); diff --git a/htdocs/core/tpl/objectline_create.tpl.php b/htdocs/core/tpl/objectline_create.tpl.php index 31ad9716155..e17648a7643 100644 --- a/htdocs/core/tpl/objectline_create.tpl.php +++ b/htdocs/core/tpl/objectline_create.tpl.php @@ -521,30 +521,56 @@ jQuery(document).ready(function() { var defaultkey = ''; var defaultprice = ''; 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 = '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; $(data).each(function() { - if (this.id != 'pmpprice') + if (this.id != 'pmpprice' && this.id != 'costprice') { 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) - var defaultbuyprice = 'global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '1')?'bestsupplierprice':''); ?>'; // We set here default value to use - console.log(this.id+" "+this.price+" "+defaultbuyprice+" "+(this.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 + console.log("id="+this.id+"-price="+this.price+"-"+(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 (this.id == 'pmpprice') { // If margin is calculated on PMP, we set it by defaut (but only if value is not 0) - var defaultbuyprice = 'global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp')?'pmp':''); ?>'; - console.log(this.id+" "+this.price+" "+defaultbuyprice); - if (this.price > 0 && 'pmp' == defaultbuyprice) { defaultkey = this.id; defaultprice = this.price; } + console.log("id="+this.id+"-price="+this.price); + if ('pmp' == defaultbuyprice || 'costprice' == defaultbuyprice) + { + 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 += ''; }); options += ''; - console.log("defaultkey="+defaultkey); + console.log("finally selected defaultkey="+defaultkey+" defaultprice="+defaultprice); $("#fournprice_predef").html(options).show(); if (defaultkey != '') diff --git a/htdocs/fourn/ajax/getSupplierPrices.php b/htdocs/fourn/ajax/getSupplierPrices.php index 9a94553930d..794a0addcf4 100644 --- a/htdocs/fourn/ajax/getSupplierPrices.php +++ b/htdocs/fourn/ajax/getSupplierPrices.php @@ -1,6 +1,7 @@ - * Copyright (C) 2015 Francis Appels + * Copyright (C) 2015 Francis Appels + * Copyright (C) 2016 Laurent Destailleur * * 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 @@ -18,7 +19,7 @@ /** * \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 @@ -36,6 +37,8 @@ $idprod=GETPOST('idprod','int'); $prices = array(); $langs->load('stocks'); +$langs->load('margins'); + /* * View @@ -92,6 +95,10 @@ if ($idprod > 0) // Add price for 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() + + // 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); diff --git a/htdocs/langs/en_US/margins.lang b/htdocs/langs/en_US/margins.lang index 4cfaa989cd1..b705f25ba42 100644 --- a/htdocs/langs/en_US/margins.lang +++ b/htdocs/langs/en_US/margins.lang @@ -35,8 +35,9 @@ MargeBrute=Raw margin MargeNette=Net margin MargeType1=Margin on Best supplier price MargeType2=Margin on Weighted Average Price (WAP) -MARGIN_TYPE_DETAILS=Raw margin : Selling price - Buying price
Net margin : Selling price - Cost price -MarginTypeDesc=Margin on best buying price : Selling price - Best supplier price defined on product card
Margin on Weighted Average Price (WAP) : Selling price - Product Weighted Average Price (WAP) or best supplier price if WAP not yet defined +MargeType3=Margin on Cost Price +MARGIN_TYPE_DETAILS=Raw margin : Selling price - Buying price
Net margin : Selling price - Cost price +MarginTypeDesc=* Margin on best buying price = Selling price - Best supplier price defined on product card
* Margin on Weighted Average Price (WAP) = Selling price - Product Weighted Average Price (WAP) or best supplier price if WAP not yet defined
* 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 BuyingCost=Cost price UnitCharges=Unit charges diff --git a/htdocs/margin/admin/margin.php b/htdocs/margin/admin/margin.php index 706d14ebe12..6e84b13e286 100644 --- a/htdocs/margin/admin/margin.php +++ b/htdocs/margin/admin/margin.php @@ -1,5 +1,6 @@ + * Copyright (C) 2016 Laurent Destailleur * * 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 @@ -145,20 +146,15 @@ if (isset($conf->global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '1') print '/> '; print $langs->trans('MargeType1'); print '
'; -/*print $langs->trans('MargeNette'); -print ' global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == '2') - print 'checked '; -print '/>';*/ -// TODO Check that PMP is available when stock module is not enabled. If not, make this choice greyed when stock module disabled. -//if (! empty($conf->stock->enabled)) -//{ - print ' global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp') - print 'checked '; - print '/> '; - print $langs->trans('MargeType2'); -//} +print ' global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'pmp') print 'checked '; +print '/> '; +print $langs->trans('MargeType2'); +print '
'; +print ' global->MARGIN_TYPE) && $conf->global->MARGIN_TYPE == 'costprice') print 'checked '; +print '/> '; +print $langs->trans('MargeType3'); print ''; print ''; print ''; diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 8c744fbb6d3..a0703d73caf 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -106,6 +106,8 @@ class Product extends CommonObject //! Stock var $stock_reel; + //! Cost price + var $cost_price; //! Average price value for product entry into stock (PMP) var $pmp; //! Stock alert