From 9769f2ffad886ea5962213e78e26a28c541a6c28 Mon Sep 17 00:00:00 2001 From: safavimohadeseh78 Date: Tue, 3 Nov 2026 13:04:08 +0330 Subject: [PATCH] feat(convert): let customers list and change pending requests History is limited to the signed-in customer. Update and delete only apply while the request is still pending. Co-authored-by: Cursor --- .../CopperConvertRequestController.php | 51 +++++++++ app/Services/CopperConvertRequestService.php | 101 +++++++++++++++--- routes/customer.php | 3 + 3 files changed, 139 insertions(+), 16 deletions(-) diff --git a/app/Http/Controllers/Customer/CopperConvertRequestController.php b/app/Http/Controllers/Customer/CopperConvertRequestController.php index 1c8aa24..1d0673b 100644 --- a/app/Http/Controllers/Customer/CopperConvertRequestController.php +++ b/app/Http/Controllers/Customer/CopperConvertRequestController.php @@ -10,6 +10,16 @@ use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; class CopperConvertRequestController extends Controller { + public function index(CopperConvertRequestService $service) + { + $customer = auth('customer')->user(); + if (!$customer instanceof Customer) { + throw new UnprocessableEntityHttpException('مشتری یافت نشد.'); + } + + return response()->json($service->listForCustomer($customer)); + } + public function store(Request $request, CopperConvertRequestService $service) { $customer = auth('customer')->user(); @@ -35,4 +45,45 @@ class CopperConvertRequestController extends Controller return response()->json($row); } + + public function update(Request $request, int $id, CopperConvertRequestService $service) + { + $customer = $this->customer(); + self::assertCustomerIdentityVerified($customer); + if (!$customer->trade_active) { + throw new UnprocessableEntityHttpException('امکان سفارش برای شما غیرفعال است.'); + } + + $source = (string) $request->input('source'); + if (!in_array($source, ['katod', 'maftoul', 'shamsh'], true)) { + throw new UnprocessableEntityHttpException('نوع دارایی نامعتبر است.'); + } + + $row = $service->update( + $customer, + $id, + $source, + max(0, (int) $request->input('rings15')), + max(0, (int) $request->input('rings25')) + ); + + return response()->json($row); + } + + public function destroy(int $id, CopperConvertRequestService $service) + { + $service->remove($this->customer(), $id); + + return response()->json(['ok' => true]); + } + + private function customer(): Customer + { + $customer = auth('customer')->user(); + if (!$customer instanceof Customer) { + throw new UnprocessableEntityHttpException('مشتری یافت نشد.'); + } + + return $customer; + } } diff --git a/app/Services/CopperConvertRequestService.php b/app/Services/CopperConvertRequestService.php index cb9b1b9..0b89879 100644 --- a/app/Services/CopperConvertRequestService.php +++ b/app/Services/CopperConvertRequestService.php @@ -30,22 +30,32 @@ class CopperConvertRequestService $quote = $this->quote($customer, $source, $rings15, $rings25); - return CopperConvertRequest::query()->create([ - 'customer_id' => $customer->id, - 'status' => 'pending', - 'source' => $source, - 'source_product_id' => $quote['source']->id, - 'asset_unit' => $quote['unit'], - 'consumed_amount' => $quote['consumed'], - 'leftover_amount' => $quote['leftover'], - 'source_unit_price' => $quote['source_unit_price'], - 'wire15_product_id' => $quote['wire15']?->id, - 'wire15_rings' => $rings15, - 'wire15_unit_price' => $quote['price15'], - 'wire25_product_id' => $quote['wire25']?->id, - 'wire25_rings' => $rings25, - 'wire25_unit_price' => $quote['price25'], - ]); + return CopperConvertRequest::query()->create( + $this->quoteAttributes($customer, $source, $rings15, $rings25, $quote) + ); + } + + public function update(Customer $customer, int $id, string $source, int $rings15, int $rings25): CopperConvertRequest + { + if ($rings15 < 1 && $rings25 < 1) { + throw new UnprocessableEntityHttpException('حداقل یک حلقه انتخاب کنید.'); + } + + return DB::transaction(function () use ($customer, $id, $source, $rings15, $rings25) { + $row = $this->ownedPending($customer, $id); + $quote = $this->quote($customer, $source, $rings15, $rings25); + $row->fill($this->quoteAttributes($customer, $source, $rings15, $rings25, $quote)); + $row->save(); + + return $row; + }); + } + + public function remove(Customer $customer, int $id): void + { + DB::transaction(function () use ($customer, $id) { + $this->ownedPending($customer, $id)->delete(); + }); } public function listForAdmin(): array @@ -82,6 +92,29 @@ class CopperConvertRequestService ->all(); } + public function listForCustomer(Customer $customer): array + { + return CopperConvertRequest::query() + ->where('customer_id', $customer->id) + ->orderByDesc('id') + ->limit(50) + ->get() + ->map(function (CopperConvertRequest $row) { + return [ + 'id' => $row->id, + 'status' => $row->status, + 'source' => $row->source, + 'asset_unit' => $row->asset_unit, + 'consumed_amount' => $row->consumed_amount, + 'leftover_amount' => $row->leftover_amount, + 'wire15_rings' => $row->wire15_rings, + 'wire25_rings' => $row->wire25_rings, + 'created_at' => optional($row->created_at)->toDateTimeString(), + ]; + }) + ->all(); + } + public function approve(int $id, int $adminId): CopperConvertRequest { $row = DB::transaction(function () use ($id, $adminId) { @@ -166,6 +199,42 @@ class CopperConvertRequestService } } + private function ownedPending(Customer $customer, int $id): CopperConvertRequest + { + $row = CopperConvertRequest::query() + ->where('customer_id', $customer->id) + ->lockForUpdate() + ->find($id); + if (!$row) { + throw new UnprocessableEntityHttpException('درخواست تبدیل پیدا نشد.'); + } + if ($row->status !== 'pending') { + throw new UnprocessableEntityHttpException('فقط درخواست در انتظار تایید قابل تغییر است.'); + } + + return $row; + } + + private function quoteAttributes(Customer $customer, string $source, int $rings15, int $rings25, array $quote): array + { + return [ + 'customer_id' => $customer->id, + 'status' => 'pending', + 'source' => $source, + 'source_product_id' => $quote['source']->id, + 'asset_unit' => $quote['unit'], + 'consumed_amount' => $quote['consumed'], + 'leftover_amount' => $quote['leftover'], + 'source_unit_price' => $quote['source_unit_price'], + 'wire15_product_id' => $quote['wire15']?->id, + 'wire15_rings' => $rings15, + 'wire15_unit_price' => $quote['price15'], + 'wire25_product_id' => $quote['wire25']?->id, + 'wire25_rings' => $rings25, + 'wire25_unit_price' => $quote['price25'], + ]; + } + private function sourceLabel(string $source): string { if ($source === 'katod') { diff --git a/routes/customer.php b/routes/customer.php index e586c62..e5210da 100644 --- a/routes/customer.php +++ b/routes/customer.php @@ -132,7 +132,10 @@ Route::middleware(['auth:customer', 'customer.active'])->group(function () use ( Route::get('order/pending', [SingleOrderController::class, 'pendingColleague']); Route::get('order/{id}/status', [SingleOrderController::class, 'colleagueStatus']); Route::post('order', [OrderController::class, 'store']); + Route::get('copper-convert-request', [CopperConvertRequestController::class, 'index']); Route::post('copper-convert-request', [CopperConvertRequestController::class, 'store']); + Route::put('copper-convert-request/{id}', [CopperConvertRequestController::class, 'update']); + Route::delete('copper-convert-request/{id}', [CopperConvertRequestController::class, 'destroy']); //-----------------single order Route::post('single/order/table', [SingleOrderController::class, 'table']);