File: /var/www/ipsremont-demo/app/Models/Repair/Repair.php
<?php
namespace App\Models\Repair;
use App\Helpers\CurrencyHelper;
use App\Helpers\UserHelper;
use App\Models\ActTc;
use App\Models\BaseModel;
use App\Models\Branch;
use App\Models\Device;
use App\Models\ErrorCodes;
use App\Models\Order;
use App\Models\Permission;
use App\Models\RepairAttachment;
use App\Models\RepairChanges;
use App\Models\RepairItems;
use App\Models\Service\Service;
use App\Models\WorkCompleteCertificate;
use App\Repository\Errors\ErrorsRepository;
use App\Services\Service\ServiceService;
use App\Services\Status\StatusService;
use App\Traits\My;
use App\Traits\Sortable;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
/**
* @property int $id
* @property int $user_id
* @property int $service_id
* @property int $branch_id
* @property string $status
* @property int $created_by_manager
* @property string $name
* @property string $email
* @property string $phone
* @property string $serial_number
* @property string $device_id
* @property string $additional_info
* @property string $sold_at
* @property string $repair_date
* @property float $price
* @property int $bottom
* @property string $deleted_at
* @property string $created_at
* @property string $updated_at
* @property int $category_id
* @property string $work_description
* @property string $closed_at
* @property string $inner_nbr
* @property string $address
* @property string $device_external_id
* @property int $error_code
* @property string $close_date
* @property float $custom_price
* @property float $custom_price_rub
* @property int $export_status
* @property string $report_name
* @property int $device_name
* @property string $device_sku
* @property integer $use_catalog_component
* @property int $pre_sale
*
* @property Device $device
* @property Collection|Order[] $orders
* @property Collection|RepairItems[] $custom_parts
* @property Collection|RepairItems[] $repairItems
* @property Collection $attachments
* @property ActTc $actts
* @property WorkCompleteCertificate $workCompleteCertificate
* @property Branch $branch
* @property Service $service
*/
class Repair extends BaseModel
{
use SoftDeletes, Sortable, My;
const STATUS_NEW = 'new'; // Новый
const STATUS_ORDERED_PARTS = 'ordered_parts'; // Заказаны детали
const STATUS_PARTIALLY_SHIPPED = 'partially_shipped'; // Частично отгружено
const STATUS_SHIPPED = 'shipped'; // Отгружено
const STATUS_COMPLETED = 'completed'; // Завершен
const STATUS_REPORT = 'report'; // Включен в отчет
const STATUS_CANCELED = 'canceled'; // Отменен
const EXPORT_STATUS_NEW = 0;
const EXPORT_STATUS_IN_PROGRESS = 1;
const EXPORT_STATUS_DONE = 2;
const EXPORT_STATUS_ERROR = 3;
const CATEGORY_1 = 1;
const CATEGORY_2 = 2;
const CATEGORY_3 = 3;
public $order_id = 0;
protected $_status = null;
protected $fillable = [
'name',
'email',
'phone',
'status',
'additional_info',
'custom_price',
'custom_price_rub',
'serial_number',
'device_id',
'pre_sale',
'sold_at',
'repair_date',
'closed_at',
'category_id',
'work_description',
'inner_nbr',
'address',
'error_code',
'use_catalog_component',
'device_sku',
'device_name',
];
protected static $labels = [
'user_id' => 'orders.user_id',
'service_id' => 'orders.service_id',
'branch_id' => 'orders.branch_id',
'order_id' => 'repairs.order_id',
'created_by_manager' => 'orders.created_by_manager',
'email' => 'repairs.customer_email',
'phone' => 'repairs.customer_phone',
'name' => 'repairs.customer_name',
'address' => 'repairs.customer_address',
'status' => 'orders.status',
'additional_info' => 'repairs.additional_info',
'serial_number' => 'repairs.serial_number',
'device_id' => 'repairs.device_id',
'sold_at' => 'repairs.sold_at',
'repair_date' => 'repairs.repair_date',
'price' => 'repairs.price',
'category_id' => 'repairs.category_id',
'work_description' => 'repairs.work_description',
'closed_at' => 'repairs.closed_at',
'inner_nbr' => 'repairs.inner_nbr',
'error_category' => 'repairs.errorCategory',
'error_code' => 'repairs.errorCodes',
'custom_price' => 'repairs.customPrice',
'export_status' => 'repairs.exportStatus',
'pre_sale' => 'repairs.pre_sale',
];
public static function getCategories(): array
{
return [
1 => __('repairs.category1'),
2 => __('repairs.category2'),
3 => __('repairs.category3'),
];
}
public static function getEditableStatuses(): array
{
return [self::STATUS_NEW, self::STATUS_ORDERED_PARTS, self::STATUS_PARTIALLY_SHIPPED, self::STATUS_SHIPPED];
}
public static function getManagerEditableStatuses(): array
{
return [self::STATUS_NEW, self::STATUS_ORDERED_PARTS, self::STATUS_PARTIALLY_SHIPPED, self::STATUS_SHIPPED];
}
public function isAllowEdit(): bool
{
$user = UserHelper::getUser();
$serviceCanEdit = $user->isService() && in_array($this->status, self::getEditableStatuses());
$managerCanEdit = $user->isManager() && in_array($this->status, self::getManagerEditableStatuses());
return $serviceCanEdit || $managerCanEdit;
}
public function isAllowCreateOrder(): bool
{
$user = UserHelper::getUser();
$serviceCanEdit = $user->isService() && in_array($this->status, self::getEditableStatuses());
$managerCanEdit = $user->isManager() && in_array($this->status, self::getEditableStatuses());
return $serviceCanEdit || $managerCanEdit;
}
public static function columns()
{
$user = UserHelper::getUser();
$fields = [['displayName' => 'repairs.id', 'field' => 'id', 'class' => 'w-150px', 'sort' => true, 'sortType' => 'desc']];
if ($user->isService()) {
$fields[] = ['displayName' => 'repairs.inner_nbr_grid', 'field' => 'inner_nbr', 'sort' => true, 'sortType' => 'desc'];
}
$fields[] = ['displayName' => 'orders.id', 'field' => 'order_id', 'sort' => false, 'sortType' => 'desc'];
$branches = $user->getBranchIds();
if (can(Permission::branchesAll) || count($branches) > 1) {
$fields[] = ['displayName' => 'orders.branch_id', 'field' => 'branch_id', 'sort' => true, 'sortType' => 'asc'];
}
if (!$user->isService()) {
$fields[] = ['displayName' => 'orders.service_id', 'field' => 'service_id', 'sort' => true, 'sortType' => 'asc'];
}
$fields = array_merge($fields, [
['displayName' => 'repairs.serial_number_grid', 'field' => 'serial_number', 'sort' => true, 'sortType' => 'asc'],
['displayName' => 'repairs.device_id', 'field' => 'device_id', 'sort' => true, 'sortType' => 'desc'],
['displayName' => 'repairs.status', 'field' => 'status', 'sort' => true, 'sortType' => 'asc'],
['displayName' => 'grid.createdAt', 'field' => 'created_at', 'sort' => true, 'sortType' => 'asc'],
['displayName' => 'repairs.closed_at_grid', 'field' => 'closed_at', 'sort' => true, 'sortType' => 'desc'],
['displayName' => '', 'field' => 'action', 'sort' => false],
]);
return [
'fields' => $fields,
'sortDefault' => [
['field' => 'bottom', 'sort' => 'asc'],
['field' => 'created_at', 'sort' => 'desc'],
],
];
}
/**
* The attributes that should be cast.
*
* @var array
*/
protected $casts = [
'sold_at' => 'datetime:Y-m-d',
'repair_date' => 'datetime:Y-m-d',
'closed_at' => 'datetime:Y-m-d',
'close_date' => 'datetime:Y-m-d',
];
public function getNumber()
{
return '#' . sprintf("%'.06d", $this->id);
}
public function getDevice(): Device
{
return $this->device()->firstOrNew();
}
public function getOrdersNumbers()
{
$orders = $this->orders()->get();
$names = [];
foreach ($orders as $order) {
$names[$order->id] = $order->getNumber();
}
return $names;
}
public function status()
{
if (!$this->_status) {
$this->_status = StatusService::getRepairBySlug($this->status);
}
return $this->_status;
}
public function getStatus()
{
return $this->status()->slug;
}
public function getSerial()
{
return $this->serial_number;
}
public function getSold()
{
return $this->sold_at ? $this->sold_at->format(config('crud.formatDatePicker')) : '';
}
public function getRepairDate()
{
return $this->repair_date ? $this->repair_date->format(config('crud.formatDatePicker')) : '';
}
public function getClosedDate()
{
return $this->closed_at ? $this->closed_at->format(config('crud.formatDatePicker')) : '';
}
public function service()
{
return $this->belongsTo(Service::class);
}
public function branch()
{
return $this->belongsTo(Branch::class);
}
public function getService()
{
return $this->service->name ?? '-';
}
public function getBranch()
{
return $this->branch->name ?? '-';
}
public function getPrice()
{
return $this->price;
}
public function getCustomOrDefaultPrice(): ?float
{
return $this->custom_price ?? $this->price;
}
public function getPriceConverted(): string
{
$price = $this->getCustomOrDefaultPrice();
return CurrencyHelper::getPriceConverted($price);
}
public function getPriceFor1S(): string
{
return str_replace('.', ',', $this->custom_price_rub ?? $this->getCustomOrDefaultPrice());
}
public function getAdditionalInfo()
{
return $this->additional_info;
}
public function repair_changes()
{
return $this->hasMany(RepairChanges::class)->orderBy('repair_changes.id', 'desc');
}
/**
* Scope a query to only include My items
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeMy($query)
{
if (!Auth::check()) {
return $query;
}
if (Auth::user()->isService()) {
return $query
->whereIn('branch_id', Auth::user()->getBranchIds())
->where(['service_id' => Auth::user()->getCurrentServiceId()]);
}
if (can(Permission::branchesAll) && can(Permission::servicesAll)) {
return $query;
} elseif (can(Permission::servicesAll)) // если менеджер то видит заявки своего бранча,
{
return $query
->whereIn('branch_id', Auth::user()->getBranchIds());
} else {
// получить список доступных менеджеру сервисов. там сложная схема, это и привязанные через relation и обработка branchesAll и servicesAll
$services = ServiceService::getAvailable()->get()->pluck('id')->toArray();
return $query
->whereIn('service_id', $services);
}
}
public function getName(): string
{
return htmlspecialchars_decode($this->name);
}
public function getEmail()
{
return $this->email;
}
public function getPhone()
{
return $this->phone;
}
public function getAddress()
{
return $this->address;
}
public function getInnerNbr()
{
return $this->inner_nbr;
}
public function getCategoryName()
{
if (!$this->category_id) {
return;
}
return self::getCategories()[$this->category_id] ?? '';
}
public function getId()
{
return $this->id;
}
public function errorCode()
{
return $this->hasOne(ErrorCodes::class, 'external_id', 'error_code')->withTrashed()->first();
}
public function getErrorGroup()
{
$group = ErrorsRepository::getByGroup($this->errorCode()->external_group_id);
return $group ? $group->name : '';
}
public function getErrorCode()
{
return $this->error_code;
}
public function getErrorName()
{
return $this->errorCode()->name;
}
public static function cart_columns($type = '')
{
$columns = [];
$columns["fields"]["name"] = [
"displayName" => 'repairs.vendor_code',
"field" => "name",
"sort" => false,
"class" => 'w-50',
"sortType" => 'asc',
];
$columns["fields"]["amount"] = [
"displayName" => 'orders.amount',
"field" => "amount",
"sort" => false,
"class" => 'text-center w-200px',
"sortType" => 'asc',
];
$columns["fields"]["price_1"] = [
"displayName" => 'repairs.price_1',
"field" => "price_1",
"sort" => false,
"class" => 'text-right w-200px',
"sortType" => 'asc',
];
$columns["fields"]["price"] = [
"displayName" => 'orders.price',
"field" => "price",
"sort" => false,
"class" => 'text-right w-200px',
"sortType" => 'asc',
];
if ($type == 'create') {
$columns["fields"]["actions"] = [
"displayName" => '',
"field" => 'action',
"class" => 'w-200px',
"sort" => false,
];
}
return $columns;
}
public function getPreSale()
{
return $this->pre_sale;
}
// MARK: - Relations
public function device(): BelongsTo
{
return $this->belongsTo(Device::class)->withTrashed();
}
public function orders(): HasMany
{
return $this->hasMany(Order::class, 'repair_id', 'id');
}
public function custom_parts(): HasMany
{
return $this->repairItems();
}
public function repairItems(): HasMany
{
return $this->hasMany(RepairItems::class);
}
public function attachments(): HasMany
{
return $this->hasMany(RepairAttachment::class, 'repair_id');
}
public function acttc(): HasOne
{
return $this->hasOne(ActTc::class);
}
public function workCompleteCertificate(): HasOne
{
return $this->hasOne(WorkCompleteCertificate::class);
}
}