visit rd and pd stored in database and pdorder fixed the create order and processing order
This commit is contained in:
parent
e1906cadbb
commit
e53a503ffa
73
resources/PD_Orders/invoiceModel.js
Normal file
73
resources/PD_Orders/invoiceModel.js
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import mongoose, { Schema } from "mongoose";
|
||||||
|
|
||||||
|
const orderItemSchema = new Schema({
|
||||||
|
productId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: "Product",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
SKU: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
categoryName: {
|
||||||
|
type: String, // Directly store category name
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
brandName: {
|
||||||
|
type: String, // Directly store brand name
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
price: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
GST: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
HSN_Code: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
quantity: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
default: 1,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const invoiceSchema = new mongoose.Schema({
|
||||||
|
invoiceId: { type: String, required: true, unique: true },
|
||||||
|
orderId: {
|
||||||
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
|
ref: "PdOrder",
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
items: [orderItemSchema],
|
||||||
|
subtotal: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
gstTotal: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
invoiceAmount: { type: Number, required: true },
|
||||||
|
courier_name: { type: String },
|
||||||
|
courier_tracking_id: { type: String },
|
||||||
|
courierStatus: {
|
||||||
|
type: String,
|
||||||
|
enum: ["processing", "dispatched", "delivered"],
|
||||||
|
default: "processing",
|
||||||
|
},
|
||||||
|
courierstatus_timeline: {
|
||||||
|
processing: { type: Date },
|
||||||
|
dispatched: { type: Date },
|
||||||
|
delivered: { type: Date },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const Invoice = mongoose.model("Invoice", invoiceSchema);
|
@ -1,11 +1,12 @@
|
|||||||
// Adjust the path to where your PdOrder model is located
|
|
||||||
|
|
||||||
import mongoose from "mongoose";
|
import mongoose from "mongoose";
|
||||||
import { PdOrder } from "./pdOrderModal.js";
|
import { PdOrder } from "./pdOrderModal.js";
|
||||||
import sendEmail from "../../Utils/sendEmail.js";
|
import sendEmail from "../../Utils/sendEmail.js";
|
||||||
|
import { Invoice } from "./invoiceModel.js";
|
||||||
|
|
||||||
|
// Controller for placing an order
|
||||||
export const createOrder = async (req, res) => {
|
export const createOrder = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
|
// Destructure the request body
|
||||||
const {
|
const {
|
||||||
paymentMode,
|
paymentMode,
|
||||||
shipTo,
|
shipTo,
|
||||||
@ -16,6 +17,7 @@ export const createOrder = async (req, res) => {
|
|||||||
grandTotal,
|
grandTotal,
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
|
||||||
|
// Check for required fields
|
||||||
if (
|
if (
|
||||||
!paymentMode ||
|
!paymentMode ||
|
||||||
!shipTo ||
|
!shipTo ||
|
||||||
@ -25,11 +27,10 @@ export const createOrder = async (req, res) => {
|
|||||||
!gstTotal ||
|
!gstTotal ||
|
||||||
!grandTotal
|
!grandTotal
|
||||||
) {
|
) {
|
||||||
return res.status(400).json({ error: "All fields are required." });
|
return res.status(400).json({ error: "Missing required fields" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the order
|
|
||||||
const addedBy = req.user._id;
|
const addedBy = req.user._id;
|
||||||
|
// Create a new PdOrder instance
|
||||||
const newOrder = new PdOrder({
|
const newOrder = new PdOrder({
|
||||||
paymentMode,
|
paymentMode,
|
||||||
shipTo,
|
shipTo,
|
||||||
@ -48,6 +49,7 @@ export const createOrder = async (req, res) => {
|
|||||||
description: item.description,
|
description: item.description,
|
||||||
image: item.image,
|
image: item.image,
|
||||||
quantity: item.count,
|
quantity: item.count,
|
||||||
|
remainingQuantity: item.count,
|
||||||
})),
|
})),
|
||||||
subtotal,
|
subtotal,
|
||||||
gstTotal,
|
gstTotal,
|
||||||
@ -55,14 +57,103 @@ export const createOrder = async (req, res) => {
|
|||||||
addedBy,
|
addedBy,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save the order to the database
|
// Save the new order
|
||||||
const savedOrder = await newOrder.save();
|
const savedOrder = await newOrder.save();
|
||||||
|
// console.log(savedOrder);
|
||||||
// Return the created order as a response
|
return res.status(201).json({
|
||||||
return res.status(201).json({ placedOrder: savedOrder });
|
message: "Order placed successfully",
|
||||||
|
placedOrder: savedOrder,
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Error creating order:", error);
|
console.error(error);
|
||||||
return res.status(500).json({ error: "Internal Server Error" });
|
return res.status(500).json({ error: "Internal server error" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Controller for processing an order and generating invoice
|
||||||
|
export const processOrder = async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { orderId, invoiceItems } = req.body;
|
||||||
|
|
||||||
|
if (!orderId || !invoiceItems || !Array.isArray(invoiceItems)) {
|
||||||
|
return res.status(400).json({ error: 'Missing required fields or invalid data' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find the order by ID
|
||||||
|
const order = await PdOrder.findById(orderId);
|
||||||
|
|
||||||
|
if (!order) {
|
||||||
|
return res.status(404).json({ error: 'Order not found' });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate quantities
|
||||||
|
for (const item of invoiceItems) {
|
||||||
|
const orderItem = order.orderItem.find(i => i.productId.toString() === item.productId.toString());
|
||||||
|
if (orderItem && item.quantity > orderItem.remainingQuantity) {
|
||||||
|
return res.status(400).json({ error: `Product '${item.name}' has more quantity than remaining in the order.` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate unique invoice number
|
||||||
|
const existingInvoices = await Invoice.find({ orderId });
|
||||||
|
const invoiceNumber = existingInvoices.length + 1;
|
||||||
|
const invoiceId = `ch/${order.uniqueId}/${invoiceItems.length}/${invoiceNumber}`;
|
||||||
|
|
||||||
|
// Calculate subtotal, gstTotal, and invoiceAmount
|
||||||
|
let subtotal = 0;
|
||||||
|
let gstTotal = 0;
|
||||||
|
let invoiceAmount = 0;
|
||||||
|
|
||||||
|
invoiceItems.forEach(item => {
|
||||||
|
const itemSubtotal = item.price * item.quantity;
|
||||||
|
const itemGST = (item.price * item.GST) / 100 * item.quantity;
|
||||||
|
|
||||||
|
subtotal += itemSubtotal;
|
||||||
|
gstTotal += itemGST;
|
||||||
|
invoiceAmount += itemSubtotal + itemGST;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new invoice
|
||||||
|
const newInvoice = new Invoice({
|
||||||
|
invoiceId,
|
||||||
|
orderId,
|
||||||
|
items: invoiceItems,
|
||||||
|
subtotal,
|
||||||
|
gstTotal,
|
||||||
|
invoiceAmount,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Save the invoice
|
||||||
|
const savedInvoice = await newInvoice.save();
|
||||||
|
|
||||||
|
// Update the order's order items with the remaining quantity
|
||||||
|
let allItemsProcessed = true;
|
||||||
|
order.orderItem.forEach(item => {
|
||||||
|
const invoicedItem = invoiceItems.find(i => i.productId.toString() === item.productId.toString());
|
||||||
|
if (invoicedItem) {
|
||||||
|
item.remainingQuantity -= invoicedItem.quantity;
|
||||||
|
if (item.remainingQuantity < 0) {
|
||||||
|
item.remainingQuantity = 0; // Ensure it does not go negative
|
||||||
|
}
|
||||||
|
if (item.remainingQuantity > 0) {
|
||||||
|
allItemsProcessed = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update the order status
|
||||||
|
order.status = allItemsProcessed ? 'processing' : 'pending';
|
||||||
|
|
||||||
|
// Save the updated order
|
||||||
|
await order.save();
|
||||||
|
|
||||||
|
return res.status(201).json({
|
||||||
|
message: 'Invoice created and order processed successfully',
|
||||||
|
invoice: savedInvoice,
|
||||||
|
order: order,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return res.status(500).json({ error: 'Internal server error' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -49,20 +49,13 @@ const orderItemSchema = new Schema({
|
|||||||
required: true,
|
required: true,
|
||||||
default: 1,
|
default: 1,
|
||||||
},
|
},
|
||||||
});
|
remainingQuantity: {
|
||||||
|
type: Number,
|
||||||
const StatusHistorySchema = new mongoose.Schema({
|
|
||||||
status: {
|
|
||||||
type: String,
|
|
||||||
enum: ["new", "dispatched", "cancelled", "processing", "delivered"], // Ensure this matches your status enum
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
timestamp: {
|
|
||||||
type: Date,
|
|
||||||
default: Date.now,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const pdOrderSchema = new Schema(
|
const pdOrderSchema = new Schema(
|
||||||
{
|
{
|
||||||
paymentMode: {
|
paymentMode: {
|
||||||
@ -93,13 +86,12 @@ const pdOrderSchema = new Schema(
|
|||||||
},
|
},
|
||||||
status: {
|
status: {
|
||||||
type: String,
|
type: String,
|
||||||
enum: ["new", "dispatched", "cancelled", "processing", "delivered"],
|
enum: ['new','pending','processing','dispatched', 'cancelled', 'delivered'],
|
||||||
default: "new",
|
default: 'new'
|
||||||
},
|
|
||||||
statusUpdatedAt: {
|
|
||||||
type: Date,
|
|
||||||
default: Date.now,
|
|
||||||
},
|
},
|
||||||
|
invoices: [
|
||||||
|
{ type: mongoose.Schema.Types.ObjectId, ref: 'Invoice' }
|
||||||
|
],
|
||||||
uniqueId: {
|
uniqueId: {
|
||||||
type: String,
|
type: String,
|
||||||
unique: true,
|
unique: true,
|
||||||
@ -110,15 +102,6 @@ const pdOrderSchema = new Schema(
|
|||||||
ref: "User",
|
ref: "User",
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
status_timeline: {
|
|
||||||
new: { type: Date },
|
|
||||||
paid: { type: Date },
|
|
||||||
processing: { type: Date },
|
|
||||||
dispatched: { type: Date },
|
|
||||||
delivered: { type: Date },
|
|
||||||
cancelled: { type: Date },
|
|
||||||
returned: { type: Date },
|
|
||||||
},
|
|
||||||
iscancelled: {
|
iscancelled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
@ -126,26 +109,23 @@ const pdOrderSchema = new Schema(
|
|||||||
order_Cancelled_Reason: {
|
order_Cancelled_Reason: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
courier_name: { type: String },
|
|
||||||
courier_tracking_id: { type: String },
|
|
||||||
isDelivered: { type: Boolean, required: true, default: false },
|
isDelivered: { type: Boolean, required: true, default: false },
|
||||||
DeliveredDate: { type: String, default: "" },
|
DeliveredDate: { type: String, default: "" },
|
||||||
statusHistory: [StatusHistorySchema], // Add this field to store the status history
|
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Middleware to update the statusUpdatedAt field whenever status changes
|
// Middleware to generate uniqueId before saving the document
|
||||||
pdOrderSchema.pre("save", function (next) {
|
pdOrderSchema.pre('save', async function(next) {
|
||||||
if (this.isModified("status")) {
|
if (this.isNew) {
|
||||||
this.statusUpdatedAt = Date.now();
|
const year = new Date().getFullYear().toString().slice(-2); // Get the last 2 digits of the year
|
||||||
// Add the new status and timestamp to statusHistory
|
const orderItemCount = this.orderItem.length; // Count the number of order items
|
||||||
this.statusHistory.push({
|
const unique6CharId = nanoid(6); // Generate a 6-character unique ID
|
||||||
status: this.status,
|
|
||||||
timestamp: this.statusUpdatedAt,
|
this.uniqueId = `${year}-${orderItemCount}-${unique6CharId}`;
|
||||||
});
|
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
export const PdOrder = mongoose.model("PdOrder", pdOrderSchema);
|
export const PdOrder = mongoose.model("PdOrder", pdOrderSchema);
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import {
|
|||||||
getPlacedOrderById,
|
getPlacedOrderById,
|
||||||
getProcessingOrdersAdmin,
|
getProcessingOrdersAdmin,
|
||||||
updateOrderStatusById,
|
updateOrderStatusById,
|
||||||
|
processOrder,
|
||||||
} from "./pdOrderController.js";
|
} from "./pdOrderController.js";
|
||||||
|
|
||||||
const router = express.Router();
|
const router = express.Router();
|
||||||
@ -22,6 +23,10 @@ router
|
|||||||
authorizeRoles("principal-Distributor"),
|
authorizeRoles("principal-Distributor"),
|
||||||
createOrder
|
createOrder
|
||||||
);
|
);
|
||||||
|
// Define the route for processing an order
|
||||||
|
router
|
||||||
|
.route("/processing-order")
|
||||||
|
.post(isAuthenticatedUser, authorizeRoles("admin"), processOrder);
|
||||||
router
|
router
|
||||||
.route("/get-placed-order-pd")
|
.route("/get-placed-order-pd")
|
||||||
.get(
|
.get(
|
||||||
|
@ -1,20 +1,55 @@
|
|||||||
import VisitRDandPD from './VisitRD&PDModel.js';
|
import VisitRDandPD from "./VisitRD&PDModel.js";
|
||||||
|
|
||||||
const parseDate = (dateStr) => {
|
const parseDate = (dateStr) => {
|
||||||
const [day, month, year] = dateStr.split("/").map(Number);
|
const [day, month, year] = dateStr.split("/").map(Number);
|
||||||
// Create a UTC date object to ensure the correct date is stored
|
|
||||||
return new Date(Date.UTC(year, month - 1, day));
|
return new Date(Date.UTC(year, month - 1, day));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Controller for creating a visit record
|
// Controller for creating a visit record
|
||||||
export const createVisit = async (req, res) => {
|
export const createVisit = async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const visitBy = req.user._id;
|
const visitBy = req.user._id;
|
||||||
const visitUserType = req.userType;
|
const visitUserType = req.userType;
|
||||||
const { addedFor, addedForId, tradename, visitDate, note } = req.body;
|
const {
|
||||||
if (!addedFor || !addedForId || !tradename || !visitDate) {
|
addedFor,
|
||||||
return res.status(400).json({ message: 'All fields are required' });
|
addedForId,
|
||||||
|
tradename,
|
||||||
|
visitDate,
|
||||||
|
visitTime,
|
||||||
|
meetingsummary,
|
||||||
|
followup,
|
||||||
|
visitpurpose,
|
||||||
|
nextvisitdate,
|
||||||
|
} = req.body;
|
||||||
|
if (
|
||||||
|
!addedFor ||
|
||||||
|
!addedForId ||
|
||||||
|
!tradename ||
|
||||||
|
!visitDate ||
|
||||||
|
!meetingsummary
|
||||||
|
) {
|
||||||
|
return res.status(400).json({ message: "All fields are required" });
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedDate = parseDate(visitDate);
|
const parsedDate = parseDate(visitDate);
|
||||||
|
const nextvisit = parseDate(nextvisitdate);
|
||||||
|
let documents = [];
|
||||||
|
if (req.files && req.files.documents) {
|
||||||
|
const documentFiles = Array.isArray(req.files.documents)
|
||||||
|
? req.files.documents
|
||||||
|
: [req.files.documents];
|
||||||
|
for (const file of documentFiles) {
|
||||||
|
const result = await cloudinary.v2.uploader.upload(file.tempFilePath, {
|
||||||
|
folder: "chemiNova/visitdistributors",
|
||||||
|
});
|
||||||
|
|
||||||
|
documents.push({
|
||||||
|
public_id: result.public_id,
|
||||||
|
url: result.secure_url,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new visit record
|
// Create a new visit record
|
||||||
const newVisit = new VisitRDandPD({
|
const newVisit = new VisitRDandPD({
|
||||||
visitBy,
|
visitBy,
|
||||||
@ -23,16 +58,23 @@ export const createVisit = async (req, res) => {
|
|||||||
addedForId,
|
addedForId,
|
||||||
tradename,
|
tradename,
|
||||||
visitDate: parsedDate,
|
visitDate: parsedDate,
|
||||||
note,
|
visitTime,
|
||||||
|
visitpurpose,
|
||||||
|
meetingsummary,
|
||||||
|
followup,
|
||||||
|
nextvisitdate: nextvisit,
|
||||||
|
documents,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Save the visit record to the database
|
// Save the visit record to the database
|
||||||
const savedVisit = await newVisit.save();
|
const savedVisit = await newVisit.save();
|
||||||
|
|
||||||
return res.status(201).json({ message: 'Visit done successfully', visit: savedVisit });
|
return res
|
||||||
|
.status(201)
|
||||||
|
.json({ message: "Visit created successfully", visit: savedVisit });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return res.status(500).json({ message: 'Server error' });
|
return res.status(500).json({ message: "Server error" });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -42,23 +84,27 @@ export const getVisitsByDistributor = async (req, res) => {
|
|||||||
const { distributorId, distributorType } = req.params;
|
const { distributorId, distributorType } = req.params;
|
||||||
|
|
||||||
// Validate distributor type
|
// Validate distributor type
|
||||||
if (!['RetailDistributor', 'PrincipalDistributor'].includes(distributorType)) {
|
if (
|
||||||
return res.status(400).json({ message: 'Invalid distributor type' });
|
!["RetailDistributor", "PrincipalDistributor"].includes(distributorType)
|
||||||
|
) {
|
||||||
|
return res.status(400).json({ message: "Invalid distributor type" });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find all visits for the specified distributor
|
// Find all visits for the specified distributor
|
||||||
const visits = await VisitRDandPD.find({
|
const visits = await VisitRDandPD.find({
|
||||||
addedFor: distributorType,
|
addedFor: distributorType,
|
||||||
addedForId: distributorId,
|
addedForId: distributorId,
|
||||||
}).populate('visitBy', 'name email'); // Populating visitBy with user details
|
}).populate("visitBy", "name email"); // Populating visitBy with user details
|
||||||
|
|
||||||
if (!visits.length) {
|
if (!visits.length) {
|
||||||
return res.status(404).json({ message: 'No visits found for this distributor' });
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ message: "No visits found for this distributor" });
|
||||||
}
|
}
|
||||||
|
|
||||||
return res.status(200).json({ visits });
|
return res.status(200).json({ visits });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
return res.status(500).json({ message: 'Server error' });
|
return res.status(500).json({ message: "Server error" });
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -6,7 +6,7 @@ const VisitSchema = new mongoose.Schema(
|
|||||||
{
|
{
|
||||||
visitBy: {
|
visitBy: {
|
||||||
type: mongoose.Schema.Types.ObjectId,
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
refPath: "userType",
|
refPath: "visitUserType", // Corrected refPath
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
visitUserType: {
|
visitUserType: {
|
||||||
@ -21,7 +21,7 @@ const VisitSchema = new mongoose.Schema(
|
|||||||
},
|
},
|
||||||
addedForId: {
|
addedForId: {
|
||||||
type: mongoose.Schema.Types.ObjectId,
|
type: mongoose.Schema.Types.ObjectId,
|
||||||
refPath: "addedFor",
|
refPath: "addedFor", // Corrected refPath
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
tradename: {
|
tradename: {
|
||||||
@ -32,9 +32,32 @@ const VisitSchema = new mongoose.Schema(
|
|||||||
type: Date,
|
type: Date,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
note: {
|
visitTime: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
visitpurpose: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
meetingsummary: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
followup: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
|
nextvisitdate: {
|
||||||
|
type: Date,
|
||||||
|
},
|
||||||
|
documents: [{
|
||||||
|
public_id: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
url: {
|
||||||
|
type: String,
|
||||||
|
},
|
||||||
|
}],
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user