Files
hyperf_service/app/Service/Admin/Catering/Option/CateringService.php
2025-03-11 17:52:13 +08:00

366 lines
11 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
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
*/
declare(strict_types=1);
namespace App\Service\Admin\Catering\Option;
use App\Cache\Redis\Api\SiteCache;
use App\Constants\Admin\CateringCode;
use App\Constants\Common\OrderCode;
use App\Constants\ConfigCode;
use App\Exception\ErrException;
use App\Extend\StringUtil;
use App\Model\Order;
use App\Model\OrderGood;
use App\Model\OrderOptionCateringLog;
use App\Model\Site;
use App\Model\User;
use App\Service\Admin\Catering\CateringBaseService;
use App\Service\ServiceTrait\Admin\Catering\PrintTrait;
use Exception;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
class CateringService extends CateringBaseService
{
use PrintTrait;
/**
* @var OrderOptionCateringLog
*/
#[Inject]
protected OrderOptionCateringLog $orderOptionCateringLogModel;
/**
* @var Order
*/
#[Inject]
protected Order $orderModel;
/**
* @var OrderGood
*/
#[Inject]
protected OrderGood $orderGoodModel;
/**
* @var User
*/
#[Inject]
protected User $userModel;
/**
* @var OrderOptionCateringLog
*/
protected OrderOptionCateringLog $logInfo;
/**
* @var Site
*/
protected Site $siteInfo;
/**
* @var array
*/
protected array $orderList = [];
/**
* @var array
*/
protected array $orderIds = [];
/**
* @var int
*/
protected int $totalCopies = 0;
/**
* @var int
*/
protected int $printBoxMaxNum;
/**
* @var int
*/
protected int $partitionCount;
public function __construct()
{
parent::__construct();
$this->printBoxMaxNum = (int)$this->configCache->getConfigValueByKey(ConfigCode::MAXIMUM_VALUE_IN_FULL_BOX);
$this->partitionCount = (int)$this->configCache->getConfigValueByKey(ConfigCode::MAXIMUM_WHOLE_CASE_SPLIT);
}
public function handle()
{
$id = (int)$this->request->input('id');
$this->logInfo = $this->orderOptionCateringLogModel->find($id);
$this->siteInfo = $this->siteModel->find($this->logInfo->site_id);
$this->check();
$this->closePrintAndPlaceOrder();
$this->getOrderData();
$this->buildPickupCode();
$res = match ($this->request->input('type')) {
CateringCode::OPTION_PRINT_YLY => $this->printOrderByYly(),
CateringCode::CATERING_STATUS_FINISH => $this->printOrderByCoding(),
};
return $this->return->success('success', $res);
}
private function buildPickupCode(): int
{
// if ($this->isBuildPickupCode()) {
//// return $this->getPickupCode();
// }
$currentCode = 0;
$prefix = strtoupper(StringUtil::randStr(3));
$codeRanges = [];
$takeFoodCodes = [];
foreach ($this->orderList as &$order) {
foreach ($order['good_list'] as &$goodItem) {
if ($currentCode % $this->printBoxMaxNum === 0) {
$startCode = $currentCode + 1;
$endCode = min($currentCode + $this->printBoxMaxNum, $this->totalCopies);
$codeGroups = $this->splitArrayIntoPartitions(range($startCode, $endCode));
$codeRanges = $this->generateCodeRanges($codeGroups, $prefix);
}
$currentCode++;
$paddedCode = str_pad((string)$currentCode, 3, '0', STR_PAD_LEFT);
$fullCode = "$prefix-$paddedCode";
$goodItem['take_food_code'] = $fullCode;
$goodItem['heapsort'] = $codeRanges[$currentCode] ?? '';
$takeFoodCodes[] = [
'order_id' => $order['id'],
'box_num' => $goodItem['box_num'],
'take_food_code' => $fullCode,
'heapsort' => $goodItem['heapsort']
];
}
}
// $this->insertTakeFoodCode($takeFoodCodes);
return count($takeFoodCodes);
}
// private function insertTakeFoodCode(array $codeRanges)
// {
// try {
// Db::beginTransaction();
//
// /**
// * @var TakeFoodCode $takeFoodCodeModel
// */
// $takeFoodCodeModel = app(TakeFoodCode::class);
// $takeFoodCodeModel->whereIn('order_id',$this->orderId)->delete();
// if (!$takeFoodCodeModel->insertAll($takeFoodCodeArr)) throw new Exception('取餐码生成失败');
//
// if (!$this->isBuildTakeFoodToday($this->todayDate,$this->cacheLockValue)) throw new Exception('取餐码生成失败-缓存已添加');
//
// Db::commit();
// return count($takeFoodCodeArr);
// }catch (Exception $e) {
// Db::rollback();
// throw new ErrException($e->getMessage());
// }
// }
/**
* 将数组尽可能均匀地分割为指定份数
* @param array $array 输入数组
* @return array
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function splitArrayIntoPartitions(array $array): array
{
$partitionCount = $this->partitionCount;
$totalElements = count($array);
$baseChunkSize = intval($totalElements / $partitionCount);
$remainder = $totalElements % $partitionCount;
$result = [];
$currentIndex = 0;
for ($partition = 0; $partition < $partitionCount; $partition++) {
$chunkSize = $baseChunkSize + ($partition < $remainder ? 1 : 0);
if ($chunkSize === 0) {
$result[] = [];
continue;
}
$result[] = array_slice($array, $currentIndex, $chunkSize);
$currentIndex += $chunkSize;
}
return $result;
}
/**
* 生成编码范围映射表
* @param array $codeGroups 编码分组数组
* @param string $prefix 前缀字符串
* @return array
*/
private function generateCodeRanges(array $codeGroups, string $prefix): array {
$rangeMap = [];
foreach ($codeGroups as $group) {
if (empty($group)) continue;
$minCode = min($group);
$maxCode = max($group);
$rangeValue = sprintf("%03d%03d", $minCode, $maxCode);
foreach ($group as $code) {
$rangeMap[$code] = $rangeValue;
}
}
return $rangeMap;
}
/**
* @return void
*/
private function getOrderData(): void
{
$orderList = $this->orderModel
->where('site_id', $this->siteInfo->id)
->where('cycle_id', $this->cycleId)
->where('type',OrderCode::ORDER_TYPE_OPTIONAL)
->where('status',OrderCode::PAYED)
->orderBy('id')
->select(['id','cycle_id','order_sno','user_id','copies'])
->get();
if ($orderList->isEmpty()) throw new ErrException('该点暂无自选订单');
$orderList = $orderList->toArray();
$orderIds = array_column($orderList,'id');
$orderGoodArr = $this->orderGoodModel->whereIn('order_id',$orderIds)->select(['order_id','sku_id','quantity','copies'])->get();
if ($orderGoodArr->isEmpty()) throw new ErrException('商品数据丢失,请联系管理员');
$orderGoodArr = $orderGoodArr->toArray();
$userIds = array_column($orderList,'user_id');
$userInfos = $this->userModel->whereIn('id',$userIds)->select(['username', 'nickname', 'mobile', 'id'])->get();
if ($userInfos->isEmpty()) throw new ErrException('用户数据丢失,请联系管理员');
$userInfos = array_column($userInfos->toArray(),null,'id');
$skuIds = array_unique(array_column($orderGoodArr,'sku_id')); //todo code_number 还没写
$skuCodeNumberArr = $this->skuModel->where('id','in',$skuIds)->pluck('code_number','id')->toArray();
$orderGoodArr = $this->buildOrderCopiesData($orderGoodArr,$skuCodeNumberArr);
// $adminInfo = $this->adminUserModel->find($this->siteInfo->delivered_id);
$driverInfo = $this->driverSequenceModel->find($this->siteInfo->delivered_id);
foreach ($orderList as &$one) {
$one['dates'] = date('Y-m-d');
$one['site_text'] = $this->siteInfo->name;
$one['nickname'] = $userInfos[$one['user_id']]['nickname'] ?? '';
$one['mobile'] = $userInfos[$one['user_id']]['mobile'] ?? '';
$one['driver_num'] = $driverInfo->driver_num;
$one['site_order'] = $this->siteInfo->sequence;
$one['real_name'] = $driverInfo->driver_name;
$one['good_list'] = array_values($orderGoodArr[$one['id']]);
}
$this->orderList = $orderList;
$this->orderIds = $orderIds;
$this->totalCopies = array_sum(array_column($orderList,'copies'));
//节省内存 优化协程内存占用 防止内存泄露
unset($orderGoodArr,$skuCodeNumberArr,$skuIds,$userInfos,$userIds,$orderIds,$orderList);
}
/**
* @param array $data
* @param array $skuInfoArr
* @return array
*/
private function buildOrderCopiesData(array $data, array $skuInfoArr): array
{
$result = [];
foreach ($data as $item) {
// 提取关键字段
$orderId = $item["order_id"];
$copies = $item["copies"];
$skuId = $item["sku_id"];
$quantity= $item["quantity"];
// 按层级构建数组结构
if (!isset($result[$orderId])) {
$result[$orderId] = [];
}
if (!isset($result[$orderId][$copies])) {
$result[$orderId][$copies] = [
'copies' => $copies,
'sku' => []
];
}
$result[$orderId][$copies]['sku'][] = [
'id' => $skuId,
'num' => $quantity,
'code_num' => $skuInfoArr[$skuId]['code_number'] == '' ? 0 : (int)$skuInfoArr[$skuId]['code_number'],
];
}
return $result;
}
/**
* 打印置灰和截单
* @return void
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
private function closePrintAndPlaceOrder(): void
{
//生成 key
$this->__initRedisKey();
//打印一次后置灰
$this->closePrint();
//点位截单
$this->closeSite();
//如果一条线的所有点位截单 则整线截单
$this->closeWholeLine();
}
/**
* 检测数据
* @return void
*/
private function check(): void
{
if (empty($this->logInfo)) throw new ErrException('配餐数据不存在');
if ($this->logInfo->quantity <= 0) throw new ErrException('该配餐数量为0不可配餐');
}
private function printOrderByYly(): true
{
return true;
}
private function printOrderByCoding()
{
return [];
}
}