99 lines
3.3 KiB
PHP
99 lines
3.3 KiB
PHP
<?php
|
||
|
||
namespace App\Service\business;
|
||
|
||
/**
|
||
* 套餐报价与补差价
|
||
*
|
||
* 后台存倍率=1 的基准分;小程序展示/下单再乘用户倍率。
|
||
* 清单应付用「套餐价 + 当前明细合计 − 原价快照」,删行、换规格、加散件都落在这一条公式里。
|
||
*/
|
||
class PackageQuoteService
|
||
{
|
||
private static mixed $_instance;
|
||
|
||
public static function getInstance(): null|static
|
||
{
|
||
$name = get_called_class();
|
||
if (!isset(self::$_instance[$name])) {
|
||
self::$_instance[$name] = new static();
|
||
}
|
||
return self::$_instance[$name];
|
||
}
|
||
|
||
/**
|
||
* 后台改搭配:原价变了就把差额补到套餐报价上,不允许报负价
|
||
*/
|
||
public function applyOriginalDiff(int $oldOriginal, int $newOriginal, int $packageAmount): int
|
||
{
|
||
return max(0, $packageAmount + ($newOriginal - $oldOriginal));
|
||
}
|
||
|
||
/**
|
||
* 基准价乘用户倍率,仍回整数分
|
||
*/
|
||
public function applyMultiplier(int $cents, mixed $multiplier = 1): int
|
||
{
|
||
if ($cents <= 0) {
|
||
return 0;
|
||
}
|
||
$price = PriceService::getInstance();
|
||
$yuan = $price->centsToYuan($cents);
|
||
return $price->yuanToCents($yuan, $multiplier);
|
||
}
|
||
|
||
/**
|
||
* 套餐清单应付
|
||
*
|
||
* 未绑套餐:应付 = 当前明细合计。
|
||
* 已绑套餐:应付 = 套餐价快照 + 当前合计 − 原价快照(删除的套餐行会从原价里扣掉)。
|
||
*
|
||
* @param array<int, array{unit_price?:int,quantity?:int}> $items
|
||
* @return array{package_amount:int,original_amount:int,diff_amount:int,payable_amount:int,items_amount:int}
|
||
*/
|
||
public function listPayable(int $packageId, int $packageAmount, int $originalAmount, array $items): array
|
||
{
|
||
$itemsAmount = 0;
|
||
foreach ($items as $item) {
|
||
$qty = max(1, (int) ($item['quantity'] ?? 1));
|
||
$itemsAmount += (int) ($item['unit_price'] ?? 0) * $qty;
|
||
}
|
||
if ($packageId <= 0) {
|
||
return [
|
||
'package_amount' => 0,
|
||
'original_amount' => $itemsAmount,
|
||
'diff_amount' => 0,
|
||
'payable_amount' => $itemsAmount,
|
||
'items_amount' => $itemsAmount,
|
||
];
|
||
}
|
||
$payable = max(0, $packageAmount + $itemsAmount - $originalAmount);
|
||
return [
|
||
'package_amount' => $packageAmount,
|
||
'original_amount' => $originalAmount,
|
||
'diff_amount' => $payable - $packageAmount,
|
||
'payable_amount' => $payable,
|
||
'items_amount' => $itemsAmount,
|
||
];
|
||
}
|
||
|
||
/**
|
||
* 给金额数组补 *_text 元字段,方便前端直接渲染
|
||
*
|
||
* @param array<string, int> $amounts
|
||
* @return array<string, int|string>
|
||
*/
|
||
public function withText(array $amounts, bool $showPrice = true): array
|
||
{
|
||
$price = PriceService::getInstance();
|
||
foreach (['package_amount', 'original_amount', 'diff_amount', 'payable_amount', 'items_amount', 'discount_amount'] as $key) {
|
||
if (!array_key_exists($key, $amounts)) {
|
||
continue;
|
||
}
|
||
$cents = (int) $amounts[$key];
|
||
$amounts[$key . '_text'] = $showPrice ? $price->centsToYuan($cents) : PriceService::MASK;
|
||
}
|
||
return $amounts;
|
||
}
|
||
}
|