feat(Countries): Adding countries endpoint

This commit is contained in:
2023-10-05 15:59:22 -06:00
parent 55f1c6e091
commit 83e037c298
34 changed files with 669 additions and 47 deletions

7
.env
View File

@@ -1,7 +0,0 @@
SERVER_PORT=8080
API_CONFIG=/config/apiConfig.json
ROOT_PATH=/home/josepablocb/Documents/Work/EnRuta/SysS/ETAAPI
############################
# PATHS relative to ROOT
############################
LIB_PATH=lib

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
node_modules/
.env
package-lock.json
.env

View File

@@ -0,0 +1,35 @@
{
"authentication": {
"jwtSecret":"9o3BBz0EsrwXliwEJ/SFuywZoN8=",
"jwtTimeout":720,
"tokenSecret":"9Z'jMt|(h_f(&/S+zv.K",
"jwtOptions": {
"header": {
"typ": "access"
},
"audience": "https://www.etaviaporte.com",
"issuer": "etaviaporte",
"algorithm": "HS256",
"expiresIn": "1d"
}
},
"version" : {
"version" : "0.0.0",
"name": "ETA Beta",
"date":"10/2023"
},
"S3" : {
"accessKeyId": "AKIAXTQEUF6MLCHTUIKW",
"secretAccessKey": "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",
"bucket": "enruta",
"region": "us-west-1"
},
"sendgrid" : {
"HOST": "smtp.sendgrid.net",
"PORT": "465",
"username": "apikey",
"API_KEY": "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",
"FROM": "noreply@etaviaporte.com"
},
"mongodb": "mongodb://localhost/etaviaporte?retryWrites=true&w=majority"
}

6
dotenv
View File

@@ -1,7 +1,9 @@
SERVER_PORT=8080
API_CONFIG=/config/apiConfig.json
ROOT_PATH=/home/josepablocb/Documents/Work/EnRuta/SysS/ETAAPI
API_CONFIG=config/apiConfig.json
############################
# PATHS relative to ROOT
############################
LIB_PATH=/lib
LIB_PATH=lib
MODELS_PATH=lib/Models
HANDLERS_PATH=lib/Handlers

View File

