Compare commits
17 Commits
9c4e0ee974
...
a12ae1f340
| Author | SHA1 | Date | |
|---|---|---|---|
| a12ae1f340 | |||
| db85735f9b | |||
| 5a16890b7a | |||
| 361689cef4 | |||
| a7bda46acf | |||
| 7541612d67 | |||
| ecb888f692 | |||
| fadaafdad8 | |||
| eb2e920028 | |||
| 2ac550b0c4 | |||
| 9c4b73da67 | |||
| 75e5079479 | |||
| 4421c0b946 | |||
| 9ab08f39a1 | |||
| 85f9ca8b6d | |||
| c750b1a573 | |||
| 5545452b0c |
@ -9,14 +9,14 @@
|
|||||||
"keycloak": {
|
"keycloak": {
|
||||||
"url": "https://auth.tombutcher.work",
|
"url": "https://auth.tombutcher.work",
|
||||||
"realm": "master",
|
"realm": "master",
|
||||||
"clientId": "farmcontrol-client"
|
"clientId": "farmcontrol-dev"
|
||||||
},
|
},
|
||||||
"requiredRoles": []
|
"requiredRoles": []
|
||||||
},
|
},
|
||||||
"app": {
|
"app": {
|
||||||
"urlClient": "http://localhost:3000",
|
"urlClient": "https://dev.tombutcher.work",
|
||||||
"urlElectronClient": "http://localhost:3000",
|
"urlElectronClient": "http://localhost:5780",
|
||||||
"urlApi": "http://localhost:8787",
|
"urlApi": "https://dev.tombutcher.work/api",
|
||||||
"devAuthClient": "http://localhost:3500"
|
"devAuthClient": "http://localhost:3500"
|
||||||
},
|
},
|
||||||
"database": {
|
"database": {
|
||||||
|
|||||||
@ -2,6 +2,10 @@
|
|||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from 'url';
|
||||||
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
|
// Load environment variables from .env file
|
||||||
|
dotenv.config();
|
||||||
|
|
||||||
// Configure paths relative to this file
|
// Configure paths relative to this file
|
||||||
const __filename = fileURLToPath(import.meta.url);
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
|||||||
@ -349,12 +349,14 @@ export const listObjects = async ({
|
|||||||
filter = {},
|
filter = {},
|
||||||
sort = '',
|
sort = '',
|
||||||
order = 'ascend',
|
order = 'ascend',
|
||||||
|
pagination = true,
|
||||||
project, // optional: override default projection
|
project, // optional: override default projection
|
||||||
}) => {
|
}) => {
|
||||||
try {
|
try {
|
||||||
logger.trace('Listing object:', {
|
logger.trace('Listing object:', {
|
||||||
model,
|
model,
|
||||||
populate,
|
populate,
|
||||||
|
pagination,
|
||||||
page,
|
page,
|
||||||
limit,
|
limit,
|
||||||
filter,
|
filter,
|
||||||
@ -363,7 +365,7 @@ export const listObjects = async ({
|
|||||||
project,
|
project,
|
||||||
});
|
});
|
||||||
// Calculate the skip value based on the page number and limit
|
// Calculate the skip value based on the page number and limit
|
||||||
const skip = (page - 1) * limit;
|
const skip = pagination ? (page - 1) * limit : 0;
|
||||||
// Fix: descend should be -1, ascend should be 1
|
// Fix: descend should be -1, ascend should be 1
|
||||||
const sortOrder = order === 'descend' ? -1 : 1;
|
const sortOrder = order === 'descend' ? -1 : 1;
|
||||||
|
|
||||||
@ -389,7 +391,7 @@ export const listObjects = async ({
|
|||||||
.find(filter)
|
.find(filter)
|
||||||
.sort({ [sort]: sortOrder })
|
.sort({ [sort]: sortOrder })
|
||||||
.skip(skip)
|
.skip(skip)
|
||||||
.limit(Number(limit));
|
.limit(pagination ? Number(limit) : undefined);
|
||||||
|
|
||||||
// Handle populate (array or single value)
|
// Handle populate (array or single value)
|
||||||
if (populate) {
|
if (populate) {
|
||||||
@ -599,7 +601,7 @@ export const listObjectsByProperties = async ({
|
|||||||
} else {
|
} else {
|
||||||
// If no properties specified, just return all objects without grouping
|
// If no properties specified, just return all objects without grouping
|
||||||
// Ensure pipeline is not empty by adding a $match stage if needed
|
// Ensure pipeline is not empty by adding a $match stage if needed
|
||||||
if (pipeline.length === 0) {
|
if (pipeline.length === 0 && masterFilter == {}) {
|
||||||
pipeline.push({ $match: {} });
|
pipeline.push({ $match: {} });
|
||||||
}
|
}
|
||||||
const results = await model.aggregate(pipeline);
|
const results = await model.aggregate(pipeline);
|
||||||
@ -731,8 +733,25 @@ export const listObjectDependencies = async ({ model, id }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkStates = async ({ model, id, states }) => {
|
||||||
|
try {
|
||||||
|
const object = await getObject({ model, id, cached: true });
|
||||||
|
if (!object?.state?.type) {
|
||||||
|
logger.warn(`Object ${id} has no state type.`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (states.includes(object?.state?.type)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('checkStates error:', error);
|
||||||
|
return { error: error.message, code: 500 };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Reusable function to edit an object by ID, with audit logging and distribution
|
// Reusable function to edit an object by ID, with audit logging and distribution
|
||||||
export const editObject = async ({ model, id, updateData, user, populate }) => {
|
export const editObject = async ({ model, id, updateData, user, populate, recalculate = true }) => {
|
||||||
try {
|
try {
|
||||||
// Determine parentType from model name
|
// Determine parentType from model name
|
||||||
const parentType = model.modelName ? model.modelName : 'unknown';
|
const parentType = model.modelName ? model.modelName : 'unknown';
|
||||||
@ -810,7 +829,7 @@ export const editObject = async ({ model, id, updateData, user, populate }) => {
|
|||||||
populate,
|
populate,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (model.recalculate) {
|
if (model.recalculate && recalculate == true) {
|
||||||
logger.debug(`Recalculating ${model.modelName}`);
|
logger.debug(`Recalculating ${model.modelName}`);
|
||||||
await model.recalculate(updatedObject, user);
|
await model.recalculate(updatedObject, user);
|
||||||
}
|
}
|
||||||
@ -828,6 +847,33 @@ export const editObject = async ({ model, id, updateData, user, populate }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Reusable function to edit multiple objects
|
||||||
|
export const editObjects = async ({ model, updates, user, populate, recalculate = true }) => {
|
||||||
|
try {
|
||||||
|
const results = [];
|
||||||
|
for (const update of updates) {
|
||||||
|
const id = update._id || update.id;
|
||||||
|
const updateData = { ...update };
|
||||||
|
delete updateData._id;
|
||||||
|
delete updateData.id;
|
||||||
|
|
||||||
|
const result = await editObject({
|
||||||
|
model,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user,
|
||||||
|
populate,
|
||||||
|
recalculate,
|
||||||
|
});
|
||||||
|
results.push(result);
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('editObjects error:', error);
|
||||||
|
return { error: error.message, code: 500 };
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Reusable function to create a new object
|
// Reusable function to create a new object
|
||||||
export const newObject = async ({ model, newData, user = null }, distributeChanges = true) => {
|
export const newObject = async ({ model, newData, user = null }, distributeChanges = true) => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
98
src/database/schemas/finance/invoice.schema.js
Normal file
98
src/database/schemas/finance/invoice.schema.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
import mongoose from 'mongoose';
|
||||||
|
import { generateId } from '../../utils.js';
|
||||||
|
const { Schema } = mongoose;
|
||||||
|
import { aggregateRollups, aggregateRollupsHistory } from '../../database.js';
|
||||||
|
|
||||||
|
const invoiceSchema = new Schema(
|
||||||
|
{
|
||||||
|
_reference: { type: String, default: () => generateId()() },
|
||||||
|
totalAmount: { type: Number, required: true, default: 0 },
|
||||||
|
totalAmountWithTax: { type: Number, required: true, default: 0 },
|
||||||
|
shippingAmount: { type: Number, required: true, default: 0 },
|
||||||
|
shippingAmountWithTax: { type: Number, required: true, default: 0 },
|
||||||
|
grandTotalAmount: { type: Number, required: true, default: 0 },
|
||||||
|
totalTaxAmount: { type: Number, required: true, default: 0 },
|
||||||
|
timestamp: { type: Date, default: Date.now },
|
||||||
|
invoiceDate: { type: Date, required: false },
|
||||||
|
dueDate: { type: Date, required: false },
|
||||||
|
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: false },
|
||||||
|
customer: { type: Schema.Types.ObjectId, ref: 'customer', required: false },
|
||||||
|
invoiceType: { type: String, required: true, default: 'sales', enum: ['sales', 'purchase'] },
|
||||||
|
relatedOrderType: { type: String, required: false },
|
||||||
|
relatedOrder: { type: Schema.Types.ObjectId, refPath: 'relatedOrderType', required: false },
|
||||||
|
state: {
|
||||||
|
type: { type: String, required: true, default: 'draft' },
|
||||||
|
},
|
||||||
|
sentAt: { type: Date, required: false },
|
||||||
|
paidAt: { type: Date, required: false },
|
||||||
|
cancelledAt: { type: Date, required: false },
|
||||||
|
overdueAt: { type: Date, required: false },
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
const rollupConfigs = [
|
||||||
|
{
|
||||||
|
name: 'draft',
|
||||||
|
filter: { 'state.type': 'draft' },
|
||||||
|
rollups: [{ name: 'draft', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sent',
|
||||||
|
filter: { 'state.type': 'sent' },
|
||||||
|
rollups: [{ name: 'sent', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'partiallyPaid',
|
||||||
|
filter: { 'state.type': 'partiallyPaid' },
|
||||||
|
rollups: [{ name: 'partiallyPaid', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'paid',
|
||||||
|
filter: { 'state.type': 'paid' },
|
||||||
|
rollups: [{ name: 'paid', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'overdue',
|
||||||
|
filter: { 'state.type': 'overdue' },
|
||||||
|
rollups: [{ name: 'overdue', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cancelled',
|
||||||
|
filter: { 'state.type': 'cancelled' },
|
||||||
|
rollups: [{ name: 'cancelled', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
invoiceSchema.statics.stats = async function () {
|
||||||
|
const results = await aggregateRollups({
|
||||||
|
model: this,
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Transform the results to match the expected format
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
invoiceSchema.statics.history = async function (from, to) {
|
||||||
|
const results = await aggregateRollupsHistory({
|
||||||
|
model: this,
|
||||||
|
startDate: from,
|
||||||
|
endDate: to,
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return time-series data array
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add virtual id getter
|
||||||
|
invoiceSchema.virtual('id').get(function () {
|
||||||
|
return this._id;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configure JSON serialization to include virtuals
|
||||||
|
invoiceSchema.set('toJSON', { virtuals: true });
|
||||||
|
|
||||||
|
// Create and export the model
|
||||||
|
export const invoiceModel = mongoose.model('invoice', invoiceSchema);
|
||||||
@ -1,6 +1,12 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
||||||
import { aggregateRollups, editObject } from '../../database.js';
|
import { taxRateModel } from '../management/taxrate.schema.js';
|
||||||
|
import {
|
||||||
|
aggregateRollups,
|
||||||
|
aggregateRollupsHistory,
|
||||||
|
editObject,
|
||||||
|
getObject,
|
||||||
|
} from '../../database.js';
|
||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
@ -8,20 +14,64 @@ const orderItemSchema = new Schema(
|
|||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
orderType: { type: String, required: true },
|
orderType: { type: String, required: true },
|
||||||
|
state: {
|
||||||
|
type: { type: String, required: true, default: 'draft' },
|
||||||
|
},
|
||||||
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
||||||
itemType: { type: String, required: true },
|
itemType: { type: String, required: true },
|
||||||
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
|
item: { type: Schema.Types.ObjectId, refPath: 'itemType', required: true },
|
||||||
syncAmount: { type: String, required: true, default: null },
|
syncAmount: { type: String, required: false, default: null },
|
||||||
itemAmount: { type: Number, required: true },
|
itemAmount: { type: Number, required: true },
|
||||||
quantity: { type: Number, required: true },
|
quantity: { type: Number, required: true },
|
||||||
totalAmount: { type: Number, required: true },
|
totalAmount: { type: Number, required: true },
|
||||||
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
totalAmountWithTax: { type: Number, required: true },
|
totalAmountWithTax: { type: Number, required: true },
|
||||||
timestamp: { type: Date, default: Date.now },
|
timestamp: { type: Date, default: Date.now },
|
||||||
|
shipment: { type: Schema.Types.ObjectId, ref: 'shipment', required: false },
|
||||||
|
orderedAt: { type: Date, required: false },
|
||||||
|
receivedAt: { type: Date, required: false },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rollupConfigs = [
|
||||||
|
{
|
||||||
|
name: 'shipped',
|
||||||
|
filter: { 'state.type': 'shipped' },
|
||||||
|
rollups: [{ name: 'shipped', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'received',
|
||||||
|
filter: { 'state.type': 'received' },
|
||||||
|
rollups: [{ name: 'received', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
orderItemSchema.statics.stats = async function () {
|
||||||
|
const results = await aggregateRollups({
|
||||||
|
model: this,
|
||||||
|
baseFilter: {},
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(results);
|
||||||
|
|
||||||
|
// Transform the results to match the expected format
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
orderItemSchema.statics.history = async function (from, to) {
|
||||||
|
const results = await aggregateRollupsHistory({
|
||||||
|
model: this,
|
||||||
|
startDate: from,
|
||||||
|
endDate: to,
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return time-series data array
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
||||||
// Only purchase orders are supported for now
|
// Only purchase orders are supported for now
|
||||||
if (orderItem.orderType !== 'purchaseOrder') {
|
if (orderItem.orderType !== 'purchaseOrder') {
|
||||||
@ -33,6 +83,29 @@ orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var taxRate = orderItem.taxRate;
|
||||||
|
|
||||||
|
if (orderItem.taxRate?._id && Object.keys(orderItem.taxRate).length == 1) {
|
||||||
|
taxRate = await getObject({
|
||||||
|
model: taxRateModel,
|
||||||
|
id: orderItem.taxRate._id,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderTotalAmount = orderItem.itemAmount * orderItem.quantity;
|
||||||
|
const orderTotalAmountWithTax = orderTotalAmount * (1 + (taxRate?.rate || 0) / 100);
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: {
|
||||||
|
totalAmount: orderTotalAmount,
|
||||||
|
totalAmountWithTax: orderTotalAmountWithTax,
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
|
||||||
const rollupResults = await aggregateRollups({
|
const rollupResults = await aggregateRollups({
|
||||||
model: this,
|
model: this,
|
||||||
baseFilter: {
|
baseFilter: {
|
||||||
@ -51,21 +124,60 @@ orderItemSchema.statics.recalculate = async function (orderItem, user) {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'overallCount',
|
||||||
|
rollups: [{ name: 'overallCount', property: '_id', operation: 'count' }],
|
||||||
|
},
|
||||||
|
...rollupConfigs,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('rollupResults', rollupResults);
|
||||||
|
|
||||||
const totals = rollupResults.orderTotals || {};
|
const totals = rollupResults.orderTotals || {};
|
||||||
const totalAmount = totals.totalAmount.sum?.toFixed(2) || 0;
|
const totalAmount = totals.totalAmount.sum?.toFixed(2) || 0;
|
||||||
const totalAmountWithTax = totals.totalAmountWithTax.sum?.toFixed(2) || 0;
|
const totalAmountWithTax = totals.totalAmountWithTax.sum?.toFixed(2) || 0;
|
||||||
|
|
||||||
|
const purchaseOrder = await getObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id: orderId,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const grandTotalAmount =
|
||||||
|
parseFloat(totalAmountWithTax || 0) + parseFloat(purchaseOrder.shippingAmountWithTax || 0);
|
||||||
|
|
||||||
|
var updateData = {
|
||||||
|
totalAmount: parseFloat(totalAmount).toFixed(2),
|
||||||
|
totalAmountWithTax: parseFloat(totalAmountWithTax).toFixed(2),
|
||||||
|
totalTaxAmount: parseFloat((totalAmountWithTax - totalAmount).toFixed(2)),
|
||||||
|
grandTotalAmount: parseFloat(grandTotalAmount).toFixed(2),
|
||||||
|
};
|
||||||
|
|
||||||
|
const overallCount = rollupResults.overallCount.count || 0;
|
||||||
|
const shippedCount = rollupResults.shipped.count || 0;
|
||||||
|
const receivedCount = rollupResults.received.count || 0;
|
||||||
|
|
||||||
|
if (shippedCount > 0 && shippedCount < overallCount) {
|
||||||
|
updateData = { ...updateData, state: { type: 'partiallyShipped' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shippedCount > 0 && shippedCount == overallCount) {
|
||||||
|
updateData = { ...updateData, state: { type: 'shipped' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receivedCount > 0 && receivedCount < overallCount) {
|
||||||
|
updateData = { ...updateData, state: { type: 'partiallyReceived' } };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (receivedCount > 0 && receivedCount == overallCount) {
|
||||||
|
updateData = { ...updateData, state: { type: 'received' } };
|
||||||
|
}
|
||||||
|
|
||||||
await editObject({
|
await editObject({
|
||||||
model: purchaseOrderModel,
|
model: purchaseOrderModel,
|
||||||
id: orderId,
|
id: orderId,
|
||||||
updateData: {
|
updateData: updateData,
|
||||||
totalAmount: parseFloat(totalAmount),
|
|
||||||
totalAmountWithTax: parseFloat(totalAmountWithTax),
|
|
||||||
totalTaxAmount: parseFloat(totalAmountWithTax - totalAmount),
|
|
||||||
},
|
|
||||||
user,
|
user,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,22 +1,100 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
import { aggregateRollups, aggregateRollupsHistory } from '../../database.js';
|
||||||
|
|
||||||
const purchaseOrderSchema = new Schema(
|
const purchaseOrderSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
totalAmount: { type: Number, required: true },
|
totalAmount: { type: Number, required: true, default: 0 },
|
||||||
totalAmountWithTax: { type: Number, required: true },
|
totalAmountWithTax: { type: Number, required: true, default: 0 },
|
||||||
totalTaxAmount: { type: Number, required: true },
|
shippingAmount: { type: Number, required: true, default: 0 },
|
||||||
|
shippingAmountWithTax: { type: Number, required: true, default: 0 },
|
||||||
|
grandTotalAmount: { type: Number, required: true, default: 0 },
|
||||||
|
totalTaxAmount: { type: Number, required: true, default: 0 },
|
||||||
timestamp: { type: Date, default: Date.now },
|
timestamp: { type: Date, default: Date.now },
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
||||||
state: {
|
state: {
|
||||||
type: { type: String, required: true, default: 'draft' },
|
type: { type: String, required: true, default: 'draft' },
|
||||||
},
|
},
|
||||||
|
postedAt: { type: Date, required: false },
|
||||||
|
acknowledgedAt: { type: Date, required: false },
|
||||||
|
cancelledAt: { type: Date, required: false },
|
||||||
|
completedAt: { type: Date, required: false },
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const rollupConfigs = [
|
||||||
|
{
|
||||||
|
name: 'draft',
|
||||||
|
filter: { 'state.type': 'draft' },
|
||||||
|
rollups: [{ name: 'draft', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sent',
|
||||||
|
filter: { 'state.type': 'sent' },
|
||||||
|
rollups: [{ name: 'sent', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'acknowledged',
|
||||||
|
filter: { 'state.type': 'acknowledged' },
|
||||||
|
rollups: [{ name: 'acknowledged', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'partiallyShipped',
|
||||||
|
filter: { 'state.type': 'partiallyShipped' },
|
||||||
|
rollups: [{ name: 'partiallyShipped', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'shipped',
|
||||||
|
filter: { 'state.type': 'shipped' },
|
||||||
|
rollups: [{ name: 'shipped', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'partiallyReceived',
|
||||||
|
filter: { 'state.type': 'partiallyReceived' },
|
||||||
|
rollups: [{ name: 'partiallyReceived', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'received',
|
||||||
|
filter: { 'state.type': 'received' },
|
||||||
|
rollups: [{ name: 'received', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cancelled',
|
||||||
|
filter: { 'state.type': 'cancelled' },
|
||||||
|
rollups: [{ name: 'cancelled', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'completed',
|
||||||
|
filter: { 'state.type': 'completed' },
|
||||||
|
rollups: [{ name: 'completed', property: 'state.type', operation: 'count' }],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
purchaseOrderSchema.statics.stats = async function () {
|
||||||
|
const results = await aggregateRollups({
|
||||||
|
model: this,
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Transform the results to match the expected format
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
|
purchaseOrderSchema.statics.history = async function (from, to) {
|
||||||
|
const results = await aggregateRollupsHistory({
|
||||||
|
model: this,
|
||||||
|
startDate: from,
|
||||||
|
endDate: to,
|
||||||
|
rollupConfigs: rollupConfigs,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return time-series data array
|
||||||
|
return results;
|
||||||
|
};
|
||||||
|
|
||||||
// Add virtual id getter
|
// Add virtual id getter
|
||||||
purchaseOrderSchema.virtual('id').get(function () {
|
purchaseOrderSchema.virtual('id').get(function () {
|
||||||
return this._id;
|
return this._id;
|
||||||
|
|||||||
@ -1,43 +1,108 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import { generateId } from '../../utils.js';
|
import { generateId } from '../../utils.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
import { purchaseOrderModel } from './purchaseorder.schema.js';
|
||||||
const shipmentItemSchema = new Schema({
|
import { taxRateModel } from '../management/taxrate.schema.js';
|
||||||
itemType: { type: String, required: true },
|
import { aggregateRollups, editObject, getObject } from '../../database.js';
|
||||||
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 },
|
|
||||||
});
|
|
||||||
|
|
||||||
const shipmentSchema = new Schema(
|
const shipmentSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
purchaseOrder: { type: Schema.Types.ObjectId, ref: 'purchaseOrder', required: true },
|
orderType: { type: String, required: true },
|
||||||
vendor: { type: Schema.Types.ObjectId, ref: 'vendor', required: true },
|
order: { type: Schema.Types.ObjectId, refPath: 'orderType', required: true },
|
||||||
courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false },
|
courierService: { type: Schema.Types.ObjectId, ref: 'courierService', required: false },
|
||||||
trackingNumber: { type: String, required: false },
|
trackingNumber: { type: String, required: false },
|
||||||
items: [shipmentItemSchema],
|
amount: { type: Number, required: true },
|
||||||
cost: { net: { type: Number, required: true }, gross: { type: Number, required: true } },
|
amountWithTax: { type: Number, required: true },
|
||||||
shippedDate: { type: Date, required: false },
|
taxRate: { type: Schema.Types.ObjectId, ref: 'taxRate', required: false },
|
||||||
expectedDeliveryDate: { type: Date, required: false },
|
shippedAt: { type: Date, required: false },
|
||||||
actualDeliveryDate: { type: Date, required: false },
|
expectedAt: { type: Date, required: false },
|
||||||
|
deliveredAt: { type: Date, required: false },
|
||||||
|
cancelledAt: { type: Date, required: false },
|
||||||
state: {
|
state: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
default: 'pending',
|
|
||||||
enum: ['pending', 'shipped', 'in_transit', 'delivered', 'cancelled'],
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
notes: { type: String },
|
|
||||||
timestamp: { type: Date, default: Date.now },
|
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
shipmentSchema.statics.recalculate = async function (shipment, user) {
|
||||||
|
// Only purchase orders are supported for now
|
||||||
|
if (shipment.orderType !== 'purchaseOrder') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderId = shipment.order?._id || shipment.order;
|
||||||
|
if (!orderId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var taxRate = shipment.taxRate;
|
||||||
|
|
||||||
|
if (shipment.taxRate?._id && Object.keys(shipment.taxRate).length == 1) {
|
||||||
|
taxRate = await getObject({
|
||||||
|
model: taxRateModel,
|
||||||
|
id: shipment.taxRate._id,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const amountWithTax = shipment.amount * (1 + (taxRate?.rate || 0) / 100);
|
||||||
|
await editObject({
|
||||||
|
model: shipmentModel,
|
||||||
|
id: shipment._id,
|
||||||
|
updateData: {
|
||||||
|
amountWithTax: amountWithTax,
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const rollupResults = await aggregateRollups({
|
||||||
|
model: this,
|
||||||
|
baseFilter: {
|
||||||
|
order: new mongoose.Types.ObjectId(orderId),
|
||||||
|
orderType: shipment.orderType,
|
||||||
|
},
|
||||||
|
rollupConfigs: [
|
||||||
|
{
|
||||||
|
name: 'shipmentTotals',
|
||||||
|
rollups: [
|
||||||
|
{ name: 'amount', property: 'amount', operation: 'sum' },
|
||||||
|
{ name: 'amountWithTax', property: 'amountWithTax', operation: 'sum' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const totals = rollupResults.shipmentTotals || {};
|
||||||
|
const totalShippingAmount = totals.amount.sum?.toFixed(2) || 0;
|
||||||
|
const totalShippingAmountWithTax = totals.amountWithTax.sum?.toFixed(2) || 0;
|
||||||
|
|
||||||
|
const purchaseOrder = await getObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id: orderId,
|
||||||
|
cached: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const grandTotalAmount =
|
||||||
|
parseFloat(purchaseOrder.totalAmountWithTax || 0) + parseFloat(totalShippingAmountWithTax || 0);
|
||||||
|
await editObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id: orderId,
|
||||||
|
updateData: {
|
||||||
|
shippingAmount: parseFloat(totalShippingAmount).toFixed(2),
|
||||||
|
shippingAmountWithTax: parseFloat(totalShippingAmountWithTax).toFixed(2),
|
||||||
|
grandTotalAmount: parseFloat(grandTotalAmount).toFixed(2),
|
||||||
|
},
|
||||||
|
user,
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Add virtual id getter
|
// Add virtual id getter
|
||||||
shipmentSchema.virtual('id').get(function () {
|
shipmentSchema.virtual('id').get(function () {
|
||||||
return this._id;
|
return this._id;
|
||||||
|
|||||||
@ -24,8 +24,10 @@ import { documentJobModel } from './management/documentjob.schema.js';
|
|||||||
import { fileModel } from './management/file.schema.js';
|
import { fileModel } from './management/file.schema.js';
|
||||||
import { courierServiceModel } from './management/courierservice.schema.js';
|
import { courierServiceModel } from './management/courierservice.schema.js';
|
||||||
import { courierModel } from './management/courier.schema.js';
|
import { courierModel } from './management/courier.schema.js';
|
||||||
import { taxRateModel } from './management/taxrates.schema.js';
|
import { taxRateModel } from './management/taxrate.schema.js';
|
||||||
import { taxRecordModel } from './management/taxrecord.schema.js';
|
import { taxRecordModel } from './management/taxrecord.schema.js';
|
||||||
|
import { shipmentModel } from './inventory/shipment.schema.js';
|
||||||
|
import { invoiceModel } from './finance/invoice.schema.js';
|
||||||
|
|
||||||
// Map prefixes to models and id fields
|
// Map prefixes to models and id fields
|
||||||
export const models = {
|
export const models = {
|
||||||
@ -98,4 +100,6 @@ export const models = {
|
|||||||
COR: { model: courierModel, idField: '_id', type: 'courier', referenceField: '_reference' },
|
COR: { model: courierModel, idField: '_id', type: 'courier', referenceField: '_reference' },
|
||||||
TXR: { model: taxRateModel, idField: '_id', type: 'taxRate', referenceField: '_reference' },
|
TXR: { model: taxRateModel, idField: '_id', type: 'taxRate', referenceField: '_reference' },
|
||||||
TXD: { model: taxRecordModel, idField: '_id', type: 'taxRecord', referenceField: '_reference' },
|
TXD: { model: taxRecordModel, idField: '_id', type: 'taxRecord', referenceField: '_reference' },
|
||||||
|
SHP: { model: shipmentModel, idField: '_id', type: 'shipment', referenceField: '_reference' },
|
||||||
|
INV: { model: invoiceModel, idField: '_id', type: 'invoice', referenceField: '_reference' },
|
||||||
};
|
};
|
||||||
|
|||||||
@ -37,6 +37,7 @@ import {
|
|||||||
courierServiceRoutes,
|
courierServiceRoutes,
|
||||||
taxRateRoutes,
|
taxRateRoutes,
|
||||||
taxRecordRoutes,
|
taxRecordRoutes,
|
||||||
|
invoiceRoutes,
|
||||||
} from './routes/index.js';
|
} from './routes/index.js';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
@ -139,6 +140,7 @@ app.use('/couriers', courierRoutes);
|
|||||||
app.use('/courierservices', courierServiceRoutes);
|
app.use('/courierservices', courierServiceRoutes);
|
||||||
app.use('/taxrates', taxRateRoutes);
|
app.use('/taxrates', taxRateRoutes);
|
||||||
app.use('/taxrecords', taxRecordRoutes);
|
app.use('/taxrecords', taxRecordRoutes);
|
||||||
|
app.use('/invoices', invoiceRoutes);
|
||||||
app.use('/notes', noteRoutes);
|
app.use('/notes', noteRoutes);
|
||||||
|
|
||||||
// Start the application
|
// Start the application
|
||||||
|
|||||||
99
src/routes/finance/invoices.js
Normal file
99
src/routes/finance/invoices.js
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import express from 'express';
|
||||||
|
import { isAuthenticated } from '../../keycloak.js';
|
||||||
|
import { getFilter, convertPropertiesString } from '../../utils.js';
|
||||||
|
|
||||||
|
const router = express.Router();
|
||||||
|
import {
|
||||||
|
listInvoicesRouteHandler,
|
||||||
|
getInvoiceRouteHandler,
|
||||||
|
editInvoiceRouteHandler,
|
||||||
|
editMultipleInvoicesRouteHandler,
|
||||||
|
newInvoiceRouteHandler,
|
||||||
|
deleteInvoiceRouteHandler,
|
||||||
|
listInvoicesByPropertiesRouteHandler,
|
||||||
|
getInvoiceStatsRouteHandler,
|
||||||
|
getInvoiceHistoryRouteHandler,
|
||||||
|
sendInvoiceRouteHandler,
|
||||||
|
markInvoicePaidRouteHandler,
|
||||||
|
cancelInvoiceRouteHandler,
|
||||||
|
} from '../../services/finance/invoices.js';
|
||||||
|
|
||||||
|
// list of invoices
|
||||||
|
router.get('/', isAuthenticated, (req, res) => {
|
||||||
|
const { page, limit, property, search, sort, order } = req.query;
|
||||||
|
const allowedFilters = [
|
||||||
|
'vendor',
|
||||||
|
'customer',
|
||||||
|
'invoiceType',
|
||||||
|
'state',
|
||||||
|
'value',
|
||||||
|
'vendor._id',
|
||||||
|
'customer._id',
|
||||||
|
];
|
||||||
|
const filter = getFilter(req.query, allowedFilters);
|
||||||
|
listInvoicesRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/properties', isAuthenticated, (req, res) => {
|
||||||
|
let properties = convertPropertiesString(req.query.properties);
|
||||||
|
const allowedFilters = [
|
||||||
|
'vendor',
|
||||||
|
'customer',
|
||||||
|
'invoiceType',
|
||||||
|
'state.type',
|
||||||
|
'value',
|
||||||
|
'vendor._id',
|
||||||
|
'customer._id',
|
||||||
|
];
|
||||||
|
const filter = getFilter(req.query, allowedFilters, false);
|
||||||
|
var masterFilter = {};
|
||||||
|
if (req.query.masterFilter) {
|
||||||
|
masterFilter = JSON.parse(req.query.masterFilter);
|
||||||
|
}
|
||||||
|
listInvoicesByPropertiesRouteHandler(req, res, properties, filter, masterFilter);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/', isAuthenticated, (req, res) => {
|
||||||
|
newInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get invoice stats
|
||||||
|
router.get('/stats', isAuthenticated, (req, res) => {
|
||||||
|
getInvoiceStatsRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
// get invoice history
|
||||||
|
router.get('/history', isAuthenticated, (req, res) => {
|
||||||
|
getInvoiceHistoryRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get('/:id', isAuthenticated, (req, res) => {
|
||||||
|
getInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
// update multiple invoices
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleInvoicesRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
|
editInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.delete('/:id', isAuthenticated, async (req, res) => {
|
||||||
|
deleteInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/send', isAuthenticated, async (req, res) => {
|
||||||
|
sendInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/markpaid', isAuthenticated, async (req, res) => {
|
||||||
|
markInvoicePaidRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/cancel', isAuthenticated, async (req, res) => {
|
||||||
|
cancelInvoiceRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
export default router;
|
||||||
@ -29,6 +29,7 @@ import courierRoutes from './management/courier.js';
|
|||||||
import courierServiceRoutes from './management/courierservice.js';
|
import courierServiceRoutes from './management/courierservice.js';
|
||||||
import taxRateRoutes from './management/taxrates.js';
|
import taxRateRoutes from './management/taxrates.js';
|
||||||
import taxRecordRoutes from './management/taxrecords.js';
|
import taxRecordRoutes from './management/taxrecords.js';
|
||||||
|
import invoiceRoutes from './finance/invoices.js';
|
||||||
import noteRoutes from './misc/notes.js';
|
import noteRoutes from './misc/notes.js';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
@ -64,4 +65,5 @@ export {
|
|||||||
courierServiceRoutes,
|
courierServiceRoutes,
|
||||||
taxRateRoutes,
|
taxRateRoutes,
|
||||||
taxRecordRoutes,
|
taxRecordRoutes,
|
||||||
|
invoiceRoutes,
|
||||||
};
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listFilamentStocksRouteHandler,
|
listFilamentStocksRouteHandler,
|
||||||
getFilamentStockRouteHandler,
|
getFilamentStockRouteHandler,
|
||||||
editFilamentStockRouteHandler,
|
editFilamentStockRouteHandler,
|
||||||
|
editMultipleFilamentStocksRouteHandler,
|
||||||
newFilamentStockRouteHandler,
|
newFilamentStockRouteHandler,
|
||||||
deleteFilamentStockRouteHandler,
|
deleteFilamentStockRouteHandler,
|
||||||
listFilamentStocksByPropertiesRouteHandler,
|
listFilamentStocksByPropertiesRouteHandler,
|
||||||
@ -51,6 +52,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getFilamentStockRouteHandler(req, res);
|
getFilamentStockRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple filament stocks
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleFilamentStocksRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editFilamentStockRouteHandler(req, res);
|
editFilamentStockRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listOrderItemsRouteHandler,
|
listOrderItemsRouteHandler,
|
||||||
getOrderItemRouteHandler,
|
getOrderItemRouteHandler,
|
||||||
editOrderItemRouteHandler,
|
editOrderItemRouteHandler,
|
||||||
|
editMultipleOrderItemsRouteHandler,
|
||||||
newOrderItemRouteHandler,
|
newOrderItemRouteHandler,
|
||||||
deleteOrderItemRouteHandler,
|
deleteOrderItemRouteHandler,
|
||||||
listOrderItemsByPropertiesRouteHandler,
|
listOrderItemsByPropertiesRouteHandler,
|
||||||
@ -17,14 +18,32 @@ import {
|
|||||||
// list of order items
|
// list of order items
|
||||||
router.get('/', isAuthenticated, (req, res) => {
|
router.get('/', isAuthenticated, (req, res) => {
|
||||||
const { page, limit, property, search, sort, order } = req.query;
|
const { page, limit, property, search, sort, order } = req.query;
|
||||||
const allowedFilters = ['itemType', 'item', 'item._id', 'order', 'order._id', 'orderType'];
|
const allowedFilters = [
|
||||||
|
'itemType',
|
||||||
|
'item',
|
||||||
|
'item._id',
|
||||||
|
'order',
|
||||||
|
'order._id',
|
||||||
|
'orderType',
|
||||||
|
'shipment',
|
||||||
|
'shipment._id',
|
||||||
|
];
|
||||||
const filter = getFilter(req.query, allowedFilters);
|
const filter = getFilter(req.query, allowedFilters);
|
||||||
listOrderItemsRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
listOrderItemsRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
||||||
});
|
});
|
||||||
|
|
||||||
router.get('/properties', isAuthenticated, (req, res) => {
|
router.get('/properties', isAuthenticated, (req, res) => {
|
||||||
let properties = convertPropertiesString(req.query.properties);
|
let properties = convertPropertiesString(req.query.properties);
|
||||||
const allowedFilters = ['itemType', 'item', 'item._id', 'order', 'order._id', 'orderType'];
|
const allowedFilters = [
|
||||||
|
'itemType',
|
||||||
|
'item',
|
||||||
|
'item._id',
|
||||||
|
'order',
|
||||||
|
'order._id',
|
||||||
|
'orderType',
|
||||||
|
'shipment',
|
||||||
|
'shipment._id',
|
||||||
|
];
|
||||||
const filter = getFilter(req.query, allowedFilters, false);
|
const filter = getFilter(req.query, allowedFilters, false);
|
||||||
var masterFilter = {};
|
var masterFilter = {};
|
||||||
if (req.query.masterFilter) {
|
if (req.query.masterFilter) {
|
||||||
@ -51,6 +70,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getOrderItemRouteHandler(req, res);
|
getOrderItemRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple order items
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleOrderItemsRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editOrderItemRouteHandler(req, res);
|
editOrderItemRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listPartStocksRouteHandler,
|
listPartStocksRouteHandler,
|
||||||
getPartStockRouteHandler,
|
getPartStockRouteHandler,
|
||||||
editPartStockRouteHandler,
|
editPartStockRouteHandler,
|
||||||
|
editMultiplePartStocksRouteHandler,
|
||||||
newPartStockRouteHandler,
|
newPartStockRouteHandler,
|
||||||
deletePartStockRouteHandler,
|
deletePartStockRouteHandler,
|
||||||
listPartStocksByPropertiesRouteHandler,
|
listPartStocksByPropertiesRouteHandler,
|
||||||
@ -51,6 +52,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getPartStockRouteHandler(req, res);
|
getPartStockRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple part stocks
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultiplePartStocksRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editPartStockRouteHandler(req, res);
|
editPartStockRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,11 +7,15 @@ import {
|
|||||||
listPurchaseOrdersRouteHandler,
|
listPurchaseOrdersRouteHandler,
|
||||||
getPurchaseOrderRouteHandler,
|
getPurchaseOrderRouteHandler,
|
||||||
editPurchaseOrderRouteHandler,
|
editPurchaseOrderRouteHandler,
|
||||||
|
editMultiplePurchaseOrdersRouteHandler,
|
||||||
newPurchaseOrderRouteHandler,
|
newPurchaseOrderRouteHandler,
|
||||||
deletePurchaseOrderRouteHandler,
|
deletePurchaseOrderRouteHandler,
|
||||||
listPurchaseOrdersByPropertiesRouteHandler,
|
listPurchaseOrdersByPropertiesRouteHandler,
|
||||||
getPurchaseOrderStatsRouteHandler,
|
getPurchaseOrderStatsRouteHandler,
|
||||||
getPurchaseOrderHistoryRouteHandler,
|
getPurchaseOrderHistoryRouteHandler,
|
||||||
|
postPurchaseOrderRouteHandler,
|
||||||
|
acknowledgePurchaseOrderRouteHandler,
|
||||||
|
cancelPurchaseOrderRouteHandler,
|
||||||
} from '../../services/inventory/purchaseorders.js';
|
} from '../../services/inventory/purchaseorders.js';
|
||||||
|
|
||||||
// list of purchase orders
|
// list of purchase orders
|
||||||
@ -28,7 +32,7 @@ router.get('/properties', isAuthenticated, (req, res) => {
|
|||||||
const filter = getFilter(req.query, allowedFilters, false);
|
const filter = getFilter(req.query, allowedFilters, false);
|
||||||
var masterFilter = {};
|
var masterFilter = {};
|
||||||
if (req.query.masterFilter) {
|
if (req.query.masterFilter) {
|
||||||
masterFilter = JSON.parse(req.query.masterFilter);
|
masterFilter = getFilter(JSON.parse(req.query.masterFilter), allowedFilters, true);
|
||||||
}
|
}
|
||||||
listPurchaseOrdersByPropertiesRouteHandler(req, res, properties, filter, masterFilter);
|
listPurchaseOrdersByPropertiesRouteHandler(req, res, properties, filter, masterFilter);
|
||||||
});
|
});
|
||||||
@ -51,6 +55,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getPurchaseOrderRouteHandler(req, res);
|
getPurchaseOrderRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple purchase orders
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultiplePurchaseOrdersRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editPurchaseOrderRouteHandler(req, res);
|
editPurchaseOrderRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
@ -59,4 +68,16 @@ router.delete('/:id', isAuthenticated, async (req, res) => {
|
|||||||
deletePurchaseOrderRouteHandler(req, res);
|
deletePurchaseOrderRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/:id/post', isAuthenticated, async (req, res) => {
|
||||||
|
postPurchaseOrderRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/acknowledge', isAuthenticated, async (req, res) => {
|
||||||
|
acknowledgePurchaseOrderRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/cancel', isAuthenticated, async (req, res) => {
|
||||||
|
cancelPurchaseOrderRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@ -7,24 +7,21 @@ import {
|
|||||||
listShipmentsRouteHandler,
|
listShipmentsRouteHandler,
|
||||||
getShipmentRouteHandler,
|
getShipmentRouteHandler,
|
||||||
editShipmentRouteHandler,
|
editShipmentRouteHandler,
|
||||||
|
editMultipleShipmentsRouteHandler,
|
||||||
newShipmentRouteHandler,
|
newShipmentRouteHandler,
|
||||||
deleteShipmentRouteHandler,
|
deleteShipmentRouteHandler,
|
||||||
listShipmentsByPropertiesRouteHandler,
|
listShipmentsByPropertiesRouteHandler,
|
||||||
getShipmentStatsRouteHandler,
|
getShipmentStatsRouteHandler,
|
||||||
getShipmentHistoryRouteHandler,
|
getShipmentHistoryRouteHandler,
|
||||||
|
shipShipmentRouteHandler,
|
||||||
|
receiveShipmentRouteHandler,
|
||||||
|
cancelShipmentRouteHandler,
|
||||||
} from '../../services/inventory/shipments.js';
|
} from '../../services/inventory/shipments.js';
|
||||||
|
|
||||||
// list of shipments
|
// list of shipments
|
||||||
router.get('/', isAuthenticated, (req, res) => {
|
router.get('/', isAuthenticated, (req, res) => {
|
||||||
const { page, limit, property, search, sort, order } = req.query;
|
const { page, limit, property, search, sort, order } = req.query;
|
||||||
const allowedFilters = [
|
const allowedFilters = ['orderType', 'order', 'state', 'courierService', 'order._id', 'taxRate'];
|
||||||
'vendor',
|
|
||||||
'purchaseOrder',
|
|
||||||
'state',
|
|
||||||
'courierService',
|
|
||||||
'vendor._id',
|
|
||||||
'purchaseOrder._id',
|
|
||||||
];
|
|
||||||
const filter = getFilter(req.query, allowedFilters);
|
const filter = getFilter(req.query, allowedFilters);
|
||||||
listShipmentsRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
listShipmentsRouteHandler(req, res, page, limit, property, filter, search, sort, order);
|
||||||
});
|
});
|
||||||
@ -32,17 +29,17 @@ router.get('/', isAuthenticated, (req, res) => {
|
|||||||
router.get('/properties', isAuthenticated, (req, res) => {
|
router.get('/properties', isAuthenticated, (req, res) => {
|
||||||
let properties = convertPropertiesString(req.query.properties);
|
let properties = convertPropertiesString(req.query.properties);
|
||||||
const allowedFilters = [
|
const allowedFilters = [
|
||||||
'vendor',
|
'orderType',
|
||||||
'purchaseOrder',
|
'order',
|
||||||
'state.type',
|
'state.type',
|
||||||
'courierService',
|
'courierService',
|
||||||
'vendor._id',
|
'order._id',
|
||||||
'purchaseOrder._id',
|
'taxRate',
|
||||||
];
|
];
|
||||||
const filter = getFilter(req.query, allowedFilters, false);
|
const filter = getFilter(req.query, allowedFilters, false);
|
||||||
var masterFilter = {};
|
var masterFilter = {};
|
||||||
if (req.query.masterFilter) {
|
if (req.query.masterFilter) {
|
||||||
masterFilter = JSON.parse(req.query.masterFilter);
|
masterFilter = getFilter(JSON.parse(req.query.masterFilter), allowedFilters, true);
|
||||||
}
|
}
|
||||||
listShipmentsByPropertiesRouteHandler(req, res, properties, filter, masterFilter);
|
listShipmentsByPropertiesRouteHandler(req, res, properties, filter, masterFilter);
|
||||||
});
|
});
|
||||||
@ -65,6 +62,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getShipmentRouteHandler(req, res);
|
getShipmentRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple shipments
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleShipmentsRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editShipmentRouteHandler(req, res);
|
editShipmentRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
@ -73,4 +75,16 @@ router.delete('/:id', isAuthenticated, async (req, res) => {
|
|||||||
deleteShipmentRouteHandler(req, res);
|
deleteShipmentRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.post('/:id/ship', isAuthenticated, async (req, res) => {
|
||||||
|
shipShipmentRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/receive', isAuthenticated, async (req, res) => {
|
||||||
|
receiveShipmentRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.post('/:id/cancel', isAuthenticated, async (req, res) => {
|
||||||
|
cancelShipmentRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
getStockEventRouteHandler,
|
getStockEventRouteHandler,
|
||||||
newStockEventRouteHandler,
|
newStockEventRouteHandler,
|
||||||
editStockEventRouteHandler,
|
editStockEventRouteHandler,
|
||||||
|
editMultipleStockEventsRouteHandler,
|
||||||
deleteStockEventRouteHandler,
|
deleteStockEventRouteHandler,
|
||||||
listStockEventsByPropertiesRouteHandler,
|
listStockEventsByPropertiesRouteHandler,
|
||||||
getStockEventStatsRouteHandler,
|
getStockEventStatsRouteHandler,
|
||||||
@ -51,6 +52,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getStockEventRouteHandler(req, res);
|
getStockEventRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update multiple stock events
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleStockEventsRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editStockEventRouteHandler(req, res);
|
editStockEventRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import {
|
|||||||
listFilamentsByPropertiesRouteHandler,
|
listFilamentsByPropertiesRouteHandler,
|
||||||
getFilamentRouteHandler,
|
getFilamentRouteHandler,
|
||||||
editFilamentRouteHandler,
|
editFilamentRouteHandler,
|
||||||
|
editMultipleFilamentsRouteHandler,
|
||||||
newFilamentRouteHandler,
|
newFilamentRouteHandler,
|
||||||
getFilamentStatsRouteHandler,
|
getFilamentStatsRouteHandler,
|
||||||
getFilamentHistoryRouteHandler,
|
getFilamentHistoryRouteHandler,
|
||||||
@ -66,6 +67,11 @@ router.get('/:id', isAuthenticated, (req, res) => {
|
|||||||
getFilamentRouteHandler(req, res);
|
getFilamentRouteHandler(req, res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// update filaments info
|
||||||
|
router.put('/', isAuthenticated, async (req, res) => {
|
||||||
|
editMultipleFilamentsRouteHandler(req, res);
|
||||||
|
});
|
||||||
|
|
||||||
// update printer info
|
// update printer info
|
||||||
router.put('/:id', isAuthenticated, async (req, res) => {
|
router.put('/:id', isAuthenticated, async (req, res) => {
|
||||||
editFilamentRouteHandler(req, res);
|
editFilamentRouteHandler(req, res);
|
||||||
|
|||||||
382
src/services/finance/invoices.js
Normal file
382
src/services/finance/invoices.js
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
import config from '../../config.js';
|
||||||
|
import { invoiceModel } from '../../database/schemas/finance/invoice.schema.js';
|
||||||
|
import log4js from 'log4js';
|
||||||
|
import mongoose from 'mongoose';
|
||||||
|
import {
|
||||||
|
deleteObject,
|
||||||
|
listObjects,
|
||||||
|
getObject,
|
||||||
|
editObject,
|
||||||
|
editObjects,
|
||||||
|
newObject,
|
||||||
|
listObjectsByProperties,
|
||||||
|
getModelStats,
|
||||||
|
getModelHistory,
|
||||||
|
checkStates,
|
||||||
|
} from '../../database/database.js';
|
||||||
|
|
||||||
|
const logger = log4js.getLogger('Invoices');
|
||||||
|
logger.level = config.server.logLevel;
|
||||||
|
|
||||||
|
export const listInvoicesRouteHandler = async (
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
page = 1,
|
||||||
|
limit = 25,
|
||||||
|
property = '',
|
||||||
|
filter = {},
|
||||||
|
search = '',
|
||||||
|
sort = '',
|
||||||
|
order = 'ascend'
|
||||||
|
) => {
|
||||||
|
const populateFields = ['vendor', 'customer', 'relatedOrder'];
|
||||||
|
const result = await listObjects({
|
||||||
|
model: invoiceModel,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
property,
|
||||||
|
filter,
|
||||||
|
search,
|
||||||
|
sort,
|
||||||
|
order,
|
||||||
|
populate: populateFields,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result?.error) {
|
||||||
|
logger.error('Error listing invoices.');
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`List of invoices (Page ${page}, Limit ${limit}). Count: ${result.length}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listInvoicesByPropertiesRouteHandler = async (
|
||||||
|
req,
|
||||||
|
res,
|
||||||
|
properties = '',
|
||||||
|
filter = {},
|
||||||
|
masterFilter = {}
|
||||||
|
) => {
|
||||||
|
const populateFields = ['vendor', 'customer', 'relatedOrder'];
|
||||||
|
const result = await listObjectsByProperties({
|
||||||
|
model: invoiceModel,
|
||||||
|
properties,
|
||||||
|
filter,
|
||||||
|
populate: populateFields,
|
||||||
|
masterFilter,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result?.error) {
|
||||||
|
logger.error('Error listing invoices.');
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`List of invoices. Count: ${result.length}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInvoiceRouteHandler = async (req, res) => {
|
||||||
|
const id = req.params.id;
|
||||||
|
const populateFields = ['vendor', 'customer', 'relatedOrder'];
|
||||||
|
const result = await getObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
populate: populateFields,
|
||||||
|
});
|
||||||
|
if (result?.error) {
|
||||||
|
logger.warn(`Invoice not found with supplied id.`);
|
||||||
|
return res.status(result.code).send(result);
|
||||||
|
}
|
||||||
|
logger.debug(`Retrieved invoice with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editInvoiceRouteHandler = async (req, res) => {
|
||||||
|
// Get ID from params
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: invoiceModel, id, states: ['draft'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking invoice states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Invoice is not in draft state.');
|
||||||
|
res.status(400).send({ error: 'Invoice is not in draft state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
vendor: req.body.vendor,
|
||||||
|
customer: req.body.customer,
|
||||||
|
invoiceType: req.body.invoiceType,
|
||||||
|
invoiceDate: req.body.invoiceDate,
|
||||||
|
dueDate: req.body.dueDate,
|
||||||
|
relatedOrderType: req.body.relatedOrderType,
|
||||||
|
relatedOrder: req.body.relatedOrder,
|
||||||
|
};
|
||||||
|
// Create audit log before updating
|
||||||
|
const result = await editObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing invoice:', result.error);
|
||||||
|
res.status(result).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const editMultipleInvoicesRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
vendor: update.vendor,
|
||||||
|
customer: update.customer,
|
||||||
|
invoiceType: update.invoiceType,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: invoiceModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing invoices:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} invoices`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const newInvoiceRouteHandler = async (req, res) => {
|
||||||
|
const newData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
vendor: req.body.vendor,
|
||||||
|
customer: req.body.customer,
|
||||||
|
invoiceType: req.body.invoiceType || 'sales',
|
||||||
|
invoiceDate: req.body.invoiceDate || new Date(),
|
||||||
|
dueDate: req.body.dueDate,
|
||||||
|
relatedOrderType: req.body.relatedOrderType,
|
||||||
|
relatedOrder: req.body.relatedOrder,
|
||||||
|
totalAmount: 0,
|
||||||
|
totalAmountWithTax: 0,
|
||||||
|
totalTaxAmount: 0,
|
||||||
|
grandTotalAmount: 0,
|
||||||
|
shippingAmount: 0,
|
||||||
|
shippingAmountWithTax: 0,
|
||||||
|
};
|
||||||
|
const result = await newObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
newData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('No invoice created:', result.error);
|
||||||
|
return res.status(result.code).send(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`New invoice with ID: ${result._id}`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteInvoiceRouteHandler = async (req, res) => {
|
||||||
|
// Get ID from params
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
const result = await deleteObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('No invoice deleted:', result.error);
|
||||||
|
return res.status(result.code).send(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Deleted invoice with ID: ${result._id}`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInvoiceStatsRouteHandler = async (req, res) => {
|
||||||
|
const result = await getModelStats({ model: invoiceModel });
|
||||||
|
if (result?.error) {
|
||||||
|
logger.error('Error fetching invoice stats:', result.error);
|
||||||
|
return res.status(result.code).send(result);
|
||||||
|
}
|
||||||
|
logger.trace('Invoice stats:', result);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getInvoiceHistoryRouteHandler = async (req, res) => {
|
||||||
|
const from = req.query.from;
|
||||||
|
const to = req.query.to;
|
||||||
|
const result = await getModelHistory({ model: invoiceModel, from, to });
|
||||||
|
if (result?.error) {
|
||||||
|
logger.error('Error fetching invoice history:', result.error);
|
||||||
|
return res.status(result.code).send(result);
|
||||||
|
}
|
||||||
|
logger.trace('Invoice history:', result);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const sendInvoiceRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: invoiceModel, id, states: ['draft'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking invoice states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Invoice is not in draft state.');
|
||||||
|
res.status(400).send({ error: 'Invoice is not in draft state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'sent' },
|
||||||
|
sentAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error sending invoice:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Sent invoice with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const markInvoicePaidRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
states: ['sent', 'partiallyPaid'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking invoice states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Invoice is not in sent or partially paid state.');
|
||||||
|
res.status(400).send({ error: 'Invoice is not in sent or partially paid state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'paid' },
|
||||||
|
paidAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error marking invoice as paid:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Marked invoice as paid with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cancelInvoiceRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Invoice with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
states: ['draft', 'sent'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking invoice states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Invoice is not in a cancellable state.');
|
||||||
|
res.status(400).send({
|
||||||
|
error: 'Invoice is not in a cancellable state (must be draft or sent).',
|
||||||
|
code: 400,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
cancelledAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: invoiceModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error cancelling invoice:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Cancelled invoice with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
@ -114,6 +115,32 @@ export const editFilamentStockRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultipleFilamentStocksRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: filamentStockModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing filament stocks:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} filament stocks`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newFilamentStockRouteHandler = async (req, res) => {
|
export const newFilamentStockRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
@ -43,6 +44,10 @@ export const listOrderItemsRouteHandler = async (
|
|||||||
path: 'taxRate',
|
path: 'taxRate',
|
||||||
strictPopulate: false,
|
strictPopulate: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'shipment',
|
||||||
|
strictPopulate: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'item',
|
path: 'item',
|
||||||
populate: { path: 'costTaxRate', strictPopulate: false },
|
populate: { path: 'costTaxRate', strictPopulate: false },
|
||||||
@ -138,6 +143,7 @@ export const editOrderItemRouteHandler = async (req, res) => {
|
|||||||
itemAmount: req.body.itemAmount,
|
itemAmount: req.body.itemAmount,
|
||||||
quantity: req.body.quantity,
|
quantity: req.body.quantity,
|
||||||
totalAmount: req.body.totalAmount,
|
totalAmount: req.body.totalAmount,
|
||||||
|
shipment: req.body.shipment,
|
||||||
taxRate: req.body.taxRate,
|
taxRate: req.body.taxRate,
|
||||||
totalAmountWithTax: req.body.totalAmountWithTax,
|
totalAmountWithTax: req.body.totalAmountWithTax,
|
||||||
};
|
};
|
||||||
@ -160,6 +166,43 @@ export const editOrderItemRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultipleOrderItemsRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
itemType: update.itemType,
|
||||||
|
item: update.item,
|
||||||
|
orderType: update.orderType,
|
||||||
|
order: update.order,
|
||||||
|
syncAmount: update.syncAmount,
|
||||||
|
itemAmount: update.itemAmount,
|
||||||
|
quantity: update.quantity,
|
||||||
|
totalAmount: update.totalAmount,
|
||||||
|
shipment: update.shipment,
|
||||||
|
taxRate: update.taxRate,
|
||||||
|
totalAmountWithTax: update.totalAmountWithTax,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing order items:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} order items`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newOrderItemRouteHandler = async (req, res) => {
|
export const newOrderItemRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
@ -175,6 +218,7 @@ export const newOrderItemRouteHandler = async (req, res) => {
|
|||||||
totalAmount: req.body.totalAmount,
|
totalAmount: req.body.totalAmount,
|
||||||
taxRate: req.body.taxRate,
|
taxRate: req.body.taxRate,
|
||||||
totalAmountWithTax: req.body.totalAmountWithTax,
|
totalAmountWithTax: req.body.totalAmountWithTax,
|
||||||
|
shipment: req.body.shipment,
|
||||||
};
|
};
|
||||||
const result = await newObject({
|
const result = await newObject({
|
||||||
model: orderItemModel,
|
model: orderItemModel,
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
@ -114,6 +115,32 @@ export const editPartStockRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultiplePartStocksRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: partStockModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing part stocks:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} part stocks`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newPartStockRouteHandler = async (req, res) => {
|
export const newPartStockRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
|
|||||||
@ -7,11 +7,15 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
getModelHistory,
|
getModelHistory,
|
||||||
|
checkStates,
|
||||||
} from '../../database/database.js';
|
} from '../../database/database.js';
|
||||||
|
import { orderItemModel } from '../../database/schemas/inventory/orderitem.schema.js';
|
||||||
|
import { shipmentModel } from '../../database/schemas/inventory/shipment.schema.js';
|
||||||
|
|
||||||
const logger = log4js.getLogger('Purchase Orders');
|
const logger = log4js.getLogger('Purchase Orders');
|
||||||
logger.level = config.server.logLevel;
|
logger.level = config.server.logLevel;
|
||||||
@ -95,6 +99,20 @@ export const editPurchaseOrderRouteHandler = async (req, res) => {
|
|||||||
|
|
||||||
logger.trace(`Purchase Order with ID: ${id}`);
|
logger.trace(`Purchase Order with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: purchaseOrderModel, id, states: ['draft'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking purchase order states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Purchase order is not in draft state.');
|
||||||
|
res.status(400).send({ error: 'Purchase order is not in draft state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const updateData = {
|
const updateData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
vendor: req.body.vendor,
|
vendor: req.body.vendor,
|
||||||
@ -118,10 +136,40 @@ export const editPurchaseOrderRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultiplePurchaseOrdersRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
vendor: update.vendor,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing purchase orders:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} purchase orders`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newPurchaseOrderRouteHandler = async (req, res) => {
|
export const newPurchaseOrderRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
vendor: req.body.vendor,
|
vendor: req.body.vendor,
|
||||||
|
totalAmount: 0,
|
||||||
|
totalAmountWithTax: 0,
|
||||||
|
totalTaxAmount: 0,
|
||||||
};
|
};
|
||||||
const result = await newObject({
|
const result = await newObject({
|
||||||
model: purchaseOrderModel,
|
model: purchaseOrderModel,
|
||||||
@ -180,3 +228,232 @@ export const getPurchaseOrderHistoryRouteHandler = async (req, res) => {
|
|||||||
logger.trace('Purchase order history:', result);
|
logger.trace('Purchase order history:', result);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const postPurchaseOrderRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Purchase Order with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: purchaseOrderModel, id, states: ['draft'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking purchase order states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Purchase order is not in draft state.');
|
||||||
|
res.status(400).send({ error: 'Purchase order is not in draft state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderItemsResult = await listObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
filter: { order: id, orderType: 'purchaseOrder' },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const shipmentsResult = await listObjects({
|
||||||
|
model: shipmentModel,
|
||||||
|
filter: { order: id, orderType: 'purchaseOrder' },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
if (orderItem.state.type != 'draft') {
|
||||||
|
logger.warn(`Order item ${orderItem._id} is not in draft state.`);
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: `Order item ${orderItem._reference} not in draft state.`, code: 400 });
|
||||||
|
}
|
||||||
|
if (!orderItem?.shipment || orderItem?.shipment == null) {
|
||||||
|
logger.warn(`Order item ${orderItem._id} does not have a shipment.`);
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: `Order item ${orderItem._reference} does not have a shipment.`, code: 400 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const shipment of shipmentsResult) {
|
||||||
|
if (shipment.state.type != 'draft') {
|
||||||
|
logger.warn(`Shipment ${shipment._id} is not in draft state.`);
|
||||||
|
return res
|
||||||
|
.status(400)
|
||||||
|
.send({ error: `Shipment ${shipment._reference} not in draft state.`, code: 400 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'ordered' },
|
||||||
|
orderedAt: new Date(),
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const shipment of shipmentsResult) {
|
||||||
|
await editObject({
|
||||||
|
model: shipmentModel,
|
||||||
|
id: shipment._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'planned' },
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'sent' },
|
||||||
|
postedAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error posting purchase order:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Posted purchase order with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const acknowledgePurchaseOrderRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Purchase Order with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: purchaseOrderModel, id, states: ['sent'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking purchase order states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Purchase order is not in sent state.');
|
||||||
|
res.status(400).send({ error: 'Purchase order is not in sent state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'acknowledged' },
|
||||||
|
acknowledgedAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error acknowledging purchase order:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Acknowledged purchase order with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cancelPurchaseOrderRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Purchase Order with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id,
|
||||||
|
states: ['sent', 'acknowledged', 'partiallyShipped', 'shipped', 'partiallyReceived'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking purchase order states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Purchase order is not in a cancellable state.');
|
||||||
|
res.status(400).send({
|
||||||
|
error: 'Purchase order is not in a cancellable state (must be draft, sent, or acknowledged).',
|
||||||
|
code: 400,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderItemsResult = await listObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
filter: { order: id, orderType: 'purchaseOrder' },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const shipmentsResult = await listObjects({
|
||||||
|
model: shipmentModel,
|
||||||
|
filter: { order: id, orderType: 'purchaseOrder' },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const allowedOrderItemStates = ['ordered', 'shipped'];
|
||||||
|
const allowedShipmentStates = ['shipped', 'planned'];
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
if (allowedOrderItemStates.includes(orderItem.state.type)) {
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const shipment of shipmentsResult) {
|
||||||
|
if (allowedShipmentStates.includes(shipment.state.type)) {
|
||||||
|
await editObject({
|
||||||
|
model: shipmentModel,
|
||||||
|
id: shipment._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
cancelledAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: purchaseOrderModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error cancelling purchase order:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Cancelled purchase order with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|||||||
@ -7,13 +7,16 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
getModelHistory,
|
getModelHistory,
|
||||||
|
checkStates,
|
||||||
} from '../../database/database.js';
|
} from '../../database/database.js';
|
||||||
const logger = log4js.getLogger('Shipments');
|
const logger = log4js.getLogger('Shipments');
|
||||||
logger.level = config.server.logLevel;
|
logger.level = config.server.logLevel;
|
||||||
|
import { orderItemModel } from '../../database/schemas/inventory/orderitem.schema.js';
|
||||||
|
|
||||||
export const listShipmentsRouteHandler = async (
|
export const listShipmentsRouteHandler = async (
|
||||||
req,
|
req,
|
||||||
@ -35,7 +38,7 @@ export const listShipmentsRouteHandler = async (
|
|||||||
search,
|
search,
|
||||||
sort,
|
sort,
|
||||||
order,
|
order,
|
||||||
populate: ['purchaseOrder', 'vendor', 'courierService'],
|
populate: ['order', 'courierService', 'taxRate'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
@ -59,7 +62,7 @@ export const listShipmentsByPropertiesRouteHandler = async (
|
|||||||
model: shipmentModel,
|
model: shipmentModel,
|
||||||
properties,
|
properties,
|
||||||
filter,
|
filter,
|
||||||
populate: ['purchaseOrder', 'vendor', 'courierService'],
|
populate: ['courierService'],
|
||||||
masterFilter,
|
masterFilter,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,7 +81,7 @@ export const getShipmentRouteHandler = async (req, res) => {
|
|||||||
const result = await getObject({
|
const result = await getObject({
|
||||||
model: shipmentModel,
|
model: shipmentModel,
|
||||||
id,
|
id,
|
||||||
populate: ['purchaseOrder', 'vendor', 'courierService', 'items.item', 'items.taxRate'],
|
populate: ['order', 'courierService', 'taxRate'],
|
||||||
});
|
});
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
logger.warn(`Shipment not found with supplied id.`);
|
logger.warn(`Shipment not found with supplied id.`);
|
||||||
@ -96,15 +99,13 @@ export const editShipmentRouteHandler = async (req, res) => {
|
|||||||
|
|
||||||
const updateData = {
|
const updateData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
purchaseOrder: req.body.purchaseOrder,
|
orderType: req.body.orderType,
|
||||||
vendor: req.body.vendor,
|
order: req.body.order,
|
||||||
courierService: req.body.courierService,
|
courierService: req.body.courierService,
|
||||||
trackingNumber: req.body.trackingNumber,
|
trackingNumber: req.body.trackingNumber,
|
||||||
shippedDate: req.body.shippedDate,
|
amount: req.body.amount,
|
||||||
expectedDeliveryDate: req.body.expectedDeliveryDate,
|
amountWithTax: req.body.amountWithTax,
|
||||||
actualDeliveryDate: req.body.actualDeliveryDate,
|
taxRate: req.body.taxRate,
|
||||||
state: req.body.state,
|
|
||||||
notes: req.body.notes,
|
|
||||||
};
|
};
|
||||||
// Create audit log before updating
|
// Create audit log before updating
|
||||||
const result = await editObject({
|
const result = await editObject({
|
||||||
@ -125,20 +126,53 @@ export const editShipmentRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultipleShipmentsRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
orderType: update.orderType,
|
||||||
|
order: update.order,
|
||||||
|
courierService: update.courierService,
|
||||||
|
trackingNumber: update.trackingNumber,
|
||||||
|
amount: update.amount,
|
||||||
|
amountWithTax: update.amountWithTax,
|
||||||
|
taxRate: update.taxRate,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: shipmentModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing shipments:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} shipments`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newShipmentRouteHandler = async (req, res) => {
|
export const newShipmentRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
purchaseOrder: req.body.purchaseOrder,
|
orderType: req.body.orderType,
|
||||||
vendor: req.body.vendor,
|
order: req.body.order,
|
||||||
courierService: req.body.courierService,
|
courierService: req.body.courierService,
|
||||||
trackingNumber: req.body.trackingNumber,
|
trackingNumber: req.body.trackingNumber,
|
||||||
items: req.body.items,
|
amount: req.body.amount,
|
||||||
cost: req.body.cost,
|
amountWithTax: req.body.amountWithTax,
|
||||||
shippedDate: req.body.shippedDate,
|
taxRate: req.body.taxRate,
|
||||||
expectedDeliveryDate: req.body.expectedDeliveryDate,
|
shippedAt: req.body.shippedAt,
|
||||||
actualDeliveryDate: req.body.actualDeliveryDate,
|
expectedAt: req.body.expectedAt,
|
||||||
state: req.body.state,
|
deliveredAt: req.body.deliveredAt,
|
||||||
notes: req.body.notes,
|
state: { type: 'draft' },
|
||||||
};
|
};
|
||||||
const result = await newObject({
|
const result = await newObject({
|
||||||
model: shipmentModel,
|
model: shipmentModel,
|
||||||
@ -197,3 +231,212 @@ export const getShipmentHistoryRouteHandler = async (req, res) => {
|
|||||||
logger.trace('Shipment history:', result);
|
logger.trace('Shipment history:', result);
|
||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const shipShipmentRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Shipment with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: shipmentModel, id, states: ['planned'] });
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking shipment states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Shipment is not in planned state.');
|
||||||
|
res.status(400).send({ error: 'Shipment is not in planned state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderItemsResult = await listObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
filter: { shipment: id },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (orderItemsResult.error) {
|
||||||
|
logger.error('Error listing order items:', orderItemsResult.error);
|
||||||
|
res.status(orderItemsResult.code).send(orderItemsResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
if (orderItem.state.type != 'ordered') {
|
||||||
|
logger.error('Order item is not in ordered state.');
|
||||||
|
res.status(400).send({ error: 'Order item is not in ordered state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
user: req.user,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'shipped' },
|
||||||
|
receivedAt: new Date(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
state: { type: 'shipped' },
|
||||||
|
shippedAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({ model: shipmentModel, id, updateData, user: req.user });
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error shipping shipment:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
logger.debug(`Shipped shipment with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const receiveShipmentRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Shipment with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({ model: shipmentModel, id, states: ['shipped'] });
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking shipment states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Shipment is not in shipped state.');
|
||||||
|
res.status(400).send({ error: 'Shipment is not in shipped state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderItemsResult = await listObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
filter: { shipment: id },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
if (orderItemsResult.error) {
|
||||||
|
logger.error('Error listing order items:', orderItemsResult.error);
|
||||||
|
res.status(orderItemsResult.code).send(orderItemsResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
if (orderItem.state.type != 'shipped') {
|
||||||
|
logger.error('Order item is not in shipped state.');
|
||||||
|
res.status(400).send({ error: 'Order item is not in shipped state.', code: 400 });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'received' },
|
||||||
|
receivedAt: new Date(),
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObject({
|
||||||
|
model: shipmentModel,
|
||||||
|
id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'delivered' },
|
||||||
|
deliveredAt: new Date(),
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error receiving shipment:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Received shipment with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const cancelShipmentRouteHandler = async (req, res) => {
|
||||||
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|
||||||
|
logger.trace(`Shipment with ID: ${id}`);
|
||||||
|
|
||||||
|
const checkStatesResult = await checkStates({
|
||||||
|
model: shipmentModel,
|
||||||
|
id,
|
||||||
|
states: ['planned', 'shipped'],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (checkStatesResult.error) {
|
||||||
|
logger.error('Error checking shipment states:', checkStatesResult.error);
|
||||||
|
res.status(checkStatesResult.code).send(checkStatesResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkStatesResult === false) {
|
||||||
|
logger.error('Shipment is not in a cancellable state.');
|
||||||
|
res.status(400).send({
|
||||||
|
error: 'Shipment is not in a cancellable state (must be planned or shipped).',
|
||||||
|
code: 400,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const orderItemsResult = await listObjects({
|
||||||
|
model: orderItemModel,
|
||||||
|
filter: { shipment: id },
|
||||||
|
pagination: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (orderItemsResult.error) {
|
||||||
|
logger.error('Error listing order items:', orderItemsResult.error);
|
||||||
|
res.status(orderItemsResult.code).send(orderItemsResult);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel related order items if they are in cancellable states
|
||||||
|
for (const orderItem of orderItemsResult) {
|
||||||
|
if (orderItem.state.type === 'draft' || orderItem.state.type === 'ordered') {
|
||||||
|
await editObject({
|
||||||
|
model: orderItemModel,
|
||||||
|
id: orderItem._id,
|
||||||
|
updateData: {
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
},
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateData = {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
state: { type: 'cancelled' },
|
||||||
|
cancelledAt: new Date(),
|
||||||
|
};
|
||||||
|
const result = await editObject({
|
||||||
|
model: shipmentModel,
|
||||||
|
id,
|
||||||
|
updateData,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error cancelling shipment:', result.error);
|
||||||
|
res.status(result.code).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Cancelled shipment with ID: ${id}`);
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
getObject,
|
getObject,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
@ -145,6 +146,32 @@ export const editStockEventRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultipleStockEventsRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: stockEventModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing stock events:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} stock events`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const deleteStockEventRouteHandler = async (req, res) => {
|
export const deleteStockEventRouteHandler = async (req, res) => {
|
||||||
// Get ID from params
|
// Get ID from params
|
||||||
const id = new mongoose.Types.ObjectId(req.params.id);
|
const id = new mongoose.Types.ObjectId(req.params.id);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
listObjects,
|
listObjects,
|
||||||
listObjectsByProperties,
|
listObjectsByProperties,
|
||||||
editObject,
|
editObject,
|
||||||
|
editObjects,
|
||||||
newObject,
|
newObject,
|
||||||
getModelStats,
|
getModelStats,
|
||||||
getModelHistory,
|
getModelHistory,
|
||||||
@ -58,7 +59,16 @@ export const listFilamentsByPropertiesRouteHandler = async (
|
|||||||
model: filamentModel,
|
model: filamentModel,
|
||||||
properties,
|
properties,
|
||||||
filter,
|
filter,
|
||||||
populate: 'vendor',
|
populate: [
|
||||||
|
{
|
||||||
|
path: 'vendor',
|
||||||
|
from: 'vendors',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'costTaxRate',
|
||||||
|
from: 'taxrates',
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result?.error) {
|
if (result?.error) {
|
||||||
@ -126,6 +136,45 @@ export const editFilamentRouteHandler = async (req, res) => {
|
|||||||
res.send(result);
|
res.send(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const editMultipleFilamentsRouteHandler = async (req, res) => {
|
||||||
|
const updates = req.body.map((update) => ({
|
||||||
|
_id: update._id,
|
||||||
|
name: update.name,
|
||||||
|
barcode: update.barcode,
|
||||||
|
url: update.url,
|
||||||
|
image: update.image,
|
||||||
|
color: update.color,
|
||||||
|
vendor: update.vendor,
|
||||||
|
type: update.type,
|
||||||
|
cost: update.cost,
|
||||||
|
costTaxRate: update.costTaxRate,
|
||||||
|
costWithTax: update.costWithTax,
|
||||||
|
diameter: update.diameter,
|
||||||
|
density: update.density,
|
||||||
|
emptySpoolWeight: update.emptySpoolWeight,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (!Array.isArray(updates)) {
|
||||||
|
return res.status(400).send({ error: 'Body must be an array of updates.', code: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await editObjects({
|
||||||
|
model: filamentModel,
|
||||||
|
updates,
|
||||||
|
user: req.user,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (result.error) {
|
||||||
|
logger.error('Error editing filaments:', result.error);
|
||||||
|
res.status(result.code || 500).send(result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug(`Edited ${updates.length} filaments`);
|
||||||
|
|
||||||
|
res.send(result);
|
||||||
|
};
|
||||||
|
|
||||||
export const newFilamentRouteHandler = async (req, res) => {
|
export const newFilamentRouteHandler = async (req, res) => {
|
||||||
const newData = {
|
const newData = {
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import config from '../../config.js';
|
import config from '../../config.js';
|
||||||
import { taxRateModel } from '../../database/schemas/management/taxrates.schema.js';
|
import { taxRateModel } from '../../database/schemas/management/taxrate.schema.js';
|
||||||
import log4js from 'log4js';
|
import log4js from 'log4js';
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import {
|
import {
|
||||||
|
|||||||
11
src/utils.js
11
src/utils.js
@ -1,4 +1,4 @@
|
|||||||
import { ObjectId } from 'mongodb';
|
import { mongoose } from 'mongoose';
|
||||||
import { auditLogModel } from './database/schemas/management/auditlog.schema.js';
|
import { auditLogModel } from './database/schemas/management/auditlog.schema.js';
|
||||||
import exifr from 'exifr';
|
import exifr from 'exifr';
|
||||||
import { natsServer } from './database/nats.js';
|
import { natsServer } from './database/nats.js';
|
||||||
@ -20,6 +20,9 @@ function buildWildcardRegexPattern(input) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function parseFilter(property, value) {
|
function parseFilter(property, value) {
|
||||||
|
if (value?._id !== undefined && value?._id !== null) {
|
||||||
|
return { [property]: { _id: new mongoose.Types.ObjectId(value._id) } };
|
||||||
|
}
|
||||||
if (typeof value === 'string') {
|
if (typeof value === 'string') {
|
||||||
var trimmed = value.trim();
|
var trimmed = value.trim();
|
||||||
if (trimmed.charAt(3) == ':') {
|
if (trimmed.charAt(3) == ':') {
|
||||||
@ -33,7 +36,7 @@ function parseFilter(property, value) {
|
|||||||
// Handle ObjectId (24-char hex)
|
// Handle ObjectId (24-char hex)
|
||||||
|
|
||||||
if (/^[a-f\d]{24}$/i.test(trimmed) && trimmed.length >= 24) {
|
if (/^[a-f\d]{24}$/i.test(trimmed) && trimmed.length >= 24) {
|
||||||
return { [property]: new ObjectId(trimmed) };
|
return { [property]: new mongoose.Types.ObjectId(trimmed) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle numbers
|
// Handle numbers
|
||||||
@ -514,7 +517,7 @@ function expandObjectIds(input) {
|
|||||||
// Helper to check if a value is an ObjectId or a 24-char hex string
|
// Helper to check if a value is an ObjectId or a 24-char hex string
|
||||||
function isObjectId(val) {
|
function isObjectId(val) {
|
||||||
// Check for MongoDB ObjectId instance
|
// Check for MongoDB ObjectId instance
|
||||||
if (val instanceof ObjectId) return true;
|
if (val instanceof mongoose.Types.ObjectId) return true;
|
||||||
// Check for exactly 24 hex characters (no special characters)
|
// Check for exactly 24 hex characters (no special characters)
|
||||||
if (typeof val === 'string' && /^[a-fA-F\d]{24}$/.test(val)) return true;
|
if (typeof val === 'string' && /^[a-fA-F\d]{24}$/.test(val)) return true;
|
||||||
return false;
|
return false;
|
||||||
@ -524,7 +527,7 @@ function expandObjectIds(input) {
|
|||||||
function expand(value) {
|
function expand(value) {
|
||||||
if (Array.isArray(value)) {
|
if (Array.isArray(value)) {
|
||||||
return value.map(expand);
|
return value.map(expand);
|
||||||
} else if (value && typeof value === 'object' && !(value instanceof ObjectId)) {
|
} else if (value && typeof value === 'object' && !(value instanceof mongoose.Types.ObjectId)) {
|
||||||
var result = {};
|
var result = {};
|
||||||
for (const [key, val] of Object.entries(value)) {
|
for (const [key, val] of Object.entries(value)) {
|
||||||
if (key === '_id') {
|
if (key === '_id') {
|
||||||
|
|||||||
379
yarn.lock
379
yarn.lock
@ -45,7 +45,7 @@
|
|||||||
"@smithy/util-utf8" "^2.0.0"
|
"@smithy/util-utf8" "^2.0.0"
|
||||||
tslib "^2.6.2"
|
tslib "^2.6.2"
|
||||||
|
|
||||||
"@aws-crypto/sha256-js@^5.2.0", "@aws-crypto/sha256-js@5.2.0":
|
"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0":
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz"
|
resolved "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz"
|
||||||
integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==
|
integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==
|
||||||
@ -61,7 +61,7 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
tslib "^2.6.2"
|
tslib "^2.6.2"
|
||||||
|
|
||||||
"@aws-crypto/util@^5.2.0", "@aws-crypto/util@5.2.0":
|
"@aws-crypto/util@5.2.0", "@aws-crypto/util@^5.2.0":
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz"
|
resolved "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz"
|
||||||
integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==
|
integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==
|
||||||
@ -514,7 +514,7 @@
|
|||||||
"@smithy/types" "^4.9.0"
|
"@smithy/types" "^4.9.0"
|
||||||
tslib "^2.6.2"
|
tslib "^2.6.2"
|
||||||
|
|
||||||
"@aws-sdk/types@^3.222.0", "@aws-sdk/types@3.930.0":
|
"@aws-sdk/types@3.930.0", "@aws-sdk/types@^3.222.0":
|
||||||
version "3.930.0"
|
version "3.930.0"
|
||||||
resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.930.0.tgz"
|
resolved "https://registry.npmjs.org/@aws-sdk/types/-/types-3.930.0.tgz"
|
||||||
integrity sha512-we/vaAgwlEFW7IeftmCLlLMw+6hFs3DzZPJw7lVHbj/5HJ0bz9gndxEsS2lQoeJ1zhiiLqAqvXxmM43s0MBg0A==
|
integrity sha512-we/vaAgwlEFW7IeftmCLlLMw+6hFs3DzZPJw7lVHbj/5HJ0bz9gndxEsS2lQoeJ1zhiiLqAqvXxmM43s0MBg0A==
|
||||||
@ -622,7 +622,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz"
|
resolved "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz"
|
||||||
integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==
|
integrity sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==
|
||||||
|
|
||||||
"@babel/core@^7.0.0", "@babel/core@^7.0.0-0", "@babel/core@^7.0.0-0 || ^8.0.0-0 <8.0.0", "@babel/core@^7.12.0", "@babel/core@^7.13.0", "@babel/core@^7.28.5", "@babel/core@^7.4.0 || ^8.0.0-0 <8.0.0":
|
"@babel/core@^7.28.5":
|
||||||
version "7.28.5"
|
version "7.28.5"
|
||||||
resolved "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz"
|
resolved "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz"
|
||||||
integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==
|
integrity sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==
|
||||||
@ -1527,34 +1527,6 @@
|
|||||||
"@eslint/core" "^0.17.0"
|
"@eslint/core" "^0.17.0"
|
||||||
levn "^0.4.1"
|
levn "^0.4.1"
|
||||||
|
|
||||||
"@grpc/grpc-js@^1.8.20":
|
|
||||||
version "1.14.1"
|
|
||||||
resolved "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.14.1.tgz"
|
|
||||||
integrity sha512-sPxgEWtPUR3EnRJCEtbGZG2iX8LQDUls2wUS3o27jg07KqJFMq6YDeWvMo1wfpmy3rqRdS0rivpLwhqQtEyCuQ==
|
|
||||||
dependencies:
|
|
||||||
"@grpc/proto-loader" "^0.8.0"
|
|
||||||
"@js-sdsl/ordered-map" "^4.4.2"
|
|
||||||
|
|
||||||
"@grpc/proto-loader@^0.7.8":
|
|
||||||
version "0.7.15"
|
|
||||||
resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.15.tgz"
|
|
||||||
integrity sha512-tMXdRCfYVixjuFK+Hk0Q1s38gV9zDiDJfWL3h1rv4Qc39oILCu1TRTDt7+fGUI8K4G1Fj125Hx/ru3azECWTyQ==
|
|
||||||
dependencies:
|
|
||||||
lodash.camelcase "^4.3.0"
|
|
||||||
long "^5.0.0"
|
|
||||||
protobufjs "^7.2.5"
|
|
||||||
yargs "^17.7.2"
|
|
||||||
|
|
||||||
"@grpc/proto-loader@^0.8.0":
|
|
||||||
version "0.8.0"
|
|
||||||
resolved "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.8.0.tgz"
|
|
||||||
integrity sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ==
|
|
||||||
dependencies:
|
|
||||||
lodash.camelcase "^4.3.0"
|
|
||||||
long "^5.0.0"
|
|
||||||
protobufjs "^7.5.3"
|
|
||||||
yargs "^17.7.2"
|
|
||||||
|
|
||||||
"@humanfs/core@^0.19.1":
|
"@humanfs/core@^0.19.1":
|
||||||
version "0.19.1"
|
version "0.19.1"
|
||||||
resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz"
|
resolved "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz"
|
||||||
@ -1638,11 +1610,6 @@
|
|||||||
"@jridgewell/resolve-uri" "^3.1.0"
|
"@jridgewell/resolve-uri" "^3.1.0"
|
||||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||||
|
|
||||||
"@js-sdsl/ordered-map@^4.4.2":
|
|
||||||
version "4.4.2"
|
|
||||||
resolved "https://registry.npmjs.org/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz"
|
|
||||||
integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw==
|
|
||||||
|
|
||||||
"@mongodb-js/saslprep@^1.3.0":
|
"@mongodb-js/saslprep@^1.3.0":
|
||||||
version "1.3.2"
|
version "1.3.2"
|
||||||
resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.2.tgz"
|
resolved "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.2.tgz"
|
||||||
@ -1720,65 +1687,12 @@
|
|||||||
resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz"
|
resolved "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz"
|
||||||
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
|
integrity sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==
|
||||||
|
|
||||||
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz"
|
|
||||||
integrity sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==
|
|
||||||
|
|
||||||
"@protobufjs/base64@^1.1.2":
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz"
|
|
||||||
integrity sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==
|
|
||||||
|
|
||||||
"@protobufjs/codegen@^2.0.4":
|
|
||||||
version "2.0.4"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz"
|
|
||||||
integrity sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==
|
|
||||||
|
|
||||||
"@protobufjs/eventemitter@^1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz"
|
|
||||||
integrity sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==
|
|
||||||
|
|
||||||
"@protobufjs/fetch@^1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz"
|
|
||||||
integrity sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==
|
|
||||||
dependencies:
|
|
||||||
"@protobufjs/aspromise" "^1.1.1"
|
|
||||||
"@protobufjs/inquire" "^1.1.0"
|
|
||||||
|
|
||||||
"@protobufjs/float@^1.0.2":
|
|
||||||
version "1.0.2"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz"
|
|
||||||
integrity sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==
|
|
||||||
|
|
||||||
"@protobufjs/inquire@^1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz"
|
|
||||||
integrity sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==
|
|
||||||
|
|
||||||
"@protobufjs/path@^1.1.2":
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz"
|
|
||||||
integrity sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==
|
|
||||||
|
|
||||||
"@protobufjs/pool@^1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz"
|
|
||||||
integrity sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==
|
|
||||||
|
|
||||||
"@protobufjs/utf8@^1.1.0":
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz"
|
|
||||||
integrity sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==
|
|
||||||
|
|
||||||
"@redis/bloom@5.10.0":
|
"@redis/bloom@5.10.0":
|
||||||
version "5.10.0"
|
version "5.10.0"
|
||||||
resolved "https://registry.npmjs.org/@redis/bloom/-/bloom-5.10.0.tgz"
|
resolved "https://registry.npmjs.org/@redis/bloom/-/bloom-5.10.0.tgz"
|
||||||
integrity sha512-doIF37ob+l47n0rkpRNgU8n4iacBlKM9xLiP1LtTZTvz8TloJB8qx/MgvhMhKdYG+CvCY2aPBnN2706izFn/4A==
|
integrity sha512-doIF37ob+l47n0rkpRNgU8n4iacBlKM9xLiP1LtTZTvz8TloJB8qx/MgvhMhKdYG+CvCY2aPBnN2706izFn/4A==
|
||||||
|
|
||||||
"@redis/client@^5.10.0", "@redis/client@5.10.0":
|
"@redis/client@5.10.0":
|
||||||
version "5.10.0"
|
version "5.10.0"
|
||||||
resolved "https://registry.npmjs.org/@redis/client/-/client-5.10.0.tgz"
|
resolved "https://registry.npmjs.org/@redis/client/-/client-5.10.0.tgz"
|
||||||
integrity sha512-JXmM4XCoso6C75Mr3lhKA3eNxSzkYi3nCzxDIKY+YOszYsJjuKbFgVtguVPbLMOttN4iu2fXoc2BGhdnYhIOxA==
|
integrity sha512-JXmM4XCoso6C75Mr3lhKA3eNxSzkYi3nCzxDIKY+YOszYsJjuKbFgVtguVPbLMOttN4iu2fXoc2BGhdnYhIOxA==
|
||||||
@ -2342,7 +2256,7 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
|
resolved "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz"
|
||||||
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==
|
||||||
|
|
||||||
"@types/node@*", "@types/node@>=13.7.0":
|
"@types/node@*":
|
||||||
version "24.10.1"
|
version "24.10.1"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz"
|
||||||
integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==
|
integrity sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==
|
||||||
@ -2396,7 +2310,7 @@ acorn-jsx@^5.3.2:
|
|||||||
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
|
||||||
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
|
||||||
|
|
||||||
"acorn@^6.0.0 || ^7.0.0 || ^8.0.0", acorn@^8.15.0, acorn@^8.9.0:
|
acorn@^8.15.0, acorn@^8.9.0:
|
||||||
version "8.15.0"
|
version "8.15.0"
|
||||||
resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz"
|
resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz"
|
||||||
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
|
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
|
||||||
@ -2656,11 +2570,6 @@ bcrypt@^6.0.0:
|
|||||||
node-addon-api "^8.3.0"
|
node-addon-api "^8.3.0"
|
||||||
node-gyp-build "^4.8.4"
|
node-gyp-build "^4.8.4"
|
||||||
|
|
||||||
bignumber.js@^9.1.1:
|
|
||||||
version "9.3.1"
|
|
||||||
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz"
|
|
||||||
integrity sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==
|
|
||||||
|
|
||||||
binary-extensions@^2.0.0:
|
binary-extensions@^2.0.0:
|
||||||
version "2.3.0"
|
version "2.3.0"
|
||||||
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz"
|
||||||
@ -2723,7 +2632,7 @@ brorand@^1.1.0:
|
|||||||
resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz"
|
||||||
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
|
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
|
||||||
|
|
||||||
browserslist@^4.24.0, browserslist@^4.26.3, "browserslist@>= 4.21.0":
|
browserslist@^4.24.0, browserslist@^4.26.3:
|
||||||
version "4.28.0"
|
version "4.28.0"
|
||||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz"
|
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz"
|
||||||
integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==
|
integrity sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==
|
||||||
@ -2768,7 +2677,7 @@ busboy@^1.6.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
streamsearch "^1.1.0"
|
streamsearch "^1.1.0"
|
||||||
|
|
||||||
bytes@^3.1.2, bytes@3.1.2:
|
bytes@3.1.2, bytes@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz"
|
resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz"
|
||||||
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==
|
||||||
@ -2814,7 +2723,7 @@ canonical-json@^0.2.0:
|
|||||||
resolved "https://registry.npmjs.org/canonical-json/-/canonical-json-0.2.0.tgz"
|
resolved "https://registry.npmjs.org/canonical-json/-/canonical-json-0.2.0.tgz"
|
||||||
integrity sha512-xeH/NgtNA7kIuKSxopJVdXqCKWyDB79aqxQRQ9FV02fvmqW7DSnjoFyzAUrBpfbwjU6lwTYOLc+HM6KupbsfVQ==
|
integrity sha512-xeH/NgtNA7kIuKSxopJVdXqCKWyDB79aqxQRQ9FV02fvmqW7DSnjoFyzAUrBpfbwjU6lwTYOLc+HM6KupbsfVQ==
|
||||||
|
|
||||||
chalk@^4.0.0, chalk@4.1.2:
|
chalk@4.1.2, chalk@^4.0.0:
|
||||||
version "4.1.2"
|
version "4.1.2"
|
||||||
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||||
@ -2887,11 +2796,6 @@ cluster-key-slot@1.1.2:
|
|||||||
resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz"
|
resolved "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz"
|
||||||
integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==
|
integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==
|
||||||
|
|
||||||
cockatiel@^3.1.1:
|
|
||||||
version "3.2.1"
|
|
||||||
resolved "https://registry.npmjs.org/cockatiel/-/cockatiel-3.2.1.tgz"
|
|
||||||
integrity sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==
|
|
||||||
|
|
||||||
color-convert@^2.0.1:
|
color-convert@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz"
|
||||||
@ -2983,17 +2887,17 @@ convert-source-map@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz"
|
||||||
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
|
||||||
|
|
||||||
cookie-signature@^1.2.1:
|
|
||||||
version "1.2.2"
|
|
||||||
resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz"
|
|
||||||
integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==
|
|
||||||
|
|
||||||
cookie-signature@1.0.7:
|
cookie-signature@1.0.7:
|
||||||
version "1.0.7"
|
version "1.0.7"
|
||||||
resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz"
|
resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz"
|
||||||
integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==
|
integrity sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==
|
||||||
|
|
||||||
cookie@^0.7.1, cookie@0.7.2:
|
cookie-signature@^1.2.1:
|
||||||
|
version "1.2.2"
|
||||||
|
resolved "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz"
|
||||||
|
integrity sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==
|
||||||
|
|
||||||
|
cookie@0.7.2, cookie@^0.7.1:
|
||||||
version "0.7.2"
|
version "0.7.2"
|
||||||
resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz"
|
resolved "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz"
|
||||||
integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
|
integrity sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==
|
||||||
@ -3064,20 +2968,6 @@ date-format@^4.0.14:
|
|||||||
resolved "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz"
|
resolved "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz"
|
||||||
integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==
|
integrity sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==
|
||||||
|
|
||||||
debug@^3.2.7:
|
|
||||||
version "3.2.7"
|
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
|
|
||||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
|
||||||
dependencies:
|
|
||||||
ms "^2.1.1"
|
|
||||||
|
|
||||||
debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0, debug@^4.4.1, debug@4, debug@4.x:
|
|
||||||
version "4.4.3"
|
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
|
|
||||||
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
|
||||||
dependencies:
|
|
||||||
ms "^2.1.3"
|
|
||||||
|
|
||||||
debug@2.6.9:
|
debug@2.6.9:
|
||||||
version "2.6.9"
|
version "2.6.9"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz"
|
||||||
@ -3085,6 +2975,13 @@ debug@2.6.9:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.0.0"
|
ms "2.0.0"
|
||||||
|
|
||||||
|
debug@4, debug@4.x, debug@^4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4, debug@^4.3.5, debug@^4.4.0, debug@^4.4.1:
|
||||||
|
version "4.4.3"
|
||||||
|
resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz"
|
||||||
|
integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.3"
|
||||||
|
|
||||||
debug@4.3.1:
|
debug@4.3.1:
|
||||||
version "4.3.1"
|
version "4.3.1"
|
||||||
resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz"
|
resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz"
|
||||||
@ -3092,6 +2989,13 @@ debug@4.3.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ms "2.1.2"
|
ms "2.1.2"
|
||||||
|
|
||||||
|
debug@^3.2.7:
|
||||||
|
version "3.2.7"
|
||||||
|
resolved "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz"
|
||||||
|
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||||
|
dependencies:
|
||||||
|
ms "^2.1.1"
|
||||||
|
|
||||||
deep-is@^0.1.3:
|
deep-is@^0.1.3:
|
||||||
version "0.1.4"
|
version "0.1.4"
|
||||||
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
|
resolved "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz"
|
||||||
@ -3129,7 +3033,7 @@ delayed-stream@~1.0.0:
|
|||||||
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz"
|
||||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||||
|
|
||||||
depd@^2.0.0, depd@~2.0.0, depd@2.0.0:
|
depd@2.0.0, depd@^2.0.0, depd@~2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz"
|
||||||
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
|
||||||
@ -3397,7 +3301,7 @@ escodegen@^2.1.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.6.1"
|
source-map "~0.6.1"
|
||||||
|
|
||||||
eslint-config-prettier@^10.1.8, "eslint-config-prettier@>= 7.0.0 <10.0.0 || >=10.1.0":
|
eslint-config-prettier@^10.1.8:
|
||||||
version "10.1.8"
|
version "10.1.8"
|
||||||
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz"
|
resolved "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz"
|
||||||
integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==
|
integrity sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==
|
||||||
@ -3436,7 +3340,7 @@ eslint-plugin-es@^4.1.0:
|
|||||||
eslint-utils "^2.0.0"
|
eslint-utils "^2.0.0"
|
||||||
regexpp "^3.0.0"
|
regexpp "^3.0.0"
|
||||||
|
|
||||||
eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.27.5:
|
eslint-plugin-import@^2.27.5:
|
||||||
version "2.32.0"
|
version "2.32.0"
|
||||||
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz"
|
||||||
integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==
|
integrity sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==
|
||||||
@ -3461,7 +3365,7 @@ eslint-plugin-import@^2.25.2, eslint-plugin-import@^2.27.5:
|
|||||||
string.prototype.trimend "^1.0.9"
|
string.prototype.trimend "^1.0.9"
|
||||||
tsconfig-paths "^3.15.0"
|
tsconfig-paths "^3.15.0"
|
||||||
|
|
||||||
"eslint-plugin-n@^15.0.0 || ^16.0.0 ", eslint-plugin-n@^15.7.0:
|
eslint-plugin-n@^15.7.0:
|
||||||
version "15.7.0"
|
version "15.7.0"
|
||||||
resolved "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-15.7.0.tgz"
|
||||||
integrity sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==
|
integrity sha512-jDex9s7D/Qial8AGVIHq4W7NswpUD5DPDL2RH8Lzd9EloWUuvUkHfv4FRLMipH5q2UtyurorBkPeNi1wVWNh3Q==
|
||||||
@ -3483,12 +3387,12 @@ eslint-plugin-prettier@^5.5.4:
|
|||||||
prettier-linter-helpers "^1.0.0"
|
prettier-linter-helpers "^1.0.0"
|
||||||
synckit "^0.11.7"
|
synckit "^0.11.7"
|
||||||
|
|
||||||
eslint-plugin-promise@^6.0.0, eslint-plugin-promise@^6.1.1:
|
eslint-plugin-promise@^6.1.1:
|
||||||
version "6.6.0"
|
version "6.6.0"
|
||||||
resolved "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz"
|
resolved "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz"
|
||||||
integrity sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==
|
integrity sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==
|
||||||
|
|
||||||
eslint-plugin-react@^7.28.0, eslint-plugin-react@^7.36.1:
|
eslint-plugin-react@^7.36.1:
|
||||||
version "7.37.5"
|
version "7.37.5"
|
||||||
resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz"
|
resolved "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz"
|
||||||
integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==
|
integrity sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==
|
||||||
@ -3562,7 +3466,7 @@ eslint-visitor-keys@^4.2.1:
|
|||||||
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz"
|
resolved "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz"
|
||||||
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
|
integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==
|
||||||
|
|
||||||
"eslint@^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9", "eslint@^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7", "eslint@^7.0.0 || ^8.0.0 || ^9.0.0", eslint@^8.0.1, eslint@^8.41.0, eslint@^8.8.0, eslint@>=4.19.1, eslint@>=5:
|
eslint@^8.41.0:
|
||||||
version "8.57.1"
|
version "8.57.1"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz"
|
||||||
integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
|
integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
|
||||||
@ -3606,7 +3510,7 @@ eslint-visitor-keys@^4.2.1:
|
|||||||
strip-ansi "^6.0.1"
|
strip-ansi "^6.0.1"
|
||||||
text-table "^0.2.0"
|
text-table "^0.2.0"
|
||||||
|
|
||||||
"eslint@^6.0.0 || ^7.0.0 || >=8.0.0", eslint@^9.39.1, eslint@>=7.0.0, eslint@>=8.0.0:
|
eslint@^9.39.1:
|
||||||
version "9.39.1"
|
version "9.39.1"
|
||||||
resolved "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz"
|
resolved "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz"
|
||||||
integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==
|
integrity sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==
|
||||||
@ -3698,16 +3602,6 @@ etag@^1.8.1:
|
|||||||
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
|
resolved "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz"
|
||||||
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
|
||||||
|
|
||||||
etcd3@^1.1.2:
|
|
||||||
version "1.1.2"
|
|
||||||
resolved "https://registry.npmjs.org/etcd3/-/etcd3-1.1.2.tgz"
|
|
||||||
integrity sha512-YIampCz1/OmrVo/tR3QltAVUtYCQQOSFoqmHKKeoHbalm+WdXe3l4rhLIylklu8EzR/I3PBiOF4dC847dDskKg==
|
|
||||||
dependencies:
|
|
||||||
"@grpc/grpc-js" "^1.8.20"
|
|
||||||
"@grpc/proto-loader" "^0.7.8"
|
|
||||||
bignumber.js "^9.1.1"
|
|
||||||
cockatiel "^3.1.1"
|
|
||||||
|
|
||||||
exifr@^7.1.3:
|
exifr@^7.1.3:
|
||||||
version "7.1.3"
|
version "7.1.3"
|
||||||
resolved "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz"
|
resolved "https://registry.npmjs.org/exifr/-/exifr-7.1.3.tgz"
|
||||||
@ -4202,7 +4096,7 @@ homedir-polyfill@^1.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
parse-passwd "^1.0.0"
|
parse-passwd "^1.0.0"
|
||||||
|
|
||||||
http-errors@^2.0.0, http-errors@2.0.0:
|
http-errors@2.0.0, http-errors@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz"
|
||||||
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==
|
||||||
@ -4234,13 +4128,6 @@ i@^0.3.7:
|
|||||||
resolved "https://registry.npmjs.org/i/-/i-0.3.7.tgz"
|
resolved "https://registry.npmjs.org/i/-/i-0.3.7.tgz"
|
||||||
integrity sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==
|
integrity sha512-FYz4wlXgkQwIPqhzC5TdNMLSE5+GS1IIDJZY/1ZiEPCT2S3COUVZeT5OW4BmW4r5LHLQuOosSwsvnroG9GR59Q==
|
||||||
|
|
||||||
iconv-lite@^0.6.3:
|
|
||||||
version "0.6.3"
|
|
||||||
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
|
|
||||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
|
||||||
dependencies:
|
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
|
||||||
|
|
||||||
iconv-lite@0.7.0:
|
iconv-lite@0.7.0:
|
||||||
version "0.7.0"
|
version "0.7.0"
|
||||||
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz"
|
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.0.tgz"
|
||||||
@ -4248,6 +4135,13 @@ iconv-lite@0.7.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
|
iconv-lite@^0.6.3:
|
||||||
|
version "0.6.3"
|
||||||
|
resolved "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz"
|
||||||
|
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||||
|
dependencies:
|
||||||
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
ignore-by-default@^1.0.1:
|
ignore-by-default@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz"
|
||||||
@ -4284,7 +4178,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@2, inherits@2.0.4:
|
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@ -4778,11 +4672,6 @@ locate-path@^6.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
p-locate "^5.0.0"
|
p-locate "^5.0.0"
|
||||||
|
|
||||||
lodash.camelcase@^4.3.0:
|
|
||||||
version "4.3.0"
|
|
||||||
resolved "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz"
|
|
||||||
integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==
|
|
||||||
|
|
||||||
lodash.debounce@^4.0.8:
|
lodash.debounce@^4.0.8:
|
||||||
version "4.0.8"
|
version "4.0.8"
|
||||||
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
|
resolved "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz"
|
||||||
@ -4844,11 +4733,6 @@ log4js@^6.9.1:
|
|||||||
rfdc "^1.3.0"
|
rfdc "^1.3.0"
|
||||||
streamroller "^3.1.5"
|
streamroller "^3.1.5"
|
||||||
|
|
||||||
long@^5.0.0:
|
|
||||||
version "5.3.2"
|
|
||||||
resolved "https://registry.npmjs.org/long/-/long-5.3.2.tgz"
|
|
||||||
integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==
|
|
||||||
|
|
||||||
loose-envify@^1.4.0:
|
loose-envify@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
resolved "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz"
|
||||||
@ -4886,16 +4770,16 @@ math-intrinsics@^1.1.0:
|
|||||||
resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz"
|
||||||
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==
|
||||||
|
|
||||||
media-typer@^1.1.0:
|
|
||||||
version "1.1.0"
|
|
||||||
resolved "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz"
|
|
||||||
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==
|
|
||||||
|
|
||||||
media-typer@0.3.0:
|
media-typer@0.3.0:
|
||||||
version "0.3.0"
|
version "0.3.0"
|
||||||
resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
|
resolved "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz"
|
||||||
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==
|
||||||
|
|
||||||
|
media-typer@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz"
|
||||||
|
integrity sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==
|
||||||
|
|
||||||
memory-pager@^1.0.2:
|
memory-pager@^1.0.2:
|
||||||
version "1.5.0"
|
version "1.5.0"
|
||||||
resolved "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz"
|
resolved "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz"
|
||||||
@ -4906,17 +4790,17 @@ merge-descriptors@^2.0.0:
|
|||||||
resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz"
|
||||||
integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==
|
integrity sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==
|
||||||
|
|
||||||
mime-db@^1.54.0:
|
|
||||||
version "1.54.0"
|
|
||||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz"
|
|
||||||
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
|
||||||
|
|
||||||
mime-db@1.52.0:
|
mime-db@1.52.0:
|
||||||
version "1.52.0"
|
version "1.52.0"
|
||||||
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
|
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz"
|
||||||
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
|
||||||
|
|
||||||
mime-types@^2.1.12:
|
mime-db@^1.54.0:
|
||||||
|
version "1.54.0"
|
||||||
|
resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz"
|
||||||
|
integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==
|
||||||
|
|
||||||
|
mime-types@^2.1.12, mime-types@~2.1.24:
|
||||||
version "2.1.35"
|
version "2.1.35"
|
||||||
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
|
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
|
||||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
||||||
@ -4930,13 +4814,6 @@ mime-types@^3.0.0, mime-types@^3.0.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mime-db "^1.54.0"
|
mime-db "^1.54.0"
|
||||||
|
|
||||||
mime-types@~2.1.24:
|
|
||||||
version "2.1.35"
|
|
||||||
resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz"
|
|
||||||
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
|
|
||||||
dependencies:
|
|
||||||
mime-db "1.52.0"
|
|
||||||
|
|
||||||
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz"
|
||||||
@ -4947,6 +4824,13 @@ minimalistic-crypto-utils@^1.0.1:
|
|||||||
resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz"
|
resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz"
|
||||||
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
|
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
|
||||||
|
|
||||||
|
minimatch@9.0.1:
|
||||||
|
version "9.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz"
|
||||||
|
integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
|
||||||
version "3.1.2"
|
version "3.1.2"
|
||||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||||
@ -4961,13 +4845,6 @@ minimatch@^9.0.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^2.0.1"
|
brace-expansion "^2.0.1"
|
||||||
|
|
||||||
minimatch@9.0.1:
|
|
||||||
version "9.0.1"
|
|
||||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz"
|
|
||||||
integrity sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==
|
|
||||||
dependencies:
|
|
||||||
brace-expansion "^2.0.1"
|
|
||||||
|
|
||||||
minimist@^1.2.0, minimist@^1.2.6:
|
minimist@^1.2.0, minimist@^1.2.6:
|
||||||
version "1.2.8"
|
version "1.2.8"
|
||||||
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz"
|
||||||
@ -5048,11 +4925,6 @@ mquery@5.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
debug "4.x"
|
debug "4.x"
|
||||||
|
|
||||||
ms@^2.1.1, ms@^2.1.3, ms@2.1.3:
|
|
||||||
version "2.1.3"
|
|
||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
|
||||||
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
|
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
|
||||||
@ -5063,6 +4935,11 @@ ms@2.1.2:
|
|||||||
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz"
|
||||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||||
|
|
||||||
|
ms@2.1.3, ms@^2.1.1, ms@^2.1.3:
|
||||||
|
version "2.1.3"
|
||||||
|
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"
|
||||||
|
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
|
||||||
|
|
||||||
multer@^2.0.2:
|
multer@^2.0.2:
|
||||||
version "2.0.2"
|
version "2.0.2"
|
||||||
resolved "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz"
|
resolved "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz"
|
||||||
@ -5447,7 +5324,7 @@ pg-types@2.2.0:
|
|||||||
postgres-date "~1.0.4"
|
postgres-date "~1.0.4"
|
||||||
postgres-interval "^1.1.0"
|
postgres-interval "^1.1.0"
|
||||||
|
|
||||||
pg@^8.16.3, pg@>=8.0:
|
pg@^8.16.3:
|
||||||
version "8.16.3"
|
version "8.16.3"
|
||||||
resolved "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz"
|
resolved "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz"
|
||||||
integrity sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==
|
integrity sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==
|
||||||
@ -5541,7 +5418,7 @@ prettier-linter-helpers@^1.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
fast-diff "^1.1.2"
|
fast-diff "^1.1.2"
|
||||||
|
|
||||||
prettier@^3.6.2, prettier@>=3.0.0:
|
prettier@^3.6.2:
|
||||||
version "3.6.2"
|
version "3.6.2"
|
||||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz"
|
resolved "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz"
|
||||||
integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==
|
integrity sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==
|
||||||
@ -5560,24 +5437,6 @@ proto-list@~1.2.1:
|
|||||||
resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz"
|
resolved "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz"
|
||||||
integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
|
integrity sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==
|
||||||
|
|
||||||
protobufjs@^7.2.5, protobufjs@^7.5.3:
|
|
||||||
version "7.5.4"
|
|
||||||
resolved "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.4.tgz"
|
|
||||||
integrity sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg==
|
|
||||||
dependencies:
|
|
||||||
"@protobufjs/aspromise" "^1.1.2"
|
|
||||||
"@protobufjs/base64" "^1.1.2"
|
|
||||||
"@protobufjs/codegen" "^2.0.4"
|
|
||||||
"@protobufjs/eventemitter" "^1.1.0"
|
|
||||||
"@protobufjs/fetch" "^1.1.0"
|
|
||||||
"@protobufjs/float" "^1.0.2"
|
|
||||||
"@protobufjs/inquire" "^1.1.0"
|
|
||||||
"@protobufjs/path" "^1.1.2"
|
|
||||||
"@protobufjs/pool" "^1.1.0"
|
|
||||||
"@protobufjs/utf8" "^1.1.0"
|
|
||||||
"@types/node" ">=13.7.0"
|
|
||||||
long "^5.0.0"
|
|
||||||
|
|
||||||
proxy-addr@^2.0.7:
|
proxy-addr@^2.0.7:
|
||||||
version "2.0.7"
|
version "2.0.7"
|
||||||
resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz"
|
resolved "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz"
|
||||||
@ -5845,7 +5704,7 @@ safe-array-concat@^1.1.2, safe-array-concat@^1.1.3:
|
|||||||
has-symbols "^1.1.0"
|
has-symbols "^1.1.0"
|
||||||
isarray "^2.0.5"
|
isarray "^2.0.5"
|
||||||
|
|
||||||
safe-buffer@^5.0.1, safe-buffer@~5.2.0, safe-buffer@5.2.1:
|
safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz"
|
||||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||||
@ -5867,17 +5726,12 @@ safe-regex-test@^1.1.0:
|
|||||||
es-errors "^1.3.0"
|
es-errors "^1.3.0"
|
||||||
is-regex "^1.2.1"
|
is-regex "^1.2.1"
|
||||||
|
|
||||||
safer-buffer@^2.1.0, "safer-buffer@>= 2.1.2 < 3.0.0":
|
"safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.1.0:
|
||||||
version "2.1.2"
|
version "2.1.2"
|
||||||
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
resolved "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz"
|
||||||
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
|
||||||
|
|
||||||
semver@^5.6.0:
|
semver@^5.6.0, semver@^5.7.0:
|
||||||
version "5.7.2"
|
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
|
||||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
|
||||||
|
|
||||||
semver@^5.7.0:
|
|
||||||
version "5.7.2"
|
version "5.7.2"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz"
|
||||||
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
|
||||||
@ -5887,22 +5741,7 @@ semver@^6.3.1:
|
|||||||
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz"
|
||||||
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
|
||||||
|
|
||||||
semver@^7.0.0:
|
semver@^7.0.0, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4:
|
||||||
version "7.7.3"
|
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz"
|
|
||||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
|
||||||
|
|
||||||
semver@^7.3.8:
|
|
||||||
version "7.7.3"
|
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz"
|
|
||||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
|
||||||
|
|
||||||
semver@^7.5.3:
|
|
||||||
version "7.7.3"
|
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz"
|
|
||||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
|
||||||
|
|
||||||
semver@^7.5.4:
|
|
||||||
version "7.7.3"
|
version "7.7.3"
|
||||||
resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz"
|
resolved "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz"
|
||||||
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==
|
||||||
@ -6110,7 +5949,7 @@ socks-proxy-agent@^8.0.5:
|
|||||||
debug "^4.3.4"
|
debug "^4.3.4"
|
||||||
socks "^2.8.3"
|
socks "^2.8.3"
|
||||||
|
|
||||||
socks@^2.7.1, socks@^2.8.3:
|
socks@^2.8.3:
|
||||||
version "2.8.7"
|
version "2.8.7"
|
||||||
resolved "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz"
|
resolved "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz"
|
||||||
integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==
|
integrity sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==
|
||||||
@ -6168,16 +6007,16 @@ standard@^17.1.2:
|
|||||||
standard-engine "^15.1.0"
|
standard-engine "^15.1.0"
|
||||||
version-guard "^1.1.1"
|
version-guard "^1.1.1"
|
||||||
|
|
||||||
statuses@^2.0.1:
|
|
||||||
version "2.0.2"
|
|
||||||
resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz"
|
|
||||||
integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==
|
|
||||||
|
|
||||||
statuses@2.0.1:
|
statuses@2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz"
|
resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz"
|
||||||
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
|
||||||
|
|
||||||
|
statuses@^2.0.1:
|
||||||
|
version "2.0.2"
|
||||||
|
resolved "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz"
|
||||||
|
integrity sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==
|
||||||
|
|
||||||
stop-iteration-iterator@^1.1.0:
|
stop-iteration-iterator@^1.1.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz"
|
||||||
@ -6200,13 +6039,6 @@ streamsearch@^1.1.0:
|
|||||||
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
|
||||||
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
|
||||||
|
|
||||||
string_decoder@^1.1.1:
|
|
||||||
version "1.3.0"
|
|
||||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
|
||||||
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
|
||||||
dependencies:
|
|
||||||
safe-buffer "~5.2.0"
|
|
||||||
|
|
||||||
"string-width-cjs@npm:string-width@^4.2.0":
|
"string-width-cjs@npm:string-width@^4.2.0":
|
||||||
version "4.2.3"
|
version "4.2.3"
|
||||||
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
resolved "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz"
|
||||||
@ -6293,6 +6125,13 @@ string.prototype.trimstart@^1.0.8:
|
|||||||
define-properties "^1.2.1"
|
define-properties "^1.2.1"
|
||||||
es-object-atoms "^1.0.0"
|
es-object-atoms "^1.0.0"
|
||||||
|
|
||||||
|
string_decoder@^1.1.1:
|
||||||
|
version "1.3.0"
|
||||||
|
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz"
|
||||||
|
integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
|
||||||
|
dependencies:
|
||||||
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
|
||||||
version "6.0.1"
|
version "6.0.1"
|
||||||
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz"
|
||||||
@ -6329,6 +6168,13 @@ strnum@^2.1.0:
|
|||||||
resolved "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz"
|
resolved "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz"
|
||||||
integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==
|
integrity sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==
|
||||||
|
|
||||||
|
supports-color@8.1.1:
|
||||||
|
version "8.1.1"
|
||||||
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz"
|
||||||
|
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
||||||
|
dependencies:
|
||||||
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
supports-color@^5.5.0:
|
supports-color@^5.5.0:
|
||||||
version "5.5.0"
|
version "5.5.0"
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz"
|
||||||
@ -6343,13 +6189,6 @@ supports-color@^7.1.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
has-flag "^4.0.0"
|
has-flag "^4.0.0"
|
||||||
|
|
||||||
supports-color@8.1.1:
|
|
||||||
version "8.1.1"
|
|
||||||
resolved "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz"
|
|
||||||
integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==
|
|
||||||
dependencies:
|
|
||||||
has-flag "^4.0.0"
|
|
||||||
|
|
||||||
supports-preserve-symlinks-flag@^1.0.0:
|
supports-preserve-symlinks-flag@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz"
|
||||||
@ -6779,6 +6618,19 @@ yargs-parser@^21.1.1:
|
|||||||
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz"
|
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz"
|
||||||
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==
|
||||||
|
|
||||||
|
yargs@17.7.2:
|
||||||
|
version "17.7.2"
|
||||||
|
resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz"
|
||||||
|
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
|
||||||
|
dependencies:
|
||||||
|
cliui "^8.0.1"
|
||||||
|
escalade "^3.1.1"
|
||||||
|
get-caller-file "^2.0.5"
|
||||||
|
require-directory "^2.1.1"
|
||||||
|
string-width "^4.2.3"
|
||||||
|
y18n "^5.0.5"
|
||||||
|
yargs-parser "^21.1.1"
|
||||||
|
|
||||||
yargs@^16.2.0:
|
yargs@^16.2.0:
|
||||||
version "16.2.0"
|
version "16.2.0"
|
||||||
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
|
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
|
||||||
@ -6792,19 +6644,6 @@ yargs@^16.2.0:
|
|||||||
y18n "^5.0.5"
|
y18n "^5.0.5"
|
||||||
yargs-parser "^20.2.2"
|
yargs-parser "^20.2.2"
|
||||||
|
|
||||||
yargs@^17.7.2, yargs@17.7.2:
|
|
||||||
version "17.7.2"
|
|
||||||
resolved "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz"
|
|
||||||
integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==
|
|
||||||
dependencies:
|
|
||||||
cliui "^8.0.1"
|
|
||||||
escalade "^3.1.1"
|
|
||||||
get-caller-file "^2.0.5"
|
|
||||||
require-directory "^2.1.1"
|
|
||||||
string-width "^4.2.3"
|
|
||||||
y18n "^5.0.5"
|
|
||||||
yargs-parser "^21.1.1"
|
|
||||||
|
|
||||||
yauzl@^2.10.0:
|
yauzl@^2.10.0:
|
||||||
version "2.10.0"
|
version "2.10.0"
|
||||||
resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz"
|
resolved "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user