197 lines
4.5 KiB
JavaScript
197 lines
4.5 KiB
JavaScript
"use strict";
|
|
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;
|
|
}
|
|
};
|
|
|
|
const createSearchRequest = async (searchRequestFields = {}) => {
|
|
return await db.SearchRequest.create(searchRequestFields);
|
|
};
|
|
|
|
const findSearchRequestsForRealEstate = async realEstate => {
|
|
const {
|
|
price,
|
|
area,
|
|
adType,
|
|
realEstateType,
|
|
locationLat,
|
|
locationLong,
|
|
accessRoadType,
|
|
balcony,
|
|
newBuilding,
|
|
elevator,
|
|
gardenSize,
|
|
numberOfRooms,
|
|
numberOfFloors,
|
|
floor
|
|
} = realEstate;
|
|
|
|
if (!locationLat || !locationLong) {
|
|
return [];
|
|
}
|
|
|
|
const stGeometry = sequelize.fn(
|
|
"ST_GEOMFROMTEXT",
|
|
`POINT (${locationLong} ${locationLat})`,
|
|
4326
|
|
);
|
|
const areaToSearchColumn = sequelize.col("areaToSearch");
|
|
const contains = sequelize.fn("ST_Contains", areaToSearchColumn, stGeometry);
|
|
|
|
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 - not null
|
|
|
|
//Price and area should be defined for every property
|
|
if (price != null) {
|
|
query.priceMin = {
|
|
[Op.lte]: price
|
|
};
|
|
query.priceMax = {
|
|
[Op.gte]: price
|
|
};
|
|
}
|
|
|
|
if (area != null) {
|
|
query.sizeMin = {
|
|
[Op.lte]: area
|
|
};
|
|
query.sizeMax = {
|
|
[Op.gte]: area
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
//Other attributes can be defined or not depending on RealEstate type
|
|
//we check what to include in query based on real estate type object
|
|
if (realEstateTypeObject.hasGardenSize) {
|
|
if (gardenSize != null) {
|
|
query.gardenSizeMin = {
|
|
[Op.lte]: gardenSize
|
|
};
|
|
query.gardenSizeMax = {
|
|
[Op.gte]: gardenSize
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
if (realEstateTypeObject.hasNumberOfRoom) {
|
|
if (numberOfRooms != null) {
|
|
query.numberOfRoomsMin = {
|
|
[Op.lte]: numberOfRooms
|
|
};
|
|
query.numberOfRoomsMax = {
|
|
[Op.gte]: numberOfRooms
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
if (realEstateTypeObject.hasNumberOfFloors) {
|
|
if (numberOfFloors != null) {
|
|
query.numberOfFloorsMin = {
|
|
[Op.lte]: numberOfFloors
|
|
};
|
|
query.numberOfFloorsMax = {
|
|
[Op.gte]: numberOfFloors
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
if (realEstateTypeObject.hasFloorProp) {
|
|
if (floor != null) {
|
|
query.floorMin = {
|
|
[Op.lte]: floor
|
|
};
|
|
query.floorMax = {
|
|
[Op.gte]: floor
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
//AccessRoadType is defined - should exits for each ad and estate type
|
|
if (accessRoadType != null) {
|
|
query.accessRoadType = {
|
|
[Op.or]: {
|
|
[Op.eq]: "ANY",
|
|
[Op.eq]: accessRoadType
|
|
}
|
|
};
|
|
} else if (realEstateTypeObject.hasAccesRoadType) {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
|
|
if (realEstateTypeObject.hasBalconyProp) {
|
|
if (balcony != null) {
|
|
query.balcony = {
|
|
[Op.eq]: balcony
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
if (realEstateTypeObject.hasNewBuildingProp) {
|
|
if (newBuilding != null) {
|
|
query.newBuilding = {
|
|
[Op.eq]: newBuilding
|
|
};
|
|
} else {
|
|
checkForIncompleteWanted = true;
|
|
}
|
|
}
|
|
|
|
if (realEstateTypeObject.hasElevatorProp) {
|
|
if (elevator != null) {
|
|
query.elevator = {
|
|
[Op.eq]: elevator
|
|
};
|
|
} else {
|
|
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 });
|
|
};
|
|
|
|
module.exports = {
|
|
getSearchRequest,
|
|
createSearchRequest,
|
|
findSearchRequestsForRealEstate
|
|
};
|