店铺账号密码:把流程类型和审批状态两列都拉过来
上一版只带了「流程状态」(关店流程的审批状态)。改成按 ERP 店铺名取该店铺 最近一单申请流程(开店/变更/关店/主体注销自动),同时给出流程类型与审批状态, 列位置仍在「店铺状态」后面;两列都可搜索多选筛选、可排序。 线上:966 个账号店铺里 396 家最近一单是关店流程;状态文案与流程统计页一致。 状态映射缓存从 10 分钟放宽到 30 分钟(全量算一次要几秒,数据变化很慢)。
This commit is contained in:
parent
c88c0f165e
commit
d69a7d2ca7
@ -351,7 +351,8 @@ $navigation = [
|
||||
['name' => 'account_group_name', 'label' => '账号分组名称'],
|
||||
['name' => 'authorization_status', 'label' => '授权状态'],
|
||||
['name' => 'store_status', 'label' => '店铺状态'],
|
||||
['name' => 'flow_status', 'label' => '流程状态'],
|
||||
['name' => 'flow_type', 'label' => '流程类型'],
|
||||
['name' => 'approval_status', 'label' => '审批状态'],
|
||||
['name' => 'created_at', 'label' => '店铺创建时间', 'kind' => 'date'],
|
||||
['name' => 'updated_at', 'label' => '店铺修改时间', 'kind' => 'date'],
|
||||
],
|
||||
|
||||
@ -27,16 +27,16 @@ class StoreAccountMirrorRepository
|
||||
/** 授权状态文案;顺序同时用于下拉和排序。 */
|
||||
private const AUTHORIZATION_LABELS = ['已授权', '已过期', '未授权'];
|
||||
|
||||
/** 店铺关店流程(jst_shopInfo_flow.flowType=10)所在的数据集。 */
|
||||
private const CLOSE_FLOW_FORM_DATASET = 'jiansun.dbo.fys_shopInfo_flow';
|
||||
private const CLOSE_FLOW_OA_DATASET = 'js_data_middle_platform.dbo.flow_flow';
|
||||
private const CLOSE_FLOW_TYPE = 10;
|
||||
/** 店铺申请流程(开店/变更/关店/主体注销自动)所在的数据集。 */
|
||||
private const FLOW_FORM_DATASET = 'jiansun.dbo.fys_shopInfo_flow';
|
||||
private const FLOW_OA_DATASET = 'js_data_middle_platform.dbo.flow_flow';
|
||||
|
||||
/** 流程状态文案;顺序同时用于下拉和排序。 */
|
||||
/** 流程类型 / 审批状态文案;顺序同时用于下拉和排序。 */
|
||||
private const FLOW_TYPE_LABELS = ['店铺开店', '店铺变更', '店铺关店', '主体注销自动流程'];
|
||||
private const FLOW_STATUS_LABELS = ['流程中', '待审批', '完成', '拒绝', '撤回', '暂存', '待签署', '已签署'];
|
||||
|
||||
/** 账号店铺名 -> 状态 的缓存键(两张档案表要全表读,缓存 10 分钟)。 */
|
||||
private const STATUS_CACHE_KEY = 'store-accounts.statuses:v2';
|
||||
private const STATUS_CACHE_KEY = 'store-accounts.statuses:v3';
|
||||
|
||||
public function __construct(
|
||||
private readonly BusinessMirrorDatasetRegistry $datasets,
|
||||
@ -83,18 +83,21 @@ class StoreAccountMirrorRepository
|
||||
$statusFilters = [
|
||||
'store_status' => $this->filterValues($filters['store_status'] ?? ''),
|
||||
'authorization_status' => $this->filterValues($filters['authorization_status'] ?? ''),
|
||||
'flow_status' => $this->filterValues($filters['flow_status'] ?? ''),
|
||||
'flow_type' => $this->filterValues($filters['flow_type'] ?? ''),
|
||||
'approval_status' => $this->filterValues($filters['approval_status'] ?? ''),
|
||||
];
|
||||
$statuses = ($statusFilters['store_status'] !== []
|
||||
|| $statusFilters['authorization_status'] !== []
|
||||
|| $statusFilters['flow_status'] !== [])
|
||||
|| $statusFilters['flow_type'] !== []
|
||||
|| $statusFilters['approval_status'] !== [])
|
||||
? $this->statusesByStoreName()
|
||||
: null;
|
||||
if ($statuses !== null) {
|
||||
foreach ([
|
||||
'store_status' => 'store',
|
||||
'authorization_status' => 'authorization',
|
||||
'flow_status' => 'flow',
|
||||
'flow_type' => 'flow_type',
|
||||
'approval_status' => 'flow',
|
||||
] as $key => $bucket) {
|
||||
$expected = $statusFilters[$key];
|
||||
if ($expected === []) {
|
||||
@ -125,9 +128,11 @@ class StoreAccountMirrorRepository
|
||||
$statuses ??= $this->statusesByStoreName();
|
||||
[$sql, $bindings] = $this->statusOrderBy($statuses[$sortKey], $labels, $direction);
|
||||
$query->orderByRaw($sql, $bindings)->orderByDesc('id');
|
||||
} elseif (($filters['_sort'] ?? '') === 'flow_status') {
|
||||
} elseif (in_array($filters['_sort'] ?? '', ['flow_type', 'approval_status'], true)) {
|
||||
$statuses ??= $this->statusesByStoreName();
|
||||
[$sql, $bindings] = $this->statusOrderBy($statuses['flow'], self::FLOW_STATUS_LABELS, $direction);
|
||||
$sortedKey = $filters['_sort'] === 'flow_type' ? 'flow_type' : 'flow';
|
||||
$labels = $filters['_sort'] === 'flow_type' ? self::FLOW_TYPE_LABELS : self::FLOW_STATUS_LABELS;
|
||||
[$sql, $bindings] = $this->statusOrderBy($statuses[$sortedKey], $labels, $direction);
|
||||
$query->orderByRaw($sql, $bindings)->orderByDesc('id');
|
||||
} else {
|
||||
$query->orderByDesc('id');
|
||||
@ -154,7 +159,8 @@ class StoreAccountMirrorRepository
|
||||
'account_group_name' => $row->accountGroupName,
|
||||
'authorization_status' => $statuses['authorization'][$row->storeName] ?? '',
|
||||
'store_status' => $statuses['store'][$row->storeName] ?? '',
|
||||
'flow_status' => $statuses['flow'][$row->storeName] ?? '',
|
||||
'flow_type' => $statuses['flow_type'][$row->storeName] ?? '',
|
||||
'approval_status' => $statuses['flow'][$row->storeName] ?? '',
|
||||
'created_at' => $row->createdAt,
|
||||
'updated_at' => $row->updatedAt,
|
||||
];
|
||||
@ -213,43 +219,46 @@ class StoreAccountMirrorRepository
|
||||
: ($timestamp >= $now ? '已授权' : '已过期');
|
||||
}
|
||||
|
||||
$closeFlows = $this->closeFlowStatusByName();
|
||||
$result = ['store' => [], 'authorization' => [], 'flow' => []];
|
||||
$flows = $this->latestFlowByStoreName();
|
||||
$result = ['store' => [], 'authorization' => [], 'flow' => [], 'flow_type' => []];
|
||||
foreach ($this->mirror->connection()->table($this->datasets->get(self::DATASET)->targetTable())
|
||||
->select('storeName')->whereNotNull('storeName')->distinct()->pluck('storeName') as $name) {
|
||||
$name = (string) $name;
|
||||
$key = $this->shopKey($name);
|
||||
$result['store'][$name] = $storeStates[$key] ?? '';
|
||||
$result['authorization'][$name] = $authorizations[$key] ?? '';
|
||||
$result['flow'][$name] = $closeFlows[$key] ?? '';
|
||||
$result['flow_type'][$name] = $flows[$key]['flow_type'] ?? '';
|
||||
$result['flow'][$name] = $flows[$key]['approval_status'] ?? '';
|
||||
}
|
||||
|
||||
Cache::put(self::STATUS_CACHE_KEY, $result, now()->addMinutes(10));
|
||||
// 状态取自店铺档案与流程镜像,变化很慢;全量算一次要几秒,缓存久一点。
|
||||
Cache::put(self::STATUS_CACHE_KEY, $result, now()->addMinutes(30));
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 账号店铺 -> 关店流程状态:按 ERP 店铺名关联 jiansun.dbo.fys_shopInfo_flow 的
|
||||
* 关店流程(flowType=10),同一店铺取最近一单,状态用 OA 流程表的审批状态文案。
|
||||
* 账号店铺 -> 最近一单店铺申请流程(开店/变更/关店/主体注销自动)的类型与审批状态。
|
||||
*
|
||||
* @return array<string,string> 归一键 => 流程状态
|
||||
* 按 ERP 店铺名关联 jiansun.dbo.fys_shopInfo_flow,同一店铺取申请时间最近的一单;
|
||||
* 审批状态用中台库 OA 流程表(dbo.flow_flow)的字典文案。
|
||||
*
|
||||
* @return array<string,array{flow_type:string,approval_status:string}> 归一键 => 流程信息
|
||||
*/
|
||||
private function closeFlowStatusByName(): array
|
||||
private function latestFlowByStoreName(): array
|
||||
{
|
||||
try {
|
||||
$form = $this->datasets->get(self::CLOSE_FLOW_FORM_DATASET)->targetTable();
|
||||
$oa = $this->datasets->get(self::CLOSE_FLOW_OA_DATASET)->targetTable();
|
||||
$form = $this->datasets->get(self::FLOW_FORM_DATASET)->targetTable();
|
||||
$oa = $this->datasets->get(self::FLOW_OA_DATASET)->targetTable();
|
||||
} catch (\Throwable) {
|
||||
// 关店流程数据集尚未接入时,这一列留空即可,不影响其它列。
|
||||
// 店铺申请流程数据集尚未接入时,这两列留空即可,不影响其它列。
|
||||
return [];
|
||||
}
|
||||
|
||||
try {
|
||||
$rows = $this->mirror->connection()->table($form . ' as f')
|
||||
->leftJoin($oa . ' as o', 'o.flowId', '=', 'f.flowId')
|
||||
->where('f.flowType', self::CLOSE_FLOW_TYPE)
|
||||
->select(['f.erpShopName as erp_shop_name', 'o.flowStatus as flow_status'])
|
||||
->select(['f.erpShopName as erp_shop_name', 'f.flowType as flow_type', 'o.flowStatus as flow_status'])
|
||||
->orderByDesc('f.applyTime')->orderByDesc('f.Id')
|
||||
->get();
|
||||
} catch (\Throwable $exception) {
|
||||
@ -258,18 +267,22 @@ class StoreAccountMirrorRepository
|
||||
return [];
|
||||
}
|
||||
|
||||
$statuses = [];
|
||||
$flows = [];
|
||||
foreach ($rows as $row) {
|
||||
$key = $this->shopKey($row->erp_shop_name);
|
||||
if ($key === '' || array_key_exists($key, $statuses)) {
|
||||
if ($key === '' || array_key_exists($key, $flows)) {
|
||||
continue; // 已按申请时间倒序,首次出现的就是最近一单
|
||||
}
|
||||
$statuses[$key] = $row->flow_status === null
|
||||
? ''
|
||||
: (ShopInfoFlowMirrorRepository::APPROVAL_STATUSES[(int) $row->flow_status] ?? (string) $row->flow_status);
|
||||
$type = (int) $row->flow_type;
|
||||
$flows[$key] = [
|
||||
'flow_type' => ShopInfoFlowMirrorRepository::FLOW_TYPES[$type] ?? ('其它(' . $type . ')'),
|
||||
'approval_status' => $row->flow_status === null
|
||||
? ''
|
||||
: (ShopInfoFlowMirrorRepository::APPROVAL_STATUSES[(int) $row->flow_status] ?? (string) $row->flow_status),
|
||||
];
|
||||
}
|
||||
|
||||
return $statuses;
|
||||
return $flows;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1142,8 +1142,9 @@
|
||||
'store-management/store-accounts' => [
|
||||
'authorization_status' => ['已授权', '已过期', '未授权'],
|
||||
'store_status' => ['正常', '关闭中', '已关闭'],
|
||||
// 店铺关店流程的审批状态(取该店铺最近一单关店流程)。
|
||||
'flow_status' => ['流程中', '待审批', '完成', '拒绝', '撤回', '暂存', '待签署', '已签署'],
|
||||
// 该店铺最近一单申请流程(开店/变更/关店/主体注销自动)的类型与审批状态。
|
||||
'flow_type' => ['店铺开店', '店铺变更', '店铺关店', '主体注销自动流程'],
|
||||
'approval_status' => ['流程中', '待审批', '完成', '拒绝', '撤回', '暂存', '待签署', '已签署'],
|
||||
],
|
||||
'financial-risk-control/process-statistics' => [
|
||||
'flow_type' => ['店铺开店', '店铺变更', '店铺关店', '主体注销自动流程'],
|
||||
|
||||
@ -317,11 +317,13 @@ class StoreAccountPasswordsTest extends FeatureTestCase
|
||||
// 账号分组名称后面新增的两列。
|
||||
->assertSeeText('授权状态')
|
||||
->assertSeeText('店铺状态')
|
||||
->assertSeeText('流程状态')
|
||||
->assertSeeText('流程类型')
|
||||
->assertSeeText('审批状态')
|
||||
// 授权状态 / 店铺状态按可搜索多选渲染(提交为 xxx[])。
|
||||
->assertSee('data-directory-multi-select="authorization_status"', false)
|
||||
->assertSee('data-directory-multi-select="store_status"', false)
|
||||
->assertSee('data-directory-multi-select="flow_status"', false)
|
||||
->assertSee('data-directory-multi-select="flow_type"', false)
|
||||
->assertSee('data-directory-multi-select="approval_status"', false)
|
||||
->assertSee('CaiWuMultiSelect', false)
|
||||
->assertDontSee('data-password-dialog', false)
|
||||
->assertDontSee('data-store-password="view"', false)
|
||||
|
||||
@ -120,7 +120,7 @@ class StoreAccountMirrorRepositoryTest extends TestCase
|
||||
$this->assertSame(['A店铺', 'B店铺', 'C店铺'], array_column($sorted['data'], 'store_name'));
|
||||
}
|
||||
|
||||
public function test_it_shows_the_store_close_flow_status(): void
|
||||
public function test_it_shows_the_latest_application_flow(): void
|
||||
{
|
||||
$db = DB::connection('business_mirror');
|
||||
// 账号表用的就是带平台前缀的 ERP 店铺名(关店流程里可能写成下划线,需要归一)。
|
||||
@ -134,7 +134,7 @@ class StoreAccountMirrorRepositoryTest extends TestCase
|
||||
'erpShopName' => $erp, 'applyTime' => '2026-09-01 09:00:00',
|
||||
]);
|
||||
}
|
||||
// 甲店:最近一单关店流程在流程中;乙店:完成。丙店没有关店流程。
|
||||
// 甲店/乙店:最近一单是关店流程(流程中 / 完成);丙店只有开店流程。
|
||||
$db->table('shop_info_flow_form')->insert([
|
||||
['Id' => 1, 'flowId' => 'close-jia', 'flowType' => 10, 'erpShopName' => '拼多多_甲店', 'applyTime' => '2026-10-01 09:00:00'],
|
||||
['Id' => 2, 'flowId' => 'close-yi', 'flowType' => 10, 'erpShopName' => '拼多多-乙店', 'applyTime' => '2026-10-02 09:00:00'],
|
||||
@ -145,12 +145,20 @@ class StoreAccountMirrorRepositoryTest extends TestCase
|
||||
]);
|
||||
|
||||
$rows = collect($this->repository->paginate(1, 10)['data'])->keyBy('store_name');
|
||||
$this->assertSame('流程中', $rows['拼多多-甲店']['flow_status']);
|
||||
$this->assertSame('完成', $rows['拼多多-乙店']['flow_status']);
|
||||
$this->assertSame('', $rows['拼多多-丙店']['flow_status']);
|
||||
$this->assertSame('店铺关店', $rows['拼多多-甲店']['flow_type']);
|
||||
$this->assertSame('流程中', $rows['拼多多-甲店']['approval_status']);
|
||||
$this->assertSame('店铺关店', $rows['拼多多-乙店']['flow_type']);
|
||||
$this->assertSame('完成', $rows['拼多多-乙店']['approval_status']);
|
||||
// 丙店最近一单是开店流程,没有对应 OA 状态。
|
||||
$this->assertSame('店铺开店', $rows['拼多多-丙店']['flow_type']);
|
||||
$this->assertSame('', $rows['拼多多-丙店']['approval_status']);
|
||||
|
||||
$filtered = $this->repository->paginate(1, 10, ['flow_status' => ['流程中']]);
|
||||
$filtered = $this->repository->paginate(1, 10, ['approval_status' => ['流程中']]);
|
||||
$this->assertSame(['拼多多-甲店'], array_column($filtered['data'], 'store_name'));
|
||||
$byType = $this->repository->paginate(1, 10, ['flow_type' => ['店铺门店']]);
|
||||
$this->assertSame([], array_column($byType['data'], 'store_name'));
|
||||
$closeOnly = $this->repository->paginate(1, 10, ['flow_type' => ['店铺关店']]);
|
||||
$this->assertSame(2, $closeOnly['total']);
|
||||
}
|
||||
|
||||
public function test_it_exposes_followed_upstream_columns_to_the_page(): void
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user