299 lines
No EOL
6.9 KiB
JavaScript
299 lines
No EOL
6.9 KiB
JavaScript
const express = require('express');
|
|
const router = express.Router();
|
|
const { invoiceRepository, paymentRepository } = require('../repositories');
|
|
|
|
/**
|
|
* GET /api/plugins/financials/invoices
|
|
* Get all invoices for a site or unit
|
|
*/
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
const { site_id, unit_id, status, invoice_type } = req.query;
|
|
|
|
if (!site_id) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'site_id query parameter is required'
|
|
});
|
|
}
|
|
|
|
let invoices;
|
|
|
|
// Filter by unit_id if provided
|
|
if (unit_id) {
|
|
invoices = await invoiceRepository.findByUnitId(unit_id);
|
|
} else {
|
|
invoices = await invoiceRepository.findBySiteId(site_id);
|
|
}
|
|
|
|
// Filter by status if provided
|
|
if (status) {
|
|
invoices = invoices.filter(inv => inv.status === status);
|
|
}
|
|
|
|
// Filter by invoice_type if provided
|
|
if (invoice_type) {
|
|
invoices = invoices.filter(inv => inv.invoice_type === invoice_type);
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: invoices,
|
|
message: 'Invoices retrieved successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to get invoices:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to retrieve invoices',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /api/plugins/financials/invoices/:id
|
|
* Get invoice by ID
|
|
*/
|
|
router.get('/:id', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { site_id } = req.query;
|
|
|
|
if (!site_id) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'site_id is required'
|
|
});
|
|
}
|
|
|
|
const invoice = await invoiceRepository.findById(id);
|
|
|
|
if (!invoice) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Invoice not found'
|
|
});
|
|
}
|
|
|
|
// Verify invoice belongs to site
|
|
if (invoice.site_id !== site_id) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
error: 'Access denied'
|
|
});
|
|
}
|
|
|
|
res.json({
|
|
success: true,
|
|
data: invoice,
|
|
message: 'Invoice details retrieved successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to get invoice:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to retrieve invoice',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* POST /api/plugins/financials/invoices
|
|
* Create a new invoice
|
|
*/
|
|
router.post('/', async (req, res) => {
|
|
try {
|
|
const { site_id, unit_id, invoice_number, invoice_type, description, amount, due_date, work_order_id, notes, created_by } = req.body;
|
|
|
|
if (!site_id || !unit_id || !invoice_type || !description || !amount || !due_date) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'Missing required fields',
|
|
message: 'Site ID, unit ID, invoice type, description, amount, and due date are required'
|
|
});
|
|
}
|
|
|
|
const invoice = await invoiceRepository.createInvoice({
|
|
site_id,
|
|
unit_id,
|
|
invoice_number,
|
|
invoice_type,
|
|
description,
|
|
amount,
|
|
due_date,
|
|
work_order_id,
|
|
notes,
|
|
created_by: created_by || req.user?.id || 'system'
|
|
});
|
|
|
|
res.status(201).json({
|
|
success: true,
|
|
data: invoice,
|
|
message: 'Invoice created successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to create invoice:', error);
|
|
|
|
if (error.message.includes('already exists')) {
|
|
return res.status(409).json({
|
|
success: false,
|
|
error: 'Invoice number already exists',
|
|
message: error.message
|
|
});
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to create invoice',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* PUT /api/plugins/financials/invoices/:id/pay
|
|
* Mark invoice as paid
|
|
*/
|
|
router.put('/:id/pay', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { payment_date, payment_method, payment_reference } = req.body;
|
|
const { site_id } = req.query;
|
|
|
|
if (!site_id) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'site_id is required'
|
|
});
|
|
}
|
|
|
|
// Get invoice first to verify it exists
|
|
const invoice = await invoiceRepository.findById(id);
|
|
|
|
if (!invoice) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Invoice not found'
|
|
});
|
|
}
|
|
|
|
if (invoice.site_id !== site_id) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
error: 'Access denied'
|
|
});
|
|
}
|
|
|
|
const updatedInvoice = await invoiceRepository.markAsPaid(id, {
|
|
payment_date,
|
|
payment_method,
|
|
payment_reference
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: updatedInvoice,
|
|
message: 'Invoice marked as paid successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to mark invoice as paid:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to mark invoice as paid',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* PUT /api/plugins/financials/invoices/:id
|
|
* Update invoice
|
|
*/
|
|
router.put('/:id', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { site_id, description, amount, due_date, status, notes } = req.body;
|
|
|
|
if (!site_id) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'site_id is required'
|
|
});
|
|
}
|
|
|
|
// Get invoice first
|
|
const invoice = await invoiceRepository.findById(id);
|
|
|
|
if (!invoice) {
|
|
return res.status(404).json({
|
|
success: false,
|
|
error: 'Invoice not found'
|
|
});
|
|
}
|
|
|
|
if (invoice.site_id !== site_id) {
|
|
return res.status(403).json({
|
|
success: false,
|
|
error: 'Access denied'
|
|
});
|
|
}
|
|
|
|
const updatedInvoice = await invoiceRepository.updateById(id, {
|
|
description,
|
|
amount,
|
|
due_date,
|
|
status,
|
|
notes,
|
|
updated_at: new Date().toISOString()
|
|
});
|
|
|
|
res.json({
|
|
success: true,
|
|
data: updatedInvoice,
|
|
message: 'Invoice updated successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to update invoice:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to update invoice',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
/**
|
|
* GET /api/plugins/financials/invoices/overdue
|
|
* Get overdue invoices
|
|
*/
|
|
router.get('/overdue', async (req, res) => {
|
|
try {
|
|
const { site_id } = req.query;
|
|
|
|
if (!site_id) {
|
|
return res.status(400).json({
|
|
success: false,
|
|
error: 'site_id is required'
|
|
});
|
|
}
|
|
|
|
const overdueInvoices = await invoiceRepository.findOverdue(site_id);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: overdueInvoices,
|
|
message: 'Overdue invoices retrieved successfully'
|
|
});
|
|
} catch (error) {
|
|
console.error('Failed to get overdue invoices:', error);
|
|
res.status(500).json({
|
|
success: false,
|
|
error: 'Failed to retrieve overdue invoices',
|
|
message: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
module.exports = router; |