diff --git a/app/controllers/gardenSizes.js b/app/controllers/gardenSizes.js
index 83a8fe1..4fb5c8e 100644
--- a/app/controllers/gardenSizes.js
+++ b/app/controllers/gardenSizes.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const { getRealEstateTypeEnum } = require("../helpers/enums");
const getGardenSize = (req, res) => {
@@ -23,16 +23,20 @@ const getGardenSize = (req, res) => {
};
const postGardenSize = async (req, res) => {
- const request = await currentRERequest(req);
+ const searchRequest = await currentSearchRequest(req);
const nextStepPage = req.query.nextStep || "cijena";
- const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
+ const nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
- const realEstateType = getRealEstateTypeEnum(request.realEstateType);
+ const realEstateType = getRealEstateTypeEnum(searchRequest.realEstateType);
if (realEstateType && realEstateType.hasGardenSize) {
- request.gardenSizeMin = req.body.from;
- request.gardenSizeMax = req.body.to;
- await request.save();
+ const gardenSizeMin = req.body.from || 0;
+ const gardenSizeMax = req.body.to || 0;
+ //TODO: Validate input
+
+ searchRequest.gardenSizeMin = gardenSizeMin;
+ searchRequest.gardenSizeMax = gardenSizeMax;
+ await searchRequest.save();
}
res.redirect(nextStepUrl);
diff --git a/app/controllers/location.js b/app/controllers/location.js
index 185bee9..02076db 100644
--- a/app/controllers/location.js
+++ b/app/controllers/location.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const getLocation = async (req, res) => {
const title = "U kojem naselju tražite nekretninu?";
@@ -11,21 +11,22 @@ const getLocation = async (req, res) => {
};
const postLocation = async (req, res) => {
- let request = await currentRERequest(req);
+ let searchRequest = await currentSearchRequest(req);
const northWest = [req.body.west, req.body.north];
const northEast = [req.body.east, req.body.north];
const southEast = [req.body.east, req.body.south];
const southWest = [req.body.west, req.body.south];
- request.locationInput =
+ const locationInputValue =
req.body.locationInput && req.body.locationInput.length > 0
? req.body.locationInput
: null;
- request.boundingBox = {
+ searchRequest.areaToSearch = {
type: "Polygon",
- coordinates: [[northWest, northEast, southEast, southWest, northWest]]
+ coordinates: [[northWest, northEast, southEast, southWest, northWest]],
+ crs: { type: "name", properties: { name: "EPSG:4326" } }
};
let locationInputData;
@@ -37,10 +38,10 @@ const postLocation = async (req, res) => {
}
}
- await request.save();
+ await searchRequest.save();
const nextStepPage = req.query.nextStep || "povrsina";
- const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
+ const nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
res.redirect(nextStepUrl);
};
diff --git a/app/controllers/prices.js b/app/controllers/prices.js
index 2ae5720..91ae0ae 100644
--- a/app/controllers/prices.js
+++ b/app/controllers/prices.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const getPrice = (req, res) => {
const title = "Koja Vam okvirna cijena odgovara ?";
@@ -22,14 +22,17 @@ const getPrice = (req, res) => {
};
const postPrice = async (req, res) => {
- const request = await currentRERequest(req);
+ const searchRequest = await currentSearchRequest(req);
const nextStepPage = req.query.nextStep || "pregled";
- const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
+ const nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
+ const priceMin = req.body.from || 0;
+ const priceMax = req.body.to || 0;
+ //TODO: price validation
- request.priceMin = req.body.from;
- request.priceMax = req.body.to;
- await request.save();
+ searchRequest.priceMin = priceMin;
+ searchRequest.priceMax = priceMax;
+ await searchRequest.save();
res.redirect(nextStepUrl);
};
diff --git a/app/controllers/queryReview.js b/app/controllers/queryReview.js
index e0ec70b..ac4bd1f 100644
--- a/app/controllers/queryReview.js
+++ b/app/controllers/queryReview.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const {
realEstateTypes,
getEnumTypeTitle,
@@ -7,23 +7,23 @@ const {
const getQueryReview = async (req, res) => {
const title = "Da li je ovo to što ste tražili ?";
- const request = await currentRERequest(req);
+ const searchRequest = await currentSearchRequest(req);
const nextStep = req.query.nextStep;
- if (!request || !request.dataValues) {
+ if (!searchRequest || !searchRequest.dataValues) {
return null;
}
const {
+ id,
realEstateType,
sizeMin,
sizeMax,
gardenSizeMin,
gardenSizeMax,
priceMin,
- priceMax,
- locationInput
- } = request.dataValues;
+ priceMax
+ } = searchRequest.dataValues;
const realEstateTypeObject = getRealEstateTypeEnum(realEstateType);
const enableGardenSizeEdit = realEstateTypeObject
@@ -32,58 +32,55 @@ const getQueryReview = async (req, res) => {
const realEstateTypeTitle = realEstateType
? getEnumTypeTitle(realEstateTypes, realEstateType)
- : null;
+ : "-";
- const locationTitle = locationInput ? locationInput : "-";
+ const locationTitle = "Location description - PLACEHOLDER";
+ const sizeTitle = sizeMin && sizeMax ? `${sizeMin} - ${sizeMax} m2` : "-";
+ const gardenSizeTitle =
+ enableGardenSizeEdit && gardenSizeMin && gardenSizeMax
+ ? `${gardenSizeMin} - ${gardenSizeMax} m2`
+ : "-";
+ const priceTitle =
+ priceMin && priceMax ? `${priceMin} - ${priceMax} KM` : "-";
- const sizeTitle = sizeMin ? sizeMin + "-" + sizeMax + " m2" : null;
- const gardenSizeTitle = gardenSizeMin
- ? gardenSizeMin + "-" + gardenSizeMax + " m2"
- : null;
- const priceTitle = priceMin ? priceMin + "-" + priceMax + " KM" : null;
-
- const uniqueId = request.dataValues.uniqueId
- ? request.dataValues.uniqueId
- : "";
-
- const queryData = [
+ const queryReviewData = [
{
id: "realEstateType",
title: realEstateTypeTitle,
- url: `/vrstanekretnine/${uniqueId}?nextStep=pregled`
+ url: `/vrstanekretnine/${id}?nextStep=pregled`
},
{
id: "location",
title: locationTitle,
- url: `/lokacija/${uniqueId}?nextStep=pregled`
+ url: `/lokacija/${id}?nextStep=pregled`
},
{
id: "size",
title: sizeTitle,
- url: `/povrsina/${uniqueId}?nextStep=pregled`
+ url: `/povrsina/${id}?nextStep=pregled`
},
{
id: "gardenSize",
title: gardenSizeTitle,
- url: enableGardenSizeEdit ? `/okucnica/${uniqueId}?nextStep=pregled` : ""
+ url: enableGardenSizeEdit ? `/okucnica/${id}?nextStep=pregled` : ""
},
{
id: "price",
title: priceTitle,
- url: `/cijena/${uniqueId}?nextStep=pregled`
+ url: `/cijena/${id}?nextStep=pregled`
}
];
res.render("queryReview", {
nextStep,
- queryData,
+ queryReviewData,
title
});
};
const postQueryReview = async (req, res) => {
- const request = await currentRERequest(req);
- const nextStep = req.query.nextStep || `/posalji/${request.uniqueId}`;
+ const searchRequest = await currentSearchRequest(req);
+ const nextStep = req.query.nextStep || `/posalji/${searchRequest.id}`;
res.redirect(nextStep);
};
diff --git a/app/controllers/querySubmit.js b/app/controllers/querySubmit.js
index de48eba..1768575 100644
--- a/app/controllers/querySubmit.js
+++ b/app/controllers/querySubmit.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const { isValidEmail } = require("../helpers/email");
const { sendTemplatedEmail } = require("../helpers/awsEmail");
@@ -15,21 +15,13 @@ const getQuerySubmit = async (req, res) => {
};
const postQuerySubmit = async (req, res) => {
- const request = await currentRERequest(req);
+ const searchRequest = await currentSearchRequest(req);
const nextStep = req.query.nextStep || "/ponovo";
const emailInput = req.body.email;
const emailConfirmInput = req.body.confirm;
let error = "Greška ! Unesite validan email";
- if (!isValidEmail(emailInput) || !isValidEmail(emailConfirmInput)) {
- error = "Greška ! Unesite validan email";
- res.render("querySubmit", {
- error
- });
- return;
- }
-
if (emailInput !== emailConfirmInput) {
error = "Greška ! Unešeni emailovi nisu isti";
res.render("querySubmit", {
@@ -38,10 +30,19 @@ const postQuerySubmit = async (req, res) => {
return;
}
- request.email = req.body.email;
- request.subscribed = true;
- await request.save();
- sendTemplatedEmail(req.body.email, request);
+ if (!isValidEmail(emailInput)) {
+ error = "Greška ! Unesite validan email";
+ res.render("querySubmit", {
+ error
+ });
+ return;
+ }
+
+ searchRequest.email = emailInput;
+ searchRequest.subscribed = true;
+ await searchRequest.save();
+
+ sendTemplatedEmail(emailInput, searchRequest);
res.redirect(nextStep);
};
diff --git a/app/controllers/realEstateTypes.js b/app/controllers/realEstateTypes.js
index 853b693..7b84247 100644
--- a/app/controllers/realEstateTypes.js
+++ b/app/controllers/realEstateTypes.js
@@ -1,6 +1,6 @@
-const db = require("../models/index");
+const { currentSearchRequest } = require("../helpers/url");
+const { createSearchRequest } = require("../helpers/db/searchRequest");
-const { currentRERequest } = require("../helpers/url");
const { realEstateTypes, getRealEstateTypeEnum } = require("../helpers/enums");
const getRealEstateTypes = (req, res) => {
@@ -9,31 +9,32 @@ const getRealEstateTypes = (req, res) => {
};
const postRealEstateTypes = async (req, res) => {
- const request = await currentRERequest(req);
+ const searchRequest = await currentSearchRequest(req);
+
+ //TODO: check if selected real estate type is valid
+ const selectedRealEstateType = req.body.realEstateType || null;
const nextStepPage = req.query.nextStep || "lokacija";
- if (request && request.uniqueId) {
- const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
- request.realEstateType = req.body.realestatetype;
- if (!getRealEstateTypeEnum(request.realEstateType).hasGardenSize) {
- request.gardenSize = null;
- }
- await request.save();
+ let nextStepUrl = "";
+ if (searchRequest && searchRequest.id) {
+ nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
+ searchRequest.realEstateType = selectedRealEstateType;
- res.redirect(nextStepUrl);
+ await searchRequest.save();
} else {
- db.RealEstateRequest.create({
- realEstateType: req.body.realestatetype
- })
- .then(result => {
- const nextStepUrl = `/${nextStepPage}/${result.uniqueId}`;
- res.redirect(nextStepUrl);
- })
- .catch(e => {
- res.send(e);
+ try {
+ const newSearchRequest = await createSearchRequest({
+ realEstateType: selectedRealEstateType
});
+
+ nextStepUrl = `/${nextStepPage}/${newSearchRequest.id}`;
+ } catch (error) {
+ console.log(error);
+ nextStepUrl = `/`;
+ }
}
+ res.redirect(nextStepUrl);
};
module.exports = {
diff --git a/app/controllers/sizes.js b/app/controllers/sizes.js
index b3898c4..8c2c843 100644
--- a/app/controllers/sizes.js
+++ b/app/controllers/sizes.js
@@ -1,4 +1,4 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const { sizes, getRealEstateTypeEnum } = require("../helpers/enums");
const getSize = (req, res) => {
@@ -22,17 +22,21 @@ const getSize = (req, res) => {
};
const postSize = async (req, res) => {
- const request = await currentRERequest(req);
-
- const realEstateType = getRealEstateTypeEnum(request.realEstateType);
+ const searchRequest = await currentSearchRequest(req);
+ const realEstateType = getRealEstateTypeEnum(searchRequest.realEstateType);
+ const sizeMin = req.body.from || 0;
+ const sizeMax = req.body.to || 0;
+ //TODO: Validation, check if real estate type is valid, ...
const nextStep =
realEstateType && realEstateType.hasGardenSize ? "okucnica" : "cijena";
+
const nextStepPage = req.query.nextStep || nextStep;
- const nextStepUrl = `/${nextStepPage}/${request.uniqueId}`;
- request.sizeMin = req.body.from;
- request.sizeMax = req.body.to;
- await request.save();
+ const nextStepUrl = `/${nextStepPage}/${searchRequest.id}`;
+
+ searchRequest.sizeMin = sizeMin;
+ searchRequest.sizeMax = sizeMax;
+ await searchRequest.save();
res.redirect(nextStepUrl);
};
diff --git a/app/controllers/unsubscribe.js b/app/controllers/unsubscribe.js
index 0199fa7..a6c400f 100644
--- a/app/controllers/unsubscribe.js
+++ b/app/controllers/unsubscribe.js
@@ -1,10 +1,10 @@
-const { currentRERequest } = require("../helpers/url");
+const { currentSearchRequest } = require("../helpers/url");
const getUnsubscribe = async (req, res) => {
const title = "Uspješno ste se odjavili";
- const request = await currentRERequest(req);
- request.subscribed = false;
- await request.save();
+ const searchRequest = await currentSearchRequest(req);
+ searchRequest.subscribed = false;
+ await searchRequest.save();
res.render("unsubscribe", { nextStep: "/vrstanekretnine", title });
};
diff --git a/app/helpers/awsEmail.js b/app/helpers/awsEmail.js
index 4dbb22a..bb1c80c 100644
--- a/app/helpers/awsEmail.js
+++ b/app/helpers/awsEmail.js
@@ -69,8 +69,8 @@ const getGreetingsEmailHTML = realEstateRequest => {
- Ako želis prestati dobijati obavještenja za ovu pretragu klikni ${APP_URL}/odjava/${realEstateRequest.uniqueId}
- Ako želiš promijeniti uslove pretrage klikni ${APP_URL}/pregled/${realEstateRequest.uniqueId}
+ Ako želis prestati dobijati obavještenja za ovu pretragu klikni ${APP_URL}/odjava/${realEstateRequest.id}
+ Ako želiš promijeniti uslove pretrage klikni ${APP_URL}/pregled/${realEstateRequest.id}
Tvoj,
Javimi tim.
`;
@@ -91,9 +91,9 @@ const getGreetingsEmailTextVersion = realEstateRequest => {
${gardenSize}\n
Cijena od ${realEstateRequest.priceMin} do ${realEstateRequest.priceMax} \n
Ako želis prestati dobijati obavještenja za ovu pretragu klikni
- ${APP_URL}/odjava/${realEstateRequest.uniqueId}\n
+ ${APP_URL}/odjava/${realEstateRequest.id}\n
Ako želiš promijeniti uslove pretrage klikni
- ${APP_URL}/odpregled/${realEstateRequest.uniqueId}\n
+ ${APP_URL}/odpregled/${realEstateRequest.id}\n
Tvoj,\n Javimi tim`;
};
@@ -109,7 +109,7 @@ const sendBulkEmail = async marketAlerts => {
const RERequestUuidsArray = Array.from(new Set(RERequestUuidsMaped));
const RERequestUuids = RERequestUuidsArray.map(marketAlert => {
- return { uniqueId: marketAlert };
+ return { id: marketAlert };
});
const RERequests = await allRERequestByUiid(RERequestUuids);
@@ -117,13 +117,11 @@ const sendBulkEmail = async marketAlerts => {
RERequests.forEach(RERequest => {
var formatedRequest = {};
- formatedRequest[RERequest.uniqueId] = requestDataValues[
- RERequest.uniqueId
- ] = {
+ formatedRequest[RERequest.id] = requestDataValues[RERequest.id] = {
realEstateType: RERequest.realEstateType,
region: RERequest.region,
municipality: RERequest.municipality,
- requestUrl: `${APP_URL}/nekretnine/${RERequest.uniqueId}`
+ requestUrl: `${APP_URL}/nekretnine/${RERequest.id}`
};
});
diff --git a/app/helpers/db/searchRequest.js b/app/helpers/db/searchRequest.js
new file mode 100644
index 0000000..e4bac0c
--- /dev/null
+++ b/app/helpers/db/searchRequest.js
@@ -0,0 +1,15 @@
+"use strict";
+const db = require("../../models/index");
+
+const getSearchRequest = async searchRequestId => {
+ return await db.SearchRequest.findByPk(searchRequestId);
+};
+
+const createSearchRequest = async (searchRequestFields = {}) => {
+ return await db.SearchRequest.create(searchRequestFields);
+};
+
+module.exports = {
+ getSearchRequest,
+ createSearchRequest
+};
diff --git a/app/helpers/url.js b/app/helpers/url.js
index 10512ff..9ed771f 100644
--- a/app/helpers/url.js
+++ b/app/helpers/url.js
@@ -1,11 +1,12 @@
-const db = require("../models/index");
+const { getSearchRequest } = require("./db/searchRequest");
-const currentRERequest = async req => {
- const uniqueId = req.params["request_id"];
- if (!uniqueId) return null;
+const currentSearchRequest = async req => {
+ const searchRequestId =
+ req && req.params ? req.params["searchRequestId"] : null;
+ if (!searchRequestId) return null;
- return await db.RealEstateRequest.findOne({ where: { uniqueId } });
+ return await getSearchRequest(searchRequestId);
};
module.exports = {
- currentRERequest
+ currentSearchRequest
};
diff --git a/app/migrations/20190912191829-add-realEstates-table.js b/app/migrations/20190912191829-add-realEstates-table.js
new file mode 100644
index 0000000..e6b45b3
--- /dev/null
+++ b/app/migrations/20190912191829-add-realEstates-table.js
@@ -0,0 +1,72 @@
+"use strict";
+
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ const tableFields = {
+ id: {
+ type: Sequelize.BIGINT,
+ autoIncrement: true,
+ allowNull: false,
+ primaryKey: true
+ },
+ url: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ agencyObjectId: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ originAgencyName: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ realEstateType: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ adType: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ price: Sequelize.REAL,
+ area: Sequelize.REAL,
+ gardenSize: Sequelize.REAL,
+ streetNumber: Sequelize.INTEGER,
+ streetName: Sequelize.TEXT,
+ locality: Sequelize.TEXT,
+ municipality: Sequelize.TEXT,
+ city: Sequelize.TEXT,
+ region: Sequelize.TEXT,
+ entity: Sequelize.TEXT,
+ country: Sequelize.TEXT,
+ locationLat: Sequelize.REAL,
+ locationLong: Sequelize.REAL,
+ lastTimeCrawled: {
+ type: Sequelize.DATE,
+ allowNull: false
+ },
+ deleted: {
+ type: Sequelize.BOOLEAN,
+ allowNull: false
+ },
+ sold: {
+ type: Sequelize.BOOLEAN,
+ allowNull: false
+ },
+ createdAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ },
+ updatedAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ }
+ };
+ return queryInterface.createTable("RealEstates", tableFields);
+ },
+
+ down: queryInterface => {
+ return queryInterface.dropTable("RealEstates", {});
+ }
+};
diff --git a/app/migrations/20190912215313-add-searchRequests-table.js b/app/migrations/20190912215313-add-searchRequests-table.js
new file mode 100644
index 0000000..506cb1d
--- /dev/null
+++ b/app/migrations/20190912215313-add-searchRequests-table.js
@@ -0,0 +1,79 @@
+"use strict";
+
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ const tableFields = {
+ id: {
+ type: Sequelize.UUID,
+ defaultValue: Sequelize.UUIDV4,
+ allowNull: false,
+ primaryKey: true
+ },
+ areaToSearch: {
+ type: Sequelize.GEOMETRY("POLYGON", 4326),
+ allowNull: false,
+ defaultValue: {
+ type: "Polygon",
+ coordinates: [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]],
+ crs: { type: "name", properties: { name: "EPSG:4326" } }
+ }
+ },
+ realEstateType: {
+ type: Sequelize.TEXT,
+ allowNull: false
+ },
+ adType: {
+ type: Sequelize.TEXT,
+ allowNull: false,
+ defaultValue: "sell"
+ },
+ email: Sequelize.TEXT,
+ locality: Sequelize.TEXT,
+ municipality: Sequelize.TEXT,
+ city: Sequelize.TEXT,
+ region: Sequelize.TEXT,
+ entity: Sequelize.TEXT,
+ country: Sequelize.TEXT,
+ sizeMin: {
+ type: Sequelize.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ sizeMax: {
+ type: Sequelize.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ priceMin: {
+ type: Sequelize.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ priceMax: {
+ type: Sequelize.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ gardenSizeMin: Sequelize.INTEGER,
+ gardenSizeMax: Sequelize.INTEGER,
+ subscribed: {
+ type: Sequelize.BOOLEAN,
+ allowNull: false,
+ defaultValue: false
+ },
+ createdAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ },
+ updatedAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ }
+ };
+ return queryInterface.createTable("SearchRequests", tableFields);
+ },
+
+ down: queryInterface => {
+ return queryInterface.dropTable("SearchRequests", {});
+ }
+};
diff --git a/app/migrations/20190912215556-add-searchRequestMatches-table.js b/app/migrations/20190912215556-add-searchRequestMatches-table.js
new file mode 100644
index 0000000..c3e05ce
--- /dev/null
+++ b/app/migrations/20190912215556-add-searchRequestMatches-table.js
@@ -0,0 +1,53 @@
+"use strict";
+
+module.exports = {
+ up: (queryInterface, Sequelize) => {
+ const tableFields = {
+ id: {
+ type: Sequelize.BIGINT,
+ autoIncrement: true,
+ allowNull: false
+ },
+ searchRequestId: {
+ type: Sequelize.UUID,
+ allowNull: false,
+ primaryKey: true,
+ references: {
+ model: "SearchRequests",
+ key: "id"
+ },
+ onUpdate: "CASCADE",
+ onDelete: "SET NULL"
+ },
+ realEstateId: {
+ type: Sequelize.BIGINT,
+ allowNull: false,
+ primaryKey: true,
+ references: {
+ model: "RealEstates",
+ key: "id"
+ },
+ onUpdate: "CASCADE",
+ onDelete: "SET NULL"
+ },
+ notified: {
+ type: Sequelize.BOOLEAN,
+ allowNull: false,
+ defaultValue: false
+ },
+ createdAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ },
+ updatedAt: {
+ type: Sequelize.DATE,
+ defaultValue: Sequelize.literal("NOW()")
+ }
+ };
+ return queryInterface.createTable("SearchRequestMatches", tableFields);
+ },
+
+ down: queryInterface => {
+ return queryInterface.dropTable("SearchRequestMatches", {});
+ }
+};
diff --git a/app/models/realEstate.js b/app/models/realEstate.js
new file mode 100644
index 0000000..66b7a92
--- /dev/null
+++ b/app/models/realEstate.js
@@ -0,0 +1,65 @@
+"use strict";
+
+module.exports = (sequelize, DataTypes) => {
+ const RealEstate = sequelize.define("RealEstate", {
+ id: {
+ type: DataTypes.BIGINT,
+ autoIncrement: true,
+ allowNull: false,
+ primaryKey: true
+ },
+ url: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ agencyObjectId: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ originAgencyName: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ realEstateType: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ adType: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ price: DataTypes.REAL,
+ area: DataTypes.REAL,
+ gardenSize: DataTypes.REAL,
+ streetNumber: DataTypes.INTEGER,
+ streetName: DataTypes.TEXT,
+ locality: DataTypes.TEXT,
+ municipality: DataTypes.TEXT,
+ city: DataTypes.TEXT,
+ region: DataTypes.TEXT,
+ entity: DataTypes.TEXT,
+ country: DataTypes.TEXT,
+ locationLat: DataTypes.REAL,
+ locationLong: DataTypes.REAL,
+ lastTimeCrawled: {
+ type: DataTypes.DATE,
+ allowNull: false
+ },
+ deleted: {
+ type: DataTypes.BOOLEAN,
+ allowNull: false
+ },
+ sold: {
+ type: DataTypes.BOOLEAN,
+ allowNull: false
+ }
+ });
+
+ RealEstate.associate = models => {
+ RealEstate.belongsToMany(models.SearchRequestMatch, {
+ through: "SearchRequestMatch"
+ });
+ };
+
+ return RealEstate;
+};
diff --git a/app/models/searchRequest.js b/app/models/searchRequest.js
new file mode 100644
index 0000000..5e16c9e
--- /dev/null
+++ b/app/models/searchRequest.js
@@ -0,0 +1,72 @@
+"use strict";
+
+module.exports = (sequelize, DataTypes) => {
+ const SearchRequest = sequelize.define("SearchRequest", {
+ id: {
+ type: DataTypes.UUID,
+ defaultValue: DataTypes.UUIDV4,
+ allowNull: false,
+ primaryKey: true
+ },
+ areaToSearch: {
+ type: DataTypes.GEOMETRY("POLYGON", 4326),
+ allowNull: false,
+ defaultValue: {
+ type: "Polygon",
+ coordinates: [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]],
+ crs: { type: "name", properties: { name: "EPSG:4326" } }
+ }
+ },
+ realEstateType: {
+ type: DataTypes.TEXT,
+ allowNull: false
+ },
+ adType: {
+ type: DataTypes.TEXT,
+ allowNull: false,
+ defaultValue: "sell"
+ },
+ email: DataTypes.TEXT,
+ locality: DataTypes.TEXT,
+ municipality: DataTypes.TEXT,
+ city: DataTypes.TEXT,
+ region: DataTypes.TEXT,
+ entity: DataTypes.TEXT,
+ country: DataTypes.TEXT,
+ sizeMin: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ sizeMax: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ priceMin: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ priceMax: {
+ type: DataTypes.INTEGER,
+ allowNull: false,
+ defaultValue: 0
+ },
+ gardenSizeMin: DataTypes.INTEGER,
+ gardenSizeMax: DataTypes.INTEGER,
+ subscribed: {
+ type: DataTypes.BOOLEAN,
+ defaultValue: false,
+ allowNull: false
+ }
+ });
+
+ SearchRequest.associate = models => {
+ SearchRequest.belongsToMany(models.SearchRequestMatch, {
+ through: "SearchRequestMatch"
+ });
+ };
+
+ return SearchRequest;
+};
diff --git a/app/models/searchRequestMatch.js b/app/models/searchRequestMatch.js
new file mode 100644
index 0000000..6f9d048
--- /dev/null
+++ b/app/models/searchRequestMatch.js
@@ -0,0 +1,47 @@
+"use strict";
+
+module.exports = (sequelize, DataTypes) => {
+ const SearchRequestMatch = sequelize.define(
+ "SearchRequestMatch",
+ {
+ id: {
+ type: DataTypes.BIGINT,
+ autoIncrement: true,
+ allowNull: false
+ },
+ searchRequestId: {
+ type: DataTypes.UUID,
+ allowNull: false,
+ primaryKey: true,
+ references: {
+ model: "SearchRequest",
+ key: "id"
+ }
+ },
+ realEstateId: {
+ type: DataTypes.BIGINT,
+ allowNull: false,
+ primaryKey: true,
+ references: {
+ model: "RealEstate",
+ key: "id"
+ },
+ onUpdate: "CASCADE",
+ onDelete: "SET NULL"
+ },
+ notified: {
+ type: DataTypes.BOOLEAN,
+ allowNull: false,
+ defaultValue: false
+ }
+ },
+ {
+ name: {
+ singular: "searchRequestMatch",
+ plural: "searchRequestMatches"
+ }
+ }
+ );
+
+ return SearchRequestMatch;
+};
diff --git a/app/models/marketalert.js b/app/oldModels/marketalert.js
similarity index 100%
rename from app/models/marketalert.js
rename to app/oldModels/marketalert.js
diff --git a/app/models/realestaterequest.js b/app/oldModels/realestaterequest.js
similarity index 100%
rename from app/models/realestaterequest.js
rename to app/oldModels/realestaterequest.js
diff --git a/app/routes/index.js b/app/routes/index.js
new file mode 100644
index 0000000..6940323
--- /dev/null
+++ b/app/routes/index.js
@@ -0,0 +1,62 @@
+"use strict";
+
+const express = require("express");
+
+const welcome = require("../controllers/welcome").getWelcome;
+const {
+ getRealEstateTypes,
+ postRealEstateTypes
+} = require("../controllers/realEstateTypes");
+const { getSize, postSize } = require("../controllers/sizes");
+const { getGardenSize, postGardenSize } = require("../controllers/gardenSizes");
+const { getPrice, postPrice } = require("../controllers/prices");
+const {
+ getQueryReview,
+ postQueryReview
+} = require("../controllers/queryReview");
+const {
+ getQuerySubmit,
+ postQuerySubmit
+} = require("../controllers/querySubmit");
+const { getGoAgain } = require("../controllers/goAgain");
+const { getLocation, postLocation } = require("../controllers/location");
+const { getUnsubscribe } = require("../controllers/unsubscribe");
+const { getRealEstates } = require("../controllers/realEstates");
+const { redirect } = require("../controllers/redirect");
+
+const router = express.Router();
+
+router.get("/", welcome);
+
+router.get("/vrstanekretnine/:searchRequestId", getRealEstateTypes);
+router.get("/vrstanekretnine", getRealEstateTypes);
+router.post("/vrstanekretnine/:searchRequestId", postRealEstateTypes);
+router.post("/vrstanekretnine", postRealEstateTypes);
+
+router.get("/lokacija/:searchRequestId", getLocation);
+router.post("/lokacija/:searchRequestId", postLocation);
+
+router.get("/povrsina/:searchRequestId", getSize);
+router.post("/povrsina/:searchRequestId", postSize);
+
+router.get("/okucnica/:searchRequestId", getGardenSize);
+router.post("/okucnica/:searchRequestId", postGardenSize);
+
+router.get("/cijena/:searchRequestId", getPrice);
+router.post("/cijena/:searchRequestId", postPrice);
+
+router.get("/pregled/:searchRequestId", getQueryReview);
+router.post("/pregled/:searchRequestId", postQueryReview);
+
+router.get("/posalji/:searchRequestId", getQuerySubmit);
+router.post("/posalji/:searchRequestId", postQuerySubmit);
+
+router.get("/odjava/:searchRequestId", getUnsubscribe);
+
+router.get("/ponovo", getGoAgain);
+
+router.get("/nekretnine/:searchRequestId", getRealEstates);
+
+router.get("/redirect/:id", redirect);
+
+module.exports = router;
diff --git a/app/views/queryReview.ejs b/app/views/queryReview.ejs
index e8105b4..87f99a8 100644
--- a/app/views/queryReview.ejs
+++ b/app/views/queryReview.ejs
@@ -1,10 +1,10 @@
-<% include partials/navBar %>
+<% include partials/navBar %>