where('tenant_id', $tenantId); } if (! empty($filters['document_type'])) { $query->where('document_type', $filters['document_type']); } if (isset($filters['is_active']) && $filters['is_active'] !== '') { $query->where('is_active', (bool) $filters['is_active']); } if (! empty($filters['search'])) { $query->where('rule_name', 'like', "%{$filters['search']}%"); } return $query->orderBy('document_type')->paginate($perPage); } public function getRule(int $id): ?NumberingRule { $tenantId = session('selected_tenant_id'); $query = NumberingRule::query(); if ($tenantId) { $query->where('tenant_id', $tenantId); } return $query->find($id); } public function createRule(array $data): NumberingRule { $tenantId = session('selected_tenant_id'); return NumberingRule::create([ 'tenant_id' => $tenantId, 'document_type' => $data['document_type'], 'rule_name' => $data['rule_name'] ?? null, 'pattern' => $data['pattern'], 'reset_period' => $data['reset_period'] ?? 'daily', 'sequence_padding' => $data['sequence_padding'] ?? 2, 'is_active' => $data['is_active'] ?? true, 'created_by' => auth()->id(), ]); } public function updateRule(int $id, array $data): bool { $rule = $this->getRule($id); if (! $rule) { return false; } return $rule->update([ 'document_type' => $data['document_type'] ?? $rule->document_type, 'rule_name' => $data['rule_name'] ?? $rule->rule_name, 'pattern' => $data['pattern'] ?? $rule->pattern, 'reset_period' => $data['reset_period'] ?? $rule->reset_period, 'sequence_padding' => $data['sequence_padding'] ?? $rule->sequence_padding, 'is_active' => $data['is_active'] ?? $rule->is_active, 'updated_by' => auth()->id(), ]); } public function deleteRule(int $id): bool { $rule = $this->getRule($id); if (! $rule) { return false; } return $rule->delete(); } public function getUsedDocumentTypes(?int $excludeId = null): array { $tenantId = session('selected_tenant_id'); $query = NumberingRule::where('tenant_id', $tenantId); if ($excludeId) { $query->where('id', '!=', $excludeId); } return $query->pluck('document_type')->toArray(); } public function generatePreview(array $pattern, int $sequencePadding = 2): string { $result = ''; foreach ($pattern as $segment) { $result .= match ($segment['type'] ?? '') { 'static' => $segment['value'] ?? '', 'separator' => $segment['value'] ?? '', 'date' => now()->format($segment['format'] ?? 'ymd'), 'param' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}', 'mapping' => $segment['default'] ?? '{' . ($segment['key'] ?? '?') . '}', 'sequence' => str_pad('1', $sequencePadding, '0', STR_PAD_LEFT), default => '', }; } return $result; } }