diff --git a/backend/src/services/__tests__/scoresService-additions.test.ts b/backend/src/services/__tests__/scoresService-additions.test.ts index 021dfdf0..15c23480 100644 --- a/backend/src/services/__tests__/scoresService-additions.test.ts +++ b/backend/src/services/__tests__/scoresService-additions.test.ts @@ -82,7 +82,16 @@ describe('updateUserScoresBulk clamping', () => { const [sql] = mockQuery.mock.calls[0] as [string, unknown[]]; expect(sql).toContain('LEAST(850, GREATEST(300,'); }); -}); + + it('applies positive deltas as score increases in bulk upserts', async () => { + await updateUserScoresBulk(new Map([['user_reward', 25]])); + + const [sql, params] = mockQuery.mock.calls[0] as [string, unknown[]]; + expect(params).toEqual(['user_reward', 25]); + expect(sql).toContain('500 + $2'); + expect(sql).toContain('scores.current_score + EXCLUDED.current_score - 500'); + expect(sql).not.toContain('500 - $2'); + });}); describe('setAbsoluteUserScoresBulk', () => { it('is a noop for empty map', async () => { diff --git a/backend/src/services/scoresService.ts b/backend/src/services/scoresService.ts index c93a268a..1fd6061b 100644 --- a/backend/src/services/scoresService.ts +++ b/backend/src/services/scoresService.ts @@ -33,7 +33,7 @@ export async function updateUserScoresBulk( // Clamped the initial raw value payload insertion step to prevent violating constraints on initial inserts const valuePlaceholders = Array.from( { length: params.length / 2 }, - (_, i) => `($${i * 2 + 1}, LEAST(850, GREATEST(300, 500 - $${i * 2 + 2})))`, + (_, i) => `($${i * 2 + 1}, LEAST(850, GREATEST(300, 500 + $${i * 2 + 2})))`, ).join(', '); const sql = `