-
Notifications
You must be signed in to change notification settings - Fork 0
enh : Improve CRUD implementation for transactions #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (5)
app/Http/Controllers/API/v1/TransactionController.php (1)
27-33
: Consider adjusting therequired
setting.
This parameter is assigned a default value (20), yet it's also marked asrequired
. If you truly intend to always require a user-supplied limit, consider removing the default to ensure clients specify it. Otherwise, mark it as optional.new OA\Parameter( name: 'limit', in: 'query', description: 'Number of transactions to fetch', - required: true, + required: false, schema: new OA\Schema(type: 'integer', default: 20) ),database/migrations/2024_07_20_125016_create_transactions_table.php (2)
17-17
: Switched todatetime
.
Using a datetime column is flexible for date/time support. Confirm that references and validations across the app use the same format.
18-18
: Use of enum for 'type'.
This is fine for strictly defining 'income' or 'expense'. If you anticipate new transaction types, consider a string or separate referencing table for easier extension.app/Http/Controllers/API/ApiController.php (1)
26-35
: Trailing comma style violation noted.
Your pipeline highlights a trailing comma in this multiline array. Remove it to pass style checks.#[OA\Components( securitySchemes: [ new OA\SecurityScheme( securityScheme: 'bearerAuth', type: 'http', scheme: 'bearer', description: 'Bearer token authentication' - ), + ) ] )]🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: trailing comma in multiline
public/docs/api.json (1)
927-936
: Consider making the limit parameter optional.Since the parameter has a default value of 20, it should be optional rather than required. This allows clients to use the default pagination without explicitly providing a limit.
Apply this diff to make the limit parameter optional:
{ "name": "limit", "in": "query", "description": "Number of transactions to fetch", - "required": true, + "required": false, "schema": { "type": "integer", "default": 20 } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (9)
app/Http/Controllers/API/ApiController.php
(2 hunks)app/Http/Controllers/API/v1/Auth/AuthController.php
(2 hunks)app/Http/Controllers/API/v1/Auth/PasswordResetController.php
(2 hunks)app/Http/Controllers/API/v1/TransactionController.php
(5 hunks)app/Models/Expense.php
(0 hunks)app/Models/Income.php
(0 hunks)database/migrations/2024_07_20_125016_create_transactions_table.php
(1 hunks)database/migrations/2024_07_20_125022_create_expenses_table.php
(0 hunks)public/docs/api.json
(8 hunks)
💤 Files with no reviewable changes (3)
- database/migrations/2024_07_20_125022_create_expenses_table.php
- app/Models/Expense.php
- app/Models/Income.php
🧰 Additional context used
🪛 GitHub Actions: Checks
app/Http/Controllers/API/ApiController.php
[error] Style violation: trailing comma in multiline
app/Http/Controllers/API/v1/Auth/PasswordResetController.php
[error] Style violation: unary operator spaces
app/Http/Controllers/API/v1/Auth/AuthController.php
[error] Style violation: unary operator spaces
🔇 Additional comments (22)
app/Http/Controllers/API/v1/TransactionController.php (9)
6-6
: Nice model reference.
You're now correctly importing the unifiedTransaction
model, which aligns with the updated data structure.
50-50
: Query default looks good.
Using$request->query('limit', 20)
is consistent with the default logic.
56-56
: Pagination usage is appropriate.
This is correct for retrieving a paginated list of transactions. Keep an eye on performance for larger datasets.
71-71
: Good inclusion of 'datetime' property.
This clarifies the expected format, but see adjacent comment about the mismatch in therequired
list.
95-95
: Validation looks correct.
Requiring a numericamount
is sensible.
98-98
: Confirm the 'datetime' validation rule.
Laravel does not include a built-in'datetime'
validation. Consider'date'
or'date_format'
to ensure correct validation.
100-100
: Optional party association.
Markingparty_id
as nullable is flexible for transactions that have no party involvement.
101-101
: Correct association requirement.
Makingwallet_id
mandatory is consistent with typical wallet-based transaction logic.
109-109
: Confirm mass assignment protection.
Ensure theTransaction
model has$fillable
or$guarded
set appropriately to avoid mass assignment vulnerabilities.database/migrations/2024_07_20_125016_create_transactions_table.php (2)
14-14
: Unified table creation.
Renaming/creatingtransactions
aligns with consolidating incomes and expenses. Make sure you migrate the existing data properly.
20-20
: Nullablewallet_id
.
This is helpful for transactions that might not be wallet-based. Ensure your controller logic handles nullable wallets properly.app/Http/Controllers/API/ApiController.php (1)
9-13
: Global security annotation is a good addition.
This clarifies the bearer authentication requirement for all endpoints unless otherwise overridden.🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: trailing comma in multiline
app/Http/Controllers/API/v1/Auth/AuthController.php (3)
16-16
: LGTM! OpenAPI tag annotation is well-placed and descriptive.The tag annotation correctly categorizes the authentication endpoints and provides a clear description.
🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
22-22
: LGTM! Security annotation correctly indicates no authentication required.The
security: []
annotation is appropriate for the registration endpoint as new users should not need to authenticate.🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
75-75
: LGTM! Security annotation correctly indicates no authentication required.The
security: []
annotation is appropriate for the login endpoint as users need to authenticate through this endpoint.🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
app/Http/Controllers/API/v1/Auth/PasswordResetController.php (3)
15-15
: LGTM! OpenAPI tag annotation maintains consistency with AuthController.The tag annotation correctly categorizes the password reset endpoints under the same 'Authentication' tag.
🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
23-23
: LGTM! Security annotation correctly indicates no authentication required.The
security: []
annotation is appropriate for the password reset code endpoint as users who forgot their password cannot authenticate.🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
90-90
: LGTM! Security annotation correctly indicates no authentication required.The
security: []
annotation is appropriate for the password reset endpoint as users who are resetting their password cannot authenticate.🧰 Tools
🪛 GitHub Actions: Checks
[error] Style violation: unary operator spaces
public/docs/api.json (4)
73-74
: LGTM! Security annotations align with controller changes.The
"security": []
annotations are consistently applied to all authentication-related endpoints, matching the controller configurations.Also applies to: 123-124, 174-175, 238-239
973-973
: LGTM! Required fields are appropriately updated.The required fields for transaction creation have been correctly updated to reflect the essential attributes while making group_id optional.
1542-1547
: LGTM! Security scheme is well-defined.The bearer token authentication scheme is correctly configured according to OpenAPI specification.
1550-1554
: LGTM! Global security requirement ensures secure-by-default behavior.The global security requirement correctly enforces bearer token authentication for all endpoints by default, while allowing specific endpoints to opt-out using
"security": []
.
c7e6d3a
to
11daedb
Compare
WalkthroughThe pull request introduces a comprehensive refactoring of the transaction management system, consolidating income and expense tracking into a single Changes
Sequence DiagramsequenceDiagram
participant User
participant AuthController
participant TransactionController
participant Transaction
participant Category
participant Wallet
participant Party
User->>AuthController: Register/Login
AuthController-->>User: Authentication Token
User->>TransactionController: Create Transaction
TransactionController->>Transaction: Create New Transaction
TransactionController->>Category: Associate Categories
TransactionController->>Wallet: Update Wallet Balance
TransactionController->>Party: Link Transaction
TransactionController-->>User: Transaction Created
Poem
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Signed-off-by: nfebe <fenn25.fn@gmail.com>
11daedb
to
d4db3c1
Compare
d4db3c1
to
fc3314c
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
🔭 Outside diff range comments (1)
app/Models/Group.php (1)
Line range hint
10-20
: Update OpenAPI schema to include the slug property.The OpenAPI schema is missing the
slug
property which is now a fillable attribute in the model.Add the slug property to the schema:
#[OA\Schema( schema: 'Group', type: 'object', properties: [ new OA\Property(property: 'id', type: 'integer', description: 'ID of the group'), new OA\Property(property: 'name', type: 'string', description: 'Name of the group'), new OA\Property(property: 'description', type: 'string', description: 'Description of the group'), + new OA\Property(property: 'slug', type: 'string', description: 'URL-friendly version of the name'), ] )]
🧹 Nitpick comments (17)
database/factories/UserFactory.php (1)
33-33
: Consider using more secure test passwords.While
password123
is fine for testing, consider:
- Using environment variables for test passwords
- Implementing a more robust password generation strategy for testing different password complexity scenarios
Example implementation:
- 'password' => static::$password ??= Hash::make('password123'), + 'password' => static::$password ??= Hash::make(env('TEST_USER_PASSWORD', 'password123')),You could also create a helper method for generating test passwords with different complexity levels:
protected function generateTestPassword(): string { return env('TEST_USER_PASSWORD') ?? Str::random(12) . '!2A'; // Ensures mixed case, numbers, and symbols }app/Models/Transaction.php (3)
18-24
: Use ‘date-time’ format instead of ‘date’
OpenAPI typically uses"date-time"
to represent date and time in strings. Suggest changingformat: 'date'
toformat: 'date-time'
for better clarity and alignment with the standard.- new OA\Property(property: 'datetime', type: 'string', format: 'date', description: 'Date and time of the transaction'), + new OA\Property(property: 'datetime', type: 'string', format: 'date-time', description: 'Date and time of the transaction'),
46-46
: Potential performance overhead with $appends
Appending relationships (wallet
,party
,categories
) by default can trigger multiple queries for every transaction retrieval. Consider removing them from$appends
if you’d rather load them on-demand or use eager loading to reduce N+1 queries.
48-51
: Avoid overshadowing relationship names with accessors
All three accessors (getCategoriesAttribute
,getWalletAttribute
,getPartyAttribute
) mirror the same relationship names. This can be confusing and may lead to unexpected outcomes when calling$model->categories
vs.$model->categories()
. Renaming either the accessors or the relationship methods can improve clarity.Also applies to: 53-56, 58-61
app/Http/Controllers/API/v1/TransactionController.php (3)
27-33
: Limit parameter should be optional
Currently marked asrequired: true
, yet a default of 20 is provided. Generally, limit parameters are optional. Updating torequired: false
may be more consistent with typical API conventions.- required: true, + required: false,
96-96
: Validation for ‘datetime’
Currently set tonullable|date
. If you intend to store both date and time, you might wantdate_format:Y-m-d H:i:s
or a more precise check.- 'datetime' => 'nullable|date', + 'datetime' => 'nullable|date_format:Y-m-d H:i:s',Also applies to: 99-104
111-117
: Shadowing of $request variable
Reusing$request
to store validated data can be confusing. Prefer naming it$validatedData
to avoid overshadowing the original$request
object.-$request = $validator->validated(); +$validatedData = $validator->validated(); ... -$transaction = Transaction::create($request); +$transaction = Transaction::create($validatedData);tests/TestCase.php (1)
10-16
: Fresh seeding for each test run
migrate:fresh --seed
ensures a clean database state but can slow large test suites. Consider using transactions or rolling back changes as an alternative for faster tests.database/migrations/2024_07_20_125030_create_groups_table.php (1)
18-18
: Consider using an enum for the type column.Using a string type without constraints allows any value. Consider using an enum if you have a predefined set of group types to ensure data consistency.
- $table->string('type')->nullable(); + $table->enum('type', ['type1', 'type2', 'type3'])->nullable();Please replace 'type1', 'type2', 'type3' with your actual group types.
database/migrations/2024_07_20_125116_create_wallets_table.php (1)
17-17
: Consider reordering enum values logically.The enum values could be ordered more logically, grouping similar payment methods together (e.g., electronic methods vs physical methods).
- $table->enum('type', ['bank', 'cash', 'credit_card', 'mobile']); + $table->enum('type', ['bank', 'credit_card', 'mobile', 'cash']);database/seeders/UserSeeder.php (1)
22-36
: Consider using createMany() for better performance.Instead of multiple create() calls in a loop, consider using createMany() for better performance when creating multiple related entities.
- Party::factory(5)->create([ - 'user_id' => $user->id, - ]); + Party::factory()->count(5)->createMany( + array_fill(0, 5, ['user_id' => $user->id]) + );Similar changes can be applied to Category, Wallet, and Group creation.
database/factories/PartyFactory.php (1)
20-31
: Consider separating party types using factory states.The current implementation mixes different types of parties (individuals and institutions) in a single list. Consider using factory states to generate different types of parties.
class PartyFactory extends Factory { public function definition(): array { return [ - 'name' => $this->faker->randomElement([ - 'John Doe', - 'University of Buea', - 'Jane Doe', - 'Bob', - 'University of Cambridge', - 'Harvard University', - 'Alice', - 'Filling Station', - 'Wallibi Park', - 'Disneyland', - ]), + 'name' => $this->faker->name, 'description' => $this->faker->sentence, ]; } + + public function institution(): static + { + return $this->state(function (array $attributes) { + return [ + 'name' => $this->faker->company, + ]; + }); + } + + public function university(): static + { + return $this->state(function (array $attributes) { + return [ + 'name' => $this->faker->randomElement([ + 'University of Buea', + 'University of Cambridge', + 'Harvard University', + ]), + ]; + }); + } }database/factories/CategoryFactory.php (1)
20-31
: Consider implementing hierarchical categories.The current flat structure of categories might be limiting. Consider implementing a parent-child relationship for more flexible categorization.
Example implementation:
// In database/migrations/create_categories_table.php Schema::create('categories', function (Blueprint $table) { // ... existing columns + $table->foreignId('parent_id')->nullable()->constrained('categories')->nullOnDelete(); }); // In CategoryFactory.php public function definition(): array { return [ 'name' => $this->faker->randomElement([ 'Groceries', 'Rent', // ... other categories ]), + 'parent_id' => null, 'description' => $this->faker->sentence, 'type' => $this->faker->randomElement(['income', 'expense']), ]; } + + public function asSubcategory(): static + { + return $this->state(function (array $attributes) { + return [ + 'parent_id' => Category::factory(), + ]; + }); + }app/Http/Controllers/API/ApiController.php (1)
Line range hint
19-24
: Address the TODO comment regarding server variables.The commented-out server variables configuration needs to be resolved.
Would you like me to help implement a solution for the server variables configuration that doesn't cause an error?
public/docs/api.json (3)
898-905
: Consider making the limit parameter optional.The limit parameter for pagination is a good addition, but marking it as required might be too restrictive. Consider making it optional while keeping the default value of 20.
- "required": true, + "required": false,
970-976
: Enhance documentation for categories field.Consider adding examples to better document the categories field usage.
"categories": { "type": "array", "items": { "description": "Category ID array", - "type": "integer" + "type": "integer", + "example": 1 }, + "example": [1, 2, 3] }Also applies to: 1495-1501
1538-1541
: Improve tag descriptions.Some tag descriptions are too brief or just repeat the tag name. Consider adding more descriptive explanations.
{ "name": "Groups", - "description": "Groups" + "description": "Endpoints for managing transaction groups" }, { "name": "Party", - "description": "Party" + "description": "Endpoints for managing transaction parties" }, { "name": "Wallet", - "description": "Wallet" + "description": "Endpoints for managing transaction wallets" }Also applies to: 1547-1558
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
app/Http/Controllers/API/ApiController.php
(2 hunks)app/Http/Controllers/API/v1/Auth/AuthController.php
(2 hunks)app/Http/Controllers/API/v1/Auth/PasswordResetController.php
(2 hunks)app/Http/Controllers/API/v1/TransactionController.php
(8 hunks)app/Listeners/UserRegistered.php
(1 hunks)app/Models/Expense.php
(0 hunks)app/Models/Group.php
(2 hunks)app/Models/Income.php
(0 hunks)app/Models/Transaction.php
(2 hunks)database/factories/CategoryFactory.php
(1 hunks)database/factories/GroupFactory.php
(1 hunks)database/factories/PartyFactory.php
(1 hunks)database/factories/UserFactory.php
(2 hunks)database/factories/WalletFactory.php
(1 hunks)database/migrations/2024_07_20_125016_create_transactions_table.php
(1 hunks)database/migrations/2024_07_20_125030_create_groups_table.php
(1 hunks)database/migrations/2024_07_20_125104_create_parties_table.php
(1 hunks)database/migrations/2024_07_20_125116_create_wallets_table.php
(1 hunks)database/migrations/2024_07_20_125455_create_categories_table.php
(1 hunks)database/migrations/2025_01_25_232422_create_categorizables.php
(2 hunks)database/seeders/UserSeeder.php
(1 hunks)public/docs/api.json
(8 hunks)tests/Feature/TransactionsTest.php
(1 hunks)tests/TestCase.php
(1 hunks)
💤 Files with no reviewable changes (2)
- app/Models/Expense.php
- app/Models/Income.php
🔇 Additional comments (23)
database/factories/UserFactory.php (2)
17-17
: LGTM! Explicit null initialization improves clarity.The explicit null initialization of the password property follows good practices and makes the code's intent clearer.
Line range hint
17-35
: Verify user-transaction relationship integrity.Since this PR involves transaction management system refactoring, ensure that any user-transaction relationships are properly maintained with these user model changes.
Let's check the transaction model relationships:
✅ Verification successful
UserFactory changes are safe for transaction relationships
The changes only affect test data generation and don't impact the user-transaction relationship integrity. The Transaction model properly maintains its belongsTo relationship with the User model.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check transaction model for user relationships echo "Checking Transaction model relationships:" rg -A 5 "class Transaction|function user|belongs" app/Models/Transaction.php || echo "Transaction.php not found" echo -e "\nChecking for any relationship changes in migrations:" fd -e php -x grep -l "foreign|references" {} \; database/migrations/Length of output: 1216
Script:
#!/bin/bash # Check migrations and tests echo "Checking migrations for foreign keys:" fd . database/migrations/ -t f -e php -x grep -l "foreign|references" {} echo -e "\nChecking tests using UserFactory with transactions:" rg -l "UserFactory|Transaction::factory" tests/Length of output: 330
app/Models/Transaction.php (4)
7-7
: Import for MorphToMany Relationship
Good addition to properly define the morph-to-many relationship.
63-66
: Simple belongsTo relationships
Wallet, party, and user relationships appear straightforward and correct.Also applies to: 68-71, 73-76
78-81
: Morph-to-many relationship to categories
Implementation looks good. Ensure any relevant pivot table migrations are in place forcategorizable
references.
32-44
: Verify handling of ‘group_id’ in mass-assignment
You have addedparty_id
andwallet_id
to the fillable array, but notgroup_id
, which also appears elsewhere. Verify if you want it to be mass assignable too.app/Http/Controllers/API/v1/TransactionController.php (8)
6-6
: Import of Transaction model
Good step towards consolidating income/expense logic into a unified model.
56-56
: Using paginate on typed transactions
Looks good. This unifies the query logic for income/expense.
119-121
: Syncing categories
Approach looks correct for many-to-many associations.
170-170
: Filtering by ‘type’ for show
Matches the approach used in destroy. Consistent usage is appreciated.
233-240
: Consistent validation for update
Mirroring the store validation is good. Same note aboutdatetime
vs.date
applies here.
257-259
: Category sync on update
Correct approach to maintain many-to-many relationships.
307-307
: Consistent type-based query for destroy
Keeps logic aligned with show method.
50-50
: 🛠️ Refactor suggestionInconsistency with required: true vs. default
You’ve set a default value for$limit
, but in OpenAPI it’s required. These conflict. Either remove the default or make the parameter optional.- required: true, + required: false,Likely invalid or redundant comment.
database/migrations/2024_07_20_125016_create_transactions_table.php (1)
17-17
: Consider non-nullable datetime column.The
datetime
column being nullable might lead to data integrity issues. Transactions should typically have a timestamp.- $table->datetime('datetime')->nullable(); + $table->datetime('datetime');database/seeders/UserSeeder.php (1)
17-20
: Consider adding unique constraint validation for email and username.While the current implementation creates predictable test data, it doesn't validate potential unique constraints. Consider adding a try-catch block to handle potential duplicate key violations.
database/factories/WalletFactory.php (1)
31-31
: 🛠️ Refactor suggestionConsider using model constants for wallet types.
Hardcoding type values in the factory could lead to inconsistencies. Consider defining these as constants in the Wallet model and referencing them here.
Example implementation:
// In app/Models/Wallet.php class Wallet extends Model { + public const TYPE_BANK = 'bank'; + public const TYPE_CASH = 'cash'; + public const TYPE_CREDIT_CARD = 'credit_card'; + public const TYPE_MOBILE = 'mobile'; + + public const TYPES = [ + self::TYPE_BANK, + self::TYPE_CASH, + self::TYPE_CREDIT_CARD, + self::TYPE_MOBILE, + ]; } // In WalletFactory.php - 'type' => $this->faker->randomElement(['bank', 'cash', 'credit_card', 'mobile']), + 'type' => $this->faker->randomElement(Wallet::TYPES),app/Models/Group.php (2)
32-44
: LGTM! Well-implemented sluggable configuration.The Sluggable trait is properly implemented with correct configuration to generate slugs from the name field.
46-49
: LGTM! Proper relationship definition.The belongsTo relationship with User is correctly defined.
app/Http/Controllers/API/ApiController.php (1)
Line range hint
9-35
: LGTM! Comprehensive OpenAPI security configuration.The bearer token authentication is properly configured with clear documentation.
app/Http/Controllers/API/v1/Auth/AuthController.php (1)
Line range hint
14-91
: LGTM! Well-documented authentication endpoints.The OpenAPI documentation is comprehensive and correctly specifies:
- Authentication tag and description
- Security requirements (none for auth endpoints)
- Request/response schemas
app/Http/Controllers/API/v1/Auth/PasswordResetController.php (1)
14-14
: LGTM! OpenAPI documentation changes are well-structured.The addition of OpenAPI tags and security configurations correctly documents that these password reset endpoints are publicly accessible (no authentication required).
Also applies to: 22-22, 89-89
public/docs/api.json (1)
74-74
: LGTM! Security configurations are well-structured.The changes properly configure authentication:
- Public endpoints (/register, /login, password reset) are correctly marked as not requiring authentication
- Bearer token authentication is properly defined as the default security scheme
- Global security requirement ensures authenticated access by default
Also applies to: 124-124, 175-175, 239-239, 1524-1529, 1532-1536
'username' => fake()->unique()->userName(), | ||
'phone' => fake()->phoneNumber(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Phone number validation needs improvement
The review comment is valid. Current implementation has basic validation but could be enhanced:
- Database: Phone is nullable without uniqueness constraint
- Validation rules only check for string type and max length
- No specific phone number format validation
Locations requiring attention:
database/migrations/2014_10_12_000000_create_users_table.php
: Consider adding unique constraint if phone numbers should be uniqueapp/Http/Controllers/API/v1/Auth/AuthController.php
: Consider adding phone format validation using regex or Laravel's phone validation rule
🔗 Analysis chain
Consider adding phone number validation and uniqueness constraints.
While the username field is correctly marked as unique, the phone number field might benefit from:
- Format validation to ensure consistent phone number formats
- Potentially marking it as unique if phone numbers should be unique per user
Let's check if phone validation exists in the User model:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for phone validation rules in User model and migration
echo "Checking User model for phone validation:"
rg -A 5 "phone" app/Models/User.php || echo "User.php not found"
echo -e "\nChecking User migration for phone constraints:"
fd -e php -x grep -l "phone" {} \; -x cat {} \; database/migrations/
Length of output: 768
Script:
#!/bin/bash
# Search migrations with correct path pattern
echo "Checking migrations for phone column:"
fd . database/migrations/ -e php -x grep -l "phone" {} \; -x cat {} \;
echo -e "\nChecking for Form Request validation rules:"
fd -e php -x grep -A 5 "phone.*=>" {} \; app/Http/Requests/
echo -e "\nChecking for any phone validation rules across codebase:"
rg "phone.*=>" -A 5 app/
Length of output: 2547
database/migrations/2024_07_20_125016_create_transactions_table.php
Outdated
Show resolved
Hide resolved
2b106a8
to
ed7e2aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments.
Actionable comments posted: 9
🔭 Outside diff range comments (4)
app/Models/User.php (1)
Line range hint
19-19
: Fix typo in fillable array.There's a typo in the
$fillable
array:'lsat_name'
should be'last_name'
.- 'lsat_name', + 'last_name',app/Http/Controllers/API/ApiController.php (1)
Fix OpenAPI server variables syntax error
The error occurs because the ServerVariable objects are incorrectly instantiated using
new
within the attribute. Here's the correct syntax:#[OA\Server( url: '{protocol}://{host}/api/v1', description: 'Dynamic server URL', variables: [ new OA\ServerVariable( name: 'protocol', default: 'https', enum: ['http', 'https'] ), new OA\ServerVariable( name: 'host', default: 'api.trakli.io', enum: ['api.trakli.io', 'api.staging.example.com'] ) ] )]The variables property should be an array of ServerVariable objects without using the
new
keyword directly in the attribute definition.🔗 Analysis chain
Line range hint
22-28
: Investigate and fix the server variables error.The TODO comment indicates an issue with server variables. This should be investigated to ensure proper dynamic server URL configuration.
Let's verify the OpenAPI specification for server variables:
Would you like me to investigate the error and propose a solution?
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check OpenAPI specification for server variables syntax curl -s https://raw.githubusercontent.com/OAI/OpenAPI-Specification/main/versions/3.0.0.md | grep -A 10 "##### Server Variable Object"Length of output: 136
Script:
#!/bin/bash # Search for OpenAPI server annotations and their implementations ast-grep --pattern 'new OA\Server' # Search for other OpenAPI variable definitions ast-grep --pattern 'new OA\ServerVariable' # Check composer.json for OpenAPI library version cat composer.json # Search for any error messages related to ServerVariable rg -i "servervariable.*error" -A 2 -B 2Length of output: 68197
Script:
#!/bin/bash # Search for OpenAPI server configurations in PHP files rg -t php "@OA\\Server" -B 2 -A 2 # Search for any OpenAPI server variable examples or documentation fd -e php -e md . | xargs rg -l "ServerVariable" # Check for any OpenAPI generation errors in logs fd -e log . | xargs rg -i "openapi|swagger" -A 2 -B 2 # Look for example OpenAPI configurations fd README -e md | xargs rg -i "openapi|swagger" -A 2 -B 2Length of output: 66193
Script:
#!/bin/bash # Get the full content of ApiController.php cat app/Http/Controllers/API/ApiController.php # Check for any OpenAPI server examples in the codebase rg -B 2 -A 2 "@OA\\Server"Length of output: 3442
app/Http/Controllers/API/v1/TransactionController.php (1)
Line range hint
314-327
: Add type filtering and improve error handling.The method should maintain consistency with other endpoints by including type filtering.
Apply this diff to improve the implementation:
- public function destroy($id): JsonResponse + public function destroy($id, Request $request): JsonResponse { - $transaction = Transaction::find($id); + $type = $request->query('type'); + $query = Transaction::query(); + if (!empty($type)) { + if (!in_array($type, ['income', 'expense'])) { + return $this->failure('Invalid transaction type', 400); + } + $query->where('type', $type); + } + $transaction = $query->find($id); if (! $transaction) { - return $this->failure('Transaction not found', 404); + return $this->failure('Transaction not found', 404, [ + 'id' => $id, + 'type' => $type + ]); } $this->userCanAccessResource($transaction); - $transaction->delete(); + try { + $transaction->delete(); + } catch (\Exception $e) { + return $this->failure('Failed to delete transaction', 500, ['error' => $e->getMessage()]); + } return $this->success(['message' => 'Transaction deleted successfully']); }public/docs/api.json (1)
Line range hint
1479-1482
: Update required fields in Transaction schema.The required fields list is outdated and includes the removed
date
field.Apply this diff to fix the required fields:
"required": [ "id", "type", - "date" + "amount", + "datetime" ],
♻️ Duplicate comments (2)
database/migrations/2024_07_20_125016_create_transactions_table.php (1)
35-35
:⚠️ Potential issueFix incorrect table name in down() method.
The down() method attempts to drop 'incomes' table instead of 'transactions'.
🧰 Tools
🪛 GitHub Actions: Checks
[error] 14: Failed to create foreign key constraint 'transactions_wallet_id_foreign'. The referenced table 'wallets' does not exist. Ensure the 'wallets' table migration is created and runs before the transactions table migration.
public/docs/api.json (1)
957-959
:⚠️ Potential issueFix datetime format in OpenAPI specification.
The
datetime
field uses "date" format, but since it represents both date and time, it should use "date-time" format to comply with RFC3339.Also applies to: 1490-1493
🧹 Nitpick comments (5)
tests/Feature/TransactionsTest.php (1)
20-32
: Consider linking wallet and party to the same user.
Currently, the wallet and party are created for different, random users rather than for$this->user
. This could lead to inconsistencies if the tested logic relies on ownership or associations.app/Models/Transaction.php (2)
48-51
: Add return type hints to accessor methods.For better type safety and IDE support, add return type hints to the accessor methods.
Apply this diff to add return type hints:
- public function getCategoriesAttribute() + public function getCategoriesAttribute(): \Illuminate\Database\Eloquent\Collection { return $this->categories()->get(); } - public function getWalletAttribute() + public function getWalletAttribute(): ?\App\Models\Wallet { return $this->wallet()->first(); } - public function getPartyAttribute() + public function getPartyAttribute(): ?\App\Models\Party { return $this->party()->first(); }Also applies to: 53-56, 58-61
63-66
: Add return type hints to relationship methods.For better type safety and IDE support, add return type hints to the relationship methods.
Apply this diff to add return type hints:
- public function wallet() + public function wallet(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Wallet::class); } - public function party() + public function party(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(Party::class); } - public function user() + public function user(): \Illuminate\Database\Eloquent\Relations\BelongsTo { return $this->belongsTo(User::class); }Also applies to: 68-71, 73-76
app/Http/Controllers/API/ApiController.php (2)
41-55
: Enhance type safety and error messaging.Add type hints and improve the error message for better debugging.
Apply this diff to enhance the method:
- public function userCanAccessResource($resource, $ownerKey = 'user_id') + public function userCanAccessResource(mixed $resource, string $ownerKey = 'user_id'): void { if (auth()->id() !== $resource->{$ownerKey}) { - abort(Response::HTTP_FORBIDDEN, 'You are not authorized to access this resource.'); + abort(Response::HTTP_FORBIDDEN, + sprintf('Access denied. Resource %s#%s belongs to a different user.', + get_class($resource), + $resource->id ?? 'unknown' + ) + ); } }
57-85
: Enhance type safety and error messaging in validation.Add return type hint and improve error messages for better debugging.
Apply this diff to enhance the method:
- protected function validateRequest(Request $request, array $rules): array + protected function validateRequest(Request $request, array $rules): array { $validator = Validator::make($request->all(), $rules); if ($validator->fails()) { $errors = $validator->errors(); if ($errors->hasAny(array_keys($rules))) { return [ 'isValidated' => false, - 'message' => 'Server failed to validate request.', + 'message' => sprintf('Validation failed for fields: %s', implode(', ', array_keys($errors->messages()))), 'code' => 422, 'errors' => $errors->toArray(), ]; } return [ 'isValidated' => false, - 'message' => 'Server unable to process request.', + 'message' => 'Request validation failed for unknown fields.', 'code' => 400, 'errors' => $errors->toArray(), ]; } return ['isValidated' => true, 'data' => $validator->validated()]; }
🛑 Comments failed to post (9)
tests/Feature/TransactionsTest.php (1)
189-189: 🛠️ Refactor suggestion
Avoid relying on a random user ID.
UsingUser::find(rand(1, 5))
could yield null or a user that does not exist, creating flakiness in tests. Replace withUser::factory()->create()
to ensure a reliable user object.tests/TestCase.php (1)
11-20: 💡 Codebase verification
⚠️ Test isolation is compromised across all test filesThe current implementation affects all test files as they extend TestCase, but no database transaction handling is implemented. This will cause:
- Shared database state between tests
- Potential false positives/negatives due to data pollution
- Hard-to-debug test failures
Recommended fixes:
- Use Laravel's
RefreshDatabase
trait in TestCase.php- Remove the static flag and migration optimization
- Let each test start with a fresh database state
🔗 Analysis chain
Consider test isolation implications.
While running migrations once improves performance, it could lead to test interdependence and state pollution. Consider:
- Using database transactions for test isolation
- Implementing a test-specific cleanup mechanism
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if tests are using database transactions rg -l "RefreshDatabase|DatabaseTransactions" "tests/"Length of output: 194
Script:
#!/bin/bash # Check for actual trait usage and TestCase extension echo "=== Checking trait imports ===" rg "use .+\\{.*(?:RefreshDatabase|DatabaseTransactions).*\\}" tests/ echo -e "\n=== Checking TestCase extension ===" rg "class \w+ extends (?:TestCase|\\\Tests\\\TestCase)" tests/ echo -e "\n=== Finding all test files ===" fd "Test\.php$" tests/Length of output: 932
database/migrations/2024_07_20_125016_create_transactions_table.php (1)
14-27: 💡 Codebase verification
⚠️ Potential issueConfirmed: Migration ordering needs to be fixed
The transactions table migration (125016) runs before both the parties (125104) and wallets (125116) tables are created, which will cause foreign key constraint failures. Rename the migrations to fix the ordering:
- Keep
2024_07_20_125104_create_parties_table.php
as is- Keep
2024_07_20_125116_create_wallets_table.php
as is- Rename transactions migration to
2024_07_20_125130_create_transactions_table.php
🔗 Analysis chain
Fix migration dependencies.
The pipeline failure indicates that the 'wallets' table doesn't exist when creating foreign key constraints. This migration should run after the wallets and parties tables are created.
Add a timestamp prefix to ensure correct ordering:
- First create wallets migration (e.g.,
2024_07_20_125015_create_wallets_table.php
)- Then create parties migration
- Finally, this transactions migration
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check migration ordering ls -la database/migrations/*_create_*_table.phpLength of output: 2039
🧰 Tools
🪛 GitHub Actions: Checks
[error] 14: Failed to create foreign key constraint 'transactions_wallet_id_foreign'. The referenced table 'wallets' does not exist. Ensure the 'wallets' table migration is created and runs before the transactions table migration.
app/Models/Transaction.php (2)
26-26:
⚠️ Potential issueAdd 'datetime' to required fields.
The
datetime
field should be required as it's essential for transaction records.Apply this diff to update the required fields:
- required: ['amount', 'type'] + required: ['amount', 'type', 'datetime']📝 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.required: ['amount', 'type', 'datetime']
18-18:
⚠️ Potential issueFix the datetime format in OpenAPI schema.
The
datetime
field uses 'date' format, but since it represents both date and time, it should use 'date-time' format to comply with RFC3339.Apply this diff to fix the format:
- new OA\Property(property: 'datetime', type: 'string', format: 'date', description: 'Date and time of the transaction'), + new OA\Property(property: 'datetime', type: 'string', format: 'date-time', description: 'Date and time of the transaction'),📝 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.new OA\Property(property: 'datetime', type: 'string', format: 'date-time', description: 'Date and time of the transaction'),
app/Http/Controllers/API/v1/TransactionController.php (4)
173-188: 🛠️ Refactor suggestion
Refactor duplicate query logic and ensure consistent type filtering.
The method contains duplicate query logic and inconsistent type filtering.
Apply this diff to improve the implementation:
- if (empty($type)) { - $transaction = Transaction::find($id); - } else { - $transaction = Transaction::where('type', $type)->find($id); - } + $query = Transaction::query(); + if (!empty($type)) { + $query->where('type', $type); + } + $transaction = $query->find($id); if (! $transaction) { return $this->failure('Transaction not found', 404); } $this->userCanAccessResource($transaction);📝 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.if (! empty($type) && ! in_array($type, ['income', 'expense'])) { return $this->failure('Invalid transaction type', 400); } $query = Transaction::query(); if (!empty($type)) { $query->where('type', $type); } $transaction = $query->find($id); if (! $transaction) { return $this->failure('Transaction not found', 404); } $this->userCanAccessResource($transaction);
49-63: 🛠️ Refactor suggestion
Refactor duplicate query logic and add limit validation.
The method contains duplicate query logic and lacks validation for the limit parameter.
Apply this diff to improve the implementation:
public function index(Request $request): JsonResponse { $type = $request->query('type'); - $limit = $request->query('limit', 20); + $limit = min(max((int) $request->query('limit', 20), 1), 100); if (! empty($type) && ! in_array($type, ['income', 'expense'])) { return $this->failure('Invalid transaction type', 400); } - if (empty($type)) { - $transactions = auth()->user()->transactions()->paginate($limit); + $query = auth()->user()->transactions(); - return $this->success($transactions); - } else { - $transactions = auth()->user()->transactions()->where('type', $type)->paginate($limit); + if (!empty($type)) { + $query->where('type', $type); } + $transactions = $query->paginate($limit); return $this->success($transactions); }📝 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.$type = $request->query('type'); $limit = min(max((int) $request->query('limit', 20), 1), 100); if (! empty($type) && ! in_array($type, ['income', 'expense'])) { return $this->failure('Invalid transaction type', 400); } $query = auth()->user()->transactions(); if (!empty($type)) { $query->where('type', $type); } $transactions = $query->paginate($limit); return $this->success($transactions);
100-130: 🛠️ Refactor suggestion
Add transaction to error response and handle race conditions.
The method should include transaction details in error responses and handle potential race conditions in category sync.
Apply this diff to improve the implementation:
public function store(Request $request): JsonResponse { + \DB::beginTransaction(); + try { $validationResult = $this->validateRequest($request, [ 'amount' => 'required|numeric|min:0.01', 'type' => 'required|string|in:income,expense', 'description' => 'nullable|string', 'datetime' => 'nullable|date', 'group_id' => 'nullable|integer|exists:groups,id', 'party_id' => 'nullable|integer|exists:parties,id', 'wallet_id' => 'nullable|integer|exists:wallets,id', 'categories' => 'nullable|array', 'categories.*' => 'integer|exists:categories,id', ]); if (! $validationResult['isValidated']) { - return $this->failure($validationResult['message'], $validationResult['code'], $validationResult['errors']); + return $this->failure( + $validationResult['message'], + $validationResult['code'], + array_merge($validationResult['errors'], ['request_data' => $request->all()]) + ); } $request = $validationResult['data']; $categories = []; if (isset($request['categories'])) { $categories = $request['categories']; unset($request['categories']); } $transaction = auth()->user()->transactions()->create($request); if (! empty($categories)) { $transaction->categories()->sync($categories); } + \DB::commit(); return $this->success($transaction, statusCode: 201); + } catch (\Exception $e) { + \DB::rollBack(); + return $this->failure('Failed to create transaction', 500, ['error' => $e->getMessage()]); + } }📝 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.$validationResult = $this->validateRequest($request, [ 'amount' => 'required|numeric|min:0.01', 'type' => 'required|string|in:income,expense', 'description' => 'nullable|string', 'datetime' => 'nullable|date', 'group_id' => 'nullable|integer|exists:groups,id', 'party_id' => 'nullable|integer|exists:parties,id', 'wallet_id' => 'nullable|integer|exists:wallets,id', 'categories' => 'nullable|array', 'categories.*' => 'integer|exists:categories,id', ]); \DB::beginTransaction(); try { if (! $validationResult['isValidated']) { return $this->failure( $validationResult['message'], $validationResult['code'], array_merge($validationResult['errors'], ['request_data' => $request->all()]) ); } $request = $validationResult['data']; $categories = []; if (isset($request['categories'])) { $categories = $request['categories']; unset($request['categories']); } $transaction = auth()->user()->transactions()->create($request); if (! empty($categories)) { $transaction->categories()->sync($categories); } \DB::commit(); return $this->success($transaction, statusCode: 201); } catch (\Exception $e) { \DB::rollBack(); return $this->failure('Failed to create transaction', 500, ['error' => $e->getMessage()]); }
245-276: 🛠️ Refactor suggestion
Add transaction to error response, handle race conditions, and ensure consistent type filtering.
The method needs several improvements for better error handling and consistency.
Apply this diff to improve the implementation:
public function update(Request $request, $id): JsonResponse { + \DB::beginTransaction(); + try { $validationResult = $this->validateRequest($request, [ 'amount' => 'nullable|numeric|min:0.01', 'type' => 'nullable|string|in:income,expense', 'datetime' => 'nullable|date', 'description' => 'nullable|string', 'party_id' => 'nullable|integer|exists:parties,id', 'wallet_id' => 'nullable|integer|exists:wallets,id', 'group_id' => 'nullable|integer|exists:groups,id', 'categories' => 'nullable|array', 'categories.*' => 'integer|exists:categories,id', ]); if (! $validationResult['isValidated']) { - return $this->failure($validationResult['message'], $validationResult['code'], $validationResult['errors']); + return $this->failure( + $validationResult['message'], + $validationResult['code'], + array_merge($validationResult['errors'], ['request_data' => $request->all()]) + ); } $validatedData = $validationResult['data']; - $transaction = Transaction::find($id); + $type = $request->query('type'); + $query = Transaction::query(); + if (!empty($type)) { + $query->where('type', $type); + } + $transaction = $query->find($id); if (! $transaction) { return $this->failure('Transaction not found', 404); } $this->userCanAccessResource($transaction); $transaction->update(array_filter($validatedData, fn ($value) => $value !== null)); if (isset($validatedData['categories'])) { $transaction->categories()->sync($validatedData['categories']); } + \DB::commit(); return $this->success($transaction, 200); + } catch (\Exception $e) { + \DB::rollBack(); + return $this->failure('Failed to update transaction', 500, ['error' => $e->getMessage()]); + } }📝 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.$validationResult = $this->validateRequest($request, [ 'amount' => 'nullable|numeric|min:0.01', 'type' => 'nullable|string|in:income,expense', 'datetime' => 'nullable|date', 'description' => 'nullable|string', 'party_id' => 'nullable|integer|exists:parties,id', 'wallet_id' => 'nullable|integer|exists:wallets,id', 'group_id' => 'nullable|integer|exists:groups,id', 'categories' => 'nullable|array', 'categories.*' => 'integer|exists:categories,id', ]); \DB::beginTransaction(); try { if (! $validationResult['isValidated']) { return $this->failure( $validationResult['message'], $validationResult['code'], array_merge($validationResult['errors'], ['request_data' => $request->all()]) ); } $validatedData = $validationResult['data']; $type = $request->query('type'); $query = Transaction::query(); if (!empty($type)) { $query->where('type', $type); } $transaction = $query->find($id); if (! $transaction) { return $this->failure('Transaction not found', 404); } $this->userCanAccessResource($transaction); $transaction->update(array_filter($validatedData, fn ($value) => $value !== null)); if (isset($validatedData['categories'])) { $transaction->categories()->sync($validatedData['categories']); } \DB::commit(); return $this->success($transaction, 200); } catch (\Exception $e) { \DB::rollBack(); return $this->failure('Failed to update transaction', 500, ['error' => $e->getMessage()]); }
Signed-off-by: nfebe <fenn25.fn@gmail.com>
Signed-off-by: nfebe <fenn25.fn@gmail.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
🧹 Nitpick comments (3)
database/migrations/2024_07_20_125117_create_transactions_table.php (1)
20-25
: Add indexes for foreign keys and timestamps.Missing indexes on foreign keys and timestamps could impact query performance, especially for large datasets.
$table->foreign('wallet_id')->references('id')->on('wallets')->onDelete('cascade'); $table->foreign('party_id')->references('id')->on('parties')->onDelete('cascade'); $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->index(['wallet_id']); + $table->index(['party_id']); + $table->index(['user_id']); $table->timestamps(); + $table->index(['created_at', 'updated_at']);app/Http/Controllers/API/ApiController.php (1)
60-60
: Add return type hint to validateRequest method.The method should explicitly declare its return type for better type safety.
- protected function validateRequest(Request $request, array $rules): array + protected function validateRequest(Request $request, array $rules): array{isValidated: bool, message?: string, code?: int, errors?: array<string, array<int, string>>, data?: array}app/Http/Controllers/API/v1/TransactionController.php (1)
124-128
: Optimize categories relationship loading.Loading categories separately could lead to N+1 query issues. Consider eager loading the relationship.
- $transaction = auth()->user()->transactions()->create($request); + $transaction = auth()->user()->transactions()->create($request); + $transaction->load('categories'); if (! empty($categories)) { $transaction->categories()->sync($categories); + $transaction->load('categories'); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
app/Http/Controllers/API/ApiController.php
(2 hunks)app/Http/Controllers/API/v1/TransactionController.php
(9 hunks)app/Models/User.php
(1 hunks)database/migrations/2024_07_20_125117_create_transactions_table.php
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- app/Models/User.php
🔇 Additional comments (2)
app/Http/Controllers/API/v1/TransactionController.php (2)
73-82
: Sync OpenAPI required fields with validation rules.The OpenAPI documentation shows different required fields compared to the actual validation rules in the store method.
- required: ['amount', 'type'], + required: ['amount', 'type', 'datetime'],
261-262
: Add type filter to update method.The update method should filter by type like show/destroy methods for consistency.
- $transaction = Transaction::find($id); + $transaction = Transaction::where('type', $request->query('type'))->find($id);
database/migrations/2024_07_20_125117_create_transactions_table.php
Outdated
Show resolved
Hide resolved
ed7e2aa
to
da79e3f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
♻️ Duplicate comments (1)
app/Listeners/UserRegistered.php (1)
33-38
:⚠️ Potential issueOptimize group creation and add error handling.
The current implementation has several issues:
- Multiple database calls in the loop
- Missing slug generation (required by the Group model's Sluggable trait)
- No error handling for database operations
Here's an improved implementation:
- foreach ($defaultGroups as $group) { - $user->groups()->create([ - 'name' => $group, - 'description' => "Default group for $group", - ]); - } + try { + $groups = collect($defaultGroups)->map(function ($group) { + return [ + 'name' => $group, + 'slug' => Str::slug($group), + 'description' => "Default group for $group", + 'created_at' => now(), + 'updated_at' => now(), + ]; + })->all(); + + $user->groups()->createMany($groups); + } catch (\Exception $e) { + \Log::error('Failed to create default groups for user: ' . $user->id, [ + 'error' => $e->getMessage() + ]); + throw $e; + }Don't forget to add these imports:
use Illuminate\Support\Str; use Illuminate\Support\Facades\Log;
🧹 Nitpick comments (7)
app/Listeners/UserRegistered.php (2)
24-31
: Consider moving default groups to configuration.The hardcoded group names should be moved to configuration to allow for easier customization and maintenance.
Create a new config file
config/groups.php
:<?php return [ 'defaults' => [ 'General', 'Personal', 'Family', 'Friends', 'Work', ] ];Then update the code to use the config:
- $defaultGroups = [ - 'General', - 'Personal', - 'Family', - 'Friends', - 'Work', - ]; + $defaultGroups = config('groups.defaults');
Line range hint
1-40
: Add type hints and return types.The class is missing type hints and return types which help with code maintainability and catch potential errors early.
/** * Handle the event. * + * @param UserRegisteredEvent $event * @return void */ - public function handle(UserRegisteredEvent $event) + public function handle(UserRegisteredEvent $event): voidapp/Http/Controllers/API/ApiController.php (1)
61-89
: Enhance error messages for better clarity.While the validation logic is solid, consider making the error messages more specific to help clients better understand the validation failures.
Apply this diff to improve the error messages:
'isValidated' => false, - 'message' => 'Server failed to validate request.', + 'message' => 'Validation failed. Please check the provided data.', 'code' => 422, 'errors' => $errors->toArray(), 'isValidated' => false, - 'message' => 'Server unable to process request.', + 'message' => 'Invalid request format. Please check the request structure.', 'code' => 400, 'errors' => $errors->toArray(),database/seeders/UserSeeder.php (2)
5-9
: Consider organizing imports alphabetically for better readability.While not critical, organizing imports alphabetically is a common convention that improves code maintainability.
-use App\Models\Category; -use App\Models\Group; -use App\Models\Party; -use App\Models\User; -use App\Models\Wallet; +use App\Models\Category; +use App\Models\Group; +use App\Models\Party; +use App\Models\User; +use App\Models\Wallet;
22-36
: Consider refactoring repeated factory calls into a reusable method.The current implementation has duplicate patterns for creating related entities. This could be simplified for better maintainability.
class UserSeeder extends Seeder { + private function createRelatedEntities(User $user, string $model, int $count = 5): void + { + $model::factory($count)->create([ + 'user_id' => $user->id, + ]); + } + public function run(): void { foreach (range(1, 10) as $index) { $user = User::factory()->create([ 'email' => "user{$index}@trakli.io", 'username' => "user{$index}", ]); - Party::factory(5)->create([ - 'user_id' => $user->id, - ]); - - Category::factory(5)->create([ - 'user_id' => $user->id, - ]); - - Wallet::factory(5)->create([ - 'user_id' => $user->id, - ]); - - Group::factory(5)->create([ - 'user_id' => $user->id, - ]); + $this->createRelatedEntities($user, Party::class); + $this->createRelatedEntities($user, Category::class); + $this->createRelatedEntities($user, Wallet::class); + $this->createRelatedEntities($user, Group::class); } } }tests/Feature/TransactionsTest.php (2)
34-58
: Enhance test coverage for transaction creation.The test verifies the response structure but doesn't assert the actual values. Also, the test for the categories feature is missing.
Add these assertions to strengthen the test:
$response->assertStatus(201) ->assertJsonStructure([ 'success', 'data' => [ 'amount', 'wallet_id', 'party_id', 'datetime', ], 'message', - ]); + ]) + ->assertJson([ + 'data' => [ + 'amount' => 100, + 'type' => 'expense', + 'wallet_id' => $this->wallet->id, + 'party_id' => $this->party->id, + 'datetime' => '2025-01-01', + ] + ]); $this->assertDatabaseHas('transactions', ['id' => $response->json('data.id')]); + + // Test with categories + $categories = Category::factory()->count(2)->create(['user_id' => $this->user->id]); + $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ + 'type' => 'expense', + 'amount' => 100, + 'wallet_id' => $this->wallet->id, + 'party_id' => $this->party->id, + 'datetime' => '2025-01-01', + 'categories' => $categories->pluck('id')->toArray(), + ]); + + $response->assertStatus(201); + $transaction = Transaction::find($response->json('data.id')); + $this->assertEquals($categories->pluck('id')->toArray(), $transaction->categories->pluck('id')->toArray());
91-118
: Enhance transaction update test coverage.The test should verify the actual updated values and test the categories update feature.
Apply this diff to improve the test:
public function test_api_user_can_update_their_transactions() { - $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ - 'type' => 'expense', - 'amount' => 100, - 'wallet_id' => $this->wallet->id, - 'party_id' => $this->party->id, - 'datetime' => '2025-01-01', - ]); - - $response->assertStatus(201); + $transaction = $this->createTransaction('expense'); + $categories = Category::factory()->count(2)->create(['user_id' => $this->user->id]); - $response = $this->actingAs($this->user)->putJson('/api/v1/transactions/'.$response->json('data.id'), [ + $response = $this->actingAs($this->user)->putJson('/api/v1/transactions/'.$transaction['id'], [ 'amount' => 200, + 'categories' => $categories->pluck('id')->toArray(), ]); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'data' => [ 'amount', 'wallet_id', 'party_id', 'datetime', ], 'message', - ]); + ]) + ->assertJson([ + 'data' => [ + 'amount' => 200, + 'type' => 'expense', + 'wallet_id' => $this->wallet->id, + 'party_id' => $this->party->id, + ] + ]); + + $updatedTransaction = Transaction::find($transaction['id']); + $this->assertEquals(200, $updatedTransaction->amount); + $this->assertEquals($categories->pluck('id')->toArray(), $updatedTransaction->categories->pluck('id')->toArray()); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (28)
app/Http/Controllers/API/ApiController.php
(2 hunks)app/Http/Controllers/API/v1/TransactionController.php
(9 hunks)app/Listeners/UserRegistered.php
(1 hunks)app/Models/Category.php
(1 hunks)app/Models/Expense.php
(0 hunks)app/Models/Group.php
(2 hunks)app/Models/Income.php
(0 hunks)app/Models/Party.php
(1 hunks)app/Models/Transaction.php
(2 hunks)app/Models/User.php
(1 hunks)app/Models/Wallet.php
(1 hunks)database/factories/CategoryFactory.php
(1 hunks)database/factories/GroupFactory.php
(1 hunks)database/factories/PartyFactory.php
(1 hunks)database/factories/UserFactory.php
(2 hunks)database/factories/WalletFactory.php
(1 hunks)database/migrations/2024_07_20_125016_create_incomes_table.php
(0 hunks)database/migrations/2024_07_20_125030_create_groups_table.php
(1 hunks)database/migrations/2024_07_20_125104_create_parties_table.php
(1 hunks)database/migrations/2024_07_20_125116_create_wallets_table.php
(1 hunks)database/migrations/2024_07_20_125117_create_transactions_table.php
(1 hunks)database/migrations/2024_07_20_125455_create_categories_table.php
(1 hunks)database/migrations/2025_01_25_232422_create_categorizables.php
(2 hunks)database/seeders/UserSeeder.php
(1 hunks)public/docs/api.json
(11 hunks)tests/Feature/AuthControllerTest.php
(2 hunks)tests/Feature/TransactionsTest.php
(1 hunks)tests/TestCase.php
(1 hunks)
💤 Files with no reviewable changes (3)
- app/Models/Income.php
- database/migrations/2024_07_20_125016_create_incomes_table.php
- app/Models/Expense.php
🚧 Files skipped from review as they are similar to previous changes (18)
- app/Models/Party.php
- database/factories/GroupFactory.php
- database/migrations/2024_07_20_125104_create_parties_table.php
- database/migrations/2024_07_20_125455_create_categories_table.php
- app/Models/Wallet.php
- tests/TestCase.php
- app/Models/Category.php
- database/factories/PartyFactory.php
- tests/Feature/AuthControllerTest.php
- database/factories/CategoryFactory.php
- database/factories/WalletFactory.php
- database/factories/UserFactory.php
- database/migrations/2024_07_20_125116_create_wallets_table.php
- app/Models/Group.php
- database/migrations/2024_07_20_125030_create_groups_table.php
- database/migrations/2025_01_25_232422_create_categorizables.php
- app/Models/User.php
- database/migrations/2024_07_20_125117_create_transactions_table.php
🔇 Additional comments (14)
app/Models/Transaction.php (4)
19-24
: LGTM! Well-structured categories property.The categories property is correctly defined as an array of integers with clear description.
32-44
: LGTM! Well-organized fillable attributes.The fillable attributes are comprehensive and alphabetically ordered for better readability.
46-61
: LGTM! Accessor methods are well-implemented.The accessor methods correctly use:
first()
for single relationships (wallet, party)get()
for collection relationships (categories)
63-81
: LGTM! Well-structured relationships.The relationships are correctly defined:
- belongsTo for wallet, party, and user
- morphToMany for categories, enabling flexible categorization across different models
app/Http/Controllers/API/ApiController.php (2)
Line range hint
12-38
: LGTM! Well-defined security scheme.The OpenAPI security attributes correctly define bearer token authentication with proper documentation.
41-59
: LGTM! Robust resource access control.The method provides comprehensive access control by:
- Checking for null resources
- Verifying resource ownership
tests/Feature/TransactionsTest.php (1)
120-154
: Replace hardcoded IDs with factory-created entities.Apply this diff to fix the hardcoded IDs:
public function test_api_user_cannot_create_transaction_with_invalid_type() { $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ 'type' => 'invalid_type', 'amount' => 100, - 'wallet_id' => 1, + 'wallet_id' => $this->wallet->id, 'datetime' => '2025-01-01', ]); $response->assertStatus(422) ->assertJsonValidationErrors(['type']); } public function test_api_user_cannot_create_transaction_with_invalid_amount() { $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ 'type' => 'expense', 'amount' => -100, - 'wallet_id' => 1, + 'wallet_id' => $this->wallet->id, 'datetime' => '2025-01-01', ]);app/Http/Controllers/API/v1/TransactionController.php (5)
50-60
: Include pagination metadata in response.Apply this diff to include pagination metadata:
$query = auth()->user()->transactions(); if (! empty($type)) { $query->where('type', $type); } $transactions = $query->paginate($limit); - return $this->success($transactions); + return $this->success([ + 'data' => $transactions->items(), + 'meta' => [ + 'current_page' => $transactions->currentPage(), + 'total' => $transactions->total(), + 'per_page' => $transactions->perPage(), + 'last_page' => $transactions->lastPage(), + ] + ]);
278-278
: Watch out for zero values with array_filter.Apply this diff to preserve zero values:
- $transaction->update(array_filter($validatedData)); + $transaction->update(array_filter($validatedData, fn($value) => $value !== null));
176-181
: Inconsistent type filter for show method.Apply this diff to consistently apply the type filter:
$query = Transaction::query(); if (! empty($type)) { $query->where('type', $type); } - $transaction = $query->find($id); + $transaction = $query->where('id', $id)->first();
221-227
: Mismatch between documentation and code.The OpenAPI documentation shows these fields as required, but the validation makes them optional. Update the documentation to match the code:
required: [ - 'date', - 'party_id', - 'wallet_id', - 'amount', - 'group_id' ],
315-327
: LGTM! Good error handling implementation.The error handling using HttpException and proper status codes is well implemented.
public/docs/api.json (2)
957-959
: Fix datetime format in OpenAPI specification.The
datetime
field uses "date" format, but since it represents both date and time, it should use "date-time" format to comply with RFC3339.Apply this diff to fix the format:
"datetime": { "type": "string", - "format": "date" + "format": "date-time" },Also applies to: 1482-1485
1516-1521
: LGTM! Well-structured security implementation.The security scheme is properly defined with bearer token authentication and correctly applied globally with exceptions for authentication endpoints.
Also applies to: 1524-1528
Signed-off-by: nfebe <fenn25.fn@gmail.com>
da79e3f
to
e03efe1
Compare
Signed-off-by: nfebe <fenn25.fn@gmail.com>
Signed-off-by: nfebe <fenn25.fn@gmail.com>
e03efe1
to
1701c65
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (4)
tests/Feature/TransactionsTest.php (2)
19-32
:⚠️ Potential issueFix test data ownership in setUp method.
The wallet and party are created for different users than the test user, which could lead to authorization issues.
protected function setUp(): void { parent::setUp(); - $this->wallet = User::factory()->create()->wallets()->create([ + $this->user = User::factory()->create(); + $this->wallet = $this->user->wallets()->create([ 'name' => 'Wallet', 'balance' => 1000, ]); - $this->party = User::factory()->create()->parties()->create([ + $this->party = $this->user->parties()->create([ 'name' => 'Party', 'type' => 'personal', ]); - $this->user = User::factory()->create(); }
98-132
: 🛠️ Refactor suggestionReplace hardcoded IDs in validation tests.
Using hardcoded IDs may cause test failures if these records don't exist.
public function test_api_user_cannot_create_transaction_with_invalid_type() { $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ 'type' => 'invalid_type', 'amount' => 100, - 'wallet_id' => 1, + 'wallet_id' => $this->wallet->id, 'datetime' => '2025-01-01', ]); public function test_api_user_cannot_create_transaction_with_invalid_amount() { $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ 'type' => 'expense', 'amount' => -100, - 'wallet_id' => 1, + 'wallet_id' => $this->wallet->id, 'datetime' => '2025-01-01', ]);app/Http/Controllers/API/v1/TransactionController.php (2)
50-62
: 🛠️ Refactor suggestionInclude pagination metadata in response.
The paginated response should include metadata for better client-side handling.
$query = auth()->user()->transactions(); if (! empty($type)) { $query->where('type', $type); } $transactions = $query->paginate($limit); - return $this->success($transactions); + return $this->success([ + 'data' => $transactions->items(), + 'meta' => [ + 'current_page' => $transactions->currentPage(), + 'total' => $transactions->total(), + 'per_page' => $transactions->perPage(), + 'last_page' => $transactions->lastPage(), + ] + ]);
278-278
:⚠️ Potential issueWatch out for zero values with array_filter.
array_filter($validatedData)
will drop non-empty but falsy values like "0.0" or 0.- $transaction->update(array_filter($validatedData)); + $transaction->update(array_filter($validatedData, fn($value) => $value !== null));
🧹 Nitpick comments (2)
app/Http/Controllers/API/ApiController.php (1)
61-89
: Consider enhancing error message clarity.The error messages could be more specific to help API consumers better understand the validation failures.
'isValidated' => false, - 'message' => 'Server failed to validate request.', + 'message' => 'Validation failed: One or more required fields are invalid.', 'code' => 422, 'errors' => $errors->toArray(), 'isValidated' => false, - 'message' => 'Server unable to process request.', + 'message' => 'Bad request: The provided data is invalid.', 'code' => 400,public/docs/api.json (1)
1530-1533
: Enhance tag descriptions for better API documentation.The Authentication tag's description only mentions password reset endpoints, but it also includes registration and login endpoints.
Apply this diff to improve the description:
{ "name": "Authentication", - "description": "Endpoints for password reset" + "description": "Endpoints for user registration, login, and password reset" },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
app/Http/Controllers/API/ApiController.php
(2 hunks)app/Http/Controllers/API/v1/TransactionController.php
(9 hunks)app/Models/Party.php
(1 hunks)app/Models/User.php
(1 hunks)app/Models/Wallet.php
(1 hunks)database/migrations/2024_07_20_125117_create_transactions_table.php
(1 hunks)public/docs/api.json
(11 hunks)tests/Feature/AuthControllerTest.php
(2 hunks)tests/Feature/TransactionsTest.php
(1 hunks)tests/TestCase.php
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
- app/Models/Party.php
- tests/Feature/AuthControllerTest.php
- app/Models/Wallet.php
- tests/TestCase.php
- database/migrations/2024_07_20_125117_create_transactions_table.php
- app/Models/User.php
🔇 Additional comments (7)
app/Http/Controllers/API/ApiController.php (2)
Line range hint
12-38
: LGTM! Well-structured OpenAPI security configuration.The OpenAPI attributes are well-organized, properly defining bearer token authentication as the security scheme.
41-59
: LGTM! Robust resource access control implementation.The
userCanAccessResource
method includes proper null checks and clear error messages. This matches the previously suggested implementation.tests/Feature/TransactionsTest.php (2)
34-46
: Replace hardcoded values in createTransaction helper.The helper method uses hardcoded values which could make tests brittle.
- private function createTransaction(string $type): array + private function createTransaction(string $type, float $amount = 100.00): array { $response = $this->actingAs($this->user)->postJson('/api/v1/transactions', [ 'type' => $type, - 'amount' => 100, + 'amount' => $amount, 'wallet_id' => $this->wallet->id, 'party_id' => $this->party->id, 'datetime' => '2025-01-01', ]);
57-75
: Improve transaction retrieval test coverage.The test has several areas for improvement:
- Missing assertions for the response data
- Not testing the
limit
parameter thoroughlypublic function test_api_user_can_get_their_transactions() { - $this->createTransaction('expense'); - $this->createTransaction('income'); + $expense = $this->createTransaction('expense'); + $income = $this->createTransaction('income'); $response = $this->actingAs($this->user)->getJson('/api/v1/transactions?type=expense'); - $response->assertStatus(200); + $response->assertStatus(200) + ->assertJsonCount(1, 'data') + ->assertJsonPath('data.0.id', $expense['id']); $response = $this->actingAs($this->user)->getJson('/api/v1/transactions?type=income'); - $response->assertStatus(200); + $response->assertStatus(200) + ->assertJsonCount(1, 'data') + ->assertJsonPath('data.0.id', $income['id']); // Test limit parameter - $this->createTransaction('expense'); - $this->createTransaction('expense'); + $expense2 = $this->createTransaction('expense'); + $expense3 = $this->createTransaction('expense'); $response = $this->actingAs($this->user)->getJson('/api/v1/transactions?type=expense&limit=2'); $response->assertStatus(200) - ->assertJsonCount(2, 'data.data'); + ->assertJsonCount(2, 'data') + ->assertJsonPath('data.0.id', $expense3['id']) + ->assertJsonPath('data.1.id', $expense2['id']); + + // Test default limit + $response = $this->actingAs($this->user)->getJson('/api/v1/transactions?type=expense'); + $response->assertStatus(200) + ->assertJsonCount(3, 'data');app/Http/Controllers/API/v1/TransactionController.php (1)
Line range hint
957-959
: Fix datetime format in OpenAPI specification.The
datetime
field uses "date" format, but since it represents both date and time, it should use "date-time" format to comply with RFC3339."datetime": { "type": "string", - "format": "date" + "format": "date-time" },Also applies to: 1482-1486
public/docs/api.json (2)
73-74
: LGTM! Security implementation follows best practices.The security implementation correctly:
- Excludes authentication endpoints from bearer token requirement
- Implements global bearer token authentication for protected endpoints
- Uses standard HTTP Bearer scheme
Also applies to: 123-124, 174-175, 238-239, 1515-1528
957-959
: Fix datetime format in OpenAPI specification.The
datetime
field uses "date" format, but since it represents both date and time, it should use "date-time" format to comply with RFC3339.Apply this diff to fix the format:
"datetime": { "type": "string", - "format": "date" + "format": "date-time" },Also applies to: 1482-1485
"type" | ||
], | ||
"properties": { | ||
"amount": { | ||
"type": "number", | ||
"format": "float" | ||
}, | ||
"type": { | ||
"type": "string", | ||
"enum": [ | ||
"income", | ||
"expense" | ||
] | ||
}, | ||
"date": { | ||
"description": { | ||
"type": "string" | ||
}, | ||
"datetime": { | ||
"type": "string", | ||
"format": "date" | ||
}, | ||
"party_id": { | ||
"type": "integer" | ||
}, | ||
"description": { | ||
"type": "string" | ||
}, | ||
"wallet_id": { | ||
"type": "integer" | ||
}, | ||
"amount": { | ||
"type": "number", | ||
"format": "float" | ||
}, | ||
"group_id": { | ||
"type": "integer" | ||
}, | ||
"categories": { | ||
"type": "array", | ||
"items": { | ||
"description": "Category ID array", | ||
"type": "integer" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistency in required fields between POST and PUT endpoints.
The POST endpoint requires only amount
and type
, while the PUT endpoint requires additional fields (date
, party_id
, wallet_id
, group_id
). This inconsistency could lead to confusion.
Apply this diff to align the required fields:
"required": [
"date",
"party_id",
"wallet_id",
"amount",
- "group_id"
+ "type"
],
Also, ensure that the Transaction schema's required fields match the endpoint requirements.
Also applies to: 1093-1103, 1458-1458, 1487-1493
}, | ||
{ | ||
"name": "limit", | ||
"in": "query", | ||
"description": "Number of transactions to fetch", | ||
"required": true, | ||
"schema": { | ||
"type": "integer", | ||
"default": 20 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider making the limit parameter optional.
The limit
parameter is marked as required but has a default value. This is contradictory as required parameters should not have default values.
Apply this diff to fix the parameter definition:
{
"name": "limit",
"in": "query",
"description": "Number of transactions to fetch",
- "required": true,
+ "required": false,
"schema": {
"type": "integer",
"default": 20
}
}
📝 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.
}, | |
{ | |
"name": "limit", | |
"in": "query", | |
"description": "Number of transactions to fetch", | |
"required": true, | |
"schema": { | |
"type": "integer", | |
"default": 20 | |
} | |
}, | |
{ | |
"name": "limit", | |
"in": "query", | |
"description": "Number of transactions to fetch", | |
"required": false, | |
"schema": { | |
"type": "integer", | |
"default": 20 | |
} |
protected function validateRequest(Request $request, array $rules): array | ||
{ | ||
$validator = Validator::make($request->all(), $rules); | ||
|
||
if ($validator->fails()) { | ||
$errors = $validator->errors(); | ||
|
||
if ($errors->hasAny(array_keys($rules))) { | ||
return [ | ||
'isValidated' => false, | ||
'message' => 'Server failed to validate request.', | ||
'code' => 422, | ||
'errors' => $errors->toArray(), | ||
]; | ||
} | ||
|
||
return [ | ||
'isValidated' => false, | ||
'message' => 'Server unable to process request.', | ||
'code' => 400, | ||
'errors' => $errors->toArray(), | ||
]; | ||
} | ||
|
||
return ['isValidated' => true, 'data' => $validator->validated()]; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use Form Requests for this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes but we would have to write FormRequests
for each endpoint! I did not want to do that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok. It makes the code cleaner in my own opinion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. It usually does make things cleaner when you have large and complex requests. There is no need to have 4 different FormRequests
(4 + files) for the CRUD operations in this file and then we would have to repeat this across all the models, in reality only a few of the requests (e.g store) are big a enough to need the FormRequests
which I do use in other code bases but in this case I think this small function takes the bull by the horn we can use to validate all the simple requests based on the rules passed without adding any new files to the project.
Summary by CodeRabbit
Release Notes
New Features
Transaction
model.Category
,Group
,Party
, andWallet
models.Improvements
Bug Fixes
Breaking Changes
Income
andExpense
models.groups
,parties
, andwallets
tables.