From b6c71426773ab05ba8975f4335d07775d3b62bd2 Mon Sep 17 00:00:00 2001 From: sky121113 Date: Fri, 5 Jun 2026 21:56:41 +0800 Subject: [PATCH] =?UTF-8?q?[FIX]=20=E4=BF=AE=E6=AD=A3=E5=95=86=E5=93=81?= =?UTF-8?q?=E8=88=87=E6=A9=9F=E5=8F=B0=E5=A0=B1=E8=A1=A8=E5=9B=A0=20order?= =?UTF-8?q?=5Fitems=20=E8=88=87=20dispense=5Frecords=20=E8=81=AF=E7=B5=90?= =?UTF-8?q?=E7=94=A2=E7=94=9F=E7=AC=9B=E5=8D=A1=E7=88=BE=E7=A9=8D=E5=B0=8E?= =?UTF-8?q?=E8=87=B4=E4=BB=B6=E6=95=B8=E9=87=8D=E8=A4=87=E5=8A=A0=E7=B8=BD?= =?UTF-8?q?=E7=9A=84=E5=95=8F=E9=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/Admin/AnalysisController.php | 102 +++++++++++------- 1 file changed, 63 insertions(+), 39 deletions(-) diff --git a/app/Http/Controllers/Admin/AnalysisController.php b/app/Http/Controllers/Admin/AnalysisController.php index d4ce8ce..9bd1ee0 100644 --- a/app/Http/Controllers/Admin/AnalysisController.php +++ b/app/Http/Controllers/Admin/AnalysisController.php @@ -99,6 +99,15 @@ class AnalysisController extends Controller 42 => __('Pickup Voucher'), ]; + // 子查詢:取得每個 order_id + product_id 的銷售單價 + $itemPriceQuery = \Illuminate\Support\Facades\DB::table('order_items') + ->select([ + 'order_id', + 'product_id', + \Illuminate\Support\Facades\DB::raw('MIN(price) as unit_price') + ]) + ->groupBy('order_id', 'product_id'); + // 6. 執行主報表統計 SQL (按機台分組) // 子查詢 A:營業額 (計算機台實收) $salesQuery = \Illuminate\Support\Facades\DB::table('orders as o') @@ -130,16 +139,18 @@ class AnalysisController extends Controller // 如果篩選特定商品,營業額只計算有成功出貨的該商品金額 if ($selectedProductId && $selectedProductId !== 'ALL') { - $salesQuery->join('order_items as oi', 'oi.order_id', '=', 'o.id') - ->leftJoin('dispense_records as dr', function($join) { - $join->on('dr.order_id', '=', 'oi.order_id') - ->on('dr.product_id', '=', 'oi.product_id') + $salesQuery->join('dispense_records as dr', function($join) { + $join->on('dr.order_id', '=', 'o.id') ->where('dr.dispense_status', '=', 1); }) - ->where('oi.product_id', $selectedProductId) + ->leftJoinSub($itemPriceQuery, 'oi', function($join) { + $join->on('oi.order_id', '=', 'dr.order_id') + ->on('oi.product_id', '=', 'dr.product_id'); + }) + ->where('dr.product_id', $selectedProductId) ->select([ 'o.machine_id', - \Illuminate\Support\Facades\DB::raw('SUM(CASE WHEN dr.id IS NOT NULL THEN oi.subtotal ELSE 0 END) as total_sales') + \Illuminate\Support\Facades\DB::raw('SUM(COALESCE(oi.unit_price, 0)) as total_sales') ]); } $salesQuery->groupBy('o.machine_id'); @@ -269,16 +280,18 @@ class AnalysisController extends Controller // 如果篩選特定商品,營業額只計算有成功出貨的商品價格 if ($selectedProductId && $selectedProductId !== 'ALL') { - $trendSalesQuery->join('order_items as oi', 'oi.order_id', '=', 'o.id') - ->leftJoin('dispense_records as dr', function($join) { - $join->on('dr.order_id', '=', 'oi.order_id') - ->on('dr.product_id', '=', 'oi.product_id') + $trendSalesQuery->join('dispense_records as dr', function($join) { + $join->on('dr.order_id', '=', 'o.id') ->where('dr.dispense_status', '=', 1); }) - ->where('oi.product_id', $selectedProductId) + ->leftJoinSub($itemPriceQuery, 'oi', function($join) { + $join->on('oi.order_id', '=', 'dr.order_id') + ->on('oi.product_id', '=', 'dr.product_id'); + }) + ->where('dr.product_id', $selectedProductId) ->select([ \Illuminate\Support\Facades\DB::raw("DATE_FORMAT(o.created_at, '%Y-%m-%d') as date"), - \Illuminate\Support\Facades\DB::raw('SUM(CASE WHEN dr.id IS NOT NULL THEN oi.subtotal ELSE 0 END) as total_sales') + \Illuminate\Support\Facades\DB::raw('SUM(COALESCE(oi.unit_price, 0)) as total_sales') ]); } $trendSalesQuery->groupBy('date'); @@ -449,24 +462,35 @@ class AnalysisController extends Controller $products = $productsQuery->active()->get(['id', 'name', 'barcode']); // 5. 執行主報表統計 SQL - // 計算各商品的銷售數量、銷售額、總成本、利潤 - $mainQuery = \Illuminate\Support\Facades\DB::table('order_items as oi') - ->join('orders as o', 'o.id', '=', 'oi.order_id') - ->leftJoin('dispense_records as dr', function($join) { - $join->on('dr.order_id', '=', 'oi.order_id') - ->on('dr.product_id', '=', 'oi.product_id') - ->where('dr.dispense_status', '=', 1); - }) - ->leftJoin('products as p', 'p.id', '=', 'oi.product_id') + // 子查詢:取得每個 order_id + product_id 的銷售單價與品名 + $itemPriceQuery = \Illuminate\Support\Facades\DB::table('order_items') ->select([ - 'oi.product_id', + 'order_id', + 'product_id', + \Illuminate\Support\Facades\DB::raw('MIN(price) as unit_price'), + \Illuminate\Support\Facades\DB::raw('MIN(barcode) as barcode'), + \Illuminate\Support\Facades\DB::raw('MIN(product_name) as product_name') + ]) + ->groupBy('order_id', 'product_id'); + + // 計算各商品的銷售數量、銷售額、總成本、利潤 (以出貨成功為主體) + $mainQuery = \Illuminate\Support\Facades\DB::table('dispense_records as dr') + ->join('orders as o', 'o.id', '=', 'dr.order_id') + ->leftJoinSub($itemPriceQuery, 'oi', function($join) { + $join->on('oi.order_id', '=', 'dr.order_id') + ->on('oi.product_id', '=', 'dr.product_id'); + }) + ->leftJoin('products as p', 'p.id', '=', 'dr.product_id') + ->select([ + 'dr.product_id', \Illuminate\Support\Facades\DB::raw('COALESCE(p.barcode, oi.barcode) as barcode'), \Illuminate\Support\Facades\DB::raw('COALESCE(p.name, oi.product_name) as name'), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN 1 ELSE 0 END) as SIGNED) as total_quantity'), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN oi.price ELSE 0 END) as DECIMAL(10,2)) as total_sales'), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN COALESCE(p.cost, 0) ELSE 0 END) as DECIMAL(10,2)) as total_cost'), - \Illuminate\Support\Facades\DB::raw('CAST((SUM(CASE WHEN dr.id IS NOT NULL THEN oi.price ELSE 0 END) - SUM(CASE WHEN dr.id IS NOT NULL THEN COALESCE(p.cost, 0) ELSE 0 END)) as DECIMAL(10,2)) as total_profit') + \Illuminate\Support\Facades\DB::raw('CAST(COUNT(dr.id) as SIGNED) as total_quantity'), + \Illuminate\Support\Facades\DB::raw('CAST(SUM(COALESCE(oi.unit_price, 0)) as DECIMAL(10,2)) as total_sales'), + \Illuminate\Support\Facades\DB::raw('CAST(SUM(COALESCE(p.cost, 0)) as DECIMAL(10,2)) as total_cost'), + \Illuminate\Support\Facades\DB::raw('CAST((SUM(COALESCE(oi.unit_price, 0)) - SUM(COALESCE(p.cost, 0))) as DECIMAL(10,2)) as total_profit') ]) + ->where('dr.dispense_status', 1) ->where('o.payment_status', \App\Models\Transaction\Order::PAYMENT_STATUS_SUCCESS) ->whereNull('o.deleted_at') ->whereBetween('o.created_at', [$startDate, $endDate]); @@ -492,10 +516,10 @@ class AnalysisController extends Controller // 套用特定商品篩選 if ($selectedProductId && $selectedProductId !== 'ALL') { - $mainQuery->where('oi.product_id', $selectedProductId); + $mainQuery->where('dr.product_id', $selectedProductId); } - $mainQuery->groupBy('oi.product_id') + $mainQuery->groupBy('dr.product_id') ->groupBy(\Illuminate\Support\Facades\DB::raw('COALESCE(p.barcode, oi.barcode)')) ->groupBy(\Illuminate\Support\Facades\DB::raw('COALESCE(p.name, oi.product_name)')); $tableData = $mainQuery->get(); @@ -526,20 +550,20 @@ class AnalysisController extends Controller ]; // 7. 圖表日走勢統計 SQL - $trendQuery = \Illuminate\Support\Facades\DB::table('order_items as oi') - ->join('orders as o', 'o.id', '=', 'oi.order_id') - ->leftJoin('dispense_records as dr', function($join) { - $join->on('dr.order_id', '=', 'oi.order_id') - ->on('dr.product_id', '=', 'oi.product_id') - ->where('dr.dispense_status', '=', 1); + $trendQuery = \Illuminate\Support\Facades\DB::table('dispense_records as dr') + ->join('orders as o', 'o.id', '=', 'dr.order_id') + ->leftJoinSub($itemPriceQuery, 'oi', function($join) { + $join->on('oi.order_id', '=', 'dr.order_id') + ->on('oi.product_id', '=', 'dr.product_id'); }) - ->leftJoin('products as p', 'p.id', '=', 'oi.product_id') + ->leftJoin('products as p', 'p.id', '=', 'dr.product_id') ->select([ \Illuminate\Support\Facades\DB::raw("DATE_FORMAT(o.created_at, '%Y-%m-%d') as date"), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN 1 ELSE 0 END) as SIGNED) as total_quantity'), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN oi.price ELSE 0 END) as DECIMAL(10,2)) as total_sales'), - \Illuminate\Support\Facades\DB::raw('CAST(SUM(CASE WHEN dr.id IS NOT NULL THEN COALESCE(p.cost, 0) ELSE 0 END) as DECIMAL(10,2)) as total_cost') + \Illuminate\Support\Facades\DB::raw('CAST(COUNT(dr.id) as SIGNED) as total_quantity'), + \Illuminate\Support\Facades\DB::raw('CAST(SUM(COALESCE(oi.unit_price, 0)) as DECIMAL(10,2)) as total_sales'), + \Illuminate\Support\Facades\DB::raw('CAST(SUM(COALESCE(p.cost, 0)) as DECIMAL(10,2)) as total_cost') ]) + ->where('dr.dispense_status', 1) ->where('o.payment_status', \App\Models\Transaction\Order::PAYMENT_STATUS_SUCCESS) ->whereNull('o.deleted_at') ->whereBetween('o.created_at', [$startDate, $endDate]); @@ -561,7 +585,7 @@ class AnalysisController extends Controller } if ($selectedProductId && $selectedProductId !== 'ALL') { - $trendQuery->where('oi.product_id', $selectedProductId); + $trendQuery->where('dr.product_id', $selectedProductId); } $trendQuery->groupBy('date')->orderBy('date', 'asc');