Ordini
This commit is contained in:
21
src/server/models/cart.js
Normal file → Executable file
21
src/server/models/cart.js
Normal file → Executable file
@@ -1,6 +1,9 @@
|
||||
|
||||
const mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const shared_consts = require('../tools/shared_nodejs');
|
||||
|
||||
const Order = require('../models/order');
|
||||
|
||||
const CartSchema = new Schema({
|
||||
@@ -16,6 +19,9 @@ const CartSchema = new Schema({
|
||||
{ type: Schema.Types.ObjectId, ref: 'Order' }
|
||||
}
|
||||
],
|
||||
note: {
|
||||
type: String
|
||||
},
|
||||
modify_at: {
|
||||
type: Date
|
||||
},
|
||||
@@ -89,7 +95,16 @@ module.exports.updateCartByCartId = async function (cartId, newCart) {
|
||||
const totalQty = newCart.totalQty;
|
||||
const totalPrice = newCart.totalPrice;
|
||||
|
||||
return await Cart.findOneAndUpdate({ _id: cartId }, { $set: { items, totalPrice, totalQty } }, { new: false })
|
||||
const modify_at = new Date();
|
||||
|
||||
return await Cart.findOneAndUpdate({ _id: cartId }, {
|
||||
$set: {
|
||||
items,
|
||||
totalPrice,
|
||||
totalQty,
|
||||
modify_at
|
||||
}
|
||||
}, { new: false })
|
||||
.then((ris) => {
|
||||
return ris;
|
||||
}).catch(err => {
|
||||
@@ -99,6 +114,10 @@ module.exports.updateCartByCartId = async function (cartId, newCart) {
|
||||
|
||||
}
|
||||
|
||||
module.exports.deleteCartByCartId = async function (cartId) {
|
||||
return await Cart.remove({ _id: cartId });
|
||||
}
|
||||
|
||||
|
||||
module.exports.createCart = async function (newCart) {
|
||||
return await newCart.save()
|
||||
|
||||
@@ -14,7 +14,6 @@ mongoose.plugin(schema => {
|
||||
const cfgserverSchema = new Schema({
|
||||
chiave: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 1,
|
||||
},
|
||||
|
||||
179
src/server/models/orderscart.js
Executable file
179
src/server/models/orderscart.js
Executable file
@@ -0,0 +1,179 @@
|
||||
const mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const shared_consts = require('../tools/shared_nodejs');
|
||||
|
||||
const Order = require('../models/order');
|
||||
|
||||
const { ObjectID } = require('mongodb');
|
||||
|
||||
const OrdersCartSchema = new Schema({
|
||||
idapp: {
|
||||
type: String
|
||||
},
|
||||
numorder: { type: Number },
|
||||
userId: { type: Schema.Types.ObjectId, ref: 'User' },
|
||||
totalQty: { type: Number, default: 0 },
|
||||
totalPrice: { type: Number, default: 0 },
|
||||
items: [
|
||||
{
|
||||
order:
|
||||
{ type: Schema.Types.ObjectId, ref: 'Order' }
|
||||
}
|
||||
],
|
||||
status: {
|
||||
type: Number
|
||||
},
|
||||
note: {
|
||||
type: String
|
||||
},
|
||||
modify_at: {
|
||||
type: Date
|
||||
},
|
||||
created_at: {
|
||||
type: Date
|
||||
},
|
||||
});
|
||||
|
||||
var OrdersCart = module.exports = mongoose.model('OrdersCart', OrdersCartSchema);
|
||||
|
||||
module.exports.findAllIdApp = async function (idapp, userId) {
|
||||
const myfind = { idapp, userId };
|
||||
|
||||
return await OrdersCart.findOne(myfind);
|
||||
};
|
||||
|
||||
|
||||
module.exports.getNewNumOrder = async function (uid, idapp) {
|
||||
let query = { userId: uid, idapp }
|
||||
let numorder = 1;
|
||||
let numorderrec = await OrdersCart.find(query).sort({ numorder: -1 }).limit(1);
|
||||
if (numorderrec.length <= 0)
|
||||
numorder = 1;
|
||||
else
|
||||
numorder = numorderrec[0].numorder;
|
||||
|
||||
if (numorder) {
|
||||
numorder++
|
||||
} else {
|
||||
numorder = 1;
|
||||
}
|
||||
|
||||
return numorder;
|
||||
|
||||
};
|
||||
|
||||
module.exports.getOrdersCartByUserId = async function (uid, idapp) {
|
||||
let query = { userId: uid, idapp, status: { $gte: shared_consts.OrderStatus.CHECKOUT_CONFIRMED } }
|
||||
const myorderscart = await OrdersCart.find(query);
|
||||
|
||||
for (let ind = 0; ind < myorderscart.length; ind++) {
|
||||
for (const idkey in myorderscart[ind].items) {
|
||||
try {
|
||||
idorder = myorderscart[ind].items[idkey]._id.toString();
|
||||
const myorder = myorderscart[ind].items[idkey].order;
|
||||
if (!!myorder) {
|
||||
idorder = myorderscart[ind].items[idkey].order._id.toString();
|
||||
}
|
||||
const myord = await Order.getTotalOrderById(idorder);
|
||||
if (myord.length > 0) {
|
||||
myorderscart[ind].items[idkey]._doc.order = myord[0];
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('err', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if (!!mycart) {
|
||||
for (const idkey in mycart.items) {
|
||||
try {
|
||||
idorder = mycart.items[idkey]._id.toString();
|
||||
const myorder = mycart.items[idkey].order;
|
||||
if (!!myorder) {
|
||||
idorder = mycart.items[idkey].order._id.toString();
|
||||
}
|
||||
const myord = await Order.getTotalOrderById(idorder);
|
||||
if (myord.length > 0) {
|
||||
mycart.items[idkey]._doc.order = myord[0];
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('err', e);
|
||||
}
|
||||
}
|
||||
return mycart;
|
||||
}*/
|
||||
return myorderscart
|
||||
// return null;
|
||||
}
|
||||
|
||||
module.exports.updateOrdersCartById = function (id, newOrdersCart, callback) {
|
||||
let query = { id: id }
|
||||
OrdersCart.find(query, function (err, c) {
|
||||
if (err) throw err
|
||||
|
||||
//exist cart in databse
|
||||
if (c.length > 0) {
|
||||
OrdersCart.findOneAndUpdate(
|
||||
{ _id: id },
|
||||
{
|
||||
$set: {
|
||||
items: newOrdersCart.items,
|
||||
totalQty: newOrdersCart.totalQty,
|
||||
totalPrice: newOrdersCart.totalPrice,
|
||||
userId: userId,
|
||||
status: newOrdersCart.status,
|
||||
numorder: newOrdersCart.numorder,
|
||||
note: newOrdersCart.note,
|
||||
modify_at: new Date(),
|
||||
}
|
||||
},
|
||||
{ new: true },
|
||||
callback
|
||||
)
|
||||
} else {
|
||||
//no cart in database
|
||||
newOrdersCart.save(callback)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
module.exports.createOrdersCart = async function (newOrdersCart) {
|
||||
return await newOrdersCart.save()
|
||||
}
|
||||
|
||||
OrdersCartSchema.pre('save', async function (next) {
|
||||
|
||||
try {
|
||||
if (this.isNew) {
|
||||
try {
|
||||
const myrec = await User.findOne({ idapp: this.idapp }).limit(1).sort({ neworder: -1 });
|
||||
|
||||
if (!!myrec) {
|
||||
this.neworder = myrec._doc.neworder + 1;
|
||||
} else {
|
||||
this.neworder = 1;
|
||||
}
|
||||
} catch (e) {
|
||||
this.neworder = 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (user.isModified('password')) {
|
||||
bcrypt.genSalt(10, (err, salt) => {
|
||||
bcrypt.hash(user.password, salt, (err, hash) => {
|
||||
user.password = hash;
|
||||
next();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
next();
|
||||
}
|
||||
*/
|
||||
|
||||
next();
|
||||
} catch (e) {
|
||||
console.error(e.message);
|
||||
}
|
||||
});
|
||||
@@ -25,6 +25,9 @@ const producerSchema = new Schema({
|
||||
referent: {
|
||||
type: String,
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
},
|
||||
region: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
@@ -22,6 +22,10 @@ const productSchema = new Schema({
|
||||
idStorehouses: [
|
||||
{ type: Schema.Types.ObjectId, ref: 'Storehouse' }
|
||||
],
|
||||
code: {
|
||||
type: String,
|
||||
lowercase: true
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
@@ -50,6 +54,12 @@ const productSchema = new Schema({
|
||||
quantityAvailable: {
|
||||
type: Number
|
||||
},
|
||||
canBeShipped: { // è spedibile
|
||||
type: Boolean
|
||||
},
|
||||
canBeBuyOnline: { // è acquistabile online
|
||||
type: Boolean
|
||||
},
|
||||
stars: {
|
||||
type: Number
|
||||
},
|
||||
@@ -62,6 +72,12 @@ const productSchema = new Schema({
|
||||
img: {
|
||||
type: String,
|
||||
},
|
||||
img2: {
|
||||
type: String,
|
||||
},
|
||||
img3: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
var Product = module.exports = mongoose.model('Product', productSchema);
|
||||
@@ -75,13 +91,17 @@ module.exports.executeQueryTable = function (idapp, params) {
|
||||
return tools.executeQueryTable(this, idapp, params);
|
||||
};
|
||||
|
||||
module.exports.findAllIdApp = async function (idapp) {
|
||||
const myfind = { idapp };
|
||||
module.exports.findAllIdApp = async function (idapp, code) {
|
||||
let myfind = { idapp };
|
||||
|
||||
if (code) {
|
||||
myfind = { ...myfind, code }
|
||||
}
|
||||
|
||||
// return await Product.find(myfind);
|
||||
|
||||
const query = [
|
||||
{ $match: { idapp } },
|
||||
{ $match: myfind },
|
||||
{ "$addFields": { "myidProd": { "$toObjectId": "$idProducer" } } },
|
||||
{
|
||||
$lookup: {
|
||||
@@ -125,6 +145,10 @@ module.exports.getProductByTitle = function (query, sort, callback) {
|
||||
Product.find(query, null, sort, callback)
|
||||
}
|
||||
|
||||
module.exports.getProductByCode = function (idapp, code) {
|
||||
return Product.findOne({ idapp, code })
|
||||
}
|
||||
|
||||
module.exports.filterProductByDepartment = function (department, callback) {
|
||||
let regexp = new RegExp(`${department}`, 'i')
|
||||
var query = { department: { $regex: regexp } };
|
||||
|
||||
49
src/server/models/sharewithus.js
Executable file
49
src/server/models/sharewithus.js
Executable file
@@ -0,0 +1,49 @@
|
||||
mongoose = require('mongoose');
|
||||
const Schema = mongoose.Schema;
|
||||
|
||||
const tools = require('../tools/general');
|
||||
|
||||
mongoose.Promise = global.Promise;
|
||||
mongoose.level = "F";
|
||||
|
||||
|
||||
// Resolving error Unknown modifier: $pushAll
|
||||
mongoose.plugin(schema => {
|
||||
schema.options.usePushEach = true
|
||||
});
|
||||
|
||||
const ShareWithUsSchema = new Schema({
|
||||
idapp: {
|
||||
type: String,
|
||||
},
|
||||
userId: {
|
||||
type: String,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
},
|
||||
numshared: {
|
||||
type: Number,
|
||||
},
|
||||
rating: {
|
||||
type: Number,
|
||||
},
|
||||
});
|
||||
|
||||
var ShareWithUs = module.exports = mongoose.model('ShareWithUs', ShareWithUsSchema);
|
||||
|
||||
module.exports.getFieldsForSearch = function () {
|
||||
return [{field: 'description', type: tools.FieldType.string}]
|
||||
};
|
||||
|
||||
module.exports.executeQueryTable = function (idapp, params) {
|
||||
params.fieldsearch = this.getFieldsForSearch();
|
||||
return tools.executeQueryTable(this, idapp, params);
|
||||
};
|
||||
|
||||
module.exports.findAllIdApp = async function (idapp) {
|
||||
const myfind = { idapp };
|
||||
|
||||
return await ShareWithUs.find(myfind);
|
||||
};
|
||||
|
||||
@@ -32,234 +32,245 @@ mongoose.plugin(schema => {
|
||||
mongoose.set('debug', process.env.DEBUG);
|
||||
|
||||
const UserSchema = new mongoose.Schema({
|
||||
userId: {
|
||||
type: String,
|
||||
},
|
||||
email: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 1,
|
||||
unique: false,
|
||||
/*validate: {
|
||||
validator: validator.isEmail,
|
||||
message: '{VALUE} is not a valid email'
|
||||
}*/
|
||||
},
|
||||
idapp: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
index: {
|
||||
type: Number
|
||||
},
|
||||
ind_order: {
|
||||
type: Number
|
||||
},
|
||||
old_order: {
|
||||
type: Number
|
||||
},
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 6,
|
||||
unique: false,
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
trim: true,
|
||||
},
|
||||
surname: {
|
||||
type: String,
|
||||
trim: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
require: true,
|
||||
minlength: 6,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
require: true,
|
||||
},
|
||||
linkreg: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
verified_email: {
|
||||
type: Boolean,
|
||||
},
|
||||
made_gift: {
|
||||
type: Boolean,
|
||||
},
|
||||
tokens: [{
|
||||
access: {
|
||||
userId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
browser: {
|
||||
email: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 1,
|
||||
unique: false,
|
||||
/*validate: {
|
||||
validator: validator.isEmail,
|
||||
message: '{VALUE} is not a valid email'
|
||||
}*/
|
||||
},
|
||||
token: {
|
||||
idapp: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
date_login: {
|
||||
type: Date
|
||||
},
|
||||
}],
|
||||
perm: {
|
||||
type: Number
|
||||
},
|
||||
ipaddr: {
|
||||
type: String,
|
||||
},
|
||||
date_reg: {
|
||||
type: Date,
|
||||
},
|
||||
date_deleted: {
|
||||
type: Date,
|
||||
},
|
||||
date_tokenforgot: {
|
||||
type: Date
|
||||
},
|
||||
tokenforgot: {
|
||||
type: String,
|
||||
},
|
||||
lasttimeonline: {
|
||||
type: Date
|
||||
},
|
||||
news_on: {
|
||||
type: Boolean
|
||||
},
|
||||
aportador_solidario: { // da cancellare
|
||||
type: String,
|
||||
},
|
||||
aportador_iniziale: {
|
||||
type: String,
|
||||
},
|
||||
aportador_solidario_nome_completo: {
|
||||
type: String,
|
||||
},
|
||||
aportador_solidario_ind_order: {
|
||||
type: Number,
|
||||
},
|
||||
note: {
|
||||
type: String,
|
||||
},
|
||||
deleted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sospeso: {
|
||||
type: Boolean
|
||||
},
|
||||
non_voglio_imbarcarmi: {
|
||||
type: Boolean
|
||||
},
|
||||
navinonpresenti: {
|
||||
type: Boolean
|
||||
},
|
||||
subaccount: {
|
||||
type: Boolean
|
||||
},
|
||||
cart: {
|
||||
type: Object
|
||||
},
|
||||
profile: {
|
||||
img: {
|
||||
type: String
|
||||
},
|
||||
nationality: {
|
||||
type: String
|
||||
},
|
||||
intcode_cell: {
|
||||
type: String
|
||||
},
|
||||
iso2_cell: {
|
||||
type: String
|
||||
},
|
||||
cell: {
|
||||
type: String
|
||||
},
|
||||
country_pay: {
|
||||
type: String
|
||||
},
|
||||
email_paypal: {
|
||||
type: String
|
||||
},
|
||||
payeer_id: {
|
||||
type: String
|
||||
},
|
||||
advcash_id: {
|
||||
type: String
|
||||
},
|
||||
revolut: {
|
||||
type: String
|
||||
},
|
||||
link_payment: {
|
||||
type: String
|
||||
},
|
||||
note_payment: {
|
||||
type: String
|
||||
},
|
||||
paymenttypes: [],
|
||||
username_telegram: {
|
||||
type: String
|
||||
},
|
||||
teleg_id: {
|
||||
index: {
|
||||
type: Number
|
||||
},
|
||||
teleg_id_old: {
|
||||
ind_order: {
|
||||
type: Number
|
||||
},
|
||||
teleg_checkcode: {
|
||||
old_order: {
|
||||
type: Number
|
||||
},
|
||||
manage_telegram: {
|
||||
type: Boolean
|
||||
username: {
|
||||
type: String,
|
||||
required: true,
|
||||
trim: true,
|
||||
minlength: 6,
|
||||
unique: false,
|
||||
},
|
||||
dateofbirth: {
|
||||
name: {
|
||||
type: String,
|
||||
trim: true,
|
||||
},
|
||||
surname: {
|
||||
type: String,
|
||||
trim: true,
|
||||
},
|
||||
password: {
|
||||
type: String,
|
||||
require: true,
|
||||
minlength: 6,
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
require: true,
|
||||
},
|
||||
linkreg: {
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
verified_email: {
|
||||
type: Boolean,
|
||||
},
|
||||
made_gift: {
|
||||
type: Boolean,
|
||||
},
|
||||
tokens: [{
|
||||
access: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
browser: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
token: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
date_login: {
|
||||
type: Date
|
||||
},
|
||||
}],
|
||||
perm: {
|
||||
type: Number
|
||||
},
|
||||
ipaddr: {
|
||||
type: String,
|
||||
},
|
||||
date_reg: {
|
||||
type: Date,
|
||||
},
|
||||
my_dream: {
|
||||
date_deleted: {
|
||||
type: Date,
|
||||
},
|
||||
date_tokenforgot: {
|
||||
type: Date
|
||||
},
|
||||
tokenforgot: {
|
||||
type: String,
|
||||
},
|
||||
saw_and_accepted: {
|
||||
lasttimeonline: {
|
||||
type: Date
|
||||
},
|
||||
news_on: {
|
||||
type: Boolean
|
||||
},
|
||||
aportador_solidario: { // da cancellare
|
||||
type: String,
|
||||
},
|
||||
aportador_iniziale: {
|
||||
type: String,
|
||||
},
|
||||
aportador_solidario_nome_completo: {
|
||||
type: String,
|
||||
},
|
||||
aportador_solidario_ind_order: {
|
||||
type: Number,
|
||||
},
|
||||
saw_zoom_presentation: {
|
||||
note: {
|
||||
type: String,
|
||||
},
|
||||
deleted: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
sospeso: {
|
||||
type: Boolean
|
||||
},
|
||||
ask_zoom_partecipato: {
|
||||
non_voglio_imbarcarmi: {
|
||||
type: Boolean
|
||||
},
|
||||
qualified: {
|
||||
navinonpresenti: {
|
||||
type: Boolean
|
||||
},
|
||||
qualified_2invitati: {
|
||||
subaccount: {
|
||||
type: Boolean
|
||||
},
|
||||
special_req: {
|
||||
type: Boolean
|
||||
cart: {
|
||||
type: Object
|
||||
},
|
||||
sex: {
|
||||
type: Number,
|
||||
profile: {
|
||||
img: {
|
||||
type: String
|
||||
},
|
||||
nationality: {
|
||||
type: String
|
||||
},
|
||||
intcode_cell: {
|
||||
type: String
|
||||
},
|
||||
iso2_cell: {
|
||||
type: String
|
||||
},
|
||||
cell: {
|
||||
type: String
|
||||
},
|
||||
country_pay: {
|
||||
type: String
|
||||
},
|
||||
email_paypal: {
|
||||
type: String
|
||||
},
|
||||
payeer_id: {
|
||||
type: String
|
||||
},
|
||||
advcash_id: {
|
||||
type: String
|
||||
},
|
||||
revolut: {
|
||||
type: String
|
||||
},
|
||||
link_payment: {
|
||||
type: String
|
||||
},
|
||||
note_payment: {
|
||||
type: String
|
||||
},
|
||||
paymenttypes: [],
|
||||
username_telegram: {
|
||||
type: String
|
||||
},
|
||||
teleg_id: {
|
||||
type: Number
|
||||
},
|
||||
teleg_id_old: {
|
||||
type: Number
|
||||
},
|
||||
teleg_checkcode: {
|
||||
type: Number
|
||||
},
|
||||
manage_telegram: {
|
||||
type: Boolean
|
||||
},
|
||||
dateofbirth: {
|
||||
type: Date,
|
||||
},
|
||||
my_dream: {
|
||||
type: String,
|
||||
},
|
||||
saw_and_accepted: {
|
||||
type: Number,
|
||||
},
|
||||
saw_zoom_presentation: {
|
||||
type: Boolean
|
||||
},
|
||||
ask_zoom_partecipato: {
|
||||
type: Boolean
|
||||
},
|
||||
qualified: {
|
||||
type: Boolean
|
||||
},
|
||||
qualified_2invitati: {
|
||||
type: Boolean
|
||||
},
|
||||
special_req: {
|
||||
type: Boolean
|
||||
},
|
||||
sex: {
|
||||
type: Number,
|
||||
},
|
||||
chisei: {
|
||||
type: String
|
||||
},
|
||||
iltuoimpegno: {
|
||||
type: String
|
||||
},
|
||||
come_aiutare: {
|
||||
type: String
|
||||
},
|
||||
socio: {
|
||||
type: Boolean,
|
||||
},
|
||||
socioresidente: {
|
||||
type: Boolean,
|
||||
},
|
||||
myshares: [{
|
||||
description: { type: String },
|
||||
rating: { type: Number },
|
||||
}]
|
||||
},
|
||||
chisei: {
|
||||
type: String
|
||||
},
|
||||
iltuoimpegno: {
|
||||
type: String
|
||||
},
|
||||
come_aiutare: {
|
||||
type: String
|
||||
},
|
||||
},
|
||||
|
||||
});
|
||||
})
|
||||
;
|
||||
|
||||
UserSchema.methods.toJSON = function () {
|
||||
const user = this;
|
||||
@@ -1352,7 +1363,7 @@ UserSchema.statics.getUsersListByParams = function (params) {
|
||||
|
||||
myclParamQuery = new queryclass.CParamsQuery(params);
|
||||
|
||||
const filterMatchBefore = `${ myclParamQuery.filter }`;
|
||||
const filterMatchBefore = `${myclParamQuery.filter}`;
|
||||
|
||||
return User.find(
|
||||
{ $match: filterMatchBefore },
|
||||
|
||||
0
src/server/models/variant.js
Normal file → Executable file
0
src/server/models/variant.js
Normal file → Executable file
Reference in New Issue
Block a user