Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
7 / 7
CRAP
100.00% covered (success)
100.00%
1 / 1
InAppNotificationCampaignController
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
7 / 7
7
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 index
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 show
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 store
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 update
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 destroy
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 assign
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace App\Http\Controllers\v2\Admin;
4
5use App\Http\Controllers\Controller;
6use App\Http\Models\InAppNotificationCampaign;
7use App\Http\Requests\v2\InAppNotification\AssignInAppNotificationCampaignRequest;
8use App\Http\Requests\v2\InAppNotification\CreateInAppNotificationCampaignRequest;
9use App\Http\Requests\v2\InAppNotification\DeleteInAppNotificationCampaignRequest;
10use App\Http\Requests\v2\InAppNotification\IndexInAppNotificationCampaignRequest;
11use App\Http\Requests\v2\InAppNotification\ShowInAppNotificationCampaignRequest;
12use App\Http\Requests\v2\InAppNotification\UpdateInAppNotificationCampaignRequest;
13use App\Http\Resources\v2\InAppNotificationCampaignResource;
14use App\Http\Services\InAppNotificationCampaignService;
15use App\Http\Services\InAppNotificationService;
16use Illuminate\Http\JsonResponse;
17use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
18
19/**
20 * Controller for managing in-app notification campaigns.
21 *
22 * Only accessible by users with the VENGRESO_ADMIN role.
23 * Provides CRUD operations and campaign assignment.
24 */
25class InAppNotificationCampaignController extends Controller
26{
27    public function __construct(
28        private readonly InAppNotificationCampaignService $campaignService,
29        private readonly InAppNotificationService $notificationService
30    ) {}
31
32    /**
33     * Get all campaigns ordered by priority.
34     *
35     * @param  IndexInAppNotificationCampaignRequest  $request  Validated request (authorization only)
36     *
37     * @response 200 {
38     *   "result": {
39     *     "data": [
40     *       {
41     *         "id": "507f1f77bcf86cd799439011",
42     *         "id_slug": "grammar-reengage-2026-q1",
43     *         "priority": 1,
44     *         "title": "Try our new feature!",
45     *         "body": "Improve your writing with FlyGrammar",
46     *         "display_mode": "banner",
47     *         "is_active": true,
48     *         "...": "..."
49     *       }
50     *     ]
51     *   }
52     * }
53     */
54    public function index(IndexInAppNotificationCampaignRequest $request): AnonymousResourceCollection
55    {
56        $campaigns = $this->campaignService->getAll();
57
58        return InAppNotificationCampaignResource::collection($campaigns);
59    }
60
61    /**
62     * Get a single campaign by ID.
63     *
64     * @param  ShowInAppNotificationCampaignRequest  $request  Validated request (authorization only)
65     * @param  InAppNotificationCampaign  $inAppNotificationCampaign  The campaign (route model binding)
66     *
67     * @response 200 {
68     *   "result": {
69     *     "data": {
70     *       "id": "507f1f77bcf86cd799439011",
71     *       "id_slug": "grammar-reengage-2026-q1",
72     *       "...": "..."
73     *     }
74     *   }
75     * }
76     */
77    public function show(ShowInAppNotificationCampaignRequest $request, InAppNotificationCampaign $inAppNotificationCampaign): InAppNotificationCampaignResource
78    {
79        return new InAppNotificationCampaignResource($inAppNotificationCampaign);
80    }
81
82    /**
83     * Create a new campaign.
84     *
85     * @param  CreateInAppNotificationCampaignRequest  $request  Validated request with campaign data
86     *
87     * @response 201 {
88     *   "result": {
89     *     "data": {
90     *       "id": "507f1f77bcf86cd799439011",
91     *       "id_slug": "grammar-reengage-2026-q1",
92     *       "...": "..."
93     *     }
94     *   }
95     * }
96     */
97    public function store(CreateInAppNotificationCampaignRequest $request): JsonResponse
98    {
99        $campaign = $this->campaignService->create($request->validated());
100
101        return (new InAppNotificationCampaignResource($campaign))
102            ->response()
103            ->setStatusCode(201);
104    }
105
106    /**
107     * Update an existing campaign.
108     *
109     * @param  UpdateInAppNotificationCampaignRequest  $request  Validated request with update data
110     * @param  InAppNotificationCampaign  $inAppNotificationCampaign  The campaign (route model binding)
111     *
112     * @response 200 {
113     *   "result": {
114     *     "data": {
115     *       "id": "507f1f77bcf86cd799439011",
116     *       "...": "..."
117     *     }
118     *   }
119     * }
120     */
121    public function update(UpdateInAppNotificationCampaignRequest $request, InAppNotificationCampaign $inAppNotificationCampaign): InAppNotificationCampaignResource
122    {
123        $campaign = $this->campaignService->update($inAppNotificationCampaign, $request->validated());
124
125        return new InAppNotificationCampaignResource($campaign);
126    }
127
128    /**
129     * Delete a campaign.
130     *
131     * @param  DeleteInAppNotificationCampaignRequest  $request  Validated request (authorization only)
132     * @param  InAppNotificationCampaign  $inAppNotificationCampaign  The campaign (route model binding)
133     *
134     * @response 204 No content
135     */
136    public function destroy(DeleteInAppNotificationCampaignRequest $request, InAppNotificationCampaign $inAppNotificationCampaign): JsonResponse
137    {
138        $this->campaignService->delete($inAppNotificationCampaign);
139
140        return response()->json(null, 204);
141    }
142
143    /**
144     * Assign a campaign to matching users, creating per-user notification records.
145     *
146     * @param  AssignInAppNotificationCampaignRequest  $request  Validated request (authorization only)
147     * @param  InAppNotificationCampaign  $inAppNotificationCampaign  The campaign (route model binding)
148     *
149     * @response 200 {
150     *   "result": {
151     *     "assigned_count": 150
152     *   }
153     * }
154     */
155    public function assign(AssignInAppNotificationCampaignRequest $request, InAppNotificationCampaign $inAppNotificationCampaign): JsonResponse
156    {
157        $count = $this->notificationService->assignCampaignToUsers(
158            (string) $inAppNotificationCampaign->_id
159        );
160
161        return response()->json(['assigned_count' => $count]);
162    }
163}