| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- <?php
- namespace App\Module\Mex\Logic;
- use App\Module\Mex\Models\MexTransaction;
- use App\Module\Mex\Enums\TransactionType;
- use App\Module\Mex\Events\TransactionCreatedEvent;
- use Illuminate\Support\Facades\DB;
- /**
- * 农贸市场成交记录逻辑
- *
- * 处理成交记录相关的核心业务逻辑
- */
- class MexTransactionLogic
- {
- /**
- * 获取交易大厅成交记录
- *
- * @param int $page 页码
- * @param int $pageSize 每页数量
- * @param int|null $itemId 商品ID筛选
- * @return array 成交记录列表
- */
- public static function getPublicTransactions(int $page = 1, int $pageSize = 20, ?int $itemId = null): array
- {
- $query = MexTransaction::query()
- ->where('is_admin_operation', false) // 只显示用户交易,不显示管理员操作
- ->orderBy('created_at', 'desc');
- if ($itemId) {
- $query->where('item_id', $itemId);
- }
- $transactions = $query->paginate($pageSize, ['*'], 'page', $page);
- $result = [];
- foreach ($transactions->items() as $transaction) {
- // 根据交易类型确定显示的用户ID
- // USER_SELL表示用户卖出,显示卖方ID;USER_BUY表示用户买入,显示买方ID
- $userId = ($transaction->transaction_type->value === 'USER_SELL')
- ? $transaction->seller_id
- : $transaction->buyer_id;
- $result[] = [
- 'id' => $transaction->id,
- 'user_id' => $userId,
- 'item_id' => $transaction->item_id,
- 'quantity' => $transaction->quantity,
- 'price' => $transaction->price,
- 'total_amount' => $transaction->total_amount,
- 'transaction_type' => $transaction->transaction_type->value,
- 'transaction_type_desc' => $transaction->transaction_type->getDescription(),
- 'created_at' => $transaction->created_at,
- ];
- }
- return [
- 'transactions' => $result,
- 'total' => $transactions->total(),
- 'page' => $page,
- 'page_size' => $pageSize,
- ];
- }
- /**
- * 获取用户成交记录
- *
- * @param int $userId 用户ID
- * @param int $page 页码
- * @param int $pageSize 每页数量
- * @return array 成交记录列表
- */
- public static function getUserTransactions(int $userId, int $page = 1, int $pageSize = 20): array
- {
- $transactions = MexTransaction::where(function ($query) use ($userId) {
- $query->where('buyer_id', $userId)
- ->orWhere('seller_id', $userId);
- })
- ->where('is_admin_operation', false)
- ->orderBy('created_at', 'desc')
- ->paginate($pageSize, ['*'], 'page', $page);
- $result = [];
- foreach ($transactions->items() as $transaction) {
- $isUserBuyer = $transaction->buyer_id === $userId;
- $isUserSeller = $transaction->seller_id === $userId;
-
- $result[] = [
- 'id' => $transaction->id,
- 'item_id' => $transaction->item_id,
- 'quantity' => $transaction->quantity,
- 'price' => $transaction->price,
- 'total_amount' => $transaction->total_amount,
- 'transaction_type' => $transaction->transaction_type->value,
- 'transaction_type_desc' => $transaction->transaction_type->getDescription(),
- 'user_role' => $isUserBuyer ? 'buyer' : ($isUserSeller ? 'seller' : 'unknown'),
- 'user_role_desc' => $isUserBuyer ? '买方' : ($isUserSeller ? '卖方' : '未知'),
- 'counterparty_id' => $isUserBuyer ? $transaction->seller_id : $transaction->buyer_id,
- 'created_at' => $transaction->created_at,
- ];
- }
- return [
- 'transactions' => $result,
- 'total' => $transactions->total(),
- 'page' => $page,
- 'page_size' => $pageSize,
- ];
- }
- /**
- * 获取商品成交统计
- *
- * @param int $itemId 商品ID
- * @param int $days 统计天数
- * @return array 统计信息
- */
- public static function getItemTransactionStats(int $itemId, int $days = 7): array
- {
- $startDate = now()->subDays($days)->startOfDay();
-
- $stats = MexTransaction::where('item_id', $itemId)
- ->where('created_at', '>=', $startDate)
- ->selectRaw('
- COUNT(*) as total_transactions,
- SUM(quantity) as total_quantity,
- SUM(total_amount) as total_amount,
- AVG(price) as avg_price,
- MIN(price) as min_price,
- MAX(price) as max_price
- ')
- ->first();
- $latestPrice = self::getLatestPrice($itemId);
- return [
- 'item_id' => $itemId,
- 'days' => $days,
- 'total_transactions' => $stats->total_transactions ?? 0,
- 'total_quantity' => $stats->total_quantity ?? 0,
- 'total_amount' => $stats->total_amount ?? '0.00000',
- 'avg_price' => $stats->avg_price ? number_format($stats->avg_price, 5) : '0.00000',
- 'min_price' => $stats->min_price ?? '0.00000',
- 'max_price' => $stats->max_price ?? '0.00000',
- 'latest_price' => $latestPrice,
- 'start_date' => $startDate,
- 'end_date' => now(),
- ];
- }
- /**
- * 获取市场成交统计
- *
- * @param int $days 统计天数
- * @return array 统计信息
- */
- public static function getMarketStats(int $days = 7): array
- {
- $startDate = now()->subDays($days)->startOfDay();
-
- $stats = MexTransaction::where('created_at', '>=', $startDate)
- ->selectRaw('
- COUNT(*) as total_transactions,
- COUNT(DISTINCT item_id) as active_items,
- SUM(quantity) as total_quantity,
- SUM(total_amount) as total_amount,
- AVG(price) as avg_price
- ')
- ->first();
- // 按交易类型统计
- $typeStats = MexTransaction::where('created_at', '>=', $startDate)
- ->groupBy('transaction_type')
- ->selectRaw('
- transaction_type,
- COUNT(*) as count,
- SUM(quantity) as quantity,
- SUM(total_amount) as amount
- ')
- ->get();
- $typeStatsFormatted = [];
- foreach ($typeStats as $typeStat) {
- $typeStatsFormatted[$typeStat->transaction_type] = [
- 'count' => $typeStat->count,
- 'quantity' => $typeStat->quantity,
- 'amount' => $typeStat->amount,
- ];
- }
- return [
- 'days' => $days,
- 'total_transactions' => $stats->total_transactions ?? 0,
- 'active_items' => $stats->active_items ?? 0,
- 'total_quantity' => $stats->total_quantity ?? 0,
- 'total_amount' => $stats->total_amount ?? '0.00000',
- 'avg_price' => $stats->avg_price ? number_format($stats->avg_price, 5) : '0.00000',
- 'type_stats' => $typeStatsFormatted,
- 'start_date' => $startDate,
- 'end_date' => now(),
- ];
- }
- /**
- * 获取商品最新成交价格
- *
- * @param int $itemId 商品ID
- * @return string|null 最新价格
- */
- public static function getLatestPrice(int $itemId): ?string
- {
- $transaction = MexTransaction::where('item_id', $itemId)
- ->orderBy('created_at', 'desc')
- ->first();
- return $transaction ? $transaction->price : null;
- }
- /**
- * 创建成交记录
- *
- * @param array $data 成交数据
- * @return MexTransaction|null 成交记录
- */
- public static function createTransaction(array $data): ?MexTransaction
- {
- try {
- $transaction = MexTransaction::create([
- 'buy_order_id' => $data['buy_order_id'] ?? null,
- 'sell_order_id' => $data['sell_order_id'] ?? null,
- 'buyer_id' => $data['buyer_id'],
- 'seller_id' => $data['seller_id'],
- 'item_id' => $data['item_id'],
- 'currency_type' => $data['currency_type'] ?? 2, // 默认使用钻石币种
- 'quantity' => $data['quantity'],
- 'price' => $data['price'],
- 'total_amount' => $data['total_amount'],
- 'transaction_type' => $data['transaction_type'],
- 'is_admin_operation' => $data['is_admin_operation'] ?? false,
- 'admin_user_id' => $data['admin_user_id'] ?? null,
- ]);
- // 触发成交记录创建事件
- if ($transaction) {
- event(new TransactionCreatedEvent($transaction));
- }
- return $transaction;
- } catch (\Exception $e) {
- return null;
- }
- }
- /**
- * 获取最后撮合时间信息(使用撮合日志)
- *
- * @return array 最后撮合时间信息
- */
- public static function getLastMatchTimes(): array
- {
- // 使用撮合日志服务获取最后撮合时间
- return \App\Module\Mex\Services\MexMatchLogService::getLastMatchTimes();
- }
- /**
- * 获取商品价格趋势
- *
- * @param int $itemId 商品ID
- * @param int $days 统计天数
- * @return array 价格趋势数据
- */
- public static function getItemPriceTrend(int $itemId, int $days = 7): array
- {
- $startDate = now()->subDays($days)->startOfDay();
- $transactions = MexTransaction::where('item_id', $itemId)
- ->where('created_at', '>=', $startDate)
- ->orderBy('created_at', 'asc')
- ->select('price', 'created_at')
- ->get();
- $trend = [];
- foreach ($transactions as $transaction) {
- $date = $transaction->created_at->format('Y-m-d');
- if (!isset($trend[$date])) {
- $trend[$date] = [];
- }
- $trend[$date][] = $transaction->price;
- }
- // 计算每日平均价格
- $result = [];
- foreach ($trend as $date => $prices) {
- $avgPrice = array_sum($prices) / count($prices);
- $result[] = [
- 'date' => $date,
- 'avg_price' => number_format($avgPrice, 5),
- 'min_price' => min($prices),
- 'max_price' => max($prices),
- 'transaction_count' => count($prices),
- ];
- }
- return $result;
- }
- }
|