plugin-financials/repositories/BaseFinancialRepository.js
2025-11-03 13:51:33 +02:00

235 lines
6.9 KiB
JavaScript

const BaseRepository = require('../../../src/database/repository');
const logger = require('../../../src/utils/logger');
/**
* Base Financial Repository
*
* Extends core BaseRepository to handle pg_ prefixed plugin tables.
* All financial plugin repositories should extend this class.
*
* Features:
* - Uses pg_ prefix to identify plugin tables in main schema
* - Inherits all BaseRepository methods (findOne, findAll, create, etc.)
* - Multi-tenant support via site_id
* - Database abstraction (works with any supported database)
*/
class BaseFinancialRepository extends BaseRepository {
constructor(tableName) {
super(tableName);
this.schema = 'public'; // Use main schema with pg_ prefixed tables
}
/**
* Get database connection
* @returns {Object} Database connection
*/
getConnection() {
if (global.dbConnection && typeof global.dbConnection.getConnection === 'function') {
return global.dbConnection.getConnection();
}
throw new Error('No database connection available');
}
/**
* Check if connection is Supabase client
* @param {Object} connection
* @returns {boolean}
*/
isSupabase(connection) {
return connection && typeof connection.from === 'function' && typeof connection.auth === 'object';
}
/**
* Override findAll to handle pg_ prefixed tables in main schema
*/
async findAll(criteria = {}, options = {}) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
// Supabase style - use pg_ prefixed tables in public schema
let query = connection.from(this.tableName).select('*');
// Apply criteria
if (Object.keys(criteria).length > 0) {
query = query.match(criteria);
}
// Apply ordering
if (options.orderBy) {
const ascending = options.orderDirection === 'asc' || options.orderDirection === 'ASC';
query = query.order(options.orderBy, { ascending });
}
// Apply limit
if (options.limit) query = query.limit(options.limit);
const { data, error } = await query;
if (error) throw error;
return data || [];
} else {
// Knex style - for other databases
return super.findAll(criteria, options);
}
}
/**
* Override findOne to handle pg_ prefixed tables in main schema
*/
async findOne(criteria) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const { data, error } = await connection
.from(this.tableName)
.select('*')
.match(criteria)
.limit(1);
if (error) throw error;
return data && data[0];
} else {
return super.findOne(criteria);
}
}
/**
* Override create to handle pg_ prefixed tables in main schema
*/
async create(data) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const { data: result, error } = await connection
.from(this.tableName)
.insert([data])
.select();
if (error) throw error;
return result && result[0];
} else {
return super.create(data);
}
}
/**
* Override updateById to handle pg_ prefixed tables in main schema
*/
async updateById(id, updateData) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const { data, error } = await connection
.from(this.tableName)
.update(updateData)
.eq('id', id)
.select();
if (error) throw error;
return data && data[0];
} else {
return super.updateById(id, updateData);
}
}
/**
* Override deleteById to handle pg_ prefixed tables in main schema
*/
async deleteById(id) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const { error } = await connection
.from(this.tableName)
.delete()
.eq('id', id);
if (error) throw error;
return true;
} else {
return super.deleteById(id);
}
}
/**
* Override count to handle pg_ prefixed tables in main schema
*/
async count(criteria = {}) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const { count, error } = await connection
.from(this.tableName)
.select('*', { count: 'exact', head: true })
.match(criteria);
if (error) throw error;
return count || 0;
} else {
return super.count(criteria);
}
}
/**
* Override findWhere to handle pg_ prefixed tables in main schema
*/
async findWhere(conditions, options = {}) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
let query = connection.from(this.tableName).select('*');
// Apply conditions
for (const [field, condition] of Object.entries(conditions)) {
if (condition.eq !== undefined) query = query.eq(field, condition.eq);
if (condition.neq !== undefined) query = query.neq(field, condition.neq);
if (condition.gt !== undefined) query = query.gt(field, condition.gt);
if (condition.gte !== undefined) query = query.gte(field, condition.gte);
if (condition.lt !== undefined) query = query.lt(field, condition.lt);
if (condition.lte !== undefined) query = query.lte(field, condition.lte);
if (condition.like !== undefined) query = query.like(field, condition.like);
if (condition.in !== undefined) query = query.in(field, condition.in);
}
// Apply ordering
if (options.orderBy) {
const ascending = options.orderDirection === 'asc' || options.orderDirection === 'ASC';
query = query.order(options.orderBy, { ascending });
}
// Apply limit
if (options.limit) query = query.limit(options.limit);
const { data, error } = await query;
if (error) throw error;
return data || [];
} else {
return super.findWhere(conditions, options);
}
}
/**
* Override paginate to handle pg_ prefixed tables in main schema
*/
async paginate(criteria = {}, page = 1, limit = 10, options = {}) {
const connection = this.getConnection();
if (this.isSupabase(connection)) {
const offset = (page - 1) * limit;
let query = connection
.from(this.tableName)
.select('*', { count: 'exact' })
.match(criteria);
query = query.range(offset, offset + limit - 1);
const { data, error, count } = await query;
if (error) throw error;
const total = typeof count === 'number' ? count : (data ? data.length : 0);
const totalPages = Math.ceil(total / limit);
return {
data: data || [],
pagination: {
page,
limit,
total,
totalPages,
hasNext: page < totalPages,
hasPrev: page > 1
}
};
} else {
return super.paginate(criteria, page, limit, options);
}
}
}
module.exports = BaseFinancialRepository;