| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180 |
- <?php
- namespace App\Http\Controllers;
- use App\Http\Requests\FilterRequest;
- use Illuminate\Support\Facades\DB;
- use Illuminate\Support\Facades\Schema;
- class FilterController extends Controller
- {
- const DB_TABLES = [
- 'orders' => 'orders_view',
- 'product_sku' => 'mafs_view',
- 'products' => 'products',
- 'reclamations' => 'reclamations_view',
- 'maf_order' => 'maf_orders_view',
- 'import' => 'imports',
- 'responsibles' => 'responsibles',
- 'users' => 'users',
- 'contracts' => 'contracts',
- 'spare_parts' => 'spare_parts_view',
- 'spare_part_orders' => 'spare_part_orders_view',
- 'notifications' => 'user_notifications',
- 'notification_logs' => 'notification_delivery_logs',
- ];
- const SKIP_YEAR_FILTER = [
- 'reclamations',
- 'notifications',
- 'notification_logs',
- ];
- /**
- * Маппинг виртуальных столбцов (аксессоров Eloquent) на реальные столбцы БД.
- * Ключ — имя таблицы из DB_TABLES, значение — массив 'виртуальный_столбец' => 'реальный_столбец'.
- */
- const COLUMN_MAP = [
- 'spare_part_orders' => [
- 'status_name' => 'status',
- 'with_documents_text' => 'with_documents',
- ],
- 'spare_parts' => [
- 'customer_price_txt' => 'customer_price',
- 'expertise_price_txt' => 'expertise_price',
- 'purchase_price_txt' => 'purchase_price',
- ],
- 'products' => [
- 'product_price_txt' => 'product_price',
- 'installation_price_txt' => 'installation_price',
- 'total_price_txt' => 'total_price',
- ],
- ];
- /**
- * Маппинг значений: реальное значение БД => отображаемое значение.
- * Ключ — имя таблицы, затем реальный столбец.
- */
- const VALUE_MAP = [
- 'notifications' => [
- 'type' => [
- 'platform' => 'Площадки',
- 'reclamation' => 'Рекламации',
- 'schedule' => 'График монтажей',
- ],
- 'event' => [
- 'created' => 'Создание',
- 'status_changed' => 'Смена статуса',
- 'schedule_added' => 'Добавлено в график',
- ],
- ],
- 'spare_part_orders' => [
- 'with_documents' => [
- 0 => 'Нет',
- 1 => 'Да',
- ],
- 'status' => [
- 'ordered' => 'Заказано',
- 'in_stock' => 'На складе',
- 'shipped' => 'Отгружено',
- ],
- ],
- 'notification_logs' => [
- 'channel' => [
- 'in_app' => 'Браузер',
- 'browser' => 'Браузер',
- 'push' => 'Android/iOS',
- 'email' => 'Email',
- ],
- 'status' => [
- 'sent' => 'Отправлено',
- 'failed' => 'Ошибка',
- 'skipped' => 'Пропущено',
- 'dead_letter' => 'Dead letter',
- ],
- ],
- ];
- public function getFilters(FilterRequest $request)
- {
- $table = $request->validated('table');
- $column = $request->validated('column');
- if(!array_key_exists($table, self::DB_TABLES)) {
- abort(400, 'Table not found');
- }
- $gp = session('gp_' . $table);
- $dbTable = self::DB_TABLES[$table];
- // Определяем реальный столбец БД
- $dbColumn = self::resolveDbColumn($table, $dbTable, $column);
- if ($dbColumn && Schema::hasColumn($dbTable, $dbColumn)) {
- $q = DB::table($dbTable)->select($dbColumn)->distinct();
- if (!in_array($table, self::SKIP_YEAR_FILTER) && Schema::hasColumn($dbTable, 'year')) {
- $q->where('year' , year());
- }
- if (Schema::hasColumn($dbTable, 'deleted_at')) {
- $q->whereNull('deleted_at');
- }
- if(isset($gp['filters']) && is_array($gp['filters']) && count($gp['filters'])) {
- foreach ($gp['filters'] as $colName => $vals) {
- if ($colName === $column) continue;
- $filterDbColumn = self::resolveDbColumn($table, $dbTable, $colName);
- if (!$filterDbColumn || !Schema::hasColumn($dbTable, $filterDbColumn)) continue;
- $q->where(function ($query) use ($filterDbColumn, $vals) {
- foreach (explode('||', $vals) as $val) {
- if($val == '-пусто-') {
- $query->orWhereNull($filterDbColumn);
- } else {
- $query->orWhere($filterDbColumn, '=', $val);
- }
- }
- });
- }
- }
- $result = $q->orderBy($dbColumn)->get()->pluck($dbColumn)->toArray();
- // Конвертация цен из копеек в рубли для отображения
- if (str_ends_with($dbColumn, '_price')) {
- $result = array_map(function ($val) {
- if ($val === null) {
- return $val;
- }
- return $val / 100;
- }, $result);
- }
- // Применяем маппинг значений, если есть
- if (isset(self::VALUE_MAP[$table][$dbColumn])) {
- $map = self::VALUE_MAP[$table][$dbColumn];
- $result = array_map(fn($val) => $map[$val] ?? $val, $result);
- }
- } else {
- $result = [];
- }
- return response()->json($result, 200, [], JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
- }
- /**
- * Определяет реальный столбец БД по имени столбца из заголовка.
- * Приоритет: прямое совпадение в БД → COLUMN_MAP для конкретной таблицы.
- */
- public static function resolveDbColumn(string $table, string $dbTable, string $column): ?string
- {
- // 1. Прямое совпадение — столбец существует в БД
- if (Schema::hasColumn($dbTable, $column)) {
- return $column;
- }
- // 2. Явный маппинг для конкретной таблицы
- if (isset(self::COLUMN_MAP[$table][$column])) {
- return self::COLUMN_MAP[$table][$column];
- }
- return null;
- }
- }
|