Skip to content

Commit

Permalink
Merge pull request #1381 from Easya-Solutions/2024_rc_customer_price_…
Browse files Browse the repository at this point in the history
…period

CORE product: Ajout des dates de debut et de fin de validité d'un prix de vente client et de la remise
  • Loading branch information
kkhelifa-opendsi authored Feb 25, 2025
2 parents df29f4a + 7be415d commit 43b9b1c
Show file tree
Hide file tree
Showing 21 changed files with 371 additions and 85 deletions.
30 changes: 18 additions & 12 deletions htdocs/comm/propal/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -1129,19 +1129,25 @@
if ($result) {
// If there is some prices specific to the customer
if (count($prodcustprice->lines) > 0) {
$pu_ht = price($prodcustprice->lines[0]->price);
$pu_ttc = price($prodcustprice->lines[0]->price_ttc);
$price_min = price($prodcustprice->lines[0]->price_min);
$price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
$price_base_type = $prodcustprice->lines[0]->price_base_type;
/*$tva_tx = ($prodcustprice->lines[0]->default_vat_code ? $prodcustprice->lines[0]->tva_tx.' ('.$prodcustprice->lines[0]->default_vat_code.' )' : $prodcustprice->lines[0]->tva_tx);
if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($prodcustprice->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$pu_ht = price($custprice_line->price);
$pu_ttc = price($custprice_line->price_ttc);
$price_min = price($custprice_line->price_min);
$price_min_ttc = price($custprice_line->price_min_ttc);
$price_base_type = $custprice_line->price_base_type;
/*$tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx.' ('.$custprice_line->default_vat_code.' )' : $custprice_line->tva_tx);
if ($custprice_line->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$custprice_line->default_vat_code.')';
}
$tva_npr = $custprice_line->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
}*/
break;
}
}
$tva_npr = $prodcustprice->lines[0]->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
}*/
}
}
} elseif (!empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY)) {
Expand Down
15 changes: 11 additions & 4 deletions htdocs/comm/propal/class/propal.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -1458,10 +1458,17 @@ public function createFromClone(User $user, $socid = 0, $forceentity = null, $up
if ($result) {
// If there is some prices specific to the customer
if (count($prodcustprice->lines) > 0) {
$pu_ht = price($prodcustprice->lines[0]->price);
$tva_tx = ($prodcustprice->lines[0]->default_vat_code ? $prodcustprice->lines[0]->tva_tx.' ('.$prodcustprice->lines[0]->default_vat_code.' )' : $prodcustprice->lines[0]->tva_tx);
if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($prodcustprice->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$pu_ht = price($custprice_line->price);
$tva_tx = ($custprice_line->default_vat_code ? $custprice_line->tva_tx . ' (' . $custprice_line->default_vat_code . ' )' : $custprice_line->tva_tx);
if ($custprice_line->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' (' . $custprice_line->default_vat_code . ')';
}
$remise_percent = $custprice_line->remise_percent;
break;
}
}
}
}
Expand Down
30 changes: 18 additions & 12 deletions htdocs/commande/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -831,18 +831,24 @@
$result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
if ($result >= 0) {
if (count($prodcustprice->lines) > 0) {
$pu_ht = price($prodcustprice->lines[0]->price);
$pu_ttc = price($prodcustprice->lines[0]->price_ttc);
$price_min = price($prodcustprice->lines[0]->price_min);
$price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
$price_base_type = $prodcustprice->lines[0]->price_base_type;
$tva_tx = $prodcustprice->lines[0]->tva_tx;
if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
}
$tva_npr = $prodcustprice->lines[0]->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($prodcustprice->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$pu_ht = price($custprice_line->price);
$pu_ttc = price($custprice_line->price_ttc);
$price_min = price($custprice_line->price_min);
$price_min_ttc = price($custprice_line->price_min_ttc);
$price_base_type = $custprice_line->price_base_type;
$tva_tx = $custprice_line->tva_tx;
if ($custprice_line->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' (' . $custprice_line->default_vat_code . ')';
}
$tva_npr = $custprice_line->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
}
break;
}
}
}
} else {
Expand Down
24 changes: 15 additions & 9 deletions htdocs/contrat/card.php
Original file line number Diff line number Diff line change
Expand Up @@ -519,16 +519,22 @@
$result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
if ($result) {
if (count($prodcustprice->lines) > 0) {
$price_min = price($prodcustprice->lines[0]->price_min);
$price_min_ttc = price($prodcustprice->lines[0]->price_min_ttc);
/*$tva_tx = $prodcustprice->lines[0]->tva_tx;
if ($prodcustprice->lines[0]->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($prodcustprice->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$price_min = price($custprice_line->price_min);
$price_min_ttc = price($custprice_line->price_min_ttc);
/*$tva_tx = $custprice_line->tva_tx;
if ($custprice_line->default_vat_code && !preg_match('/\(.*\)/', $tva_tx)) {
$tva_tx .= ' ('.$custprice_line->default_vat_code.')';
}
$tva_npr = $custprice_line->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
}*/
break;
}
}
$tva_npr = $prodcustprice->lines[0]->recuperableonly;
if (empty($tva_tx)) {
$tva_npr = 0;
}*/
}
}
}
Expand Down
20 changes: 17 additions & 3 deletions htdocs/core/class/html.form.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -2698,8 +2698,8 @@ public function select_produits_list($selected = '', $htmlname = 'productid', $f
//Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql .= ', pcp.rowid as idprodcustprice, pcp.price as custprice, pcp.price_ttc as custprice_ttc,';
$sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref';
$selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref";
$sql .= ' pcp.price_base_type as custprice_base_type, pcp.tva_tx as custtva_tx, pcp.default_vat_code as custdefault_vat_code, pcp.ref_customer as custref, pcp.remise_percent as custremise_percent';
$selectFields .= ", idprodcustprice, custprice, custprice_ttc, custprice_base_type, custtva_tx, custdefault_vat_code, custref, custremise_percent";
}
// Units
if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
Expand Down Expand Up @@ -2750,7 +2750,20 @@ public function select_produits_list($selected = '', $htmlname = 'productid', $f

//Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($socid)) {
$sql .= " LEFT JOIN " . $this->db->prefix() . "product_customer_price as pcp ON pcp.fk_soc=" . ((int) $socid) . " AND pcp.fk_product=p.rowid";
$now = dol_now();
$sql .= " LEFT JOIN (";
$sql .= " SELECT pcp1.*";
$sql .= " FROM " . $this->db->prefix() . "product_customer_price AS pcp1";
$sql .= " LEFT JOIN (";
$sql .= " SELECT fk_soc, fk_product, MIN(date_begin) AS date_begin";
$sql .= " FROM " . $this->db->prefix() . "product_customer_price";
$sql .= " WHERE fk_soc = " . ((int) $socid);
$sql .= " AND date_begin <= '" . $this->db->idate($now) . "'";
$sql .= " AND (date_end IS NULL OR '" . $this->db->idate($now) . "' <= date_end)";
$sql .= " GROUP BY fk_soc, fk_product";
$sql .= " ) AS pcp2 ON pcp1.fk_soc = pcp2.fk_soc AND pcp1.fk_product = pcp2.fk_product AND pcp1.date_begin = pcp2.date_begin";
$sql .= " WHERE pcp2.fk_soc IS NOT NULL";
$sql .= " ) AS pcp ON pcp.fk_soc = " . ((int) $socid) . " AND pcp.fk_product = p.rowid";
}
// Units
if (getDolGlobalInt('PRODUCT_USE_UNITS')) {
Expand Down Expand Up @@ -3238,6 +3251,7 @@ protected function constructProductListOption(&$objp, &$opt, &$optJson, $price_l
$outpricebasetype = $objp->custprice_base_type;
$outtva_tx = $objp->custtva_tx;
$outdefault_vat_code = $objp->custdefault_vat_code;
$outdiscount = $objp->custremise_percent;
}
}

