CaiWuXiTong/modules/EcommerceFinance/Repositories/StoreViolationPushRepository.php

129 lines
4.6 KiB
PHP
Raw Permalink 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 Modules\EcommerceFinance\Repositories;
use Illuminate\Database\Connection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
/**
* 店铺违规信息预警:推送取数、状态回写与推送日志(business_mirror)。
*/
class StoreViolationPushRepository
{
public const LOG_TABLE = 'store_violation_push_logs';
private Connection $connection;
public function __construct()
{
$this->connection = DB::connection((string) config('upstream_mirrors.connection', 'business_mirror'));
}
/**
* 即时推送候选:需提醒 + 未处理 + 未推送 + 指定级别。
*
* @param list<string> $levels
* @return Collection<int,object>
*/
public function instantCandidates(array $levels, bool $retryFailed, int $limit): Collection
{
return $this->connection->table(StoreViolationRecordRepository::TABLE)
->where('needs_alert', true)
->where('handling_status', (string) config('store_violations.default_handling_status', '未处理'))
->whereIn('alert_level', $levels)
->where(function ($query) use ($retryFailed): void {
$query->where('push_status', '未推送');
if ($retryFailed) {
$query->orWhere('push_status', '推送失败');
}
})
->orderByRaw("CASE alert_level WHEN 'P0' THEN 0 WHEN 'P1' THEN 1 ELSE 2 END")
->orderBy('id')
->limit(max($limit, 1))
->get();
}
/**
* 每日汇总取数:各级别待处理数量与超时未认领记录。
*
* @return array{pending:array<string,int>,overdue:Collection<int,object>,p2_pending:Collection<int,object>}
*/
public function digestData(int $overdueLimit = 20): array
{
$defaultStatus = (string) config('store_violations.default_handling_status', '未处理');
$pending = [];
foreach ($this->connection->table(StoreViolationRecordRepository::TABLE)
->selectRaw('alert_level, COUNT(*) AS aggregate')
->where('needs_alert', true)
->where('handling_status', $defaultStatus)
->groupBy('alert_level')
->get() as $row) {
$pending[(string) $row->alert_level] = (int) $row->aggregate;
}
$overdue = $this->connection->table(StoreViolationRecordRepository::TABLE)
->whereIn('alert_level', array_keys((array) config('store_violations.alert_levels', [])))
->whereNotIn('handling_status', StoreViolationRecordRepository::FINAL_HANDLING_STATUSES)
->whereNotNull('handling_deadline')
->where('handling_deadline', '<', Carbon::now())
->where('needs_alert', true)
->orderBy('handling_deadline')
->limit(max($overdueLimit, 1))
->get(['id', 'platform', 'shop_name', 'owner_name', 'alert_level', 'violation_type', 'handling_deadline']);
$p2 = $this->connection->table(StoreViolationRecordRepository::TABLE)
->where('needs_alert', true)
->where('alert_level', 'P2')
->where('handling_status', $defaultStatus)
->where('push_status', '未推送')
->orderBy('id')
->get(['id']);
return ['pending' => $pending, 'overdue' => $overdue, 'p2_pending' => $p2];
}
/** @param list<int> $ids */
public function markPushed(array $ids, Carbon $at): void
{
if ($ids === []) {
return;
}
foreach (array_chunk($ids, 500) as $chunk) {
$this->connection->table(StoreViolationRecordRepository::TABLE)
->whereIn('id', $chunk)
->update(['push_status' => '已推送', 'last_pushed_at' => $at, 'updated_at' => $at]);
}
}
public function markPushFailed(int $id, Carbon $at): void
{
$this->connection->table(StoreViolationRecordRepository::TABLE)
->where('id', $id)
->update(['push_status' => '推送失败', 'last_pushed_at' => $at, 'updated_at' => $at]);
}
/** @param array<string,mixed> $entry */
public function log(array $entry): void
{
if (! $this->available()) {
return;
}
$now = now();
$this->connection->table(self::LOG_TABLE)->insert($entry + [
'created_at' => $now,
'updated_at' => $now,
]);
}
public function available(): bool
{
return \Illuminate\Support\Facades\Schema::connection($this->connection->getName())
->hasTable(self::LOG_TABLE);
}
}