Merge branch 'add-even-more-filters' into 'master'
Add even more filters See merge request saburly/marketalarm/web!77
This commit was merged in pull request #77.
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
const db = require("../../models/index");
|
const db = require("../../models/index");
|
||||||
const sequelize = require("sequelize");
|
const sequelize = require("sequelize");
|
||||||
const Op = sequelize.Op;
|
const Op = sequelize.Op;
|
||||||
|
const { AD_CATEGORY } = require("../../common/enums");
|
||||||
|
|
||||||
const bulkUpsertRealEstates = async realEstateData => {
|
const bulkUpsertRealEstates = async realEstateData => {
|
||||||
try {
|
try {
|
||||||
const fieldsToUpdateIfDuplicate = [
|
const fieldsToUpdateIfDuplicate = [
|
||||||
@@ -102,6 +104,9 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
accessRoadType
|
accessRoadType
|
||||||
} = searchRequest;
|
} = searchRequest;
|
||||||
|
|
||||||
|
//Needed for defining which attribute should exist or not
|
||||||
|
const realEstateTypeObject = AD_CATEGORY[realEstateType];
|
||||||
|
|
||||||
const longitudeColumn = sequelize.col("locationLong");
|
const longitudeColumn = sequelize.col("locationLong");
|
||||||
const latitudeColumn = sequelize.col("locationLat");
|
const latitudeColumn = sequelize.col("locationLat");
|
||||||
|
|
||||||
@@ -175,8 +180,13 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
[Op.and]: geoSearchQueryPart
|
[Op.and]: geoSearchQueryPart
|
||||||
};
|
};
|
||||||
|
|
||||||
//Every other attribute is checked separately and included in query only if it is defined
|
//Every other attribute is checked separately and included in query only if it is defined for real estate type
|
||||||
if (gardenSizeMax && gardenSizeMin) {
|
|
||||||
|
if (
|
||||||
|
realEstateTypeObject.hasGardenSize &&
|
||||||
|
gardenSizeMax != null &&
|
||||||
|
gardenSizeMin != null
|
||||||
|
) {
|
||||||
query.gardenSize = {
|
query.gardenSize = {
|
||||||
[Op.lte]: gardenSizeMax,
|
[Op.lte]: gardenSizeMax,
|
||||||
[Op.gte]: gardenSizeMin
|
[Op.gte]: gardenSizeMin
|
||||||
@@ -192,7 +202,11 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numberOfRoomsMin && numberOfRoomsMax) {
|
if (
|
||||||
|
realEstateTypeObject.hasNumberOfRoom &&
|
||||||
|
numberOfRoomsMin != null &&
|
||||||
|
numberOfRoomsMax != null
|
||||||
|
) {
|
||||||
query.numberOfRooms = {
|
query.numberOfRooms = {
|
||||||
[Op.lte]: numberOfRoomsMax,
|
[Op.lte]: numberOfRoomsMax,
|
||||||
[Op.gte]: numberOfRoomsMin
|
[Op.gte]: numberOfRoomsMin
|
||||||
@@ -208,7 +222,11 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numberOfFloorsMin && numberOfFloorsMax) {
|
if (
|
||||||
|
realEstateTypeObject.hasNumberOfFloors &&
|
||||||
|
numberOfFloorsMin != null &&
|
||||||
|
numberOfFloorsMax != null
|
||||||
|
) {
|
||||||
query.numberOfFloors = {
|
query.numberOfFloors = {
|
||||||
[Op.lte]: numberOfFloorsMax,
|
[Op.lte]: numberOfFloorsMax,
|
||||||
[Op.gte]: numberOfFloorsMin
|
[Op.gte]: numberOfFloorsMin
|
||||||
@@ -224,7 +242,11 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (floorMin && floorMax) {
|
if (
|
||||||
|
realEstateTypeObject.hasFloorProp &&
|
||||||
|
floorMin != null &&
|
||||||
|
floorMax != null
|
||||||
|
) {
|
||||||
query.floor = {
|
query.floor = {
|
||||||
[Op.lte]: floorMax,
|
[Op.lte]: floorMax,
|
||||||
[Op.gte]: floorMin
|
[Op.gte]: floorMin
|
||||||
@@ -239,8 +261,10 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
//Logic for balcony, newBuilding and elevator from users side
|
||||||
if (balcony) {
|
//If true is checked, then I want characteristic to be true but,
|
||||||
|
//if it is not checked, then I dont care - it can be null or false or true
|
||||||
|
if (realEstateTypeObject.hasBalconyProp && balcony === true) {
|
||||||
query.balcony = {
|
query.balcony = {
|
||||||
[Op.eq]: balcony
|
[Op.eq]: balcony
|
||||||
};
|
};
|
||||||
@@ -252,7 +276,7 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newBuilding) {
|
if (realEstateTypeObject.hasNewBuildingProp && newBuilding === true) {
|
||||||
query.newBuilding = {
|
query.newBuilding = {
|
||||||
[Op.eq]: newBuilding
|
[Op.eq]: newBuilding
|
||||||
};
|
};
|
||||||
@@ -264,7 +288,7 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elevator) {
|
if (realEstateTypeObject.hasElevatorProp && elevator === true) {
|
||||||
query.elevator = {
|
query.elevator = {
|
||||||
[Op.eq]: elevator
|
[Op.eq]: elevator
|
||||||
};
|
};
|
||||||
@@ -275,7 +299,8 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
//If user wants 'ANY' road type acces then it is not included in query -
|
||||||
|
//returns every road type and null values
|
||||||
if (accessRoadType !== "ANY") {
|
if (accessRoadType !== "ANY") {
|
||||||
query.accessRoadType = {
|
query.accessRoadType = {
|
||||||
[Op.eq]: accessRoadType
|
[Op.eq]: accessRoadType
|
||||||
|
|||||||
@@ -49,128 +49,383 @@ const findSearchRequestsForRealEstate = async realEstate => {
|
|||||||
|
|
||||||
const geoSearchQueryPart = sequelize.where(contains, true);
|
const geoSearchQueryPart = sequelize.where(contains, true);
|
||||||
|
|
||||||
//General query contains only attributes that are defined for every RealEstate - not null
|
|
||||||
const query = {
|
|
||||||
adType,
|
|
||||||
realEstateType,
|
|
||||||
subscribed: true,
|
|
||||||
[Op.and]: geoSearchQueryPart
|
|
||||||
};
|
|
||||||
//Needed for defining which attribute should exist or not
|
//Needed for defining which attribute should exist or not
|
||||||
const realEstateTypeObject = AD_CATEGORY[realEstateType];
|
const realEstateTypeObject = AD_CATEGORY[realEstateType];
|
||||||
//Needed to decide on including incomplete RealEstates data
|
|
||||||
|
// ?? Needed to decide on including incomplete RealEstates data
|
||||||
let checkForIncompleteWanted = false;
|
let checkForIncompleteWanted = false;
|
||||||
|
|
||||||
//Attributes are checked separately and included in query only if defined
|
//Attributes are checked separately to make different query parts
|
||||||
//Price and area should be defined for every property
|
|
||||||
|
|
||||||
if (price) {
|
//If price is null it will be excluded from query - it will show properties with null price values
|
||||||
query.priceMin = {
|
//User always defines price and area (sliders) - not null in search req
|
||||||
[Op.lte]: price
|
let priceQuery = {};
|
||||||
};
|
if (price != null) {
|
||||||
query.priceMax = {
|
priceQuery = {
|
||||||
[Op.gte]: price
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
priceMin: {
|
||||||
|
[Op.lte]: price
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
priceMax: {
|
||||||
|
[Op.gte]: price
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area) {
|
let areaQuery = {};
|
||||||
query.sizeMin = {
|
if (area != null) {
|
||||||
[Op.lte]: area
|
areaQuery = {
|
||||||
};
|
[Op.and]: [
|
||||||
query.sizeMax = {
|
{
|
||||||
[Op.gte]: area
|
sizeMin: {
|
||||||
|
[Op.lte]: area
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sizeMax: {
|
||||||
|
[Op.gte]: area
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
checkForIncompleteWanted = true;
|
checkForIncompleteWanted = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Other attributes can be defined or not depending on RealEstate type
|
//Other attributes can be defined or not depending on RealEstate type
|
||||||
if (gardenSize) {
|
//we check what to include in query based on real estate type object
|
||||||
query.gardenSizeMin = {
|
let gardenSizeQuery = {};
|
||||||
[Op.lte]: gardenSize
|
if (realEstateTypeObject.hasGardenSize) {
|
||||||
};
|
if (gardenSize != null) {
|
||||||
query.gardenSizeMax = {
|
gardenSizeQuery = {
|
||||||
[Op.gte]: gardenSize
|
[Op.and]: [
|
||||||
};
|
{
|
||||||
} else if (realEstateTypeObject.hasGardenSize) {
|
gardenSizeMin: {
|
||||||
checkForIncompleteWanted = true;
|
[Op.lte]: gardenSize
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
gardenSizeMax: {
|
||||||
|
[Op.gte]: gardenSize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
checkForIncompleteWanted = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numberOfRooms) {
|
let numberOfRoomsQuery = {};
|
||||||
query.numberOfRoomsMin = {
|
if (realEstateTypeObject.hasNumberOfRoom) {
|
||||||
[Op.lte]: numberOfRooms
|
if (numberOfRooms != null) {
|
||||||
};
|
//If real estate has defined number of rooms ex. 3 it returns req
|
||||||
query.numberOfRoomsMax = {
|
// that accepts 3 rooms or ones that don't have defined number - null
|
||||||
[Op.gte]: numberOfRooms
|
//Ex. they didnt choose advanced filters at all
|
||||||
};
|
numberOfRoomsQuery = {
|
||||||
} else if (realEstateTypeObject.hasNumberOfRoom) {
|
[Op.and]: [
|
||||||
checkForIncompleteWanted = true;
|
{
|
||||||
|
numberOfRoomsMin: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.lte]: numberOfRooms,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
numberOfRoomsMax: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.gte]: numberOfRooms,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
// If real estate dont have defined number of rooms ex. null
|
||||||
|
//It returns requests that didn't choose number of rooms - also null
|
||||||
|
//Or ones that picked some values but also picked to includeIncomplete ads
|
||||||
|
numberOfRoomsQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
numberOfRoomsMin: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
numberOfRoomsMax: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Same logic for number of Floors and floors
|
||||||
|
let numberOfFloorsQuery = {};
|
||||||
|
if (realEstateTypeObject.hasNumberOfFloors) {
|
||||||
|
if (numberOfFloors != null) {
|
||||||
|
numberOfFloorsQuery = {
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
numberOfFloorsMin: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.lte]: numberOfFloors,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
numberOfFloorsMax: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.gte]: numberOfFloors,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
numberOfFloorsQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
numberOfFloorsMin: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
numberOfFloorsMax: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let floorQuery = {};
|
||||||
|
if (realEstateTypeObject.hasFloorProp) {
|
||||||
|
if (floor != null) {
|
||||||
|
floorQuery = {
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
floorMin: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.lte]: floor,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
floorMax: {
|
||||||
|
[Op.or]: {
|
||||||
|
[Op.gte]: floor,
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
floorQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
floorMin: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
floorMax: {
|
||||||
|
[Op.is]: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (numberOfFloors) {
|
//Logic for balcony, newBuilding and elevator
|
||||||
query.numberOfFloorsMin = {
|
//If user dont check checkbox for ex. elevator it does not mean he only wants no elevator
|
||||||
[Op.lte]: numberOfFloors
|
//If real estate characteristic =true find all req, one that wants charachertistic or dont care - dont need query
|
||||||
};
|
//If real estate characteristic = false, find all req exept for ones that wants characteristic to be true
|
||||||
query.numberOfFloorsMax = {
|
//If real estate characteristic = null, dont know if true or false, find req that dont care or want char and want incomplete ads
|
||||||
[Op.gte]: numberOfFloors
|
let balconyQuery = {};
|
||||||
};
|
if (realEstateTypeObject.hasBalconyProp && balcony !== true) {
|
||||||
} else if (realEstateTypeObject.hasNumberOfFloors) {
|
if (balcony === false) {
|
||||||
checkForIncompleteWanted = true;
|
balconyQuery = {
|
||||||
|
balcony: {
|
||||||
|
[Op.ne]: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (balcony === null) {
|
||||||
|
balconyQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
balcony: {
|
||||||
|
[Op.ne]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
balcony: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
let newBuildingQuery = {};
|
||||||
if (floor) {
|
if (realEstateTypeObject.hasNewBuildingProp && newBuilding !== true) {
|
||||||
query.floorMin = {
|
if (newBuilding === false) {
|
||||||
[Op.lte]: floor
|
newBuildingQuery = {
|
||||||
};
|
newBuilding: {
|
||||||
query.floorMax = {
|
[Op.ne]: true
|
||||||
[Op.gte]: floor
|
}
|
||||||
};
|
};
|
||||||
} else if (realEstateTypeObject.hasFloorProp) {
|
} else if (newBuilding === null) {
|
||||||
checkForIncompleteWanted = true;
|
newBuildingQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
newBuilding: {
|
||||||
|
[Op.ne]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
newBuilding: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
let elevatorQuery = {};
|
||||||
|
if (realEstateTypeObject.hasElevatorProp && elevator !== true) {
|
||||||
|
if (elevator === false) {
|
||||||
|
elevatorQuery = {
|
||||||
|
elevator: {
|
||||||
|
[Op.ne]: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else if (elevator === null) {
|
||||||
|
elevatorQuery = {
|
||||||
|
[Op.or]: [
|
||||||
|
{
|
||||||
|
elevator: {
|
||||||
|
[Op.ne]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[Op.and]: [
|
||||||
|
{
|
||||||
|
elevator: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
includeIncompleteAds: {
|
||||||
|
[Op.eq]: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//General query consists of each individual query
|
||||||
|
const query = {
|
||||||
|
adType,
|
||||||
|
realEstateType,
|
||||||
|
subscribed: true,
|
||||||
|
[Op.and]: [
|
||||||
|
geoSearchQueryPart,
|
||||||
|
priceQuery,
|
||||||
|
areaQuery,
|
||||||
|
gardenSizeQuery,
|
||||||
|
numberOfRoomsQuery,
|
||||||
|
numberOfFloorsQuery,
|
||||||
|
floorQuery,
|
||||||
|
balconyQuery,
|
||||||
|
newBuildingQuery,
|
||||||
|
elevatorQuery
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
if (accessRoadType) {
|
//AccessRoadType is defined - should exists for each ad and estate type
|
||||||
|
if (accessRoadType != null) {
|
||||||
query.accessRoadType = {
|
query.accessRoadType = {
|
||||||
[Op.or]: {
|
[Op.or]: {
|
||||||
[Op.eq]: "ANY",
|
[Op.like]: "ANY",
|
||||||
[Op.eq]: accessRoadType
|
[Op.eq]: accessRoadType
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (realEstateTypeObject.hasAccesRoadType) {
|
} else {
|
||||||
checkForIncompleteWanted = true;
|
//Null values are returned for user request that wanted ANY acces road type
|
||||||
}
|
query.accessRoadType = {
|
||||||
|
[Op.eq]: "ANY"
|
||||||
if (balcony) {
|
|
||||||
query.balcony = {
|
|
||||||
[Op.eq]: balcony
|
|
||||||
};
|
};
|
||||||
} else if (realEstateTypeObject.hasBalconyProp) {
|
|
||||||
checkForIncompleteWanted = true;
|
|
||||||
}
|
}
|
||||||
|
//Tag to check if incomplete ads are accepted in query
|
||||||
if (newBuilding) {
|
|
||||||
query.newBuilding = {
|
|
||||||
[Op.eq]: newBuilding
|
|
||||||
};
|
|
||||||
} else if (realEstateTypeObject.hasNewBuildingProp) {
|
|
||||||
checkForIncompleteWanted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (elevator) {
|
|
||||||
query.elevator = {
|
|
||||||
[Op.eq]: elevator
|
|
||||||
};
|
|
||||||
} else if (realEstateTypeObject.hasElevatorProp) {
|
|
||||||
checkForIncompleteWanted = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//If one of the attributes that exists for property type is null
|
|
||||||
//we include in query to check if incomplete real estates are accepted
|
|
||||||
if (checkForIncompleteWanted) {
|
if (checkForIncompleteWanted) {
|
||||||
query.includeIncompleteAds = {
|
query.includeIncompleteAds = {
|
||||||
[Op.eq]: true
|
[Op.eq]: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return await db.SearchRequest.findAll({ where: query });
|
|
||||||
|
return await db.SearchRequest.findAll({
|
||||||
|
where: query
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|||||||
Reference in New Issue
Block a user