Expand Down
13 changes: 11 additions & 2 deletions htdocs/core/lib/pdf.lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -1640,9 +1640,18 @@ function pdf_getlinedesc($object, $i, $outputlangs, $hideref = 0, $hidedesc = 0,
$nbCustomerPrices = $productCustomerPriceStatic->fetchAll('', '', 1, 0, $filter);

if ($nbCustomerPrices > 0) {
$productCustomerPrice = $productCustomerPriceStatic->lines[0];
$productCustomerPrice = null;
if (count($productCustomerPriceStatic->lines) > 0) {
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($productCustomerPriceStatic->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$productCustomerPrice = $custprice_line;
break;
}
}
}

if (!empty($productCustomerPrice->ref_customer)) {
if (isset($productCustomerPrice) && !empty($productCustomerPrice->ref_customer)) {
switch ($conf->global->PRODUIT_CUSTOMER_PRICES_PDF_REF_MODE) {
case 1:
$ref_prodserv = $productCustomerPrice->ref_customer;
Expand Down
6 changes: 6 additions & 0 deletions htdocs/core/modules/modProduct.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -368,22 +368,28 @@ public function __construct($db)
$this->export_permission[$r] = array(array("produit", "export"));
$this->export_fields_array[$r] = array('p.rowid'=>"Id", 'p.ref'=>"Ref", 'p.label'=>"Label",
's.nom'=>'ThirdParty',
'pr.date_begin' => "AppliedPricesFrom",
'pr.date_end' => "AppliedPricesTo",
'pr.price_base_type'=>"PriceBase",
'pr.price'=>"PriceUnitPriceHT", 'pr.price_ttc'=>"PriceUnitPriceTTC",
'pr.price_min'=>"MinPriceUnitPriceHT", 'pr.price_min_ttc'=>"MinPriceUnitPriceTTC",
'pr.tva_tx'=>'PriceVATRate',
'pr.default_vat_code'=>'PriceVATCode',
'pr.remise_percent' => 'Discount',
'pr.datec'=>'DateCreation');
if (is_object($mysoc) && $usenpr) {
$this->export_fields_array[$r]['pr.recuperableonly'] = 'NPR';
}
$this->export_entities_array[$r] = array('p.rowid'=>"product", 'p.ref'=>"product", 'p.label'=>"Label",
's.nom'=>'company',
'pr.date_begin' => "product",
'pr.date_end' => "product",
'pr.price_base_type'=>"product", 'pr.price'=>"product",
'pr.price_ttc'=>"product",
'pr.price_min'=>"product", 'pr.price_min_ttc'=>"product",
'pr.tva_tx'=>'product',
'pr.default_vat_code'=>'product',
'pr.remise_percent' => 'product',
'pr.recuperableonly'=>'product',
'pr.datec'=>"product");
$this->export_sql_start[$r] = 'SELECT DISTINCT ';
Expand Down
6 changes: 6 additions & 0 deletions htdocs/core/modules/modService.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -327,22 +327,28 @@ public function __construct($db)
$this->export_permission[$r] = array(array("service", "export"));
$this->export_fields_array[$r] = array('p.rowid'=>"Id", 'p.ref'=>"Ref",
's.nom'=>'ThirdParty',
'pr.date_begin' => "AppliedPricesFrom",
'pr.date_end' => "AppliedPricesTo",
'pr.price_base_type'=>"PriceBase",
'pr.price'=>"PriceUnitPriceHT", 'pr.price_ttc'=>"PriceUnitPriceTTC",
'pr.price_min'=>"MinPriceUnitPriceHT", 'pr.price_min_ttc'=>"MinPriceUnitPriceTTC",
'pr.tva_tx'=>'PriceVATRate',
'pr.default_vat_code'=>'PriceVATCode',
'pr.remise_percent' => 'Discount',
'pr.datec'=>'DateCreation');
if (is_object($mysoc) && $usenpr) {
$this->export_fields_array[$r]['pr.recuperableonly'] = 'NPR';
}
$this->export_entities_array[$r] = array('p.rowid'=>"product", 'p.ref'=>"product",
's.nom'=>'company',
'pr.date_begin' => "product",
'pr.date_end' => "product",
'pr.price_base_type'=>"product", 'pr.price'=>"product",
'pr.price_ttc'=>"product",
'pr.price_min'=>"product", 'pr.price_min_ttc'=>"product",
'pr.tva_tx'=>'product',
'pr.default_vat_code'=>'product',
'pr.remise_percent' => 'product',
'pr.recuperableonly'=>'product',
'pr.datec'=>"product");
$this->export_sql_start[$r] = 'SELECT DISTINCT ';
Expand Down
7 changes: 7 additions & 0 deletions htdocs/core/tpl/objectline_create.tpl.php
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,13 @@ function(data) {
$('#tva_tx option[value="'+stringforvatrateselection+'"]').prop('selected', true);

<?php
// Price by customer
if (!empty($conf->global->PRODUIT_CUSTOMER_PRICES) && !empty($object->socid)) {
?>
$("#remise_percent").val(data.discount);
<?php
}

if (!empty($conf->global->PRODUIT_AUTOFILL_DESC) && $conf->global->PRODUIT_AUTOFILL_DESC == 1) {
if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) { ?>
var proddesc = data.desc_trans;
Expand Down
16 changes: 16 additions & 0 deletions htdocs/install/mysql/migration/17.0.0-18.0.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -654,3 +654,19 @@ ALTER TABLE llx_c_type_contact MODIFY COLUMN element VARCHAR(64) NOT NULL;

-- delete a constant that should not be set
DELETE FROM llx_const WHERE name = 'INVOICE_USE_RETAINED_WARRANTY' AND value = -1;

-- Customer price - add discount and validate period
ALTER TABLE llx_product_customer_price ADD COLUMN date_begin date AFTER ref_customer;
ALTER TABLE llx_product_customer_price ADD COLUMN date_end date AFTER date_begin;
ALTER TABLE llx_product_customer_price ADD COLUMN remise_percent real DEFAULT 0 AFTER localtax2_type;
ALTER TABLE llx_product_customer_price_log ADD COLUMN date_begin date AFTER ref_customer;
ALTER TABLE llx_product_customer_price_log ADD COLUMN date_end date AFTER date_begin;
ALTER TABLE llx_product_customer_price_log ADD COLUMN remise_percent real DEFAULT 0 AFTER localtax2_type;
ALTER TABLE llx_product_customer_price DROP CONSTRAINT fk_product_customer_price_fk_product;
ALTER TABLE llx_product_customer_price DROP CONSTRAINT fk_product_customer_price_fk_soc;
ALTER TABLE llx_product_customer_price DROP INDEX uk_customer_price_fk_product_fk_soc;
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc, date_begin);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_soc FOREIGN KEY (fk_soc) REFERENCES llx_societe(rowid);
UPDATE llx_product_customer_price SET date_begin = datec WHERE date_begin IS NULL;
UPDATE llx_product_customer_price_log SET date_begin = datec WHERE date_begin IS NULL;
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

ALTER TABLE llx_product_customer_price ADD INDEX idx_product_customer_price_fk_user (fk_user);
ALTER TABLE llx_product_customer_price ADD INDEX idx_product_customer_price_fk_soc (fk_soc);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc);
ALTER TABLE llx_product_customer_price ADD UNIQUE INDEX uk_customer_price_fk_product_fk_soc (fk_product, fk_soc, date_begin);

ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_user FOREIGN KEY (fk_user) REFERENCES llx_user (rowid);
ALTER TABLE llx_product_customer_price ADD CONSTRAINT fk_product_customer_price_fk_product FOREIGN KEY (fk_product) REFERENCES llx_product(rowid);
Expand Down
3 changes: 3 additions & 0 deletions htdocs/install/mysql/tables/llx_product_customer_price.sql
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ create table llx_product_customer_price
fk_product integer NOT NULL,
fk_soc integer NOT NULL,
ref_customer varchar(128),
date_begin date NOT NULL,
date_end date,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
Expand All @@ -41,6 +43,7 @@ create table llx_product_customer_price
localtax1_type varchar(10) NOT NULL DEFAULT '0',
localtax2_tx double(7,4) DEFAULT 0, -- Other local VAT 2
localtax2_type varchar(10) NOT NULL DEFAULT '0',
remise_percent real DEFAULT 0,
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ create table llx_product_customer_price_log
fk_product integer NOT NULL,
fk_soc integer DEFAULT 0 NOT NULL,
ref_customer varchar(30),
date_begin date NOT NULL,
date_end date,
price double(24,8) DEFAULT 0,
price_ttc double(24,8) DEFAULT 0,
price_min double(24,8) DEFAULT 0,
Expand All @@ -40,6 +42,7 @@ create table llx_product_customer_price_log
localtax1_type varchar(10) NOT NULL DEFAULT '0',
localtax2_tx double(7,4) DEFAULT 0, -- Other local VAT 2
localtax2_type varchar(10) NOT NULL DEFAULT '0',
remise_percent real DEFAULT 0,
fk_user integer,
import_key varchar(14) -- Import key
)ENGINE=innodb;
1 change: 1 addition & 0 deletions htdocs/langs/en_US/products.lang
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ UpdateVAT=Update vat
UpdateDefaultPrice=Update default price
UpdateLevelPrices=Update prices for each level
AppliedPricesFrom=Applied from
AppliedPricesTo=Applied to
SellingPrice=Selling price
SellingPriceHT=Selling price (excl. tax)
SellingPriceTTC=Selling price (inc. tax)
Expand Down
1 change: 1 addition & 0 deletions htdocs/langs/fr_FR/products.lang
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ UpdateVAT=Modifier TVA
UpdateDefaultPrice=Modifier prix par défaut
UpdateLevelPrices=Modifier prix pour chaque niveau
AppliedPricesFrom=Pratiqués à partir du
AppliedPricesTo=Pratiqués jusqu'au
SellingPrice=Prix de vente
SellingPriceHT=Prix de vente HT
SellingPriceTTC=Prix de vente TTC
Expand Down
21 changes: 14 additions & 7 deletions htdocs/product/ajax/products.php
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,20 @@
$result = $prodcustprice->fetchAll('', '', 0, 0, $filter);
if ($result) {
if (count($prodcustprice->lines) > 0) {
$found = true;
$outprice_ht = price($prodcustprice->lines[0]->price);
$outprice_ttc = price($prodcustprice->lines[0]->price_ttc);
$outpricebasetype = $prodcustprice->lines[0]->price_base_type;
$outtva_tx_formated = price($prodcustprice->lines[0]->tva_tx);
$outtva_tx = price2num($prodcustprice->lines[0]->tva_tx);
$outdefault_vat_code = $prodcustprice->lines[0]->default_vat_code;
$date_now = (int) floor(dol_now() / 86400) * 86400; // date without hours
foreach ($prodcustprice->lines as $k => $custprice_line) {
if ($custprice_line->date_begin <= $date_now && (empty($custprice_line->date_end) || $date_now <= $custprice_line->date_end)) {
$found = true;
$outprice_ht = price($custprice_line->price);
$outprice_ttc = price($custprice_line->price_ttc);
$outpricebasetype = $custprice_line->price_base_type;
$outtva_tx_formated = price($custprice_line->tva_tx);
$outtva_tx = price2num($custprice_line->tva_tx);
$outdefault_vat_code = $custprice_line->default_vat_code;
$outdiscount = $custprice_line->remise_percent;
break;
}
}
}
}
}
Expand Down
Loading

0 comments on commit 43b9b1c

Please sign in to comment.