| @@ -2,9 +2,11 @@ | ||
| 2 | 2 | |
| 3 | 3 | namespace FluentCart\Api\Resource; |
| 4 | 4 | |
| 5 | 5 | use FluentCart\App\App; |
| 6 | +use FluentCart\App\Helpers\AttributeHelper; | |
| 6 | 7 | use FluentCart\App\Models\OrderItem; |
| 8 | +use FluentCart\App\Models\ProductVariation; | |
| 7 | 9 | use FluentCart\Framework\Database\Orm\Builder; |
| 8 | 10 | use FluentCart\Framework\Support\Arr; |
| 9 | 11 | use FluentCart\Framework\Support\Collection; |
| 10 | 12 | use FluentCart\Framework\Support\DateTime; |
| @@ -226,19 +228,38 @@ | ||
| 226 | 228 | $isExist = !empty($orderItem); |
| 227 | 229 | |
| 228 | 230 | $itemData = Arr::only($item, ['id', 'title', 'post_id', 'object_id', 'post_title', 'quantity', 'unit_price', 'cost', 'tax_amount', 'discount_total', 'line_total']); |
| 229 | 231 | $itemData['subtotal'] = Arr::get($item, 'quantity', 0) * Arr::get($item, 'unit_price', 0); |
| 230 | - $itemData['line_total'] = $itemData['subtotal'] - Arr::get($item, 'discount_total', 0) + Arr::get($item, 'tax_amount', 0); | |
| 232 | + $itemData['line_total'] = $itemData['subtotal'] - Arr::get($item, 'discount_total', 0); | |
| 231 | 233 | $fulfillment_type = Arr::get($item, 'fulfillment_type', 'physical'); |
| 232 | 234 | |
| 233 | 235 | |
| 234 | 236 | if (empty($isExist)) { |
| 235 | 237 | unset($itemData['id']); |
| 238 | + | |
| 239 | + // Snapshot the variant's attribute map + variation type into | |
| 240 | + // other_info so items added on order-edit carry the same data as | |
| 241 | + // the create path (AdminOrderProcessor), not just what the picker sent. | |
| 242 | + $otherInfo = Arr::get($item, 'other_info', []); | |
| 243 | + if (!is_array($otherInfo)) { | |
| 244 | + $otherInfo = []; | |
| 245 | + } | |
| 246 | + if (!array_key_exists('item_attributes', $otherInfo)) { | |
| 247 | + $otherInfo['item_attributes'] = AttributeHelper::getProductItemAttributes($variationId, $productId); | |
| 248 | + } | |
| 249 | + if (empty($otherInfo['variation_type'])) { | |
| 250 | + // Resolve server-side from the variation (same as the create | |
| 251 | + // path) — admin orders don't go through the cart, so the snapshot | |
| 252 | + // is the server's responsibility, not the request's. | |
| 253 | + $variation = ProductVariation::query()->with('product_detail')->find($variationId); | |
| 254 | + $otherInfo['variation_type'] = ($variation && $variation->product_detail) ? (string) $variation->product_detail->variation_type : ''; | |
| 255 | + } | |
| 256 | + | |
| 236 | 257 | $item = wp_parse_args([ |
| 237 | 258 | 'order_id' => $id, |
| 238 | 259 | 'cart_index' => $idx + 1, |
| 239 | 260 | 'fulfillment_type' => $fulfillment_type, |
| 240 | - 'other_info' => json_encode(Arr::get($item, 'other_info', [])), | |
| 261 | + 'other_info' => json_encode($otherInfo), | |
| 241 | 262 | 'payment_type' => Arr::get($item, 'payment_type', Arr::get($item, 'other_info.payment_type', '')), |
| 242 | 263 | 'shipping_charge' => Arr::get($item, 'shipping_charge', 0), |
| 243 | 264 | 'created_at' => DateTime::now(), |
| 244 | 265 | 'updated_at' => DateTime::now(), |
| @@ -247,8 +268,13 @@ | ||
| 247 | 268 | $newItems[] = $item; |
| 248 | 269 | } else { |
| 249 | 270 | $existingData = Arr::only($itemData, ['id', 'quantity', 'unit_price', 'cost', 'subtotal', 'tax_amount', 'discount_total', 'line_total', 'shipping_charge']) + ['updated_at' => DateTime::now()]; |
| 250 | 271 | $existingData['fulfilled_quantity'] = $fulfillment_type === 'physical' ? Arr::get($item, 'fulfilled_quantity', 0) : Arr::get($item, 'quantity', 0); |
| 272 | + $incomingLineMeta = Arr::get($item, 'line_meta'); | |
| 273 | + if (is_array($incomingLineMeta) && array_key_exists('coupon_discount', $incomingLineMeta)) { | |
| 274 | + $incomingLineMeta['coupon_discount'] = (int) $incomingLineMeta['coupon_discount']; | |
| 275 | + $existingData['line_meta'] = json_encode($incomingLineMeta); | |
| 276 | + } | |
| 251 | 277 | $existingItems[] = $existingData; |
| 252 | 278 | } |
| 253 | 279 | } |
| 254 | 280 | else if(isset($productId) && isset($variationId) && $isCustom){ |
| @@ -310,8 +336,10 @@ | ||
| 310 | 336 | * |
| 311 | 337 | */ |
| 312 | 338 | public static function topProductsSold($params = []) |
| 313 | 339 | { |
| 340 | + $params = is_array($params) ? $params : []; | |
| 341 | + | |
| 314 | 342 | return OrderItem::search(Arr::only($params, ['created_at'])) |
| 315 | 343 | ->select('post_id') |
| 316 | 344 | ->selectRaw('SUM(quantity) as total_sold') |
| 317 | 345 | ->groupBy('post_id') |