acct_type, UserActions::ViewGlobalTransactions)) { return ResponseHelper::returnUnauthorized(); } $user = Auth::user(); $productIdHash = $request->input('product_id'); $storeIdHash = $request->input('store_id'); $query = GlobalTransaction::with(['user:id,name,hashkey', 'product:id,name,hashkey', 'store:id,name,hashkey']); if ($productIdHash) { $product = Product::where('hashkey', $productIdHash)->first(); if ($product) { $query->where('product_id', $product->id); } else { return response()->json([]); } } if ($storeIdHash) { $store = Store::where('hashkey', $storeIdHash)->first(); if ($store) { $query->where('store_id', $store->id); } } // Access Control: Ultimate can see everything. // Others see transactions they created or relate to them. if ($user->acct_type !== UserTypes::ULTIMATE) { $query->where(function($q) use ($user) { $q->where('user_id', $user->id) ->orWhere('created_by', $user->id); }); } $transactions = $query->orderBy('created_at', 'desc')->get(); // Transform for frontend $transformed = $transactions->map(function ($tx) { return [ 'id' => $tx->id, 'hashkey' => $tx->hashkey, 'amount' => $tx->amount, 'type' => $tx->type ? $tx->type->label() : 'Unknown', 'status' => $tx->status, 'description' => $tx->description, 'created_at' => $tx->created_at, 'flow' => $tx->flow ? [ 'value' => $tx->flow->value, 'label' => match($tx->flow) { TransactionFlow::INCOME => 'Income', TransactionFlow::EXPENSE => 'Expense', TransactionFlow::NEUTRAL => 'Neutral', default => 'Unknown' } ] : null, 'user' => $tx->user ? $tx->user->name : null, 'product' => $tx->product ? $tx->product->name : null, 'store' => $tx->store ? $tx->store->name : null, ]; }); return response()->json($transformed); } /** * Create a new global transaction. * Handles POST /admin/transactions/create */ public function store(Request $request) { if (!UserPermissions::isActionPermitted(Auth::user()->acct_type, UserActions::CreateGlobalTransaction)) { return ResponseHelper::returnUnauthorized(); } $user = Auth::user(); $validator = Validator::make($request->all(), [ 'user_hash' => 'nullable|string', 'amount' => 'required|numeric', 'type' => 'required|integer', 'description' => 'nullable|string', 'product_hash' => 'nullable|string', 'store_hash' => 'nullable|string', 'status' => 'nullable|string', ]); if ($validator->fails()) { return response()->json(['success' => false, 'errors' => $validator->errors()], 422); } $data = $validator->validated(); // Resolve IDs from hashes $targetUserId = $user->id; if (isset($data['user_hash'])) { $targetUser = UserController::findUserIdByHash($data['user_hash']); if ($targetUser) $targetUserId = $targetUser; } $productId = null; if (isset($data['product_hash'])) { $product = Product::where('hashkey', $data['product_hash'])->first(); if ($product) $productId = $product->id; } $storeId = null; if (isset($data['store_hash'])) { $store = Store::where('hashkey', $data['store_hash'])->first(); if ($store) $storeId = $store->id; } /** @var GlobalTransaction $transaction */ $transaction = GlobalTransaction::create([ 'user_id' => $targetUserId, 'amount' => $data['amount'], 'type' => $data['type'], 'description' => $data['description'] ?? '', 'product_id' => $productId, 'store_id' => $storeId, 'status' => $data['status'] ?? 'completed', 'flow' => $request->has('flow') ? $request->input('flow') : ProductTransactionType::from($data['type'])->flow(), 'created_by' => $user->id, ]); return response()->json([ 'success' => true, 'message' => 'Transaction recorded successfully', 'hashkey' => $transaction->hashkey ]); } /** * Get all product transaction types for dropdown selection. */ public function getTypes() { $types = collect(ProductTransactionType::cases())->map(function ($type) { return [ 'value' => $type->value, 'label' => $type->label(), 'flow' => $type->flow()->value, 'flow_label' => $type->flow()->name ]; }); return response()->json($types); } }