1+ <?php
2+
3+ namespace App \Http \Controllers \Api ;
4+
5+ use App \Http \Controllers \Controller ;
6+ use App \Models \Order ;
7+ use Illuminate \Http \Request ;
8+ use Illuminate \Http \JsonResponse ;
9+
10+ class AdminOrderController extends Controller
11+ {
12+ /**
13+ * Display a listing of all orders (admin only).
14+ */
15+ public function index (Request $ request ): JsonResponse
16+ {
17+ try {
18+ $ query = Order::with (['user ' , 'items.productVariant.product ' , 'payments ' , 'shipments ' ]);
19+
20+ // Filter by user
21+ if ($ request ->has ('user_id ' )) {
22+ $ query ->where ('user_id ' , $ request ->user_id );
23+ }
24+
25+ // Filter by status
26+ if ($ request ->has ('status ' )) {
27+ $ query ->where ('status ' , $ request ->status );
28+ }
29+
30+ // Filter by payment status
31+ if ($ request ->has ('payment_status ' )) {
32+ $ query ->where ('payment_status ' , $ request ->payment_status );
33+ }
34+
35+ // Filter by shipping status
36+ if ($ request ->has ('shipping_status ' )) {
37+ $ query ->where ('shipping_status ' , $ request ->shipping_status );
38+ }
39+
40+ // Filter by date range
41+ if ($ request ->has ('date_from ' )) {
42+ $ query ->where ('created_at ' , '>= ' , $ request ->date_from );
43+ }
44+
45+ if ($ request ->has ('date_to ' )) {
46+ $ query ->where ('created_at ' , '<= ' , $ request ->date_to );
47+ }
48+
49+ // Search by order number
50+ if ($ request ->has ('search ' )) {
51+ $ search = $ request ->search ;
52+ $ query ->where ('order_number ' , 'like ' , "% {$ search }% " );
53+ }
54+
55+ // Sorting
56+ $ sortBy = $ request ->get ('sort_by ' , 'created_at ' );
57+ $ sortDirection = $ request ->get ('sort_direction ' , 'desc ' );
58+
59+ switch ($ sortBy ) {
60+ case 'total_amount ' :
61+ $ query ->orderBy ('total_amount ' , $ sortDirection );
62+ break ;
63+ case 'status ' :
64+ $ query ->orderBy ('status ' , $ sortDirection );
65+ break ;
66+ case 'user_id ' :
67+ $ query ->orderBy ('user_id ' , $ sortDirection );
68+ break ;
69+ case 'created_at ' :
70+ default :
71+ $ query ->orderBy ('created_at ' , $ sortDirection );
72+ break ;
73+ }
74+
75+ $ perPage = min ($ request ->get ('per_page ' , 15 ), 100 );
76+ $ orders = $ query ->paginate ($ perPage );
77+
78+ return response ()->json ([
79+ 'success ' => true ,
80+ 'data ' => $ orders ,
81+ 'message ' => 'Orders retrieved successfully '
82+ ]);
83+
84+ } catch (\Exception $ e ) {
85+ return response ()->json ([
86+ 'success ' => false ,
87+ 'message ' => 'Failed to retrieve orders ' ,
88+ 'error ' => $ e ->getMessage ()
89+ ], 500 );
90+ }
91+ }
92+
93+ /**
94+ * Display the specified order (admin only).
95+ */
96+ public function show (Order $ order ): JsonResponse
97+ {
98+ try {
99+ $ order ->load (['user ' , 'items.productVariant.product ' , 'payments ' , 'shipments ' , 'billingAddress ' , 'shippingAddress ' ]);
100+
101+ return response ()->json ([
102+ 'success ' => true ,
103+ 'data ' => $ order ,
104+ 'message ' => 'Order retrieved successfully '
105+ ]);
106+
107+ } catch (\Exception $ e ) {
108+ return response ()->json ([
109+ 'success ' => false ,
110+ 'message ' => 'Failed to retrieve order ' ,
111+ 'error ' => $ e ->getMessage ()
112+ ], 500 );
113+ }
114+ }
115+
116+ /**
117+ * Update order status (admin only).
118+ */
119+ public function updateStatus (Request $ request , Order $ order ): JsonResponse
120+ {
121+ try {
122+ $ validated = $ request ->validate ([
123+ 'status ' => 'required|in:pending,paid,processing,shipped,delivered,cancelled ' ,
124+ 'notify_customer ' => 'boolean ' ,
125+ ]);
126+
127+ $ oldStatus = $ order ->status ;
128+ $ order ->status = $ validated ['status ' ];
129+ $ order ->save ();
130+
131+ // Update related statuses based on new status
132+ switch ($ validated ['status ' ]) {
133+ case 'paid ' :
134+ $ order ->markAsPaid ();
135+ break ;
136+ case 'shipped ' :
137+ $ order ->markAsShipped ();
138+ break ;
139+ case 'delivered ' :
140+ $ order ->markAsDelivered ();
141+ break ;
142+ case 'cancelled ' :
143+ $ order ->cancel ();
144+ break ;
145+ }
146+
147+ // TODO: Send email notification if notify_customer is true
148+
149+ return response ()->json ([
150+ 'success ' => true ,
151+ 'data ' => $ order ->fresh ()->load (['user ' , 'items.productVariant.product ' ]),
152+ 'message ' => 'Order status updated successfully ' ,
153+ 'previous_status ' => $ oldStatus ,
154+ 'new_status ' => $ order ->status
155+ ]);
156+
157+ } catch (\Illuminate \Validation \ValidationException $ e ) {
158+ return response ()->json ([
159+ 'success ' => false ,
160+ 'message ' => 'Validation failed ' ,
161+ 'errors ' => $ e ->errors ()
162+ ], 422 );
163+
164+ } catch (\Exception $ e ) {
165+ return response ()->json ([
166+ 'success ' => false ,
167+ 'message ' => 'Failed to update order status ' ,
168+ 'error ' => $ e ->getMessage ()
169+ ], 500 );
170+ }
171+ }
172+
173+ /**
174+ * Get order statistics (admin only).
175+ */
176+ public function stats (Request $ request ): JsonResponse
177+ {
178+ try {
179+ $ query = Order::query ();
180+
181+ // Filter by date range
182+ if ($ request ->has ('date_from ' )) {
183+ $ query ->where ('created_at ' , '>= ' , $ request ->date_from );
184+ }
185+
186+ if ($ request ->has ('date_to ' )) {
187+ $ query ->where ('created_at ' , '<= ' , $ request ->date_to );
188+ }
189+
190+ $ stats = [
191+ 'total_orders ' => (clone $ query )->count (),
192+ 'total_revenue ' => (clone $ query )->sum ('total_amount ' ),
193+ 'pending_orders ' => (clone $ query )->where ('status ' , 'pending ' )->count (),
194+ 'paid_orders ' => (clone $ query )->where ('status ' , 'paid ' )->count (),
195+ 'shipped_orders ' => (clone $ query )->where ('status ' , 'shipped ' )->count (),
196+ 'delivered_orders ' => (clone $ query )->where ('status ' , 'delivered ' )->count (),
197+ 'cancelled_orders ' => (clone $ query )->where ('status ' , 'cancelled ' )->count (),
198+ 'average_order_value ' => (clone $ query )->where ('status ' , 'delivered ' )->avg ('total_amount ' ),
199+ ];
200+
201+ return response ()->json ([
202+ 'success ' => true ,
203+ 'data ' => $ stats ,
204+ 'message ' => 'Order statistics retrieved successfully '
205+ ]);
206+
207+ } catch (\Exception $ e ) {
208+ return response ()->json ([
209+ 'success ' => false ,
210+ 'message ' => 'Failed to retrieve order statistics ' ,
211+ 'error ' => $ e ->getMessage ()
212+ ], 500 );
213+ }
214+ }
215+
216+ /**
217+ * Process refund for an order (admin only).
218+ */
219+ public function refund (Request $ request , Order $ order ): JsonResponse
220+ {
221+ try {
222+ $ validated = $ request ->validate ([
223+ 'amount ' => 'nullable|numeric|min:0 ' ,
224+ 'reason ' => 'required|string|max:255 ' ,
225+ ]);
226+
227+ $ user = auth ()->user ();
228+
229+ // Check if order can be refunded
230+ if (!in_array ($ order ->status , ['paid ' , 'shipped ' , 'delivered ' ])) {
231+ return response ()->json ([
232+ 'success ' => false ,
233+ 'message ' => 'Order cannot be refunded in its current status '
234+ ], 422 );
235+ }
236+
237+ // Get the payment
238+ $ payment = $ order ->payments ()->where ('status ' , 'succeeded ' )->first ();
239+ if (!$ payment ) {
240+ return response ()->json ([
241+ 'success ' => false ,
242+ 'message ' => 'No successful payment found for this order '
243+ ], 404 );
244+ }
245+
246+ // TODO: Process refund via Stripe
247+ // For now, we'll just update the order status
248+
249+ return response ()->json ([
250+ 'success ' => true ,
251+ 'data ' => $ order ->fresh (),
252+ 'message ' => 'Refund processed successfully '
253+ ]);
254+
255+ } catch (\Illuminate \Validation \ValidationException $ e ) {
256+ return response ()->json ([
257+ 'success ' => false ,
258+ 'message ' => 'Validation failed ' ,
259+ 'errors ' => $ e ->errors ()
260+ ], 422 );
261+
262+ } catch (\Exception $ e ) {
263+ return response ()->json ([
264+ 'success ' => false ,
265+ 'message ' => 'Failed to process refund ' ,
266+ 'error ' => $ e ->getMessage ()
267+ ], 500 );
268+ }
269+ }
270+ }
0 commit comments