From c4da868a962575a2c1b67ddabeca12b6fc71a934 Mon Sep 17 00:00:00 2001 From: DeathKaioken Date: Sat, 6 Dec 2025 10:07:13 +0100 Subject: [PATCH] feat: coffee + tax prework but broken --- controller/admin/CoffeeController.js | 14 ++++++ controller/tax/taxController.js | 17 ++++++++ models/Tax.js | 19 ++++++++ .../subscriptions/CoffeeRepository.js | 6 +++ repositories/tax/taxRepository.js | 43 +++++++++++++++++++ routes/getRoutes.js | 1 + services/subscriptions/CoffeeService.js | 4 ++ services/tax/taxService.js | 9 ++++ 8 files changed, 113 insertions(+) create mode 100644 controller/tax/taxController.js create mode 100644 models/Tax.js create mode 100644 repositories/tax/taxRepository.js create mode 100644 services/tax/taxService.js diff --git a/controller/admin/CoffeeController.js b/controller/admin/CoffeeController.js index 14d73bb..0660eea 100644 --- a/controller/admin/CoffeeController.js +++ b/controller/admin/CoffeeController.js @@ -247,3 +247,17 @@ exports.remove = async (req, res) => { res.status(500).json({ error: 'Failed to delete product' }); } }; + +exports.listActive = async (req, res) => { + try { + const rows = await CoffeeService.listActive(); + const items = (rows || []).map(r => ({ + ...r, + pictureUrl: r.object_storage_id ? buildPictureUrlFromKey(r.object_storage_id) : '' + })); + res.json(items); + } catch (e) { + logger.error('[CoffeeController.listActive] error', { msg: e.message }); + res.status(500).json({ error: 'Failed to fetch active coffee products' }); + } +}; diff --git a/controller/tax/taxController.js b/controller/tax/taxController.js new file mode 100644 index 0000000..79d1fc9 --- /dev/null +++ b/controller/tax/taxController.js @@ -0,0 +1,17 @@ +const service = require('../../services/tax/taxService'); + +async function listVatRates(req, res) { + // Admin-only check + if (!req.user || req.user.role !== 'admin') { + return res.status(403).json({ success: false, message: 'Forbidden: Admins only.' }); + } + + try { + const data = await service.getAllVatRates(); + res.json({ success: true, data }); + } catch (e) { + res.status(500).json({ success: false, message: 'Failed to fetch VAT rates', error: e.message }); + } +} + +module.exports = { listVatRates }; \ No newline at end of file diff --git a/models/Tax.js b/models/Tax.js new file mode 100644 index 0000000..c2f2306 --- /dev/null +++ b/models/Tax.js @@ -0,0 +1,19 @@ +class Tax { + constructor(row) { + this.id = row.id; + this.country_code = row.country_code; + this.country_name = row.country_name; + this.is_eu = !!row.is_eu; + this.effective_year = row.effective_year; + this.standard_rate = row.standard_rate; + this.reduced_rate_1 = row.reduced_rate_1; + this.reduced_rate_2 = row.reduced_rate_2; + this.super_reduced_rate = row.super_reduced_rate; + this.parking_rate = row.parking_rate; + this.coffee_subscription_vat_rate = row.coffee_subscription_vat_rate; + this.created_at = row.created_at; + this.updated_at = row.updated_at; + } +} + +module.exports = Tax; \ No newline at end of file diff --git a/repositories/subscriptions/CoffeeRepository.js b/repositories/subscriptions/CoffeeRepository.js index 066142a..4356f4c 100644 --- a/repositories/subscriptions/CoffeeRepository.js +++ b/repositories/subscriptions/CoffeeRepository.js @@ -76,6 +76,12 @@ class CoffeeRepository { const [result] = await cx.query('DELETE FROM coffee_table WHERE id = ?', [id]); return result.affectedRows > 0; } + + async listActive(conn) { + const cx = conn || db; + const [rows] = await cx.query('SELECT * FROM coffee_table WHERE state = TRUE ORDER BY id DESC'); + return rows || []; + } } module.exports = new CoffeeRepository(); diff --git a/repositories/tax/taxRepository.js b/repositories/tax/taxRepository.js new file mode 100644 index 0000000..6ed9af0 --- /dev/null +++ b/repositories/tax/taxRepository.js @@ -0,0 +1,43 @@ +const mysql = require('mysql2/promise'); +require('dotenv').config(); + +const NODE_ENV = process.env.NODE_ENV || 'development'; + +function getDbConfig() { + if (NODE_ENV === 'development') { + return { + host: process.env.DEV_DB_HOST || 'localhost', + port: Number(process.env.DEV_DB_PORT) || 3306, + user: process.env.DEV_DB_USER || 'root', + password: process.env.DEV_DB_PASSWORD || '', + database: process.env.DEV_DB_NAME || 'profitplanet_centralserver', + ssl: undefined + }; + } + return { + host: process.env.DB_HOST, + port: Number(process.env.DB_PORT) || 3306, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME + }; +} + +async function listAllVatRates() { + const conn = await mysql.createConnection(getDbConfig()); + try { + const [rows] = await conn.query(` + SELECT id, country_code, country_name, is_eu, effective_year, + standard_rate, reduced_rate_1, reduced_rate_2, super_reduced_rate, + parking_rate, coffee_subscription_vat_rate, created_at, updated_at + FROM vat_rates + ORDER BY country_name ASC + `); + return rows; + } finally { + await conn.end(); + } +} + +// export +module.exports = { listAllVatRates }; \ No newline at end of file diff --git a/routes/getRoutes.js b/routes/getRoutes.js index b127397..cb7a631 100644 --- a/routes/getRoutes.js +++ b/routes/getRoutes.js @@ -108,6 +108,7 @@ router.get('/company-stamps/mine/active', authMiddleware, adminOnly, forceCompan router.get('/company-stamps/all', authMiddleware, adminOnly, forceCompanyForAdmin, CompanyStampController.listAll); // Admin: coffee products router.get('/admin/coffee', authMiddleware, adminOnly, CoffeeController.list); +router.get('/admin/coffee/active', authMiddleware, adminOnly, CoffeeController.listActive); // Matrix GETs diff --git a/services/subscriptions/CoffeeService.js b/services/subscriptions/CoffeeService.js index cce175f..c492e06 100644 --- a/services/subscriptions/CoffeeService.js +++ b/services/subscriptions/CoffeeService.js @@ -95,6 +95,10 @@ class CoffeeService { throw e; } } + + async listActive() { + return CoffeeRepository.listActive(); + } } module.exports = new CoffeeService(); diff --git a/services/tax/taxService.js b/services/tax/taxService.js new file mode 100644 index 0000000..96960b3 --- /dev/null +++ b/services/tax/taxService.js @@ -0,0 +1,9 @@ +const Tax = require('../../models/Tax'); +const repo = require('../../repositories/tax/taxRepository'); + +async function getAllVatRates() { + const rows = await repo.listAllVatRates(); + return rows.map(r => new Tax(r)); +} + +module.exports = { getAllVatRates }; \ No newline at end of file