HEX
Server: nginx/1.18.0
System: Linux test-ipsremont 5.4.0-214-generic #234-Ubuntu SMP Fri Mar 14 23:50:27 UTC 2025 x86_64
User: ips (1000)
PHP: 8.0.30
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: /var/www/ipsremont-demo/app/Repository/Order/OrderRepository.php
<?php


namespace App\Repository\Order;

use App\Helpers\UserHelper;
use App\Http\Requests\Order\AddToCartRequest;
use App\Http\Requests\Order\Create1cRequest;
use App\Http\Requests\Order\CreateRequest;
use App\Http\Requests\Order\IndexRequest;
use App\Http\Requests\Order\UpdateRequest;
use App\Models\Branch;
use App\Models\Cart;
use App\Models\Order;
use App\Models\OrderItems;
use App\Models\Part;
use App\Models\Permission;
use App\Models\Service\Service;
use App\Repository\Address\AddressRepository;
use App\Repository\BaseRepository;
use App\Services\ImportService;
use App\Services\Log\LogService;
use App\Services\Repair\RepairService;
use App\Services\Service\ServiceService;
use App\Services\Status\StatusService;
use App\Traits\GridTrait;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Validator;

class OrderRepository extends BaseRepository
{

    use GridTrait;

    public static function getAvailableOrders()
    {
        $user = UserHelper::getUser();
        $query = self::getAvailable();
        if (!Auth::check()) {
            return $query;
        }

        if ($user->isService()) {
            return $query->whereIn('branch_id', $user->getBranchIds())->where(['service_id' => $user->getCurrentServiceId()]);
        }

        if (can(Permission::branchesAll) && can(Permission::servicesAll)) {
            return $query;
        }

        // если менеджер, то видит заявки своего подразделения
        if (can(Permission::servicesAll)) {
            return $query->whereIn('branch_id', $user->getBranchIds());
        }

        // получить список доступных менеджеру сервисов. там сложная схема, это и привязанные через relation и обработка branchesAll и servicesAll
        $services = ServiceService::getAvailable()->get()->pluck('id')->toArray();

        return $query->whereIn('service_id', $services);
    }

    public static function getAvailableByStatus($id)
    {
        $query = self::getAvailableOrders();

        $query->where('id', $id);

        $query->where(function ($query) {
            if (Auth::user()->isService()) {
                $query->where('status', 'new')->orWhere('status', 'awaiting_confirmation');
            }
            if (Auth::user()->isManager()) {
                $query->where('status', 'new')->orWhere('status', 'awaiting_confirmation');
            }
        });

        return $query;
    }

    public static function getAvailableOpenedOrders($repair_id)
    {
        $query = self::getAvailableOrders();

        $query->where('repair_id', $repair_id)
            ->where('status', '!=', 'completed')
            ->where('status', '!=', 'canceled');

        return $query;
    }

    public function getLast($limit = 5)
    {
        $query = static::getAvailableOrders();
        $query->orderBy('updated_at', 'desc');

        return $query->limit($limit);
    }

    public function search(IndexRequest $request)
    {
        $query = self::getAvailableOrders();

        $this->makeQueryOrdered(Order::class, $query, $request);

        if (isset($request->id) && !empty($request->id)) {
            $query->where('id', $request->id);
        }
        if (isset($request->repair_id) && !empty($request->repair_id)) {
            $query->where('repair_id', $request->repair_id);
        }

        if (isset($request->part_external_id) && !empty($request->part_external_id)) {
            $query->whereHas('order_items', function ($query) use ($request) {
                $query->where('part_external_id', $request->part_external_id);
            });
        }

        if (isset($request->branch_id) && !empty($request->branch_id)) {
            $query->where('branch_id', $request->branch_id);
        }

        if (isset($request->service_id) && !empty($request->service_id)) {
            $query->where('service_id', $request->service_id);
        }

        if (isset($request->status) && !empty($request->status)) {
            $query->where('status', $request->status);
        }

        if (isset($request->client) && !empty($request->client)) {
            $query->where(function ($query) use ($request) {
                $query
                    ->orWhere('name', 'like', '%' . $request->client . '%')
                    ->orWhere('email', 'like', '%' . $request->client . '%')
                    ->orWhere('phone', 'like', '%' . $request->client . '%');
            });
        }

        if (isset($request->date_start) && !empty($request->date_start)) {
            $query->where('created_at', '>=', $request->date_start);
            $query->where('created_at', '<=', $request->date_end);
        }

        $perPage = $request->per_page ?? config('crud.defaultPerPage');
        $data = $query->paginate((int) $perPage)->appends($request->all());

        return $data;
    }

    public static function getQuery()
    {
        return Order::query();
    }

