feat(server): evaluate price alerts per product and fix gold discharge rounding

Alerts now bind to a product_id and share one evaluator; displayed gold within a rounding step discharges the full wallet.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-18 22:23:20 +03:30
co-authored by Cursor
parent 341b2da2c9
commit b0296c6e94
10 changed files with 454 additions and 55 deletions
@@ -13,6 +13,9 @@ class PriceTriggerController extends Controller
public function table(Request $request)
{
$query = PriceTrigger::query()->with('customer');
if (PriceTrigger::hasProductIdColumn()) {
$query->with('product:id,title');
}
TableEngine::create($query, $request->all())
->initSearch(['customer_id', 'target_price', 'action', 'price_condition'])
@@ -31,7 +34,12 @@ class PriceTriggerController extends Controller
'is_active' => $data['is_active'] ?? true,
]);
return response()->json($trigger->load('customer'), 201);
$relations = ['customer'];
if (PriceTrigger::hasProductIdColumn()) {
$relations[] = 'product:id,title';
}
return response()->json($trigger->load($relations), 201);
}
public function update(Request $request, int $id)
@@ -71,12 +79,17 @@ class PriceTriggerController extends Controller
{
$rules = [
'customer_id' => ($partial ? 'sometimes|' : '') . 'required|integer|exists:customers,id',
'product_id' => ($partial ? 'sometimes|' : '') . 'required|integer|exists:products,id',
'target_price' => ($partial ? 'sometimes|' : '') . 'required|numeric|min:1',
'price_condition' => ($partial ? 'sometimes|' : '') . 'required|in:>,<',
'action' => ($partial ? 'sometimes|' : '') . 'required|in:sms,email',
'is_active' => 'sometimes|boolean',
];
if (! PriceTrigger::hasProductIdColumn()) {
unset($rules['product_id']);
}
$data = $request->validate($rules);
if (isset($data['price_condition']) && !in_array($data['price_condition'], ['>', '<'], true)) {