@@ -1,8 +1,9 @@
'use strict';
const express = require('express');
require('dotenv').config();
const { ROOT_PATH , LIB_PATH } = process.env;
const { ROOT_PATH, LIB_PATH, API_CONFIG } = process.env;
const apiConfig = require( `${ROOT_PATH}/${API_CONFIG}` );
const express = require('express');
const cors = require('cors');
const compression = require('compression');
const morgan = require('morgan');
@@ -10,12 +11,20 @@ const helmet = require('helmet');
const bodyParser = require('body-parser');
const fileUpload = require('express-fileupload');
const sections = require('./sections/sections.js');
const middleWares = require( `${ROOT_PATH}/${LIB_PATH}/Middlewares.js` );
const middlewares = require( `${ROOT_PATH}/${LIB_PATH}/Middlewares.js` );
const mongoose = require('mongoose');
mongoose.connect(
apiConfig.mongodb,
{ useNewUrlParser: true }
).then( ( val ) => {
console.log( "MongoDB Connected" );
});//catch throw error so service stops!
const app = express();
const serverPort = process.env.SERVER_PORT || 3000;
app.use( middleWares.Auth );
app.use( middlewares.Auth );
app.use(
fileUpload({
limits: { fileSize: 4 * 1024 * 1024 },
@@ -39,24 +48,24 @@ app.use(morgan('dev'));
app.use(helmet());
app.use(compression());
app.use(cors({
origin: '*',
methods: [
'GET',
'POST',
'PATCH',
'PUT',
'DELETE'
],
allowedHeaders: ['Content-Type', 'Authorization']
origin: '*',
methods: [
'GET',
'POST',
'PATCH',
'PUT',
'DELETE'
],
allowedHeaders: ['Content-Type', 'Authorization']
}));
app.use( middleWares.errorJSON );
app.use( middlewares.errorJSON );
app.use( sections );
app.use( middleWares.error404 );
app.use( middlewares.error404 );
app.listen( serverPort , function(err){
if( !err ){
console.log('API listen on port', serverPort );
}else{
console.log( err );
}
if( !err ){
console.log('API listen on port', serverPort );
}else{
console.log( err );
}
});

View File

@@ -0,0 +1,9 @@
'user strict';
const { ROOT_PATH, HANDLERS_PATH, MODELS_PATH, API_CONFIG } = process.env;
const companiesModel = require( `${ROOT_PATH}/${MODELS_PATH}/companies.model.js` );
async function getCompanyData( id ){
return await companiesModel.findById( id );
}
module.exports = { getCompanyData };

View File

@@ -0,0 +1,9 @@
'user strict';
const { ROOT_PATH, HANDLERS_PATH, MODELS_PATH, API_CONFIG } = process.env;
const usersModel = require( `${ROOT_PATH}/${MODELS_PATH}/users.model.js` );
async function getUserData( id ){
return await usersModel.findById( id , { password : 0 } );
}
module.exports = { getUserData };

30
lib/Misc.js Normal file
View File

@@ -0,0 +1,30 @@
"use strict";
function getPagination( query ){
let limit = {
page : 0,
elements : 10
};
if( query.page ){
limit.page = parseInt( query.page ) || 0;
}
if( query.elements ){
limit.elements = parseInt( query.elements ) || 10;
}
return limit;
}
async function queryPage( page , elements , model ){
const skip = elements * page;
const total = await model.count();
const list = await model.find( {} , null, { skip : skip } );
return {
total : total,
limit : elements,
skip : skip,
data : list
}
}
module.exports = { getPagination , queryPage };

View File

@@ -0,0 +1,16 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
categories: [{ type: Schema.Types.ObjectId, ref: 'product-categories' }],
company: { type: Schema.Types.ObjectId, ref: 'companies' },
branch_name: { type: String },
phone: { type: String },
city: { type: String },
state: { type: String },
truck_type: [{ type: String }],
description:{type: String},
address : { type: String }
});
module.exports = mongoose.model( "branches", schema );

View File

@@ -0,0 +1,33 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
company: { type: Schema.Types.ObjectId, ref: 'companies', required: true},
client: { type: String, required: true },
material: { type: String },
origin: { type: String },
destination: { type: String },
truck_type: { type: String },
num_tons: { type: Number },
price_per_ton: { type: Number },
tonnage: { type: String },
pickup_distance: { type: Number },
delivery_distance: { type: Number },
warehouse_distance: { type: Number },
total_km_travel: { type: Number },
cost_per_liter: { type: Number },
fuel_price_per_liter: { type: Number },
other_fuel_expenses: { type: Number },
total_fuel_consumed: { type: Number },
total_cost_fuel: { type: Number },
driver_salary: { type: Number },
accomadation_allowance: { type: Number },
other_administrative_expenses: { type: Number },
total_before_tax: { type: Number },
total_utility_per_km: { type: Number },
total_profit: { type: Number },
profit_percentage: { type: Number },
total_administrative_expenses: { type: Number }
});
module.exports = mongoose.model( "budgets", schema );

View File

@@ -0,0 +1,11 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
country_name: { type: String },
country_code: { type: String },
state_name: { type: String },
city_name: { type: String, required: true }
});
module.exports = mongoose.model( "cities", schema );

View File

@@ -0,0 +1,65 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const meta_data = new Schema({
meta_group: { type: String },
meta_key: { type: String },
meta_value: { type: String },
});
const company_contacts = new Schema({
meta_key: { type: String },
meta_value: { type: String },
});
const address = new Schema({
street_address1: { type: String },
street_address2: { type: String },
city: { type: String },
state: { type: String },
country: { type: String },
zipcode: { type: String },
landmark: { type: String },
lat: { type: String },
lng: { type: String },
});
const schema = new Schema({
company_serial_number: { type: String },
company_code: { type: String },
is_company: { type: String }, //1000
company_name: { type: String, required: true },
company_legal_name: { type: String },
company_description: { type: String },
rfc: { type: String },
company_type: [{ type: String }], // SHIPPER , CARRIER
is_broker: { type: Boolean, default: false },
membership: { type: String },
membership_start_at: { type: Date },
meta_data: [meta_data],
categories: [{ type: Schema.Types.ObjectId, ref: 'productcategories' }],
products: { type: Schema.Types.ObjectId, ref: 'products' },
users: [{ type: Schema.Types.ObjectId, ref: 'users' }],
branches: [{ type: Schema.Types.ObjectId, ref: 'branches' }],
company_city: [{ type: String }],
company_state: [{ type: String }],
truck_type: [{ type: String }],
street_address1: { type: String },
street_address2: { type: String },
city: { type: String },
state: { type: String },
country: { type: String },
zipcode: { type: String },
landmark: { type: String },
lat: { type: String },
lng: { type: String },
is_hidden: { type: Boolean, default: false },
});
module.exports = mongoose.model( "branches", schema );

View File