    public function save(CreateRequest $request)
    {
        $request->validate($request->rules());

        $repair = null;
        if ($request->repair_id) {
            $repair = RepairService::getById($request->repair_id); //if repair is not available redirect to 404
        }

        $parts = $this->getParts();
        if (empty($parts[0])) {
            return ['errors' => 'orders.emptyParts'];
        }

        $result = self::checkService($request);
        if (isset($result['errors'])) {
            return $result;
        }

        $prices = [];
        $external_ids = [];
        $total_price = 0;
        foreach ($parts as $part) {
            $p = Part::where('id', $part->part_id)->first();
            array_push($prices, $p->price);
            array_push($external_ids, $p->external_id);
            $total_price += $p->price * $part->amount;
        }

        $address = AddressRepository::getById($request->address_id);

        $order = new Order();
        $order->_save($request, $total_price, $address);

        foreach ($parts as $key => $part) {
            $model = new OrderItems();
            $model->_save($order->id, $part->part_id, $part->amount, $prices[$key], $external_ids[$key]);
        }

        $order_parts = OrderItems::where('order_id', $order->id)->get();

        LogService::updatedRelations($order, 'parts', $order_parts);

        $this->deleteFromCart();

        return ['success' => 'orders.messageCreate', 'model' => $order];
    }

    public static function formData1c($item): array
    {
        $statusModel = StatusService::getOrderByName($item['status']);
        $status = $statusModel ? $statusModel->slug : $item['status'];
        $data = [
            'service_code' => $item['service_code'],
            'branch_code' => $item['branch_code'],
            'code' => $item['code'],
            'status' => (string) $status,
            'created_by_manager' => $item['created_by_manager'],
            'repair' => $item['type'],
            'name' => 'Заявка на ТМЦ ' . $item['code'] . ' от ' . date('Y-m-d H:i:s', strtotime($item['date'])),
            'email' => $item['email'] ?? '1c@test.com',
            'phone' => $item['phone'] ?? null,
            'country' => $item['country'] ?? null,
            'city' => $item['city'] ?? null,
            'address' => $item['address'] ?? null,
            'additional_info' => $item['additional_info'],
            'price' => $item['price'] ?? null,
            'created_at' => $item['created_at'],
            'parts' => (isset($item['parts'])) ? $item['parts'] : '',
            'invoice' => $item['invoice'],
        ];

        array_walk($data, function (&$value) {
            $value = is_string($value) ? trim($value) : $value;
        });

        return $data;
    }

    public static function save1c($item): array
    {
        $result = '';
        $data = self::formData1c($item);

        $data['user_id'] = 1;

        $request = new Create1cRequest();
        $validator = Validator::make($data, $request->rules());

        foreach ($item['parts']->part as $part) {
            $partCode = trim($part->code);
            $local_part = Part::where('external_id', $partCode)->first();
            if (!$local_part) {
                $result .= 'Деталь ' . $partCode . ' не существует.';
            }
        }

        if ($validator->fails() || empty($item['parts']) || $result) {
            if ($validator->fails()) {
                $result .= json_encode($validator->errors(), JSON_UNESCAPED_UNICODE) . ' ';
            }
            if (empty($item['parts'])) {
                $result .= 'Детали заявки отсутствуют. ';
            }
            $order_id = '0';
        } else {
            echo '- Создание заявки', PHP_EOL;
            $service = Service::query()->where('external_id', $item['service_code'])->first();
            $branch = Branch::query()->where('external_id', $item['branch_code'])->first();
            if (empty($service)) {
                $result .= json_encode(['service_code' => ['Данный сервис отсутствует в системе']], JSON_UNESCAPED_UNICODE) . ' ';
                $order_id = '0';
            } elseif (empty($branch)) {
                $result .= json_encode(['branch_code' => ['Данное подразделение отсутствует в системе']], JSON_UNESCAPED_UNICODE) . ' ';
                $order_id = '0';
            } else {
                $order = new Order();
                $order = $order->save1c($data);
                $order->save();
                $order_id = $order->id;

                echo '- Создание заявки ' . $order_id . ' items', PHP_EOL;
                $res = self::orderItems($item['parts'], $order_id, true);

                $order_parts = $res['order_parts'];
                $sum = $res['sum'];
                $order->price = $sum;
                $order->save();

                LogService::updatedRelations($order, 'parts', $order_parts);

                $result = 1;
            }
        }

        return ['result' => $result, 'order_id' => $order_id];
    }

