1a12fb870b
- New /developers/ page with API docs, SDKs, pricing, use cases - OpenAPI 3.0 spec for Orders, Missions, Photos, Analytics - Case study: Glasskiosken i Flatenbadet — complete ROI analysis - Updated /order/ with recurring missions and frequency dropdown
127 lines
4.5 KiB
JavaScript
127 lines
4.5 KiB
JavaScript
/**
|
|
* quiXzoom Frilans Payout — Database Layer
|
|
* Raw SQL via pg (no ORM per REXO standards)
|
|
*/
|
|
|
|
import pg from 'pg';
|
|
const { Pool } = pg;
|
|
|
|
const pool = new Pool({
|
|
connectionString: process.env.DATABASE_URL || 'postgresql://wavult_admin:EgoVVPQuVSioCiMgJWmMoVvnjgiJPaD6hPR8xkZo@wavult-identity-core.cvi0qcksmsfj.eu-north-1.rds.amazonaws.com:5432/wavult_identity',
|
|
ssl: { rejectUnauthorized: false },
|
|
});
|
|
|
|
// ── Frilans Accounts ────────────────────────────────────────────────────────
|
|
|
|
export async function createAccount(data) {
|
|
const { userId, country, currency, taxHandling, personalNumber, payoutMethod } = data;
|
|
|
|
const result = await pool.query(`
|
|
INSERT INTO frilans_accounts (user_id, country, currency, tax_handling, personal_number, payout_method)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
RETURNING *
|
|
`, [userId, country, currency, taxHandling, personalNumber, payoutMethod]);
|
|
|
|
return result.rows[0];
|
|
}
|
|
|
|
export async function getAccountByUserId(userId) {
|
|
const result = await pool.query(
|
|
'SELECT * FROM frilans_accounts WHERE user_id = $1 AND status = $2',
|
|
[userId, 'active']
|
|
);
|
|
return result.rows[0] || null;
|
|
}
|
|
|
|
export async function updateAccount(accountId, updates) {
|
|
const fields = Object.keys(updates);
|
|
const values = Object.values(updates);
|
|
const setClause = fields.map((f, i) => `${f} = $${i + 2}`).join(', ');
|
|
|
|
const result = await pool.query(`
|
|
UPDATE frilans_accounts
|
|
SET ${setClause}, updated_at = NOW()
|
|
WHERE id = $1
|
|
RETURNING *
|
|
`, [accountId, ...values]);
|
|
|
|
return result.rows[0];
|
|
}
|
|
|
|
// ── Payouts ─────────────────────────────────────────────────────────────────
|
|
|
|
export async function createPayout(data) {
|
|
const { accountId, amount, netAmount, currency, platformFee, processingFee, taxAmount, method, scheduledDate } = data;
|
|
|
|
const result = await pool.query(`
|
|
INSERT INTO frilans_payouts (account_id, amount, net_amount, currency, platform_fee, processing_fee, tax_amount, method, scheduled_date)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
RETURNING *
|
|
`, [accountId, amount, netAmount, currency, platformFee, processingFee, taxAmount, method, scheduledDate]);
|
|
|
|
return result.rows[0];
|
|
}
|
|
|
|
export async function listPayouts(accountId) {
|
|
const result = await pool.query(
|
|
'SELECT * FROM frilans_payouts WHERE account_id = $1 ORDER BY created_at DESC',
|
|
[accountId]
|
|
);
|
|
return result.rows;
|
|
}
|
|
|
|
export async function getPayoutById(payoutId) {
|
|
const result = await pool.query(
|
|
'SELECT * FROM frilans_payouts WHERE id = $1',
|
|
[payoutId]
|
|
);
|
|
return result.rows[0] || null;
|
|
}
|
|
|
|
// ── Documents ───────────────────────────────────────────────────────────────
|
|
|
|
export async function createDocument(data) {
|
|
const { accountId, type, s3Url } = data;
|
|
|
|
const result = await pool.query(`
|
|
INSERT INTO frilans_documents (account_id, type, s3_url, status)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING *
|
|
`, [accountId, type, s3Url, 'verified']);
|
|
|
|
return result.rows[0];
|
|
}
|
|
|
|
export async function listDocuments(accountId) {
|
|
const result = await pool.query(
|
|
'SELECT * FROM frilans_documents WHERE account_id = $1 ORDER BY uploaded_at DESC',
|
|
[accountId]
|
|
);
|
|
return result.rows;
|
|
}
|
|
|
|
// ── Tax Summary ─────────────────────────────────────────────────────────────
|
|
|
|
export async function getTaxSummary(accountId, year) {
|
|
const result = await pool.query(`
|
|
SELECT
|
|
COALESCE(SUM(amount), 0) as total_earnings,
|
|
COALESCE(SUM(tax_amount), 0) as total_tax_paid,
|
|
COALESCE(SUM(platform_fee + processing_fee), 0) as total_fees_paid,
|
|
COALESCE(SUM(net_amount), 0) as net_earnings
|
|
FROM frilans_payouts
|
|
WHERE account_id = $1
|
|
AND EXTRACT(YEAR FROM created_at) = $2
|
|
AND status = 'completed'
|
|
`, [accountId, year]);
|
|
|
|
return result.rows[0];
|
|
}
|
|
|
|
// ── Health Check ────────────────────────────────────────────────────────────
|
|
|
|
export async function healthCheck() {
|
|
const result = await pool.query('SELECT NOW()');
|
|
return result.rows[0];
|
|
}
|