PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.4
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.4
1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk 1.2.0 All 47 releases
fluent-cart / app / Models / OrderItem.php

OrderItem.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.4, at app/Models/OrderItem.php

271 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Models;
4
5 use FluentCart\App\Helpers\Helper;
6 use FluentCart\App\Helpers\OrderItemHelper;
7 use FluentCart\App\Models\Concerns\CanSearch;
8 use FluentCart\App\Models\Concerns\CanUpdateBatch;
9 use FluentCart\App\Models\WpModels\PostMeta;
10 use FluentCart\Framework\Database\Orm\Relations\HasOne;
11 use FluentCart\Framework\Support\Arr;
12
13 /**
14 * OrderItem Model - DB Model for Order Items
15 *
16 * Database Model
17 *
18 * @package FluentCart\App\Models
19 *
20 * @version 1.0.0
21 */
22 class OrderItem extends Model
23 {
24 use CanSearch, CanUpdateBatch;
25
26 protected $table = 'fct_order_items';
27
28 /**
29 * The attributes that are mass assignable.
30 *
31 * @var array
32 */
33 protected $fillable = [
34 'order_id',
35 'post_id',
36 'fulfillment_type',
37 'fulfilled_quantity',
38 'post_title',
39 'title',
40 'object_id',
41 'cart_index',
42 'quantity',
43 'unit_price',
44 'cost',
45 'subtotal',
46 'tax_amount',
47 'discount_total',
48 'refund_total',
49 'line_total',
50 'rate',
51 'other_info',
52 'line_meta',
53 'referrer',
54 'object_type',
55 'payment_type',
56 'created_at',
57 // 'shipping_charge'
58 ];
59 protected $appends = ['payment_info', 'setup_info', 'is_custom', 'variation_display_title'];
60
61 protected $casts = [
62 'unit_price' => 'double',
63 'cost' => 'double',
64 'subtotal' => 'double',
65 'tax_amount' => 'double',
66 'shipping_charge' => 'double',
67 'discount_total' => 'double',
68 'line_total' => 'double',
69 'refund_total' => 'double',
70 ];
71
72 protected static function booted()
73 {
74 static::retrieved(function ($product) {
75 $product->append('formatted_total');
76 });
77 }
78
79 protected function getFormattedTotalAttribute()
80 {
81 if ($this->line_total == 0 && $this->discount_total == 0) {
82 return Helper::toDecimal($this->subtotal);
83 }
84 return Helper::toDecimal($this->line_total);
85 }
86
87 public function getCouponDiscountAttribute()
88 {
89 return (int)($this->line_meta['coupon_discount'] ?? 0);
90 }
91
92 public function setOtherInfoAttribute($value)
93 {
94 if (is_array($value) || is_object($value)) {
95 $this->attributes['other_info'] = json_encode($value);
96 } else {
97 $this->attributes['other_info'] = $value;
98 }
99 }
100
101 public function getOtherInfoAttribute($value)
102 {
103 if (is_string($value)) {
104 $decoded = json_decode($value, true);
105 return is_array($decoded) ? $decoded : [];
106 }
107
108 return [];
109 }
110
111 public function setLineMetaAttribute($value)
112 {
113 if (is_array($value) || is_object($value)) {
114 $this->attributes['line_meta'] = json_encode($value);
115 } else {
116 $this->attributes['line_meta'] = [];
117 }
118 }
119
120 public function getLineMetaAttribute($value)
121 {
122 if (is_string($value)) {
123 $decoded = json_decode($value, true);
124 if ($decoded) {
125 return $decoded;
126 }
127 }
128
129 return [];
130 }
131
132 public function getFullNameAttribute($value)
133 {
134 return $this->title . ' ' . $this->post_title;
135 }
136
137 public function order()
138 {
139 return $this->belongsTo(Order::class, 'order_id', 'id');
140 }
141
142 public function product()
143
144 {
145 return $this->belongsTo(Product::class, 'post_id', 'ID');
146 }
147
148
149 public function variants()
150 {
151 return $this->belongsTo(ProductVariation::class, 'object_id', 'id');
152 }
153
154 public function product_downloads()
155 {
156 return $this->belongsTo(ProductDownload::class, 'post_id', 'post_id');
157 }
158
159 public function createItem($orderItems)
160 {
161 return $this->belongsTo(ProductVariation::class, 'variation_id', 'id');
162 }
163
164 public function processCustom($product, $orderId)
165 {
166 return (new OrderItemHelper())->processCustom($product, $orderId);
167 }
168
169 /**
170 * Get subscription payment info if available
171 *
172 * @return string
173 */
174 public function getPaymentInfoAttribute(): string
175 {
176 return $this->getSubscriptionInfo('payment');
177 }
178
179 /**
180 * Get subscription setup info if available
181 *
182 * @return string
183 */
184 public function getSetupInfoAttribute(): string
185 {
186 return $this->getSubscriptionInfo('setup');
187 }
188
189 /**
190 * Helper method to get subscription info
191 *
192 * @param string $type 'payment' or 'setup'
193 * @return string
194 */
195
196 private function getSubscriptionInfo(string $type): string
197 {
198 if ($this->payment_type !== 'subscription') {
199 return '';
200 }
201
202 $otherInfo = $this->other_info ?? [];
203 $unitPrice = $this->unit_price ?? 0;
204
205 if ($type === 'payment') {
206 return Helper::generateSubscriptionInfo($otherInfo, $unitPrice) ?? '';
207 }
208
209 if ($type === 'setup') {
210 return Helper::generateSetupFeeInfo($otherInfo) ?? '';
211 }
212
213 return '';
214 }
215
216 public function productImage(): HasOne
217 {
218 return $this->hasOne(PostMeta::class, 'post_id', 'post_id')
219 ->where('postmeta.meta_key', 'fluent-products-gallery-image');
220 }
221
222 public function variantImages(): HasOne
223 {
224 return $this->hasOne(ProductMeta::class, 'object_id', 'object_id')
225 ->where('object_type', 'product_variant_info')
226 ->where('meta_key', 'product_thumbnail');
227 }
228
229 public function getIsCustomAttribute()
230 {
231 return $this->other_info['is_custom'] ?? false;
232 }
233
234 public function getViewUrlAttribute()
235 {
236 return $this->is_custom
237 ? ($this->other_info['view_url'] ?? '')
238 : '';
239 }
240
241 public function getDisplayTitle()
242 {
243 if ($this->post_title == $this->title) {
244 return $this->title;
245 }
246
247 return $this->post_title . ' - ' . $this->title;
248
249 }
250
251 /**
252 * Labeled attribute combination resolved from the frozen
253 * other_info['item_attributes'] snapshot, e.g. "Color: Red | Size: XS".
254 * Falls back to the stored variation title when no attribute snapshot
255 * resolves (custom/simple items, or attrs whose groups were removed).
256 *
257 * @return string
258 */
259 public function getVariationDisplayTitleAttribute()
260 {
261 // Order items carry the item_attributes snapshot (written at order
262 // creation), so resolve directly — getDisplayAttributesString renders
263 // the labeled combination and falls back to the variation title.
264 return \FluentCart\App\Helpers\AttributeHelper::getDisplayAttributesString(
265 Arr::get($this->other_info, 'item_attributes', []),
266 $this,
267 'order_item'
268 );
269 }
270 }
271