CORE-POS / IS4C

Cooperative Operational Retail Environment
http://www.core-pos.com
GNU General Public License v2.0
64 stars 44 forks source link

Accurate margin reports for variable-weight items #1007

Open flathat opened 5 years ago

flathat commented 5 years ago

When the Parser UPC->handleItem() deals with variable weight items (items with price in the upc of a label, such as 0020012300187 for a $1.87 item) and cannot assign a two-decimal quantity that when multiplied by normal_price produces the price on the label it reverts to a quantity of 1 and a cost of products.cost. This, as alluded to in the comments, affects reports, such as margin reports, making them incorrect for the item involved and overall for totals that include that item. This actually happens quite frequently.

I'm looking for a way to make accurate margin reports that include these items.

Reports would need the normal_price and cost of the item at the time of the transaction in order to calculate a new quantity and cost for purposes of the report. I haven't found a very straightforward way to do that, although cost- and price-history could at least theoretically help. Other ideas?

I have however found that if quantity can be recorded to four decimals instead of two it eliminates the problem of a price in the transaction (and on the receipt) that disagrees with the label price. I tested (code below) this on scale (label) prices between $0.10 and $30.00 and for each of those on normal_prices between $0.10 and $30.00, a total of 8,940,100 instances, and found these numbers of failures to match the label price:

quantity with N decimals Failures to match label price
2 7,654,610
3 2,694,185
4-9 0

Might it be possible to make quantity a 4-decimal value, as cost recently became 3-decimal?

Test:

<?php
/* All those actually in dlog_90_view, bulk depts
$n_prices = array(1.99,3.29,3.99,4.39,5.99,6.39,6.89,6.99, 7.29, 7.49, 7.69, 7.99, 8.99, 10.39, 11.39,20.69,
25.69);
 */

$d2_bad = 0;
$d3_bad = 0;
$n_tested = 0;
$s_tested = 0;
$s_price_start = 10;
$s_price_end = 3000;
$n_price_start = 10;
$n_price_end = 3000;
$raw_decimals = 4;

// normal_price's
//foreach ($n_prices as $n_price) {
for($n=$n_price_start ; $n < $n_price_end ; $n++) {
    if (($n % 100) == 0){
        echo "Begin: $n_price\n";
    }
    $n_tested++;
    $n_price = ($n / 100);
    // scale or "sticker" prices
    for($s=$s_price_start ; $s < $s_price_end ; $s++) {
        $s_tested++;
        //$scale_price = $s;
        $scale_price = ($s / 100);
        $raw_quant = round(($scale_price / $n_price),$raw_decimals);
        //$raw_quant = ($scale_price / $n_price);
        $round_quant = round($raw_quant,2);
        //echo "n: $n_price  s: $scale_price \n";
        $scale_pr2 = ($round_quant * $n_price);
        $scale_pr2_R = round($scale_pr2,2);
        $scale_pr3 = ($raw_quant * $n_price);
        $scale_pr3_R = round($scale_pr3,2);
        // Do the derived prices == the scale_price?
        $d2 = ($scale_pr2_R == $scale_price) ? "OK" : "Bad";
        if ($d2 == "Bad") {
            $d2_bad++;
        }
        $d3 = ($scale_pr3_R == $scale_price) ? "OK" : "Bad";
        if ($d3 == "Bad") {
            //echo "n: $n_price  s: $scale_price s_pr2_r: $scale_pr2_R  d2: $d2 s_pr3_r: $scale_pr3_R  d3: $d3\n";
            $d3_bad++;
        }
    }
}

echo "\n";
printf("Done. scale_price_range: %.2f - %.2f\n", ($s_price_start / 100), ($s_price_end/100));
printf("'raw'-quantity to %d decimals", $raw_decimals);
echo "n_prices_tested: $n_tested  s_prices_tested: " . number_format($s_tested,0) . "\n";
printf("round_bad: %s  raw_bad: %s\n", number_format($d2_bad,0), number_format($d3_bad,0));
echo "Bye\n";
gohanman commented 5 years ago

I'd prefer to just modify the cost in-line so it's scaled correctly but quantity remains one.

The quantity field can already hold 4 or more digits (insert IEEE 754 caveats here) but there may be weights & measures regulatory issues if those kind of values accidentally wind up on something customer facing. Claiming something weighs 1.2345 pounds when the store has no weighing equipment that precise is problematic.

I might be overly paranoid here about the impact of widening out quantity in these cases; my instinct is to keep changes narrower in general.