diff --git a/app/Http/Controllers/BillingPlanController.php b/app/Http/Controllers/BillingPlanController.php index 90e7bba8..8dd6fc86 100644 --- a/app/Http/Controllers/BillingPlanController.php +++ b/app/Http/Controllers/BillingPlanController.php @@ -42,7 +42,51 @@ public function create() */ public function store(Request $request) { - // + $validated = $request->validate([ + 'name' => 'required|string|max:255', + 'frequency' => 'required|string|in:Monthly,Yearly', + 'is_active' => 'boolean', + 'amount' => 'required|numeric|min:0', + 'description' => 'required|string', + ]); + + try { + $billingPlan = SubscriptionPlan::where('name', '=', $validated['name'])->first(); + + if($billingPlan){ + return response()->json([ + "status" => "error", + "status_code" => 403, + "message" => "Billing plan already exists!", + "data" => [] + ], 403); + } + + $billingPlan = new SubscriptionPlan; + $billingPlan->name = $validated['name']; + $billingPlan->duration = $validated['frequency']; + $billingPlan->price = $validated['amount']; + $billingPlan->description = $validated['description']; + $billingPlan->save(); + + return response()->json([ + "status" => "success", + "status_code" => 201, + "message" => "Billing plan successfully created!", + "data" => [ + ...$billingPlan->toArray() + ] + ], 201); + + } catch (\Throwable $th) { + print_r($th); + return response()->json([ + "status" => "error", + "status_code" => 500, + "message" => "Internal Server Error!", + "data" => [] + ], 500); + } } /** diff --git a/resources/docs/docs.json b/resources/docs/docs.json index 9d9db0d1..ec136d85 100644 --- a/resources/docs/docs.json +++ b/resources/docs/docs.json @@ -603,6 +603,57 @@ } }, "/api/v1/billing-plans": { + "post": { + "summary": "Create new billing plan", + "tags": ["Billing"], + "security": [ + { + "bearerAuth": [] + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BillingPlan" + } + } + } + }, + "responses": { + "201": { + "description": "Billing plan created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BillingPlanResponse" + } + } + } + }, + "403": { + "description": "Billing plan already exists", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, "get": { "summary": "Get billing plans", "tags": ["Billing"], @@ -633,14 +684,59 @@ } } }, - "delete": { - "summary": "Delete billing plan", + "put": { + "summary": "Update billing plan", "tags": ["Billing"], "security": [ { "bearerAuth": [] } ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BillingPlan" + } + } + } + }, + "responses": { + "201": { + "description": "Billing plan created successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BillingPlanResponse" + } + } + } + }, + "404": { + "description": "Billing plan not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal Server Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + } + }, + "delete": { + "summary": "Delete billing plan", "parameters": [ { "name": "id", diff --git a/routes/api.php b/routes/api.php index e301c90f..5c7d409f 100755 --- a/routes/api.php +++ b/routes/api.php @@ -125,6 +125,7 @@ Route::delete('/products/{product_id}', [ProductController::class, 'delete']); Route::get('/billing-plans', [BillingPlanController::class, 'index']); + Route::post('/billing-plans', [BillingPlanController::class, 'store']); Route::get('/billing-plans/{id}', [BillingPlanController::class, 'getBillingPlan']); Route::put('/billing-plans/{id}', [BillingPlanController::class, 'update']); Route::delete('/billing-plans/{id}', [BillingPlanController::class, 'destroy']); diff --git a/tests/Feature/BillingPlanControllerTest.php b/tests/Feature/BillingPlanControllerTest.php index 24671541..379ef747 100644 --- a/tests/Feature/BillingPlanControllerTest.php +++ b/tests/Feature/BillingPlanControllerTest.php @@ -11,6 +11,63 @@ class BillingPlanControllerTest extends TestCase { use RefreshDatabase; + /** @test */ + public function it_creates_a_billing_plan_successfully() + { + $user = User::factory()->create(); + $this->actingAs($user); + $saved = SubscriptionPlan::where('name', '=', 'Discounted Plan')->first(); + + if($saved) $saved->delete(); + + $data = [ + 'name' => 'Discounted Plan', + 'frequency' => 'Yearly', + 'amount' => 20000, + 'is_active' => true, + 'description' => 'A discounted plan description', + ]; + + $response = $this->postJson("/api/v1/billing-plans", $data); + + // Assert: Check the response status and structure + $response->assertStatus(201) + ->assertJsonStructure([ + 'data' => [ + 'id', + 'name', + 'duration', + 'price', + 'description', + 'created_at', + 'updated_at', + ], + 'message', + 'status_code', + 'status' + ]); + + $this->assertDatabaseHas('subscription_plans', [ + 'name' => 'Discounted Plan', + 'duration' => 'Yearly', + 'price' => 20000, + 'description' => 'A discounted plan description', + ]); + + + $res = $this->postJson("/api/v1/billing-plans", $data); + + // Assert: Check the response status and structure + $res->assertStatus(403) + ->assertJsonStructure([ + 'data' => [], + 'message', + 'status_code', + 'status' + ]); + + } + /** @test */ public function it_updates_a_billing_plan_successfully() {