    public static function orderItems($parts, $orderId, bool $flush = false): array
    {
        $orderParts = [];
        $sum = 0;

        if ($flush) {
            echo ' - Очищаем детали заявки' . PHP_EOL;
            OrderItems::where('order_id', $orderId)->delete();
        }

        foreach ($parts->part as $part) {
            $code = trim($part->code);
            $quantity = (int) trim($part->quantity);

            echo ' - Импортируем в заявку ' . $orderId . ' деталь ' . $code . PHP_EOL;

            /** @var Part $localPart */
            $localPart = Part::where('external_id', $code)->first();
            $partId = empty($localPart) ? 0 : $localPart->id;

            if ($partId) {
                $price = isset($part->price) ? (float) trim($part->price) : $localPart->price;
                echo ' - Найдено partId ' . $partId . PHP_EOL;
                switch (trim($part->action)) {
                    case ImportService::DELETE:
                        echo ' - Удаляем partId ' . $partId . PHP_EOL;
                        OrderItems::where('order_id', $orderId)->where('part_id', $partId)->delete();
                        break;
                    case ImportService::UPDATE:
                        echo ' - Обновляем partId ' . $partId . PHP_EOL;
                        $model = OrderItems::where('order_id', $orderId)->where('part_id', $partId)->first();
                        $model->_update($orderId, $partId, (int) $part->quantity, (float) $part->price, $part->code . '');
                        array_push($orderParts, $model);
                        $sum += $part->quantity * $part->price;
                        break;
                    case ImportService::NEW:
                    default:
                        echo ' - Добавляем partId ' . $partId . PHP_EOL;

                        /** @var OrderItems $model */
                        $modelIsExists = !empty(OrderItems::where('order_id', $orderId)->where('part_id', $partId)->withTrashed()->first());
                        $model = new OrderItems();
                        if ($modelIsExists) {
                            echo ' - Существует' . PHP_EOL;
                            $model->_update($orderId, $partId, $quantity, $price, trim($part->code));
                        } else {
                            $model->_save($orderId, $partId, $quantity, $price, trim($part->code));
                        }
                        $sum += $quantity * $price;
                        $orderParts[] = $model;
                        break;
                }
            }
        }

        return ['order_parts' => $orderParts, 'sum' => $sum];
    }

    public function update(UpdateRequest $request)
    {
        $model = self::getAvailableOrders()->findOrFail($request->id);
        if ($model) {
            if (canServiceActions($model->service_id)) {
                $address = AddressRepository::getById($request->address_id);
                $model->_update($request, $address);
            }
        }
    }

    public static function update1c($item)
    {
        echo ' - Поиск заявки ' . $item['code'] . PHP_EOL;

        /** @var ?Order $order */
        $order = OrderRepository::getBy1sKey($item['code'], date('Y', strtotime($item['created_at'])));
        if (!empty($order)) {
            echo ' - Обновляем заявку ' . $order->id . PHP_EOL;
            $data = self::formData1c($item);
            $request = new Create1cRequest();
            $validator = Validator::make($data, $request->rules());
            $order_id = $order->id;

            if ($validator->fails()) {
                echo ' - валидация провалилась' . PHP_EOL;
                $result = $validator->errors();
            } else {
                echo ' - Обновляем заявку' . PHP_EOL;
                $order = $order->save1c($data);
                $order->update();
                $result = 1;

                echo ' - Обновляем делали в заявке' . PHP_EOL;
                $res = self::orderItems($item['parts'], $order_id, true);
                $orderParts = $res['order_parts'];
                $sum = $res['sum'];
                $order->price = $sum;
                $order->save();

                LogService::updatedRelations($order, 'parts', $orderParts);
            }
        } else {
            echo ' - Не найдено ' . $item['code'] . PHP_EOL;
            $result = 'Заявка ' . $item['code'] . ' не существует';
            $order_id = 0;
        }

        return ['result' => $result, 'order_id' => $order_id];
    }

    public static function checkService($request)
    {
        if ($request->service_id) {
            if (!canServiceActions($request->service_id)) {
                return ['errors' => 'orders.wrongService'];
            }
        }
    }

    public function count()
    {
        return Cart::my()->count();
    }

    public function part($part_id)
    {
        return Cart::my()->where('part_id', $part_id)->first();
    }

    public function addToCart($part_id, $amount)
    {
        $item = $this->part($part_id);
        $_amount = ($item) ? $item->amount + $amount : $amount;

        Cart::updateOrCreate(
            ['user_id' => Auth::user()->getAuthIdentifier(), 'part_id' => $part_id],
            ['amount' => $_amount,]
        );
    }

    public function getParts()
    {
        $items = Cart::query()->my()->get();
        foreach ($items as $key => $item) {
            if (!isset($item->part)) {
                Cart::query()->where('id', $item->id)->delete();
                unset($items[$key]);
            }
        }

        return $items;
    }

    public function deleteFromCart()
    {
        Cart::my()->delete();
    }

    public function deleteOneFromCart(AddToCartRequest $request)
    {
        Cart::my()->where('part_id', $request->part_id)->delete();
    }

    public static function getNewOrdersForReceiver(array $branchIds): Collection
    {
        $query = static::getQuery();

        $query->whereIn('branch_id', $branchIds);

        $query->where('status', Order::STATUS_NEW)->where('external_id', '');

        $query->orWhere(function ($query) {
            $query->where('status', Order::STATUS_AWAITING_CONFIRMATION)
                ->where('external_id', '<>', '')
                ->where('dispatch', '1');
        });

        return $query->limit(500)->orderBy('updated_at')->get();
    }

    public static function getBy1sKey(string $externalId, int $year, bool $withTrashed = false)
    {
        $query = Order::query()->where('external_id', $externalId)->whereYear('created_at', $year);
        if ($withTrashed) {
            $query->withTrashed();
        }

        return $query->orderBy('created_at', 'DESC')->first();
    }

}