Merge branch 'results-link' of gitlab.com:saburly/marketalarm/web into no-all-results-email

This commit is contained in:
Naida Vatric
2020-01-07 01:01:57 +01:00
16 changed files with 1128 additions and 236 deletions

View File

@@ -2,7 +2,6 @@
const db = require("../../models/index");
const sequelize = require("sequelize");
const Op = sequelize.Op;
const bulkUpsertRealEstates = async realEstateData => {
try {
const fieldsToUpdateIfDuplicate = [
@@ -87,7 +86,20 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
sizeMax,
adType,
realEstateType,
areaToSearch
areaToSearch,
gardenSizeMin,
gardenSizeMax,
numberOfRoomsMin,
numberOfRoomsMax,
numberOfFloorsMin,
numberOfFloorsMax,
floorMin,
floorMax,
includeIncompleteAds,
balcony,
elevator,
newBuilding,
accessRoadType
} = searchRequest;
const longitudeColumn = sequelize.col("locationLong");
@@ -116,12 +128,20 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
const geoSearchQueryPart = sequelize.where(contains, true);
//General queries contain only attributes that are defined for every searchreq
//Query for case of complete ads
const query = {
adType,
realEstateType,
price: {
[Op.lte]: priceMax,
[Op.gte]: priceMin
[Op.or]: {
[Op.and]: {
[Op.lte]: priceMax,
[Op.gte]: priceMin
},
[Op.is]: null
}
},
area: {
[Op.lte]: sizeMax,
@@ -130,10 +150,148 @@ const findRealEstatesForSearchRequest = async (searchRequest, maxResults) => {
[Op.and]: geoSearchQueryPart
};
//Query for case of incomplete ads
const queryIncludeIncomplete = {
adType,
realEstateType,
price: {
[Op.or]: {
[Op.and]: {
[Op.lte]: priceMax,
[Op.gte]: priceMin
},
[Op.is]: null
}
},
area: {
[Op.or]: {
[Op.and]: {
[Op.lte]: sizeMax,
[Op.gte]: sizeMin
},
[Op.is]: null
}
},
[Op.and]: geoSearchQueryPart
};
//Every other attribute is checked separately and included in query only if it is defined
if (gardenSizeMax && gardenSizeMin) {
query.gardenSize = {
[Op.lte]: gardenSizeMax,
[Op.gte]: gardenSizeMin
};
queryIncludeIncomplete.gardenSize = {
[Op.or]: {
[Op.and]: {
[Op.lte]: gardenSizeMax,
[Op.gte]: gardenSizeMin
},
[Op.is]: null
}
};
}
if (numberOfRoomsMin && numberOfRoomsMax) {
query.numberOfRooms = {
[Op.lte]: numberOfRoomsMax,
[Op.gte]: numberOfRoomsMin
};
queryIncludeIncomplete.numberOfRooms = {
[Op.or]: {
[Op.and]: {
[Op.lte]: numberOfRoomsMax,
[Op.gte]: numberOfRoomsMin
},
[Op.is]: null
}
};
}
if (numberOfFloorsMin && numberOfFloorsMax) {
query.numberOfFloors = {
[Op.lte]: numberOfFloorsMax,
[Op.gte]: numberOfFloorsMin
};
queryIncludeIncomplete.numberOfFloors = {
[Op.or]: {
[Op.and]: {
[Op.lte]: numberOfFloorsMax,
[Op.gte]: numberOfFloorsMin
},
[Op.is]: null
}
};
}
if (floorMin && floorMax) {
query.floor = {
[Op.lte]: floorMax,
[Op.gte]: floorMin
};
queryIncludeIncomplete.floor = {
[Op.or]: {
[Op.and]: {
[Op.lte]: floorMax,
[Op.gte]: floorMin
},
[Op.is]: null
}
};
}
if (balcony) {
query.balcony = {
[Op.eq]: balcony
};
queryIncludeIncomplete.balcony = {
[Op.or]: {
[Op.eq]: balcony,
[Op.is]: null
}
};
}
if (newBuilding) {
query.newBuilding = {
[Op.eq]: newBuilding
};
queryIncludeIncomplete.newBuilding = {
[Op.or]: {
[Op.eq]: newBuilding,
[Op.is]: null
}
};
}
if (elevator) {
query.elevator = {
[Op.eq]: elevator
};
queryIncludeIncomplete.elevator = {
[Op.or]: {
[Op.eq]: elevator,
[Op.is]: null
}
};
}
if (accessRoadType !== "ANY") {
query.accessRoadType = {
[Op.eq]: accessRoadType
};
queryIncludeIncomplete.accessRoadType = {
[Op.or]: {
[Op.eq]: accessRoadType,
[Op.is]: null
}
};
}
const order = [["updatedAt", "desc"]];
return await db.RealEstate.findAll({
where: query,
return db.RealEstate.findAll({
where: includeIncompleteAds ? queryIncludeIncomplete : query,
limit: maxResults,
order
});

View File

@@ -2,11 +2,13 @@
const db = require("../../models/index");
const sequelize = require("sequelize");
const Op = sequelize.Op;
const { AD_CATEGORY } = require("../../common/enums");
const getSearchRequest = async searchRequestId => {
try {
return await db.SearchRequest.findByPk(searchRequestId);
} catch (error) {
console.log("searchrequest.js", error);
return null;
}
};
@@ -22,7 +24,15 @@ const findSearchRequestsForRealEstate = async realEstate => {
adType,
realEstateType,
locationLat,
locationLong
locationLong,
accessRoadType,
balcony,
newBuilding,
elevator,
gardenSize,
numberOfRooms,
numberOfFloors,
floor
} = realEstate;
if (!locationLat || !locationLong) {
@@ -39,12 +49,20 @@ const findSearchRequestsForRealEstate = async realEstate => {
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
const realEstateTypeObject = AD_CATEGORY[realEstateType];
//Needed to decide on including incomplete RealEstates data
let checkForIncompleteWanted = false;
//Attributes are checked separately and included in query only if defined
//Price and area should be defined for every property
if (price) {
query.priceMin = {
@@ -62,8 +80,96 @@ const findSearchRequestsForRealEstate = async realEstate => {
query.sizeMax = {
[Op.gte]: area
};
} else {
checkForIncompleteWanted = true;
}
//Other attributes can be defined or not depending on RealEstate type
if (gardenSize) {
query.gardenSizeMin = {
[Op.lte]: gardenSize
};
query.gardenSizeMax = {
[Op.gte]: gardenSize
};
} else if (realEstateTypeObject.hasGardenSize) {
checkForIncompleteWanted = true;
}
if (numberOfRooms) {
query.numberOfRoomsMin = {
[Op.lte]: numberOfRooms
};
query.numberOfRoomsMax = {
[Op.gte]: numberOfRooms
};
} else if (realEstateTypeObject.hasNumberOfRoom) {
checkForIncompleteWanted = true;
}
if (numberOfFloors) {
query.numberOfFloorsMin = {
[Op.lte]: numberOfFloors
};
query.numberOfFloorsMax = {
[Op.gte]: numberOfFloors
};
} else if (realEstateTypeObject.hasNumberOfFloors) {
checkForIncompleteWanted = true;
}
if (floor) {
query.floorMin = {
[Op.lte]: floor
};
query.floorMax = {
[Op.gte]: floor
};
} else if (realEstateTypeObject.hasFloorProp) {
checkForIncompleteWanted = true;
}
if (accessRoadType) {
query.accessRoadType = {
[Op.or]: {
[Op.eq]: "ANY",
[Op.eq]: accessRoadType
}
};
} else if (realEstateTypeObject.hasAccesRoadType) {
checkForIncompleteWanted = true;
}
if (balcony) {
query.balcony = {
[Op.eq]: balcony
};
} else if (realEstateTypeObject.hasBalconyProp) {
checkForIncompleteWanted = true;
}
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) {
query.includeIncompleteAds = {
[Op.eq]: true
};
}
return await db.SearchRequest.findAll({ where: query });
};