@@ -0,0 +1,10 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
country_name: { type: String, required: true },
country_code: { type: String, required: true },
phone_code: { type: String, required: true }
});
module.exports = mongoose.model( "countries", schema );

90
lib/Models/loads.model.js Normal file
View File

@@ -0,0 +1,90 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const address = new Schema({
company_name: { type: String },
street_address1: { type: String },
street_address2: { type: String },
city: { type: String },
state: { type: String },
country: { type: String },
zipcode: { type: String },
landmark: { type: String },
lat: { type: String },
lng: { type: String },
});
const pointSchema = new Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
const schema = new Schema({
shipment_code: { type: String },
company: { type: Schema.Types.ObjectId, ref: 'companies', required: true }, //shipper
carrier: { type: Schema.Types.ObjectId, ref: 'companies' }, // carrier
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
driver: { type: Schema.Types.ObjectId, ref: 'users' },
posted_by: { type: Schema.Types.ObjectId, ref: 'users' }, // shipper
posted_by_name: { type: String }, // search purpose
bidder: { type: Schema.Types.ObjectId, ref: 'users' },
origin: address,
origin_geo: {
type: pointSchema,
},
destination: address,
destination_geo: {
type: pointSchema,
},
categories: [{ type: Schema.Types.ObjectId, ref: 'product-categories' }],
product: { type: Schema.Types.ObjectId, ref: 'products' },
truck_type: { type: String },
tyre_type: { type: String },
weight: { type: Number },
estimated_cost: { type: Number },
distance: { type: Number },
actual_cost: { type: Number },
// 1. Posted Shipments (Posted)
// 2. Shipments Loading (Loading)
// 3. Enroute Shipments (In Transit)
// 4. Shipments in Unloading (Unloading)
// 5. Shipments pending finding truck
status: { type: String, default: 'Draft', enum: ['Draft', 'Published', 'Completed', 'Closed'] },
load_status: { type: String, enum: ['Published', 'Loading', 'Transit', 'Downloading', 'Delivered'] },
contract_start_date: { type: Date },
contract_end_date: { type: Date },
est_loading_date: { type: Date },
est_unloading_date: { type: Date },
published_date: { type: Date },
loaded_date: { type: Date },
transit_date: { type: Date },
delivered_date: { type: Date },
load_status_updated: { type: Date, default: Date.now() },
notes: { type: String },
payment_term: { type: String },
terms_and_conditions: { type: String },
});
module.exports = mongoose.model( "loads", schema );

View File

@@ -0,0 +1,8 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
text: { type: String, required: true }
});
module.exports = mongoose.model( "mailer", schema );

View File

@@ -0,0 +1,10 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
name: { type: String, required: true }, // free, pro
price: { type: Number },
validity : { type: Number }, // number 0f days
});
module.exports = mongoose.model( "memberships", schema );

View File

@@ -0,0 +1,10 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
meta_group: { type: Schema.Types.ObjectId, ref: 'metagroups'},// settings, terms, collaborator
meta_key: { type: String, required: true }, // collaborator
meta_value: { type: String }
});
module.exports = mongoose.model( "metadatas", schema );

View File

@@ -0,0 +1,11 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
group_label: { type: String, required: true },
group_key: { type: String, required: true },
group_field_type: { type: String,default:'text' }, // text, textarea, html, select
group_options: [{ type: String }]
});
module.exports = mongoose.model( "metagroups", schema );

26
lib/Models/news.model.js Normal file
View File

@@ -0,0 +1,26 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const attachFile = new Schema({
file:{ type: String },
originalname:{ type: String },
mimetype:{ type: String },
focus_point:[{
thumbnail:{ type: String, default:"main" },
x:{ type: Number },
y:{ type: Number },
w:{ type: Number },
h:{ type: Number },
s:{ type: Number }
}]
});
const schema = new Schema({
title : { type: String, required: true },
description : { type: String, required: true },
link_text : { type: String, required: true },
link_url : { type: String, required: true },
news_image: attachFile,
});
module.exports = mongoose.model( "news", schema );

View File

@@ -0,0 +1,11 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
load: { type: Schema.Types.ObjectId, ref: 'loads' },
shipper: { type: Schema.Types.ObjectId, ref: 'companies' }, // how offers load
carrier: { type: Schema.Types.ObjectId, ref: 'companies' }, // how transport the load
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
});
module.exports = mongoose.model( "orders", schema );

View File

@@ -0,0 +1,8 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
name: { type: String, required: true } // fruit, boxes, wood
});
module.exports = mongoose.model( "productcategories", schema );

View File

@@ -0,0 +1,9 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
name: { type: String, required: true },
segment: { type: String},
});
module.exports = mongoose.model( "products", schema );

