Order.php 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. <?php
  2. namespace App\Models;
  3. use App\Helpers\Price;
  4. use App\Models\Dictionary\Area;
  5. use App\Models\Dictionary\District;
  6. use App\Models\Scopes\YearScope;
  7. use Illuminate\Database\Eloquent\Attributes\ScopedBy;
  8. use Illuminate\Database\Eloquent\Casts\Attribute;
  9. use Illuminate\Database\Eloquent\Model;
  10. use Illuminate\Database\Eloquent\Relations\BelongsTo;
  11. use Illuminate\Database\Eloquent\Relations\BelongsToMany;
  12. use Illuminate\Database\Eloquent\Relations\HasMany;
  13. use Illuminate\Database\Eloquent\Relations\HasManyThrough;
  14. use Illuminate\Database\Eloquent\SoftDeletes;
  15. use Illuminate\Support\Facades\DB;
  16. #[ScopedBy([YearScope::class])]
  17. class Order extends Model
  18. {
  19. use SoftDeletes;
  20. const DEFAULT_SORT_BY = 'created_at';
  21. const STATUS_NEW = 1;
  22. const STATUS_READY_TO_MOUNT = 2;
  23. const STATUS_READY_TO_HAND_OVER = 3;
  24. const STATUS_HANDED_OVER = 4;
  25. // set year attribute to current selected year
  26. protected static function boot(): void
  27. {
  28. parent::boot();
  29. static::creating(function($attributes) {
  30. if(!isset($attributes->year)) {
  31. $attributes->year = year();
  32. }
  33. });
  34. }
  35. protected $fillable = [
  36. 'year',
  37. 'user_id',
  38. 'district_id',
  39. 'area_id',
  40. 'object_address',
  41. 'object_type_id',
  42. 'contract_date',
  43. 'contract_number',
  44. 'comment',
  45. 'installation_date',
  46. 'ready_date',
  47. 'brigadier_id',
  48. 'order_status_id',
  49. 'tg_group_name',
  50. 'tg_group_link',
  51. 'ready_to_mount',
  52. ];
  53. public $appends = ['common_name', 'products_with_count'];
  54. public function products_sku(): HasMany
  55. {
  56. return $this->hasMany(ProductSKU::class, 'order_id', 'id');
  57. }
  58. public function products(): HasManyThrough
  59. {
  60. return $this->hasManyThrough(
  61. Product::class,
  62. ProductSKU::class,
  63. 'order_id',
  64. 'id',
  65. 'id',
  66. 'product_id');
  67. }
  68. public function user(): BelongsTo
  69. {
  70. return $this->belongsTo(User::class, 'user_id', 'id');
  71. }
  72. public function district(): BelongsTo
  73. {
  74. return $this->belongsTo(District::class);
  75. }
  76. public function area(): BelongsTo
  77. {
  78. return $this->belongsTo(Area::class);
  79. }
  80. public function objectType(): BelongsTo
  81. {
  82. return $this->belongsTo(ObjectType::class);
  83. }
  84. public function brigadier(): BelongsTo
  85. {
  86. return $this->belongsTo(User::class, 'brigadier_id', 'id');
  87. }
  88. public function orderStatus(): BelongsTo
  89. {
  90. return $this->belongsTo(OrderStatus::class);
  91. }
  92. public function getNeeds(): array
  93. {
  94. $needs = [];
  95. foreach ($this->products_sku as $sku) {
  96. $needs[$sku->product_id]['needs'] = (isset($needs[$sku->product_id])) ? $needs[$sku->product_id]['needs'] + 1 : 1;
  97. }
  98. foreach ($needs as $productId => $quantity) {
  99. $needs[$productId]['sku'] = MafOrder::query()
  100. ->where('maf_orders.product_id', $productId)
  101. ->sum('maf_orders.in_stock');
  102. }
  103. return $needs;
  104. }
  105. public function recalculateReadyToMount(): void
  106. {
  107. $result = true;
  108. foreach ($this->getNeeds() as $need) {
  109. if($need['sku'] < $need['needs']) {
  110. $result = false;
  111. break;
  112. }
  113. }
  114. if($this->order_status_id > self::STATUS_NEW) {
  115. $result = true;
  116. }
  117. $this->update(['ready_to_mount' => ($result) ? 'Да' : 'Нет']);
  118. }
  119. public function commonName(): Attribute
  120. {
  121. return Attribute::make(
  122. get: fn($value) => (string) $this->district->shortname . ', ' . $this->area->name . ', ' . $this->object_address,
  123. );
  124. }
  125. public function productsWithCount(): Attribute
  126. {
  127. $products = $this->products_sku;
  128. $ret = [];
  129. foreach ($products as $product) {
  130. if(isset($ret[$product->product->id])) {
  131. $ret[$product->product->id]['count'] += 1;
  132. } else {
  133. $ret[$product->product->id] = [
  134. 'name' => $product->product->article,
  135. 'count' => 1,
  136. ];
  137. }
  138. if($product->maf_order?->order_number) {
  139. $ret[$product->product->id]['order_numbers'][] = $product->maf_order?->order_number;
  140. }
  141. }
  142. $s = '';
  143. foreach ($ret as $product) {
  144. ;
  145. $order_numbers = (isset($product['order_numbers'])) ? ' (' . implode(', ', array_unique($product['order_numbers'])) . ')' : '';
  146. $s .= '<div>' . $product['name'] . ' - ' . $product['count'] . $order_numbers . '</div>';
  147. }
  148. return Attribute::make(
  149. get: fn($value) => (string) $s,
  150. );
  151. }
  152. }