feat(sponsors): add bulk upsert endpoint for sponsor services statistics#556
feat(sponsors): add bulk upsert endpoint for sponsor services statistics#556romanetar wants to merge 1 commit into
Conversation
Signed-off-by: romanetar <roman_ag@hotmail.com>
📝 WalkthroughWalkthroughThis pull request adds a complete bulk update endpoint for sponsor services statistics. Changes span validation rules, service interface and implementation, HTTP controller with OpenAPI documentation, route registration, database migration for endpoint authorization, and comprehensive test coverage. ChangesBulk Sponsor Statistics Update Feature
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
📘 OpenAPI / Swagger preview ➡️ https://OpenStackweb.github.io/summit-api/openapi/pr-556/ This page is automatically updated on each push to this PR. |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
tests/oauth2/OAuth2SummitSponsorApiTest.php (1)
1662-1701: ⚡ Quick winConsider verifying additional response fields for completeness.
The test verifies
forms_qtyfor both results but doesn't assert the other quantity fields sent in the first payload (purchases_qty,pages_qty,documents_qty). Adding these assertions would provide more comprehensive coverage and catch potential field mapping issues.✅ Suggested additional assertions
$this->assertIsArray($results); $this->assertCount(2, $results); $this->assertEquals(100, $results[0]->forms_qty); + $this->assertEquals(200, $results[0]->purchases_qty); + $this->assertEquals(300, $results[0]->pages_qty); + $this->assertEquals(400, $results[0]->documents_qty); $this->assertEquals(10, $results[1]->forms_qty);🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/oauth2/OAuth2SummitSponsorApiTest.php` around lines 1662 - 1701, In testBulkUpdateSponsorServicesStatistics, extend the assertions after decoding $results to verify the other fields returned by bulkUpdateSponsorServicesStatistics: assert that $results[0]->purchases_qty, $results[0]->pages_qty and $results[0]->documents_qty equal 200, 300 and 400 respectively, and also assert the behavior for the second payload (e.g. $results[1]->purchases_qty/$results[1]->pages_qty/$results[1]->documents_qty are null or unchanged) to ensure all sent fields are correctly mapped in the response.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@app/Http/Controllers/Apis/Protected/Summit/Factories/SponsorServicesStatisticsValidationRulesFactory.php`:
- Around line 36-44: The buildForBulkUpdate validation allows nested keys but
doesn't require each top-level bulk item to be an array; add a rule forcing each
element to be an array so malformed non-array items fail validation. In
buildForBulkUpdate (method buildForBulkUpdate) add a rule '*' => 'array' (or
'*'=> ['array']) before the '*.sponsor_id' / '*.forms_qty' etc. entries so each
bulk element is validated as an array prior to the nested wildcard checks.
In `@tests/oauth2/OAuth2SummitSponsorApiTest.php`:
- Around line 1703-1729: The
testBulkUpdateSponsorServicesStatisticsValidationError assigns $response but
never uses it and only asserts HTTP 412; update the test to consume the response
from the action call and assert the error412 response structure (ensure the JSON
contains top-level keys "message", "errors", and "code" per the error412 helper
pattern) instead of leaving $response unused—locate the action invocation to
OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics and add
assertions that decode the response body and verify those fields.
---
Nitpick comments:
In `@tests/oauth2/OAuth2SummitSponsorApiTest.php`:
- Around line 1662-1701: In testBulkUpdateSponsorServicesStatistics, extend the
assertions after decoding $results to verify the other fields returned by
bulkUpdateSponsorServicesStatistics: assert that $results[0]->purchases_qty,
$results[0]->pages_qty and $results[0]->documents_qty equal 200, 300 and 400
respectively, and also assert the behavior for the second payload (e.g.
$results[1]->purchases_qty/$results[1]->pages_qty/$results[1]->documents_qty are
null or unchanged) to ensure all sent fields are correctly mapped in the
response.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e98a607a-41c9-411c-9154-ac38ff443034
📒 Files selected for processing (8)
app/Http/Controllers/Apis/Protected/Summit/Factories/SponsorServicesStatisticsValidationRulesFactory.phpapp/Http/Controllers/Apis/Protected/Summit/OAuth2SummitSponsorApiController.phpapp/Services/Model/ISummitSponsorService.phpapp/Services/Model/Imp/SummitSponsorService.phpdatabase/migrations/config/Version20260611155110.phpdatabase/seeders/ApiEndpointsSeeder.phproutes/api_v1.phptests/oauth2/OAuth2SummitSponsorApiTest.php
| public static function buildForBulkUpdate(array $payload = []): array | ||
| { | ||
| return [ | ||
| '*.sponsor_id' => 'required|integer', | ||
| '*.forms_qty' => 'sometimes|integer', | ||
| '*.purchases_qty' => 'sometimes|integer', | ||
| '*.pages_qty' => 'sometimes|integer', | ||
| '*.documents_qty' => 'sometimes|integer', | ||
| ]; |
There was a problem hiding this comment.
Validate each bulk element as an array before nested wildcard checks.
Line 39 validates nested keys, but each top-level element is not required to be an array. A malformed object-shaped payload can bypass validation and then fail at Line 1289 in app/Services/Model/Imp/SummitSponsorService.php when $item['sponsor_id'] is accessed, producing a 500 instead of a 412 validation response.
Suggested fix
public static function buildForBulkUpdate(array $payload = []): array
{
return [
+ '*' => 'required|array',
'*.sponsor_id' => 'required|integer',
'*.forms_qty' => 'sometimes|integer',
'*.purchases_qty' => 'sometimes|integer',
'*.pages_qty' => 'sometimes|integer',
'*.documents_qty' => 'sometimes|integer',
];
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static function buildForBulkUpdate(array $payload = []): array | |
| { | |
| return [ | |
| '*.sponsor_id' => 'required|integer', | |
| '*.forms_qty' => 'sometimes|integer', | |
| '*.purchases_qty' => 'sometimes|integer', | |
| '*.pages_qty' => 'sometimes|integer', | |
| '*.documents_qty' => 'sometimes|integer', | |
| ]; | |
| public static function buildForBulkUpdate(array $payload = []): array | |
| { | |
| return [ | |
| '*' => 'required|array', | |
| '*.sponsor_id' => 'required|integer', | |
| '*.forms_qty' => 'sometimes|integer', | |
| '*.purchases_qty' => 'sometimes|integer', | |
| '*.pages_qty' => 'sometimes|integer', | |
| '*.documents_qty' => 'sometimes|integer', | |
| ]; | |
| } |
🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 36-36: Avoid unused parameters such as '$payload'. (undefined)
(UnusedFormalParameter)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@app/Http/Controllers/Apis/Protected/Summit/Factories/SponsorServicesStatisticsValidationRulesFactory.php`
around lines 36 - 44, The buildForBulkUpdate validation allows nested keys but
doesn't require each top-level bulk item to be an array; add a rule forcing each
element to be an array so malformed non-array items fail validation. In
buildForBulkUpdate (method buildForBulkUpdate) add a rule '*' => 'array' (or
'*'=> ['array']) before the '*.sponsor_id' / '*.forms_qty' etc. entries so each
bulk element is validated as an array prior to the nested wildcard checks.
| public function testBulkUpdateSponsorServicesStatisticsValidationError() | ||
| { | ||
| $params = [ | ||
| 'id' => self::$summit->getId(), | ||
| ]; | ||
|
|
||
| // forms_qty is a string instead of integer — should fail validation | ||
| $data = [ | ||
| [ | ||
| 'sponsor_id' => self::$sponsors[0]->getId(), | ||
| 'forms_qty' => 'not-an-integer', | ||
| ], | ||
| ]; | ||
|
|
||
| $response = $this->action( | ||
| "PUT", | ||
| "OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics", | ||
| $params, | ||
| [], | ||
| [], | ||
| [], | ||
| $this->getAuthHeaders(), | ||
| json_encode($data) | ||
| ); | ||
|
|
||
| $this->assertResponseStatus(412); | ||
| } |
There was a problem hiding this comment.
Address unused variable and verify error response structure.
The $response variable is assigned but never used. Additionally, the test only verifies the HTTP 412 status but doesn't validate the error response structure. Based on the error412 helper pattern, the response should contain message, errors, and code fields.
🧪 Proposed fix
$response = $this->action(
"PUT",
"OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics",
$params,
[],
[],
[],
$this->getAuthHeaders(),
json_encode($data)
);
+ $content = $response->getContent();
$this->assertResponseStatus(412);
+ $error = json_decode($content);
+ $this->assertNotNull($error);
+ $this->assertEquals('Validation Failed', $error->message);
+ $this->assertNotEmpty($error->errors);
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public function testBulkUpdateSponsorServicesStatisticsValidationError() | |
| { | |
| $params = [ | |
| 'id' => self::$summit->getId(), | |
| ]; | |
| // forms_qty is a string instead of integer — should fail validation | |
| $data = [ | |
| [ | |
| 'sponsor_id' => self::$sponsors[0]->getId(), | |
| 'forms_qty' => 'not-an-integer', | |
| ], | |
| ]; | |
| $response = $this->action( | |
| "PUT", | |
| "OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics", | |
| $params, | |
| [], | |
| [], | |
| [], | |
| $this->getAuthHeaders(), | |
| json_encode($data) | |
| ); | |
| $this->assertResponseStatus(412); | |
| } | |
| public function testBulkUpdateSponsorServicesStatisticsValidationError() | |
| { | |
| $params = [ | |
| 'id' => self::$summit->getId(), | |
| ]; | |
| // forms_qty is a string instead of integer — should fail validation | |
| $data = [ | |
| [ | |
| 'sponsor_id' => self::$sponsors[0]->getId(), | |
| 'forms_qty' => 'not-an-integer', | |
| ], | |
| ]; | |
| $response = $this->action( | |
| "PUT", | |
| "OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics", | |
| $params, | |
| [], | |
| [], | |
| [], | |
| $this->getAuthHeaders(), | |
| json_encode($data) | |
| ); | |
| $content = $response->getContent(); | |
| $this->assertResponseStatus(412); | |
| $error = json_decode($content); | |
| $this->assertNotNull($error); | |
| $this->assertEquals('Validation Failed', $error->message); | |
| $this->assertNotEmpty($error->errors); | |
| } |
🧰 Tools
🪛 PHPMD (2.15.0)
[warning] 1717-1717: Avoid unused local variables such as '$response'. (undefined)
(UnusedLocalVariable)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@tests/oauth2/OAuth2SummitSponsorApiTest.php` around lines 1703 - 1729, The
testBulkUpdateSponsorServicesStatisticsValidationError assigns $response but
never uses it and only asserts HTTP 412; update the test to consume the response
from the action call and assert the error412 response structure (ensure the JSON
contains top-level keys "message", "errors", and "code" per the error412 helper
pattern) instead of leaving $response unused—locate the action invocation to
OAuth2SummitSponsorApiController@bulkUpdateSponsorServicesStatistics and add
assertions that decode the response body and verify those fields.
ref https://app.clickup.com/t/9014802374/86b8pwxha?comment=90140214990302
Summary by CodeRabbit
New Features
Tests