Conversation
Implement Supabase schema and fix balance update bug
|
The failure is in the backend test job from The failing suite is
Root causeThe integration test assumes the database trigger updates
Because the rest of the backend tests passed and only this trigger suite failed, the problem is most likely that the trigger is not present or not firing in the CI-created database, not that the repository APIs are broken. Best fixMake the integration test verify that the trigger exists before asserting balances, and isolate DB state more safely. 1. Strengthen the test setupIn Suggested replacement for beforeEach(async () => {
await txRepo.query(`
TRUNCATE TABLE
transactions,
accounts,
users,
households
RESTART IDENTITY CASCADE
`);
const user = userRepo.create({
id: '11111111-1111-1111-1111-111111111111',
email: 'integration@test.com',
passwordHash: 'hashed',
displayName: 'Test User',
role: 'admin',
});
testUser = await userRepo.save(user);
const household = householdRepo.create({
id: '22222222-2222-2222-2222-222222222222',
name: 'Integration Household',
currency: 'USD',
ownerId: testUser.id,
});
testHousehold = await householdRepo.save(household);
testUser.householdId = testHousehold.id;
await userRepo.save(testUser);
});2. Add an explicit trigger existence assertionRight after module setup, verify the migration actually created the trigger/function. This turns a vague balance mismatch into a clear migration failure. Example: beforeAll(async () => {
module = await Test.createTestingModule({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
url: databaseUrl,
entities: [
UserEntity,
HouseholdEntity,
AccountEntity,
TransactionEntity,
DebtEntity,
PaymentEntity,
CategoryEntity,
BudgetEntity,
],
synchronize: false,
dropSchema: true,
migrationsRun: true,
migrations: [path.join(__dirname, '../migrations/*{.ts,.js}')],
}),
TypeOrmModule.forFeature([
UserEntity,
HouseholdEntity,
AccountEntity,
TransactionEntity,
DebtEntity,
PaymentEntity,
CategoryEntity,
BudgetEntity,
]),
],
}).compile();
txRepo = module.get(getRepositoryToken(TransactionEntity));
accountRepo = module.get(getRepositoryToken(AccountEntity));
householdRepo = module.get(getRepositoryToken(HouseholdEntity));
userRepo = module.get(getRepositoryToken(UserEntity));
const triggers = await txRepo.query(`
SELECT trigger_name
FROM information_schema.triggers
WHERE event_object_table = 'transactions'
`);
expect(triggers.length).toBeGreaterThan(0);
});If the real issue is in the migrationThe test file strongly suggests there should be a DB trigger handling:
If CI says all 4 fail, review the migration that creates the transaction balance trigger and ensure it handles these cases: -- pseudo-logic
IF TG_OP = 'INSERT' AND NEW.deleted_at IS NULL THEN
UPDATE accounts SET balance = balance + NEW.amount WHERE id = NEW.account_id;
END IF;
IF TG_OP = 'UPDATE' THEN
-- undo old value if old row counted
IF OLD.deleted_at IS NULL THEN
UPDATE accounts SET balance = balance - OLD.amount WHERE id = OLD.account_id;
END IF;
-- apply new value if new row counts
IF NEW.deleted_at IS NULL THEN
UPDATE accounts SET balance = balance + NEW.amount WHERE id = NEW.account_id;
END IF;
END IF;That logic is required for the expectations in:
Source: Recommended change summary
The highest-probability solution is: repair or reapply the transaction balance trigger migration, because the failing suite is explicitly validating trigger-driven balance updates and all trigger-related assertions failed together. |
|
The failing job is the - run: pnpm turbo run lintThe blocking error is in
Current code: async softDelete(id: string, householdId: string): Promise<void> {
const tx = await this.findOne(id, householdId);
await this.repo.softDelete(id);
}SolutionSince async softDelete(id: string, householdId: string): Promise<void> {
await this.findOne(id, householdId);
await this.repo.softDelete(id);
}Why this fixes it
Optional cleanupThe logs also show warnings in the same file for |
|
To configure your TypeORM data source to handle both your local PostgreSQL setup and a secure cloud database connection dynamically, you can adjust your connection options based on the environment. Since you are running locally without Docker and want to transition seamlessly to a cloud host (like [Aiven](https://aiven.io/free-postgresql-database) or [Supabase](https://supabase.com/database)), you can use an environment variable like Here is the cleanest way to refactor your import { DataSource } from 'typeorm';
import * as dotenv from 'dotenv';
import * as path from 'path';
// Ensure environment variables are loaded
dotenv.config({ path: path.join(__dirname, '../../.env') });
const isProduction = process.env.NODE_ENV === 'production';
const dbUrl = process.env.DATABASE_URL;
// Automatically enable SSL if running in production or connecting to a remote cloud DB
const hasRemoteConnection = dbUrl && !dbUrl.includes('localhost') && !dbUrl.includes('127.0.0.1');
const shouldEnableSSL = isProduction || hasRemoteConnection;
export const AppDataSource = new DataSource({
type: 'postgres',
url: dbUrl || 'postgres://fa_user:fa_pass@localhost:5432/family_accountant',
synchronize: !isProduction, // Use migrations for production/cloud environments
logging: !isProduction,
entities: [path.join(__dirname, '/**/*.entity{.ts,.js}')],
migrations: [path.join(__dirname, '/migrations/*{.ts,.js}')],
subscribers: [],
// Dynamic SSL Configuration
ssl: shouldEnableSSL
? {
// rejectUnauthorized: false bypasses strict CA validation certificates
// which is standard for serverless environments like Neon or Supabase
rejectUnauthorized: false,
}
: false,
});Why This Workflow Works Cleanly
Make sure your production startup script passes |
|
@copilot check the pr and comments and fix the issues |
Addressed in commit I fixed the lint blocker in |
This pull request introduces two new entities,
CategoryEntityandBudgetEntity, and integrates them into the backend data model. It also refactors transaction and household entities to support these new features and simplifies the sync logic by removing account balance adjustments from the synchronization process.Entity and Data Model Enhancements:
CategoryEntityandBudgetEntitywith full TypeORM integration, including relationships toHouseholdEntityand each other, and registered them in the application module and data source (app.module.ts,data-source.ts,category.entity.ts,budget.entity.ts) [1] [2] [3] [4] [5] [6].TransactionEntityto support category relationships: addedcategoryIdforeign key, a relation toCategoryEntity, and a unique constraint on(householdId, localId)for better data consistency (transaction.entity.ts) [1] [2].HouseholdEntityto include acurrencyfield with a default of 'USD' (household.entity.ts).rolefield toUserEntitywith a default value of 'member' (user.entity.ts).Sync and Transaction Logic Refactoring:
SyncServiceandTransactionsService, simplifying synchronization and transaction creation (sync.service.ts,transactions.service.ts) [1] [2] [3] [4] [5].Testing Adjustments:
sync.service.spec.ts) [1] [2] [3].Migration Cleanup:
1781759488049-InitialSchema.ts).