Showing AI reviews for bet-service
Project AI Score ?
62%
Quality Avg ?
63%
Security Avg ?
59%
Reviews ?
92

Review Result ?

solutionbowl/bet-service · 33fadfc2
This commit introduces validation on selection positions to ensure they are integers within valid bounds and unique, improving data integrity. It also adds detailed exposure calculation logic, focusing on multi-bet position management and winnings exposure, which increases business value. Logging is added, which is good for debugging but could potentially leak sensitive data if not controlled. The addition of sorting mechanisms and default values in schemas enhance consistency. However, some validation and error handling could be strengthened, and the commit message itself lacks detail for traceability and understanding of change context.
Quality ?
85%
Security ?
70%
Business Value ?
90%
Maintainability ?
85%
Issues & Suggested Fixes ?
1AI detects the issue
2Shows file, line, or evidence
3Suggests the fix to apply
Issue
Where commit message
Issue / Evidence issue
Suggested Fix provide a more descriptive message explaining what the commit changes and its purpose to improve maintainability and traceability
Missing Validation
Where src/controllers/multiBet.controller.js:94-104
Issue / Evidence insufficient validation feedback
Suggested Fix consider centralizing and enhancing validation error messages for better client-side handling and debugging
Error Handling
Where src/utils/multiBetExposure.js:66-78
Issue / Evidence error handling
Suggested Fix improve handling of missing race market or winner market cases, possibly by returning explicit error results or triggering alerts rather than silent successes
Logging
Where src/controllers/multiBet.controller.js:448
Issue / Evidence logging
Suggested Fix reduce or sanitize sensitive information in logs to improve security
Async Exposure Creation
Where src/utils/multiBetExposure.js:100-118
Issue / Evidence async exposure creation
Suggested Fix add error handling for the Exposure.create calls to ensure failures are caught and handled gracefully
Code Change Preview · src/controllers/multiBet.controller.js ?
Removed / Before Commit
- diff --git a/src/controllers/multiBet.controller.js b/src/controllers/multiBet.controller.js
- index 04c98e0..a87cb25 100644
- });
- }
- 
- // Validate each selection
- const validatedLegs = [];
- let combinedOdds = 1;
- marketName: market.marketType,
- runnerId: sel.runnerId,
- runnerName: runner.name,
-         odds: Number(currentOdds)
- });
- 
- // Multiply odds
- 
- // Multi-bet specific fields
- leg_number: i + 1,
Added / After Commit
+ diff --git a/src/controllers/multiBet.controller.js b/src/controllers/multiBet.controller.js
+ index 04c98e0..a87cb25 100644
+ });
+ }
+ 
+     const positions = selections.map(s => Number(s.position));
+     const hasInvalidPosition = positions.some(position =>
+       !Number.isInteger(position) || position < 1 || position > selections.length
+     );
+ 
+     if (hasInvalidPosition) {
+       return res.status(400).json({
+         status: false,
+         message: `Each selection must have a valid position between 1 and ${selections.length}`
+       });
+     }
+ 
+     if (new Set(positions).size !== positions.length) {
Removed / Before Commit
- diff --git a/src/models/Exposure.js b/src/models/Exposure.js
- index 9b488b7..38b181d 100644
- // Multi-bet specific fields
- is_multi_bet: { type: Boolean, default: false },
- leg_number: { type: Number, default: 1 },
- stake_at_leg: { type: Number, default: 0 },
- leg_profit: { type: Number, default: 0 },
- is_active: { type: Boolean, default: true }
- }, { timestamps: true });
- 
- module.exports = mongoose.model("Exposure", exposureSchema);
- \ No newline at end of file
Added / After Commit
+ diff --git a/src/models/Exposure.js b/src/models/Exposure.js
+ index 9b488b7..38b181d 100644
+ // Multi-bet specific fields
+ is_multi_bet: { type: Boolean, default: false },
+ leg_number: { type: Number, default: 1 },
+     position: { type: Number, default: 1 },
+ stake_at_leg: { type: Number, default: 0 },
+ leg_profit: { type: Number, default: 0 },
+ is_active: { type: Boolean, default: true }
+ }, { timestamps: true });
+ 
+ \ No newline at end of file
+ module.exports = mongoose.model("Exposure", exposureSchema);
Removed / Before Commit
- diff --git a/src/models/RacingBet.js b/src/models/RacingBet.js
- index 0d3ed69..7ddc6e1 100644
- 
- // Multi-bet support
- leg_number: { type: Number, default: 1 },
- leg_status: {
- type: String,
- enum: ["PENDING", "WON", "LOST", "VOID"],
- 
- // Composite unique index for multi-bet legs
- RacingBetSchema.index({ bet_id: 1, leg_number: 1 }, { unique: true });
- 
- module.exports = mongoose.model("RacingBet", RacingBetSchema);
Added / After Commit
+ diff --git a/src/models/RacingBet.js b/src/models/RacingBet.js
+ index 0d3ed69..7ddc6e1 100644
+ 
+ // Multi-bet support
+ leg_number: { type: Number, default: 1 },
+   position: { type: Number, default: 1 },
+ leg_status: {
+ type: String,
+ enum: ["PENDING", "WON", "LOST", "VOID"],
+ 
+ // Composite unique index for multi-bet legs
+ RacingBetSchema.index({ bet_id: 1, leg_number: 1 }, { unique: true });
+ RacingBetSchema.index({ bet_id: 1, position: 1 });
+ 
+ module.exports = mongoose.model("RacingBet", RacingBetSchema);
Removed / Before Commit
- diff --git a/src/utils/multiBetExposure.js b/src/utils/multiBetExposure.js
- index 31dd545..62d24fb 100644
- const forceWonLegNumber = options.forceWonLegNumber
- ? Number(options.forceWonLegNumber)
- : null;
- 
-     // Calculate confirmed amount from every won leg. Races can settle out of
-     // leg_number order, so do not stop at the first pending leg.
- const sortedLegs = await RacingBet.find({ bet_id: betId })
-       .sort({ leg_number: 1 });
- 
- let confirmedAmount = originalStake;
- 
-     // Include all already won legs in the cascading amount.
- for (const leg of sortedLegs) {
-       const legStatus = forceWonLegNumber === Number(leg.leg_number)
- ? "WON"
- : leg.leg_status;
Added / After Commit
+ diff --git a/src/utils/multiBetExposure.js b/src/utils/multiBetExposure.js
+ index 31dd545..62d24fb 100644
+ const forceWonLegNumber = options.forceWonLegNumber
+ ? Number(options.forceWonLegNumber)
+ : null;
+     const forceWonPosition = options.forceWonPosition
+       ? Number(options.forceWonPosition)
+       : null;
+ 
+     // Multi-bet progression is controlled by position, not leg_number.
+     // Only the next pending position should carry exposure.
+ const sortedLegs = await RacingBet.find({ bet_id: betId })
+       .sort({ position: 1, leg_number: 1 });
+ 
+ let confirmedAmount = originalStake;
+     let activeLeg = null;
+ 
+     // Build cascading amount only through the contiguous won path.