Files
lgp-admin-plus-api/app/Service/business/PackageQuoteService.php

99 lines
3.3 KiB
PHP
Raw Normal View History

2026-08-19 08:16:49 +08:00
<?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;
}
}