feat : statement

This commit is contained in:
2025-03-21 17:41:10 +08:00
parent 8176feb77b
commit 005fc4879a
12 changed files with 450 additions and 2 deletions

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer\Statement;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use PhpAmqpLib\Message\AMQPMessage;
#[Consumer(exchange: 'hyperf', routingKey: 'hyperf', queue: 'hyperf', name: "ChefConsumer", nums: 1)]
class ChefConsumer extends ConsumerMessage
{
public function consumeMessage($data, AMQPMessage $message): Result
{
return Result::ACK;
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer\Statement;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use PhpAmqpLib\Message\AMQPMessage;
#[Consumer(exchange: 'hyperf', routingKey: 'hyperf', queue: 'hyperf', name: "DriverConsumer", nums: 1)]
class DriverConsumer extends ConsumerMessage
{
public function consumeMessage($data, AMQPMessage $message): Result
{
return Result::ACK;
}
}

View File

@@ -0,0 +1,113 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer\Statement;
use App\Constants\Common\OrderCode;
use App\Lib\Log;
use App\Model\Cycle;
use App\Model\FinancesStatement;
use App\Model\Kitchen;
use App\Model\Order;
use Hyperf\Amqp\Message\Type;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use Hyperf\Di\Annotation\Inject;
use PhpAmqpLib\Message\AMQPMessage;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
#[Consumer(exchange: 'Finances', routingKey: 'Finances', queue: 'Finances.statement', name: "FinancesConsumer", nums: 1)]
class FinancesConsumer extends ConsumerMessage
{
/**
* @var Type|string 消息类型
*/
protected Type|string $type = Type::DIRECT;
/**
* @var FinancesStatement
*/
#[Inject]
protected FinancesStatement $financesStatementModel;
/**
* @var Cycle
*/
#[Inject]
protected Cycle $cycleModel;
/**
* @var Kitchen
*/
#[Inject]
protected Kitchen $kitchenModel;
/**
* @var Order
*/
#[Inject]
protected Order $orderModel;
/**
* @var Log
*/
#[Inject]
protected Log $log;
/**
* @param $data
* @param AMQPMessage $message
* @return Result
* @throws ContainerExceptionInterface
* @throws NotFoundExceptionInterface
*/
public function consumeMessage($data, AMQPMessage $message): Result
{
if (!$data['kitchen_id'] || !$data['cycle_id']) {
$this->log->error('FinancesConsumer:error:NoData:'.json_encode($data));
return Result::ACK;
}
$kitchen = $this->kitchenModel->where('id',$data['kitchen_id'])->first();
$cycle = $this->cycleModel->where('id',$data['cycle_id'])->first();
if (empty($kitchen) || empty($cycle)) {
$this->log->error('FinancesConsumer:error:kitchenOrCycleError:'.json_encode([
'kitchen_id' => $data['kitchen_id'],
'cycle_id' => $data['cycle_id'],
'cycle' => $cycle,
'kitchen' => $kitchen,
'data' => $data,
]));
return Result::ACK;
}
$statement = $this->financesStatementModel->getStatementByCycleIdAndKitchenId($data['cycle_id'],$data['kitchen_id']);
if (!empty($statement)) $statement->delete();
$statement = new FinancesStatement();
$statement->date = $cycle->dates;
$statement->cycle_id = $cycle->id;
$statement->kitchen_id = $kitchen->id;
$statement->discounts = $this->orderModel->getDiscountsByCycleIdAndKitchenId($cycle->id, $kitchen->id);
$statement->net_sales = $this->orderModel->getNetSalesByCycleIdAndKitchenId($cycle->id, $kitchen->id);
$statement->gross_sales = $statement->net_sales + $statement->discounts;
$statement->option_order_number = $this->orderModel->getOrderNumberByCycleIdAndKitchenId($cycle->id, $kitchen->id, OrderCode::ORDER_TYPE_OPTIONAL);
$statement->option_copies = $this->orderModel->getCopiesByCycleIdAndKitchenId($cycle->id, $kitchen->id, OrderCode::ORDER_TYPE_OPTIONAL);
$statement->meal_order_number = $this->orderModel->getOrderNumberByCycleIdAndKitchenId($cycle->id, $kitchen->id, OrderCode::ORDER_TYPE_MEAL);
$statement->meal_copies = $this->orderModel->getCopiesByCycleIdAndKitchenId($cycle->id, $kitchen->id, OrderCode::ORDER_TYPE_MEAL);
if (!$statement->save()) {
$this->log->error('FinancesConsumer:error:FinancesStatement:'.json_encode([
'statement' => $statement,
'data' => $data,
]));
}
return Result::ACK;
}
}

View File

@@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Consumer\Statement;
use Hyperf\Amqp\Result;
use Hyperf\Amqp\Annotation\Consumer;
use Hyperf\Amqp\Message\ConsumerMessage;
use PhpAmqpLib\Message\AMQPMessage;
#[Consumer(exchange: 'hyperf', routingKey: 'hyperf', queue: 'hyperf', name: "SiteConsumer", nums: 1)]
class SiteConsumer extends ConsumerMessage
{
public function consumeMessage($data, AMQPMessage $message): Result
{
return Result::ACK;
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Producer\Statement;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Amqp\Message\Type;
#[Producer(exchange: 'hyperf', routingKey: 'hyperf')]
class ChefProducer extends ProducerMessage
{
/**
* @var Type|string 消息类型
*/
protected Type|string $type = Type::DIRECT;
public function __construct($data)
{
$this->payload = $data;
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Producer\Statement;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Amqp\Message\Type;
#[Producer(exchange: 'hyperf', routingKey: 'hyperf')]
class DriverProducer extends ProducerMessage
{
/**
* @var Type|string 消息类型
*/
protected Type|string $type = Type::DIRECT;
public function __construct($data)
{
$this->payload = $data;
}
}

View File

@@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Producer\Statement;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Amqp\Message\Type;
#[Producer(exchange: 'Finances', routingKey: 'Finances')]
class FinancesProducer extends ProducerMessage
{
/**
* @var Type|string 消息类型
*/
protected Type|string $type = Type::DIRECT;
public function __construct($data)
{
/**
* $data string array => {"kitchen_id":"kitchen_id","cycle_id":"cycle_id"}
*/
$this->payload = $data;
}
}

View File

@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\Amqp\Producer\Statement;
use Hyperf\Amqp\Annotation\Producer;
use Hyperf\Amqp\Message\ProducerMessage;
use Hyperf\Amqp\Message\Type;
#[Producer(exchange: 'hyperf', routingKey: 'hyperf')]
class SiteProducer extends ProducerMessage
{
/**
* @var Type|string 消息类型
*/
protected Type|string $type = Type::DIRECT;
public function __construct($data)
{
$this->payload = $data;
}
}

View File

@@ -6,6 +6,7 @@ namespace App\Controller\Admin;
use App\Controller\AbstractController;
use App\Middleware\Admin\JwtAuthMiddleware;
use App\Service\Admin\Order\FinishService;
use App\Service\Admin\Order\OrderInfoService;
use App\Service\Admin\Order\OrderListService;
use App\Service\Admin\Order\RefundService;
@@ -29,18 +30,25 @@ class OrderController extends AbstractController
*/
#[RequestMapping(path: "list", methods: "GET")]
#[Scene(scene: "list")]
public function list()
public function list(): array
{
return (new OrderListService())->handle();
}
#[RequestMapping(path: "info", methods: "GET")]
#[Scene(scene: "info")]
public function info()
public function info(): array
{
return (new OrderInfoService())->handle();
}
#[RequestMapping(path: "finish", methods: "GET")]
#[Scene(scene: "finish")]
public function finish(): array
{
return (new FinishService())->handle();
}
/**
* @return array
* @throws ContainerExceptionInterface

View File

@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
namespace App\Model;
use Hyperf\Database\Model\Builder;
use Hyperf\DbConnection\Model\Model;
/**
* @property int $id
* @property string $date
* @property int $cycle_id
* @property int $kitchen_id
* @property string $gross_sales
* @property string $discounts
* @property string $net_sales
* @property int $option_order_number
* @property int $option_copies
* @property int $meal_order_number
* @property int $meal_copies
* @property string $create_time
*/
class FinancesStatement extends Model
{
/**
* The table associated with the model.
*/
protected ?string $table = 'finances_statement';
/**
* The attributes that are mass assignable.
*/
protected array $fillable = [];
protected array $guarded = [];
/**
* The attributes that should be cast to native types.
*/
protected array $casts = ['id' => 'integer', 'cycle_id' => 'integer', 'kitchen_id' => 'integer', 'option_order_nnumber' => 'integer', 'option_copies' => 'integer', 'meal_order_number' => 'integer', 'meal_copies' => 'integer'];
const string CREATED_AT = 'create_time';
const null UPDATED_AT = null;
/**
* @param int $cycleId
* @param int $kitchenId
* @return Builder|\Hyperf\Database\Model\Model|FinancesStatement|null
*/
public function getStatementByCycleIdAndKitchenId(int $cycleId,int $kitchenId): \Hyperf\Database\Model\Model|FinancesStatement|Builder|null
{
return $this->where('cycle_id',$cycleId)->where('kitchen_id',$kitchenId)->first();
}
}

View File

@@ -87,4 +87,56 @@ class Order extends Model
'status' => OrderCode::PLAN
]);
}
/**
* @param int $cycleId
* @param int $kitchenId
* @return int|mixed|string
*/
public function getDiscountsByCycleIdAndKitchenId(int $cycleId, int $kitchenId): mixed
{
return $this->where('cycle_id',$cycleId)->where('kitchen_id',$kitchenId)->where('status',OrderCode::FINISH)->sum('discounts') ?? 0;
}
/**
* @param int $cycleId
* @param int $kitchenId
* @return int|mixed|string
*/
public function getNetSalesByCycleIdAndKitchenId(int $cycleId, int $kitchenId): mixed
{
return $this->where('cycle_id',$cycleId)->where('kitchen_id',$kitchenId)->where('status',OrderCode::FINISH)->sum('actual_price') ?? 0;
}
/**
* @param int $cycleId
* @param int $kitchenId
* @param int $type
* @return int
*/
public function getOrderNumberByCycleIdAndKitchenId(int $cycleId, int $kitchenId,int $type): int
{
return $this
->where('cycle_id',$cycleId)
->where('kitchen_id',$kitchenId)
->where('type',$type)
->where('status',OrderCode::FINISH)
->count() ?? 0;
}
/**
* @param int $cycleId
* @param int $kitchenId
* @param int $type
* @return int
*/
public function getCopiesByCycleIdAndKitchenId(int $cycleId, int $kitchenId,int $type): int
{
return $this
->where('cycle_id',$cycleId)
->where('kitchen_id',$kitchenId)
->where('type',$type)
->where('status',OrderCode::FINISH)
->sum('copies') ?? 0;
}
}

View File

@@ -0,0 +1,65 @@
<?php
/**
* This service file is part of item.
*
* @author ctexthuang
* @contact ctexthuang@qq.com
*/
declare(strict_types=1);
namespace App\Service\Admin\Order;
use App\Constants\Common\OrderCode;
use App\Exception\ErrException;
use App\Model\Order;
use App\Model\OrderGood;
use App\Service\Admin\BaseService;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
class FinishService extends BaseService
{
/**
* @var Order
*/
#[Inject]
protected Order $orderModel;
/**
* @var OrderGood
*/
#[Inject]
protected OrderGood $orderGoodModel;
public function handle()
{
$kitchenId = (int)$this->request->input('kitchenId');
$cycleId = (int)$this->request->input('cycleId');
$orderIds = $this->orderModel
->where('kitchen_id', $kitchenId)
->where('cycle_id', $cycleId)
->whereIn('status', [
OrderCode::PLAN,
OrderCode::DEPART,
OrderCode::ARRIVE,
])
->pluck('id')
->toArray();
Db::transaction(function () use ($orderIds) {
foreach (array_chunk($orderIds, 100) as $chunk) {
$orderFinish = $this->orderModel->whereIn('id', $chunk)->update(['status' => OrderCode::FINISH]);
$orderGoodFinish = $this->orderGoodModel->whereIn('order_id', $chunk)->update(['status' => OrderCode::FINISH]);
if (!$orderFinish && !$orderGoodFinish) throw new ErrException('更新失败,数据回滚,请重新操作');
}
});
return $this->return->success();
}
}