View File

@@ -0,0 +1,21 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
load: { type: Schema.Types.ObjectId, ref: 'loads' },
shipper: { type: Schema.Types.ObjectId, ref: 'companies' }, // how offers load
carrier: { type: Schema.Types.ObjectId, ref: 'companies' }, // how transport the load
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
bidder: { type: Schema.Types.ObjectId, ref: 'users' },
comment: { type: String },
is_withdrawn: { type: Boolean, default: false },
accepted_by: { type: Schema.Types.ObjectId, ref: 'users' },
accepted_date: { type: Date },
is_accepted: { type: Boolean, default: false },
});
module.exports = mongoose.model( "proposals", schema );

View File

@@ -0,0 +1,12 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
country_name: { type: String},
country_code: { type: String },
state_name: { type: String, required: true },
state_code: { type: String }
});
module.exports = mongoose.model( "states", schema );

View File

@@ -0,0 +1,12 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const schema = new Schema({
lat: { type: String },
lng: { type: String },
user: { type: Schema.Types.ObjectId, ref: 'users' },
load: { type: Schema.Types.ObjectId, ref: 'loads' },
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
});
module.exports = mongoose.model( "trackings", schema );

64
lib/Models/users.model.js Normal file
View File

@@ -0,0 +1,64 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const pointSchema = new Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
const schema = new Schema({
first_name: { type: String },
last_name: { type: String },
middle_name: { type: String },
email: { type: String, unique: true, lowercase: true },
password: { type: String },
phone: { type: String },
phone2: { type: String },
permissions: [{ type: String, default: 'role_admin' }],
gender: { type: String },
address: { type: String },
dob: { type: String },
// vehicle_status: { type: String, enum: ['Free', 'Loading', 'Moving', 'Downloading'] },
job_role: { type: String }, // admin, owner, driver, staff
employee_id: { type: String }, //EM-1000-1 EM-1000-2
company: { type: Schema.Types.ObjectId, ref: 'companies' },
branch: { type: Schema.Types.ObjectId, ref: 'branches' },
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
active_load: { type: Schema.Types.ObjectId, ref: 'loads' },
categories: [{ type: Schema.Types.ObjectId, ref: 'product-categories' }],
user_city: [{ type: String }],
user_state: [{ type: String }],
user_description: { type: String },
truck_type: [{ type: String }],
last_location_lat: { type: String },
last_location_lng: { type: String },
last_location_geo: { type: pointSchema },
last_location_time: { type: Date },
isVerified: { type: Boolean },
verifyToken: { type: String },
verifyShortToken: { type: String },
verifyExpires: { type: Date }, // or a long integer
verifyChanges: { type: Object }, // an object (key-value map), e.g. { field: "value" }
resetToken: { type: String },
resetShortToken: { type: String },
resetExpires: { type: Date }, // or a long integer
resetAttempts: { type: Number },
is_hidden: { type: Boolean, default: false },
});
module.exports = mongoose.model( "users", schema );

View File

@@ -0,0 +1,55 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
const pointSchema = new Schema({
type: {
type: String,
enum: ['Point'],
required: true
},
coordinates: {
type: [Number],
required: true
}
});
const schema = new Schema({
company: { type: Schema.Types.ObjectId, ref: 'companies' }, // carrier
vehicle_code: { type: String },
vehicle_name: { type: String },
vehicle_number: { type: String }, //camion001 002 etc
circulation_serial_number: { type: String },
trailer_plate_1: { type: String },
trailer_plate_2: { type: String },
truck_type: { type: String },
tyre_type: { type: String },
city: { type: String },
state: { type: String },
background_tracking: { type: Boolean, default: false },
status: { type: String, enum: ['Free', 'Loading', 'Transit', 'Downloading'] },
categories: [{ type: Schema.Types.ObjectId, ref: 'product-categories' }],
published_date: { type: Date },
available_date: { type: String },
is_available: { type: Boolean, default: false },
active_load: { type: Schema.Types.ObjectId, ref: 'loads' },
load_shipper: { type: Schema.Types.ObjectId, ref: 'companies' },
available_in: [{ type: String }],
destino: { type: String },
driver: { type: Schema.Types.ObjectId, ref: 'users' },
notes: { type: String },
last_location_lat: { type: String },
last_location_lng: { type: String },
last_location_geo: { type: pointSchema },
last_location_time: { type: Date },
});
module.exports = mongoose.model( "vehicles", schema );

View File

