求教订单优惠金额均摊问题

假设一个订单购买了 2 个sku
sku1 单价为 5,数量为 3
sku2 单价为 8,数量为 5
订单总金额为 55,优惠了 20,实付 35
求每个 sku 实际均摊单价是多少?(ps: 需考虑除不尽的问题)

有误差版本:
sku1 实际均摊单价 = 5/55 * 20 = 1.82 (四舍五入取两位)
sku2 实际均摊单价 = 8/55 * 20 = 2.91 (四舍五入取两位)

1.82 * 3 + 2.91 * 5 = 20.01 ,但是实际是优惠了 20,这里算出来误差多出 0.01

求教各位大佬,如何消除这个误差

xiaobei
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 13
jcc123

把误差放在其中一个sku中

1.82 + (20-20.01) = 1.81
2周前 评论
xiaobei (楼主) 2周前
jcc123 (作者) 2周前
xiaobei (楼主) 2周前
lufeijun1234 2周前
ycstar 2周前

最后一个用总额减前面的总和

2周前 评论
xiaobei (楼主) 2周前
deatil (作者) 2周前
xiaobei (楼主) 2周前
xiaobei (楼主) 2周前
deatil (作者) 2周前
xiaobei (楼主) 2周前
deatil (作者) 2周前
xiaobei (楼主) 2周前

误差放到最后一个计算的sku中 @jcc123 说的对 计算的时候尽量使用bcmath 可以尽可能的避免你说的这个问题

2周前 评论
颠倒的玉石

肯定是总数减最后一个,我一般是平均金额保留两位,其余的都舍掉,不走5入(少了可以加,多了还真没地方减),这样总金额肯定是小于等于总优惠数。然后把差价加到最后一件商品上

2周前 评论
xiaobei (楼主) 2周前
颠倒的玉石 (作者) 2周前
xiaobei (楼主) 2周前

我也遇到过,把缺少的或者增加的,补到一个sku中;特别是测试 测的支付0.01 元 通过优惠扣减,下了 123件商品,平摊不了吧,这个应该和你遇到一样的问题了

2周前 评论
xiaobei (楼主) 2周前
liaosp (作者) 2周前
xiaobei (楼主) 2周前
liaosp (作者) 2周前
xiaobei (楼主) 2周前

假如订单总额是 53分 均摊到 3个一样的 sku 上。 多出来 53%3 = 2 分。 先平均分每一个占 17,再把多出来的两分给前两个 sku 上。 也就是 18,18,17 这样均摊了。

2周前 评论

之前做过这样的需求,订单优惠金额是要按照每个商品占订单总价的比例单独进行计算并存入数据库的。

2周前 评论

没有最优解,我们以前也遇到了,即使放在最后一个商品上,可也能不对,比如最后计算出多出1,放最后一个sku,但是最后一个sku数量是3,依然除不尽,还要考虑单价是否小于折扣

2周前 评论
xiaobei (楼主) 2周前
Imuyu (作者) 2周前

请教一下,把优惠金额均摊到每一个sku上面的意义是什么,是由于多店铺的原因吗?

2周前 评论
chowjiawei 2周前
xiaobei (楼主) 1周前
<?php

/**
 * WeEngine Document System
 *
 * (c) We7Team 2019 <https://www.w7.cc>
 *
 * This is not a free software
 * Using it under the license terms
 * visited https://www.w7.cc for more details
 */

namespace W7\Sdk\Order\Base\Distributor;

use Webmozart\Assert\Assert;

/**
 * 按比例分摊优惠
 * Class ProportionalIntegerDistributor
 * @package W7\Sdk\Order\Model\Service\Distributor
 */
final class ProportionalIntegerDistributor
{
    /**
     * 分摊优惠
     * @param array|int[] $integers
     * @param int $amount
     * @return array
     */
    public function distribute(array $integers, int $amount): array
    {
        Assert::allInteger($integers);

        $total = array_sum($integers);
        $distributedAmounts = [];

        foreach ($integers as $element) {
            $distributedAmounts[] = (int)round(($element * $amount) / $total, 0, \PHP_ROUND_HALF_DOWN);
        }

        $missingAmount = $amount - array_sum($distributedAmounts);
        for ($i = 0, $iMax = abs($missingAmount); $i < $iMax; ++$i) {
            $distributedAmounts[$i] += $missingAmount >= 0 ? 1 : -1;
        }

        return $distributedAmounts;
    }
}
1周前 评论

假设一个订单购买了 2 个 sku
sku1 单价为 5,数量为 3
sku2 单价为 8,数量为 5
订单总金额为 55,优惠了 20,实付 35

其它的方法

sku1 总金额 53 = 15 优惠比例金额 (55/15) *20 = 5.4的优惠。
sku2 总金额 8
5 = 40 优惠比例金额 (55/40) 20 = 14.6的优惠。
*
均摊到每个数量**
sku1 = 5.4 / 3 = 1.8
sku2 = 14.6 / 5 = 2.92
最后就是除不尽的问题
比方说:
sku2 = 14.6 / 3 = 4.866666666667
能不能过一个函数均摊,变成 4.86,4.87,4.87

不知道我的思路是不是对。

1周前 评论
xiaobei (楼主) 1周前
YeRic (作者) 1周前
xiaobei (楼主) 1周前

那要看你们产品上是怎么定义的呀,首先肯定是到 分。 其次就是均摊的时候是舍弃还是向上向下取。 最后一个商品用总额减就行了

1周前 评论

不要钻牛角尖 这个仅仅只是用来展示 你这个实际的优惠还是总额减

1周前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!