Compare commits
No commits in common. "0fb0493d99252773cb7452c64de4851c07117333" and "944ad34f891bda92f5e625a28854f5d50d897a1c" have entirely different histories.
0fb0493d99
...
944ad34f89
@ -33,8 +33,6 @@ import {
|
||||
documentJobsRoutes,
|
||||
courierRoutes,
|
||||
courierServiceRoutes,
|
||||
taxRateRoutes,
|
||||
taxRecordRoutes,
|
||||
} from './routes/index.js';
|
||||
import path from 'path';
|
||||
import * as fs from 'fs';
|
||||
@ -139,8 +137,6 @@ app.use('/documentprinters', documentPrintersRoutes);
|
||||
app.use('/documentjobs', documentJobsRoutes);
|
||||
app.use('/couriers', courierRoutes);
|
||||
app.use('/courierservices', courierServiceRoutes);
|
||||
app.use('/taxrates', taxRateRoutes);
|
||||
app.use('/taxrecords', taxRecordRoutes);
|
||||
app.use('/notes', noteRoutes);
|
||||
|
||||
if (process.env.SCHEDULE_HOUR) {
|
||||
|
||||
@ -25,8 +25,6 @@ import documentPrintersRoutes from './management/documentprinters.js';
|
||||
import documentJobsRoutes from './management/documentjobs.js';
|
||||
import courierRoutes from './management/courier.js';
|
||||
import courierServiceRoutes from './management/courierservice.js';
|
||||
import taxRateRoutes from './management/taxrates.js';
|
||||
import taxRecordRoutes from './management/taxrecords.js';
|
||||
import noteRoutes from './misc/notes.js';
|
||||
|
||||
export {
|
||||
@ -58,6 +56,4 @@ export {
|
||||
documentJobsRoutes,
|
||||
courierRoutes,
|
||||
courierServiceRoutes,
|
||||
taxRateRoutes,
|
||||
taxRecordRoutes,
|
||||
};
|
||||
|
||||
@ -1,46 +0,0 @@
|
||||
import express from 'express';
|
||||
import { isAuthenticated } from '../../keycloak.js';
|
||||
import { getFilter, convertPropertiesString } from '../../utils.js';
|
||||
|
||||
const router = express.Router();
|
||||
import {
|
||||
listTaxRatesRouteHandler,
|
||||
getTaxRateRouteHandler,
|
||||
editTaxRateRouteHandler,
|
||||
newTaxRateRouteHandler,
|
||||
deleteTaxRateRouteHandler,
|
||||
listTaxRatesByPropertiesRouteHandler,
|
||||
} from '../../services/management/taxrates.js';
|
||||
|
||||
// list of tax rates
|
||||
router.get('/', isAuthenticated, (req, res) => {
|
||||
const { page, limit, property, search, sort, order } = req.query;
|
||||
const allowedFilters = ['name', 'rate', 'rateType', 'active', 'country'];
|
||||
const filter = getFilter(req.query, allowedFilters);
|
||||
listTaxRatesRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
||||
});
|
||||
|
||||
router.get('/properties', isAuthenticated, (req, res) => {
|
||||
let properties = convertPropertiesString(req.query.properties);
|
||||
const allowedFilters = ['rateType', 'country', 'active'];
|
||||
const filter = getFilter(req.query, allowedFilters, false);
|
||||
listTaxRatesByPropertiesRouteHandler(req, res, properties, filter);
|
||||
});
|
||||
|
||||
router.post('/', isAuthenticated, (req, res) => {
|
||||
newTaxRateRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.get('/:id', isAuthenticated, (req, res) => {
|
||||
getTaxRateRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||
editTaxRateRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.delete('/:id', isAuthenticated, async (req, res) => {
|
||||
deleteTaxRateRouteHandler(req, res);
|
||||
});
|
||||
|
||||
export default router;
|
||||
@ -1,46 +0,0 @@
|
||||
import express from 'express';
|
||||
import { isAuthenticated } from '../../keycloak.js';
|
||||
import { getFilter, convertPropertiesString } from '../../utils.js';
|
||||
|
||||
const router = express.Router();
|
||||
import {
|
||||
listTaxRecordsRouteHandler,
|
||||
getTaxRecordRouteHandler,
|
||||
editTaxRecordRouteHandler,
|
||||
newTaxRecordRouteHandler,
|
||||
deleteTaxRecordRouteHandler,
|
||||
listTaxRecordsByPropertiesRouteHandler,
|
||||
} from '../../services/management/taxrecords.js';
|
||||
|
||||
// list of tax records
|
||||
router.get('/', isAuthenticated, (req, res) => {
|
||||
const { page, limit, property, search, sort, order } = req.query;
|
||||
const allowedFilters = ['taxRate', 'transactionType', 'transaction', 'transactionDate'];
|
||||
const filter = getFilter(req.query, allowedFilters);
|
||||
listTaxRecordsRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
||||
});
|
||||
|
||||
router.get('/properties', isAuthenticated, (req, res) => {
|
||||
let properties = convertPropertiesString(req.query.properties);
|
||||
const allowedFilters = ['taxRate', 'transactionType', 'transaction'];
|
||||
const filter = getFilter(req.query, allowedFilters, false);
|
||||
listTaxRecordsByPropertiesRouteHandler(req, res, properties, filter);
|
||||
});
|
||||
|
||||
router.post('/', isAuthenticated, (req, res) => {
|
||||
newTaxRecordRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.get('/:id', isAuthenticated, (req, res) => {
|
||||
getTaxRecordRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||
editTaxRecordRouteHandler(req, res);
|
||||
});
|
||||
|
||||
router.delete('/:id', isAuthenticated, async (req, res) => {
|
||||
deleteTaxRecordRouteHandler(req, res);
|
||||
});
|
||||
|
||||
export default router;
|
||||
@ -6,10 +6,7 @@ const itemSchema = new Schema({
|
||||
itemType: { type: String, required: true },
|
||||
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
|
||||
quantity: { type: Number, required: true },
|
||||
itemCost: { type: Number, required: true },
|
||||
totalCost: { type: Number, required: true },
|
||||
totalCostWithTax: { type: Number, required: true },
|
||||
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||
price: { type: Number, required: true },
|
||||
});
|
||||
|
||||
const purchaseOrderSchema = new Schema(
|
||||
|
||||
@ -14,10 +14,6 @@ const partSchema = new Schema(
|
||||
margin: { type: Number, required: false },
|
||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||
file: { type: mongoose.SchemaTypes.ObjectId, ref: 'file', required: false },
|
||||
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||
priceWithTax: { type: Number, required: false },
|
||||
costWithTax: { type: Number, required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
@ -19,8 +19,6 @@ const productSchema = new Schema(
|
||||
amount: { type: Number, required: false },
|
||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||
parts: [partSchema],
|
||||
priceTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||
costTaxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
@ -1,25 +0,0 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
|
||||
const taxRateSchema = new mongoose.Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
name: { required: true, type: String },
|
||||
rate: { required: true, type: Number },
|
||||
rateType: { required: true, type: String, enum: ['percentage', 'fixed'] },
|
||||
active: { required: true, type: Boolean, default: true },
|
||||
description: { required: false, type: String },
|
||||
country: { required: false, type: String },
|
||||
effectiveFrom: { required: false, type: Date },
|
||||
effectiveTo: { required: false, type: Date },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
taxRateSchema.virtual('id').get(function () {
|
||||
return this._id;
|
||||
});
|
||||
|
||||
taxRateSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
export const taxRateModel = mongoose.model('taxRate', taxRateSchema);
|
||||
@ -1,28 +0,0 @@
|
||||
import mongoose from 'mongoose';
|
||||
import { generateId } from '../../utils.js';
|
||||
const { Schema } = mongoose;
|
||||
|
||||
const taxRecordSchema = new Schema(
|
||||
{
|
||||
_reference: { type: String, default: () => generateId()() },
|
||||
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: true },
|
||||
transactionType: {
|
||||
type: String,
|
||||
required: true,
|
||||
enum: ['purchaseOrder', 'salesOrder', 'other'],
|
||||
},
|
||||
transaction: { type: Schema.Types.ObjectId, refPath: 'transactionType', required: true },
|
||||
amount: { type: Number, required: true },
|
||||
taxAmount: { type: Number, required: true },
|
||||
transactionDate: { required: true, type: Date, default: Date.now },
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
||||
taxRecordSchema.virtual('id').get(function () {
|
||||
return this._id;
|
||||
});
|
||||
|
||||
taxRecordSchema.set('toJSON', { virtuals: true });
|
||||
|
||||
export const taxRecordModel = mongoose.model('taxRecord', taxRecordSchema);
|
||||
@ -1,94 +0,0 @@
|
||||
import { jobModel } from './production/job.schema.js';
|
||||
import { subJobModel } from './production/subjob.schema.js';
|
||||
import { printerModel } from './production/printer.schema.js';
|
||||
import { filamentModel } from './management/filament.schema.js';
|
||||
import { gcodeFileModel } from './production/gcodefile.schema.js';
|
||||
import { partModel } from './management/part.schema.js';
|
||||
import { productModel } from './management/product.schema.js';
|
||||
import { vendorModel } from './management/vendor.schema.js';
|
||||
import { filamentStockModel } from './inventory/filamentstock.schema.js';
|
||||
import { purchaseOrderModel } from './inventory/purchaseorder.schema.js';
|
||||
import { stockEventModel } from './inventory/stockevent.schema.js';
|
||||
import { stockAuditModel } from './inventory/stockaudit.schema.js';
|
||||
import { partStockModel } from './inventory/partstock.schema.js';
|
||||
import { auditLogModel } from './management/auditlog.schema.js';
|
||||
import { userModel } from './management/user.schema.js';
|
||||
import { noteTypeModel } from './management/notetype.schema.js';
|
||||
import { noteModel } from './misc/note.schema.js';
|
||||
import { documentSizeModel } from './management/documentsize.schema.js';
|
||||
import { documentTemplateModel } from './management/documenttemplate.schema.js';
|
||||
import { hostModel } from './management/host.schema.js';
|
||||
import { documentPrinterModel } from './management/documentprinter.schema.js';
|
||||
import { documentJobModel } from './management/documentjob.schema.js';
|
||||
import { fileModel } from './management/file.schema.js';
|
||||
import { courierServiceModel } from './management/courierservice.schema.js';
|
||||
import { courierModel } from './management/courier.schema.js';
|
||||
import { taxRateModel } from './management/taxrates.schema.js';
|
||||
import { taxRecordModel } from './management/taxrecord.schema.js';
|
||||
|
||||
// Map prefixes to models and id fields
|
||||
export const models = {
|
||||
PRN: { model: printerModel, idField: '_id', type: 'printer', referenceField: '_reference' },
|
||||
FIL: { model: filamentModel, idField: '_id', type: 'filament', referenceField: '_reference' },
|
||||
GCF: { model: gcodeFileModel, idField: '_id', type: 'gcodeFile', referenceField: '_reference' },
|
||||
JOB: { model: jobModel, idField: '_id', type: 'job', referenceField: '_reference' },
|
||||
PRT: { model: partModel, idField: '_id', type: 'part', referenceField: '_reference' },
|
||||
PRD: { model: productModel, idField: '_id', type: 'product', referenceField: '_reference' },
|
||||
VEN: { model: vendorModel, idField: '_id', type: 'vendor', referenceField: '_reference' },
|
||||
SJB: { model: subJobModel, idField: '_id', type: 'subJob', referenceField: '_reference' },
|
||||
FLS: {
|
||||
model: filamentStockModel,
|
||||
idField: '_id',
|
||||
type: 'filamentStock',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
SEV: { model: stockEventModel, idField: '_id', type: 'stockEvent', referenceField: '_reference' },
|
||||
SAU: { model: stockAuditModel, idField: '_id', type: 'stockAudit', referenceField: '_reference' },
|
||||
PTS: { model: partStockModel, idField: '_id', type: 'partStock', referenceField: '_reference' },
|
||||
PDS: { model: null, idField: '_id', type: 'productStock', referenceField: '_reference' }, // No productStockModel found
|
||||
ADL: { model: auditLogModel, idField: '_id', type: 'auditLog', referenceField: '_reference' },
|
||||
USR: { model: userModel, idField: '_id', type: 'user', referenceField: '_reference' },
|
||||
NTY: { model: noteTypeModel, idField: '_id', type: 'noteType', referenceField: '_reference' },
|
||||
NTE: { model: noteModel, idField: '_id', type: 'note', referenceField: '_reference' },
|
||||
DSZ: {
|
||||
model: documentSizeModel,
|
||||
idField: '_id',
|
||||
type: 'documentSize',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
DTP: {
|
||||
model: documentTemplateModel,
|
||||
idField: '_id',
|
||||
type: 'documentTemplate',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
DPR: {
|
||||
model: documentPrinterModel,
|
||||
idField: '_id',
|
||||
type: 'documentPrinter',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
DJB: {
|
||||
model: documentJobModel,
|
||||
idField: '_id',
|
||||
type: 'documentJob',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
HST: { model: hostModel, idField: '_id', type: 'host', referenceField: '_reference' },
|
||||
FLE: { model: fileModel, idField: '_id', type: 'file', referenceField: '_reference' },
|
||||
POR: {
|
||||
model: purchaseOrderModel,
|
||||
idField: '_id',
|
||||
type: 'purchaseOrder',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
COS: {
|
||||
model: courierServiceModel,
|
||||
idField: '_id',
|
||||
type: 'courierService',
|
||||
referenceField: '_reference',
|
||||
},
|
||||
COR: { model: courierModel, idField: '_id', type: 'courier', referenceField: '_reference' },
|
||||
TXR: { model: taxRateModel, idField: '_id', type: 'taxRate', referenceField: '_reference' },
|
||||
TXD: { model: taxRecordModel, idField: '_id', type: 'taxRecord', referenceField: '_reference' },
|
||||
};
|
||||
@ -78,7 +78,7 @@ export const getPurchaseOrderRouteHandler = async (req, res) => {
|
||||
const result = await getObject({
|
||||
model: purchaseOrderModel,
|
||||
id,
|
||||
populate: ['vendor', 'items.item', 'items.taxRate'],
|
||||
populate: ['vendor', 'items.item'],
|
||||
});
|
||||
if (result?.error) {
|
||||
logger.warn(`Purchase Order not found with supplied id.`);
|
||||
|
||||
@ -53,7 +53,7 @@ export const listPartsByPropertiesRouteHandler = async (req, res, properties = '
|
||||
model: partModel,
|
||||
properties,
|
||||
filter,
|
||||
populate: ['vendor', 'priceTaxRate', 'costTaxRate'],
|
||||
populate: ['vendor'],
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
@ -71,7 +71,7 @@ export const getPartRouteHandler = async (req, res) => {
|
||||
const result = await getObject({
|
||||
model: partModel,
|
||||
id,
|
||||
populate: ['vendor', 'priceTaxRate', 'costTaxRate'],
|
||||
populate: ['vendor'],
|
||||
});
|
||||
if (result?.error) {
|
||||
logger.warn(`Part not found with supplied id.`);
|
||||
@ -96,10 +96,6 @@ export const editPartRouteHandler = async (req, res) => {
|
||||
price: req.body?.price,
|
||||
cost: req.body?.cost,
|
||||
priceMode: req.body?.priceMode,
|
||||
priceTaxRate: req.body?.priceTaxRate,
|
||||
costTaxRate: req.body?.costTaxRate,
|
||||
priceWithTax: req.body?.priceWithTax,
|
||||
costWithTax: req.body?.costWithTax,
|
||||
};
|
||||
// Create audit log before updating
|
||||
const result = await editObject({
|
||||
@ -130,10 +126,6 @@ export const newPartRouteHandler = async (req, res) => {
|
||||
price: req.body?.price,
|
||||
cost: req.body?.cost,
|
||||
priceMode: req.body?.priceMode,
|
||||
priceTaxRate: req.body?.priceTaxRate,
|
||||
costTaxRate: req.body?.costTaxRate,
|
||||
priceWithTax: req.body?.priceWithTax,
|
||||
costWithTax: req.body?.costWithTax,
|
||||
};
|
||||
|
||||
const result = await newObject({
|
||||
|
||||
@ -1,168 +0,0 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { taxRateModel } from '../../schemas/management/taxrates.schema.js';
|
||||
import log4js from 'log4js';
|
||||
import mongoose from 'mongoose';
|
||||
import {
|
||||
deleteObject,
|
||||
listObjects,
|
||||
getObject,
|
||||
editObject,
|
||||
newObject,
|
||||
listObjectsByProperties,
|
||||
} from '../../database/database.js';
|
||||
dotenv.config();
|
||||
|
||||
const logger = log4js.getLogger('TaxRates');
|
||||
logger.level = process.env.LOG_LEVEL;
|
||||
|
||||
export const listTaxRatesRouteHandler = async (
|
||||
req,
|
||||
res,
|
||||
page = 1,
|
||||
limit = 25,
|
||||
property = '',
|
||||
filter = {},
|
||||
search = '',
|
||||
sort = '',
|
||||
order = 'ascend'
|
||||
) => {
|
||||
const result = await listObjects({
|
||||
model: taxRateModel,
|
||||
page,
|
||||
limit,
|
||||
property,
|
||||
filter,
|
||||
search,
|
||||
sort,
|
||||
order,
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
logger.error('Error listing tax rates.');
|
||||
res.status(result.code).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`List of tax rates (Page ${page}, Limit ${limit}). Count: ${result.length}.`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const listTaxRatesByPropertiesRouteHandler = async (
|
||||
req,
|
||||
res,
|
||||
properties = '',
|
||||
filter = {}
|
||||
) => {
|
||||
const result = await listObjectsByProperties({
|
||||
model: taxRateModel,
|
||||
properties,
|
||||
filter,
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
logger.error('Error listing tax rates.');
|
||||
res.status(result.code).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`List of tax rates. Count: ${result.length}`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const getTaxRateRouteHandler = async (req, res) => {
|
||||
const id = req.params.id;
|
||||
const result = await getObject({
|
||||
model: taxRateModel,
|
||||
id,
|
||||
});
|
||||
if (result?.error) {
|
||||
logger.warn(`Tax rate not found with supplied id.`);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
logger.debug(`Retreived tax rate with ID: ${id}`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const editTaxRateRouteHandler = async (req, res) => {
|
||||
// Get ID from params
|
||||
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||
|
||||
logger.trace(`Tax rate with ID: ${id}`);
|
||||
|
||||
const updateData = {
|
||||
updatedAt: new Date(),
|
||||
name: req.body.name,
|
||||
rate: req.body.rate,
|
||||
rateType: req.body.rateType,
|
||||
active: req.body.active,
|
||||
description: req.body.description,
|
||||
country: req.body.country,
|
||||
effectiveFrom: req.body.effectiveFrom,
|
||||
effectiveTo: req.body.effectiveTo,
|
||||
};
|
||||
// Create audit log before updating
|
||||
const result = await editObject({
|
||||
model: taxRateModel,
|
||||
id,
|
||||
updateData,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
logger.error('Error editing tax rate:', result.error);
|
||||
res.status(result).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`Edited tax rate with ID: ${id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const newTaxRateRouteHandler = async (req, res) => {
|
||||
const newData = {
|
||||
updatedAt: new Date(),
|
||||
name: req.body.name,
|
||||
rate: req.body.rate,
|
||||
rateType: req.body.rateType,
|
||||
active: req.body.active,
|
||||
description: req.body.description,
|
||||
country: req.body.country,
|
||||
effectiveFrom: req.body.effectiveFrom,
|
||||
effectiveTo: req.body.effectiveTo,
|
||||
};
|
||||
const result = await newObject({
|
||||
model: taxRateModel,
|
||||
newData,
|
||||
user: req.user,
|
||||
});
|
||||
if (result.error) {
|
||||
logger.error('No tax rate created:', result.error);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
|
||||
logger.debug(`New tax rate with ID: ${result._id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const deleteTaxRateRouteHandler = async (req, res) => {
|
||||
// Get ID from params
|
||||
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||
|
||||
logger.trace(`Tax rate with ID: ${id}`);
|
||||
|
||||
const result = await deleteObject({
|
||||
model: taxRateModel,
|
||||
id,
|
||||
user: req.user,
|
||||
});
|
||||
if (result.error) {
|
||||
logger.error('No tax rate deleted:', result.error);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
|
||||
logger.debug(`Deleted tax rate with ID: ${result._id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
@ -1,164 +0,0 @@
|
||||
import dotenv from 'dotenv';
|
||||
import { taxRecordModel } from '../../schemas/management/taxrecord.schema.js';
|
||||
import log4js from 'log4js';
|
||||
import mongoose from 'mongoose';
|
||||
import {
|
||||
deleteObject,
|
||||
listObjects,
|
||||
getObject,
|
||||
editObject,
|
||||
newObject,
|
||||
listObjectsByProperties,
|
||||
} from '../../database/database.js';
|
||||
dotenv.config();
|
||||
|
||||
const logger = log4js.getLogger('TaxRecords');
|
||||
logger.level = process.env.LOG_LEVEL;
|
||||
|
||||
export const listTaxRecordsRouteHandler = async (
|
||||
req,
|
||||
res,
|
||||
page = 1,
|
||||
limit = 25,
|
||||
property = '',
|
||||
filter = {},
|
||||
search = '',
|
||||
sort = '',
|
||||
order = 'ascend'
|
||||
) => {
|
||||
const result = await listObjects({
|
||||
model: taxRecordModel,
|
||||
page,
|
||||
limit,
|
||||
property,
|
||||
filter,
|
||||
search,
|
||||
sort,
|
||||
order,
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
logger.error('Error listing tax records.');
|
||||
res.status(result.code).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`List of tax records (Page ${page}, Limit ${limit}). Count: ${result.length}.`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const listTaxRecordsByPropertiesRouteHandler = async (
|
||||
req,
|
||||
res,
|
||||
properties = '',
|
||||
filter = {}
|
||||
) => {
|
||||
const result = await listObjectsByProperties({
|
||||
model: taxRecordModel,
|
||||
properties,
|
||||
filter,
|
||||
});
|
||||
|
||||
if (result?.error) {
|
||||
logger.error('Error listing tax records.');
|
||||
res.status(result.code).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`List of tax records. Count: ${result.length}`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const getTaxRecordRouteHandler = async (req, res) => {
|
||||
const id = req.params.id;
|
||||
const result = await getObject({
|
||||
model: taxRecordModel,
|
||||
id,
|
||||
});
|
||||
if (result?.error) {
|
||||
logger.warn(`Tax record not found with supplied id.`);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
logger.debug(`Retreived tax record with ID: ${id}`);
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const editTaxRecordRouteHandler = async (req, res) => {
|
||||
// Get ID from params
|
||||
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||
|
||||
logger.trace(`Tax record with ID: ${id}`);
|
||||
|
||||
const updateData = {
|
||||
updatedAt: new Date(),
|
||||
taxRate: req.body.taxRate,
|
||||
transactionType: req.body.transactionType,
|
||||
transaction: req.body.transaction,
|
||||
amount: req.body.amount,
|
||||
taxAmount: req.body.taxAmount,
|
||||
transactionDate: req.body.transactionDate,
|
||||
};
|
||||
// Create audit log before updating
|
||||
const result = await editObject({
|
||||
model: taxRecordModel,
|
||||
id,
|
||||
updateData,
|
||||
user: req.user,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
logger.error('Error editing tax record:', result.error);
|
||||
res.status(result).send(result);
|
||||
return;
|
||||
}
|
||||
|
||||
logger.debug(`Edited tax record with ID: ${id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const newTaxRecordRouteHandler = async (req, res) => {
|
||||
const newData = {
|
||||
updatedAt: new Date(),
|
||||
taxRate: req.body.taxRate,
|
||||
transactionType: req.body.transactionType,
|
||||
transaction: req.body.transaction,
|
||||
amount: req.body.amount,
|
||||
taxAmount: req.body.taxAmount,
|
||||
transactionDate: req.body.transactionDate,
|
||||
};
|
||||
const result = await newObject({
|
||||
model: taxRecordModel,
|
||||
newData,
|
||||
user: req.user,
|
||||
});
|
||||
if (result.error) {
|
||||
logger.error('No tax record created:', result.error);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
|
||||
logger.debug(`New tax record with ID: ${result._id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
|
||||
export const deleteTaxRecordRouteHandler = async (req, res) => {
|
||||
// Get ID from params
|
||||
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||
|
||||
logger.trace(`Tax record with ID: ${id}`);
|
||||
|
||||
const result = await deleteObject({
|
||||
model: taxRecordModel,
|
||||
id,
|
||||
user: req.user,
|
||||
});
|
||||
if (result.error) {
|
||||
logger.error('No tax record deleted:', result.error);
|
||||
return res.status(result.code).send(result);
|
||||
}
|
||||
|
||||
logger.debug(`Deleted tax record with ID: ${result._id}`);
|
||||
|
||||
res.send(result);
|
||||
};
|
||||
@ -1,11 +1,65 @@
|
||||
import { models } from '../../schemas/models.js';
|
||||
import { jobModel } from '../../schemas/production/job.schema.js';
|
||||
import { subJobModel } from '../../schemas/production/subjob.schema.js';
|
||||
import { printerModel } from '../../schemas/production/printer.schema.js';
|
||||
import { filamentModel } from '../../schemas/management/filament.schema.js';
|
||||
import { gcodeFileModel } from '../../schemas/production/gcodefile.schema.js';
|
||||
import { partModel } from '../../schemas/management/part.schema.js';
|
||||
import { productModel } from '../../schemas/management/product.schema.js';
|
||||
import { vendorModel } from '../../schemas/management/vendor.schema.js';
|
||||
import { filamentStockModel } from '../../schemas/inventory/filamentstock.schema.js';
|
||||
import { purchaseOrderModel } from '../../schemas/inventory/purchaseorder.schema.js';
|
||||
import { stockEventModel } from '../../schemas/inventory/stockevent.schema.js';
|
||||
import { stockAuditModel } from '../../schemas/inventory/stockaudit.schema.js';
|
||||
import { partStockModel } from '../../schemas/inventory/partstock.schema.js';
|
||||
import { auditLogModel } from '../../schemas/management/auditlog.schema.js';
|
||||
import { userModel } from '../../schemas/management/user.schema.js';
|
||||
import { noteTypeModel } from '../../schemas/management/notetype.schema.js';
|
||||
import { noteModel } from '../../schemas/misc/note.schema.js';
|
||||
import { documentSizeModel } from '../../schemas/management/documentsize.schema.js';
|
||||
import { documentTemplateModel } from '../../schemas/management/documenttemplate.schema.js';
|
||||
import { hostModel } from '../../schemas/management/host.schema.js';
|
||||
import { documentPrinterModel } from '../../schemas/management/documentprinter.schema.js';
|
||||
import { documentJobModel } from '../../schemas/management/documentjob.schema.js';
|
||||
import { fileModel } from '../../schemas/management/file.schema.js';
|
||||
import { courierServiceModel } from '../../schemas/management/courierservice.schema.js';
|
||||
import { courierModel } from '../../schemas/management/courier.schema.js';
|
||||
|
||||
// Map prefixes to models and id fields
|
||||
const PREFIX_MODEL_MAP = {
|
||||
PRN: { model: printerModel, idField: '_id', type: 'printer' },
|
||||
FIL: { model: filamentModel, idField: '_id', type: 'filament' },
|
||||
GCF: { model: gcodeFileModel, idField: '_id', type: 'gcodeFile' },
|
||||
JOB: { model: jobModel, idField: '_id', type: 'job' },
|
||||
PRT: { model: partModel, idField: '_id', type: 'part' },
|
||||
PRD: { model: productModel, idField: '_id', type: 'product' },
|
||||
VEN: { model: vendorModel, idField: '_id', type: 'vendor' },
|
||||
SJB: { model: subJobModel, idField: '_id', type: 'subJob' },
|
||||
FLS: { model: filamentStockModel, idField: '_id', type: 'filamentStock' },
|
||||
SEV: { model: stockEventModel, idField: '_id', type: 'stockEvent' },
|
||||
SAU: { model: stockAuditModel, idField: '_id', type: 'stockAudit' },
|
||||
PTS: { model: partStockModel, idField: '_id', type: 'partStock' },
|
||||
PDS: { model: null, idField: '_id', type: 'productStock' }, // No productStockModel found
|
||||
ADL: { model: auditLogModel, idField: '_id', type: 'auditLog' },
|
||||
USR: { model: userModel, idField: '_id', type: 'user' },
|
||||
NTY: { model: noteTypeModel, idField: '_id', type: 'noteType' },
|
||||
NTE: { model: noteModel, idField: '_id', type: 'note' },
|
||||
DSZ: { model: documentSizeModel, idField: '_id', type: 'documentSize' },
|
||||
DTP: { model: documentTemplateModel, idField: '_id', type: 'documentTemplate' },
|
||||
DPR: { model: documentPrinterModel, idField: '_id', type: 'documentPrinter' },
|
||||
DJB: { model: documentJobModel, idField: '_id', type: 'documentJob' },
|
||||
HST: { model: hostModel, idField: '_id', type: 'host' },
|
||||
FLE: { model: fileModel, idField: '_id', type: 'file' },
|
||||
POR: { model: purchaseOrderModel, idField: '_id', type: 'purchaseOrder' },
|
||||
COS: { model: courierServiceModel, idField: '_id', type: 'courierService' },
|
||||
COR: { model: courierModel, idField: '_id', type: 'courier' },
|
||||
};
|
||||
|
||||
/**
|
||||
* Get all models from the PREFIX_MODEL_MAP
|
||||
* @returns {Array} Array of model entries with model, idField, and type properties
|
||||
*/
|
||||
export const getAllModels = () => {
|
||||
return Object.values(models);
|
||||
return Object.values(PREFIX_MODEL_MAP);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -14,7 +68,7 @@ export const getAllModels = () => {
|
||||
* @returns {Object|null} The model entry or null if not found
|
||||
*/
|
||||
export const getModelByName = (name) => {
|
||||
const entry = Object.values(models).find((entry) => entry.type === name);
|
||||
const entry = Object.values(PREFIX_MODEL_MAP).find((entry) => entry.type === name);
|
||||
return entry || null;
|
||||
};
|
||||
|
||||
@ -24,8 +78,8 @@ export const getModelByName = (name) => {
|
||||
* @returns {Object|null} The model entry or null if not found
|
||||
*/
|
||||
export const getModelByPrefix = (prefix) => {
|
||||
return models[prefix] || null;
|
||||
return PREFIX_MODEL_MAP[prefix] || null;
|
||||
};
|
||||
|
||||
// Export the PREFIX_MODEL_MAP for backward compatibility
|
||||
export { models };
|
||||
export { PREFIX_MODEL_MAP };
|
||||
|
||||
@ -60,7 +60,7 @@ export const getSpotlightRouteHandler = async (req, res) => {
|
||||
res.status(200).send([]);
|
||||
return;
|
||||
}
|
||||
const prefix = query.substring(0, 3).toUpperCase();
|
||||
const prefix = query.substring(0, 3);
|
||||
const delimiter = query.substring(3, 4);
|
||||
const suffix = query.substring(4);
|
||||
|
||||
@ -72,32 +72,18 @@ export const getSpotlightRouteHandler = async (req, res) => {
|
||||
res.status(400).send({ error: 'Invalid or unsupported prefix' });
|
||||
return;
|
||||
}
|
||||
const { model, idField, type, referenceField } = prefixEntry;
|
||||
|
||||
const suffixLength = suffix.length;
|
||||
const { model, idField, type } = prefixEntry;
|
||||
|
||||
// Validate ObjectId if the idField is '_id'
|
||||
if (
|
||||
idField === '_id' &&
|
||||
referenceField === '_reference' &&
|
||||
!mongoose.Types.ObjectId.isValid(suffix) &&
|
||||
suffixLength != 12
|
||||
) {
|
||||
if (idField === '_id' && !mongoose.Types.ObjectId.isValid(suffix)) {
|
||||
res.status(200).send([]);
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the object by the correct field
|
||||
const queryObj = {};
|
||||
|
||||
if (suffixLength == 12) {
|
||||
queryObj[referenceField] = suffix.toUpperCase();
|
||||
} else {
|
||||
queryObj[idField] = suffix.toLowerCase();
|
||||
}
|
||||
|
||||
queryObj[idField] = suffix.toLowerCase();
|
||||
let doc = await model.findOne(queryObj).lean();
|
||||
|
||||
if (!doc) {
|
||||
res.status(200).send([]);
|
||||
return;
|
||||
|
||||
25
src/utils.js
25
src/utils.js
@ -329,28 +329,9 @@ function getChangedValues(oldObj, newObj, old = false) {
|
||||
changes[key] = nestedChanges;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if both values are numbers (or can be converted to numbers)
|
||||
const oldIsNumber =
|
||||
typeof oldVal === 'number' ||
|
||||
(oldVal !== null && oldVal !== undefined && !isNaN(Number(oldVal)) && oldVal !== '');
|
||||
const newIsNumber =
|
||||
typeof newVal === 'number' ||
|
||||
(newVal !== null && newVal !== undefined && !isNaN(Number(newVal)) && newVal !== '');
|
||||
|
||||
let valuesDiffer;
|
||||
if (oldIsNumber && newIsNumber) {
|
||||
// Compare numbers directly (this normalizes 7.50 to 7.5)
|
||||
valuesDiffer = Number(oldVal) !== Number(newVal);
|
||||
} else {
|
||||
// Use JSON.stringify for non-number comparisons
|
||||
valuesDiffer = JSON.stringify(oldVal) !== JSON.stringify(newVal);
|
||||
}
|
||||
|
||||
if (valuesDiffer) {
|
||||
// If the old value is different from the new value, include it
|
||||
changes[key] = old ? oldVal : newVal;
|
||||
}
|
||||
} else if (JSON.stringify(oldVal) !== JSON.stringify(newVal)) {
|
||||
// If the old value is different from the new value, include it
|
||||
changes[key] = old ? oldVal : newVal;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user