'店铺开店', 9 => '店铺变更', 10 => '店铺关店', 12 => '主体注销自动流程', ]; /** OA 审批状态(flow_flow.flowStatus),取值与文案取自 OA 前端。 */ public const APPROVAL_STATUSES = [ 0 => '暂存', 1 => '流程中', 2 => '拒绝', 3 => '完成', 4 => '撤回', 5 => '待签署', 6 => '已签署', 7 => '待审批', ]; /** 店铺档案状态(fys_shopInfo.shopState 口径)。 */ private const SHOP_STATES = [0 => '正常', 3 => '关闭中', 6 => '已关闭']; public function __construct( private readonly BusinessMirrorDatasetRegistry $datasets, private readonly GenericBusinessMirrorRepository $mirror, ) { } public function ready(): bool { try { return $this->mirror->ready($this->datasets->get(self::FORM_DATASET)); } catch (\Throwable) { return false; } } /** * @param array $filters * @return array{data:list>,total:int} */ public function paginate(int $page, int $perPage, array $filters = []): array { if (! $this->ready()) { throw new RuntimeException('shop_info_flow_mirror_not_ready'); } $page = max($page, 1); $perPage = min(max($perPage, 1), 100); $connection = $this->mirror->connection(); $form = $this->datasets->get(self::FORM_DATASET)->targetTable(); $flow = $this->datasets->get(self::FLOW_DATASET)->targetTable(); $query = $connection->table($form . ' as f') ->leftJoin($flow . ' as o', 'o.flowId', '=', 'f.flowId'); $this->applyFilters($query, $filters); $total = (clone $query)->count(); $rows = $query ->select([ 'f.Id as id', 'f.flowId as flow_id', 'f.flowType as flow_type', 'f.applyUser as apply_user', 'f.applyTime as apply_time', 'f.applyDepartment as apply_department', 'f.remark as remark', 'f.platform as platform', 'f.responsibleDepartment as responsible_department', 'f.shopHead as shop_head', 'f.customerManager as customer_manager', 'f.shopType as shop_type', 'f.shopState as shop_state', 'f.shopName as shop_name', 'f.erpShopName as erp_shop_name', 'f.trademarkNumber as trademark_number', 'f.unifiedSocialCreditCode as subject_code', 'f.informationChangeType as information_change_type', 'f.changeReason as change_reason', 'f.changeSuccessful as change_successful', 'f.closeReason as close_reason', 'f.expectedClosingTime as expected_closing_time', 'f.refundType as refund_type', 'f.refundAmount as refund_amount', 'f.refundIssue as refund_issue', 'o.flowStatus as approval_status_code', 'o.approver as current_approver', 'o.subject as flow_subject', 'o.updateTime as flow_updated_at', ]) ->orderByDesc('f.applyTime')->orderByDesc('f.Id') ->forPage($page, $perPage) ->get() ->map(fn (object $row): array => $this->mapRow($row)) ->all(); return ['data' => $rows, 'total' => $total]; } /** @param array $filters */ private function applyFilters(Builder $query, array $filters): void { foreach ([ 'flow_id' => 'f.flowId', 'apply_user' => 'f.applyUser', 'erp_shop_name' => 'f.erpShopName', 'shop_name' => 'f.shopName', 'shop_head' => 'f.shopHead', 'current_approver' => 'o.approver', 'responsible_department' => 'f.responsibleDepartment', 'trademark_number' => 'f.trademarkNumber', ] as $key => $column) { $value = trim((string) ($filters[$key] ?? '')); if ($value !== '') { $query->where($column, 'like', '%' . addcslashes($value, '%_\\') . '%'); } } foreach ([['from', '>='], ['to', '<=']] as [$suffix, $operator]) { $date = trim((string) ($filters['apply_' . $suffix] ?? '')); if (preg_match('/^\d{4}-\d{2}-\d{2}$/D', $date)) { $query->whereDate('f.applyTime', $operator, $date); } } // 多选筛选:流程类型 / 审批状态 / 平台,多个取值取并集。 $flowTypes = $this->filterValues($filters['flow_type'] ?? ''); if ($flowTypes !== []) { $codes = []; foreach ($flowTypes as $label) { $code = array_search($label, self::FLOW_TYPES, true); if ($code !== false) { $codes[] = (int) $code; } } $query->whereIn('f.flowType', $codes === [] ? [-1] : $codes); } $statuses = $this->filterValues($filters['approval_status'] ?? ''); if ($statuses !== []) { $codes = []; foreach ($statuses as $label) { $code = array_search($label, self::APPROVAL_STATUSES, true); if ($code !== false) { $codes[] = (int) $code; } } $query->whereIn('o.flowStatus', $codes === [] ? [-1] : $codes); } $platforms = $this->filterValues($filters['platform'] ?? ''); if ($platforms !== []) { $query->whereIn('f.platform', $platforms); } } /** @return list */ private function filterValues(mixed $value): array { $values = []; foreach ((array) $value as $item) { if (! is_scalar($item)) { continue; } $item = trim((string) $item); if ($item !== '') { $values[$item] = true; } } return array_keys($values); } /** @return array */ private function mapRow(object $row): array { $flowType = (int) ($row->flow_type ?? 0); $statusCode = $row->approval_status_code !== null ? (int) $row->approval_status_code : null; return [ 'id' => $row->id, 'flow_id' => (string) $row->flow_id, 'flow_type' => self::FLOW_TYPES[$flowType] ?? ('其它(' . $flowType . ')'), 'flow_subject' => (string) ($row->flow_subject ?? ''), 'approval_status' => $statusCode === null ? '' : (self::APPROVAL_STATUSES[$statusCode] ?? (string) $statusCode), 'current_approver' => (string) ($row->current_approver ?? ''), 'apply_user' => (string) ($row->apply_user ?? ''), 'apply_time' => (string) ($row->apply_time ?? ''), 'apply_department' => (string) ($row->apply_department ?? ''), 'remark' => (string) ($row->remark ?? ''), 'platform' => (string) ($row->platform ?? ''), 'responsible_department' => (string) ($row->responsible_department ?? ''), 'shop_head' => (string) ($row->shop_head ?? ''), 'customer_manager' => (string) ($row->customer_manager ?? ''), 'shop_type' => (string) ($row->shop_type ?? ''), 'shop_state' => $row->shop_state === null ? '' : (self::SHOP_STATES[(int) $row->shop_state] ?? (string) $row->shop_state), 'shop_name' => (string) ($row->shop_name ?? ''), 'erp_shop_name' => (string) ($row->erp_shop_name ?? ''), 'trademark_number' => (string) ($row->trademark_number ?? ''), 'subject_code' => (string) ($row->subject_code ?? ''), 'information_change_type' => $row->information_change_type === null ? '' : (string) $row->information_change_type, 'change_reason' => (string) ($row->change_reason ?? ''), 'change_successful' => $row->change_successful === null ? null : (bool) $row->change_successful, 'close_reason' => (string) ($row->close_reason ?? ''), 'expected_closing_time' => (string) ($row->expected_closing_time ?? ''), 'refund_type' => (string) ($row->refund_type ?? ''), 'refund_amount' => $row->refund_amount === null ? null : (float) $row->refund_amount, 'refund_issue' => (string) ($row->refund_issue ?? ''), 'flow_updated_at' => (string) ($row->flow_updated_at ?? ''), ]; } }