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();
}
}