@@ -1,17 +1,18 @@
'user strict';
const { ROOT_PATH, API_CONFIG } = process.env;
const apiConfig = require( `${ROOT_PATH}/${API_CONFIG}` );
const jwt = require('jsonwebtoken');
const apiConfig = require(ROOT_PATH + API_CONFIG);
const secret = apiConfig.authentication.jwtSecret;
const jwtSecret = apiConfig.authentication.jwtSecret;
function middleware( req, res, next ){
if( req.JWT ){
req.JWT.payload = jwt.verify( req.JWT.raw, apiConfig.authentication.jwtSecret , (err, user) => {
if( err ){
return res.status(401).send({error:"Unauthorized",code:401});
}
});
req.JWT.isValid = false;
req.JWT.payload = jwt.verify( req.JWT.raw, jwtSecret );
if( !req.JWT.payload ){
return res.status(401).send({error:"Unauthorized",code:401});
}else{
req.JWT.isValid = true;
}
next();
}else{
return res.status(401).send({error:"Unauthorized",code:401});

View File

@@ -0,0 +1,8 @@
'use strict';
const router = require('express').Router();
const services= require('./services.js');
router.get('/', services.getCountriesList);
router.get('/:id', services.getCountry);
module.exports = router;

View File

@@ -0,0 +1,17 @@
"use strict";
const { ROOT_PATH, LIB_PATH, MODELS_PATH, HANDLERS_PATH } = process.env;
const { getPagination , queryPage } = require( `${ROOT_PATH}/${LIB_PATH}/Misc.js` );
const countriesModel = require( `${ROOT_PATH}/${MODELS_PATH}/countries.model.js` );
const getCountriesList = async(req, res) => {
const { page , elements } = getPagination( req.query );
const retVal = await queryPage( page , elements, countriesModel );
res.send( retVal );
};
const getCountry = async(req, res) => {
const retVal = await countriesModel.findById( req.params.id );
res.send( retVal );
};
module.exports = { getCountriesList , getCountry };

View File

@@ -7,11 +7,37 @@ const jwtValidator = require( `${ROOT_PATH}/${LIB_PATH}/jwtValidator.js` );
const test = require('./test/routes.js');
const users = require('./users/routes.js');
const countries = require('./countries/routes.js');
router.use("/test", test);
router.use('/countries', countries);
router.use('/cities', test);
router.use('/states', test);
router.use( jwtValidator.middleware );
router.use("/users", users);
router.use('/orders', test);
router.use('/companies', test);
router.use('/metaGroups', test);
router.use('/metaData', test);
router.use('/loads', test);
router.use('/vehicles', test);
router.use('/mailer', test);
router.use('/authmanagement', test);
router.use('/productCategories', test);
router.use('/memberships', test);
router.use('/checkAccount', test);
router.use('/proposals', test);
router.use('/bootresolvers', test);
router.use('/budgets', test);
router.use('/products', test);
router.use('/news', test);
router.use('/branches', test);
router.use('/trackings', test);
router.use('/upload', test);
router.use('/calendars', test);
router.use('/dashboard', test);
module.exports = router;

View File

@@ -1,6 +1,6 @@
"use strict";
const apiConfig = require( process.env.ROOT_PATH + process.env.API_CONFIG );
const { ROOT_PATH, LIB_PATH, API_CONFIG } = process.env;
const apiConfig = require( `${ROOT_PATH}/${API_CONFIG}` );
const postTest = async(req, res) => {
res.send({

View File

@@ -2,8 +2,8 @@
const router = require('express').Router();
const services= require('./services.js');
router.get('/', services.getUsers);
router.get('/', services.getProfileData);
router.get('/profile', services.getProfileData);
router.get('/:userId', services.getUserData);
router.get('/:userId', services.getProfileData);
module.exports = router;

View File

@@ -1,8 +1,8 @@
"use strict";
const { ROOT_PATH, HANDLERS_PATH, API_CONFIG } = process.env;
const UsersHandler = require( `${ROOT_PATH}/${HANDLERS_PATH}/Users.handler.js` );
const apiConfig = require( process.env.ROOT_PATH + process.env.API_CONFIG );
const getUsers = async(req, res) => {
const getUsersList = async(req, res) => {
console.log( req.params );
res.send({ user : "hello world!" });
};
@@ -13,8 +13,8 @@ const getUserData = async(req, res) => {
};
const getProfileData = async(req, res) => {
console.log( req.params );
res.send({ user : "hello world!" });
const user = await UsersHandler.getUserData( req.JWT.payload.sub );
res.send( user );
};
module.exports = { getUsers , getUserData , getProfileData};
module.exports = { getUsersList , getUserData , getProfileData};