Files
lgp-admin-plus-api/app/Service/business/ListService.php
2026-08-20 19:16:49 +08:00

238 lines
8.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Service\business;
use App\BaseApp\BaseService;
use App\Models\business\ListItemModel;
use App\Models\business\ListModel;
use App\Models\business\OrderModel;
use App\Models\business\PriceSheetModel;
use App\Models\business\WxUserModel;
/**
* 清单管理(后台)
*
* 后台看清单是为了帮客户报价与下单,所以详情里带的是「按该用户倍率算过的价格」,
* 与用户在小程序里看到的一致,否则电话里报的价和客户手机上的价对不上。
*/
class ListService extends BaseService
{
public function __construct()
{
parent::__construct();
$this->model = ListModel::class;
$this->selectField = [
'id', 'list_no', 'name', 'user_id', 'enterprise_id', 'remark',
'status', 'package_id', 'package_amount', 'original_amount',
'created_at', 'updated_at',
];
$this->queryField = [
'list_no' => 'like',
'name' => 'like',
'user_id' => '=',
'enterprise_id' => '=',
'status' => '=',
];
$this->with = ['user', 'enterprise'];
}
public function list(): array
{
$keyword = trim((string) request()->get('user_keyword', ''));
if ($keyword !== '') {
// 前端只给一个「客户」输入框,昵称与手机号都要能搜到
$userIds = WxUserModel::where('deleted_at', 0)
->where(function ($query) use ($keyword) {
$query->where('nick_name', 'like', '%' . $keyword . '%')
->orWhere('phone', 'like', '%' . $keyword . '%');
})->pluck('id')->all();
$this->whereIn = ['user_id', empty($userIds) ? [0] : $userIds];
}
$result = $this->getPageList();
$listIds = array_column($result['items'], 'id');
$counts = ListItemModel::whereIn('list_id', $listIds)
->where('deleted_at', 0)
->selectRaw('list_id, count(*) as total, sum(quantity) as quantity')
->groupBy('list_id')
->get()
->keyBy('list_id');
$orderCounts = OrderModel::whereIn('list_id', $listIds)
->where('deleted_at', 0)
->selectRaw('list_id, count(*) as total')
->groupBy('list_id')
->get()
->keyBy('list_id');
foreach ($result['items'] as &$item) {
$item['item_count'] = (int) ($counts[$item['id']]['total'] ?? 0);
$item['quantity'] = (int) ($counts[$item['id']]['quantity'] ?? 0);
$item['order_count'] = (int) ($orderCounts[$item['id']]['total'] ?? 0);
$item['user_name'] = $item['user']['nick_name'] ?? '';
$item['user_phone'] = $item['user']['phone'] ?? '';
$item['enterprise_name'] = $item['enterprise']['name'] ?? '';
}
unset($item);
return $result;
}
public function option(): mixed
{
$this->optionField = ['id', 'name'];
return $this->getOption();
}
/**
* 详情:带明细与算过倍率的价格
*/
public function detail($id): mixed
{
$info = ListModel::with([
'user',
'enterprise',
'items' => fn ($query) => $query->where('deleted_at', 0),
'items.catalogue',
'items.priceSheet',
])->where('id', $id)->where('deleted_at', 0)->first();
if (empty($info)) {
return $this->utils->notFound('清单不存在');
}
$info = $info->toArray();
$price = PriceService::getInstance();
$multiplier = $info['user']['price_number'] ?? 1;
$total = 0;
foreach ($info['items'] as &$item) {
$routine = $item['price_sheet']['routine'] ?? '';
$unit = (int) $item['unit_price'];
if ($unit <= 0) {
$unit = $price->resolveUnitPrice($routine, (string) $item['material_key'], $multiplier);
}
$item['unit_price'] = $unit;
$item['unit_price_text'] = $price->centsToYuan($unit);
$item['total_price'] = $unit * max(1, (int) $item['quantity']);
$item['routine_list'] = $price->formatRoutine($routine, true, $multiplier);
$total += $item['total_price'];
}
unset($item);
$info['total_amount'] = $total;
$info['total_amount_text'] = $price->centsToYuan($total);
$payable = PackageQuoteService::getInstance()->listPayable(
(int) ($info['package_id'] ?? 0),
(int) ($info['package_amount'] ?? 0),
(int) ($info['original_amount'] ?? 0),
$info['items']
);
$info = array_merge($info, PackageQuoteService::getInstance()->withText($payable));
return $info;
}
public function create($params): mixed
{
$params['list_no'] = SerialNoService::getInstance()->generate(SerialNoService::PREFIX_LIST, 'list', 'list_no');
return $this->insert($params);
}
public function update($id, $params): mixed
{
unset($params['list_no'], $params['user_id']);
return $this->save($id, $params);
}
public function delete($ids): mixed
{
return $this->del($ids);
}
/**
* 某个用户的全部清单,用户详情模态框里用
*/
public function byUser(int $userId): array
{
$rows = ListModel::where('user_id', $userId)->where('deleted_at', 0)->orderBy('id', 'desc')->get([
'id', 'list_no', 'name', 'status', 'created_at',
])->toArray();
$counts = ListItemModel::whereIn('list_id', array_column($rows, 'id'))
->where('deleted_at', 0)
->selectRaw('list_id, count(*) as total')
->groupBy('list_id')
->get()
->keyBy('list_id');
foreach ($rows as &$row) {
$row['item_count'] = (int) ($counts[$row['id']]['total'] ?? 0);
}
unset($row);
return $rows;
}
/**
* 后台代客下单
*/
public function toOrder(int $listId, array $params): array
{
return OrderCoreService::getInstance()->createFromList($listId, 0, $params);
}
/**
* 改明细(后台帮客户补规格与数量)
*/
public function saveItem(array $params): mixed
{
$itemId = (int) ($params['id'] ?? 0);
if ($itemId <= 0) {
$this->utils->errorThrow('参数错误');
}
$item = ListItemModel::with('list.user')->where('id', $itemId)->where('deleted_at', 0)->first();
if (empty($item)) {
$this->utils->errorThrow('明细不存在');
}
$update = ['updated_at' => time()];
foreach (['price_sheet_id', 'quantity'] as $field) {
if (array_key_exists($field, $params)) {
$update[$field] = (int) $params[$field];
}
}
foreach (['material_key', 'remark'] as $field) {
if (array_key_exists($field, $params)) {
$update[$field] = (string) $params[$field];
}
}
// 改规格后按该客户倍率重算当前单价,套餐清单才能按差额补差价
$sheetId = (int) ($update['price_sheet_id'] ?? $item['price_sheet_id']);
$material = (string) ($update['material_key'] ?? $item['material_key'] ?? 'routine');
if ($sheetId > 0) {
$sheet = PriceSheetModel::where('id', $sheetId)->where('deleted_at', 0)->first();
if (!empty($sheet)) {
$multiplier = $item['list']['user']['price_number'] ?? 1;
$update['unit_price'] = PriceService::getInstance()->resolveUnitPrice(
(string) ($sheet['routine'] ?? ''),
$material,
$multiplier
);
}
}
return ListItemModel::where('id', $itemId)->update($update);
}
/**
* 删明细
*/
public function deleteItem(array|int $ids): mixed
{
return ListItemModel::whereIn('id', (array) $ids)->update([
'deleted_at' => time(),
'updated_at' => time(),
]);
}
/**
* 导出清单报价:后台画 xlsx小程序用 text 分享
*/
public function exportQuote(int $id): array
{
$info = $this->detail($id);
if (!is_array($info)) {
$this->utils->errorThrow('清单不存在');
}
return \App\Service\common\ExcelCsvService::getInstance()->quoteFromList($info);
}
}