178 lines
6.0 KiB
PHP
178 lines
6.0 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Enums\Market\ProductTransactionType;
|
|
use App\Enums\Market\TransactionFlow;
|
|
use App\Enums\UserTypes;
|
|
use App\Http\Controllers\Helpers\ResponseHelper;
|
|
use App\Models\GlobalTransaction;
|
|
use App\Models\Market\Product;
|
|
use App\Models\Market\Store;
|
|
use Hypervel\Http\Request;
|
|
use Hypervel\Support\Facades\Auth;
|
|
use Hypervel\Support\Facades\Validator;
|
|
use App\Http\Controllers\Helpers\UserController;
|
|
use App\Http\Controllers\Helpers\Permissions\UserPermissions;
|
|
use App\Enums\UserActions;
|
|
|
|
class GlobalTransactionController
|
|
{
|
|
/**
|
|
* List transactions with optional filtering.
|
|
* Handles POST /admin/transactions/list
|
|
*/
|
|
public function list(Request $request)
|
|
{
|
|
if (!UserPermissions::isActionPermitted(Auth::user()->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);
|
|
}
|
|
}
|