From db6804145b5d79ea9aecc28b5a4a5248894045d8 Mon Sep 17 00:00:00 2001 From: Josepablo Cruz Date: Tue, 31 Mar 2026 20:28:16 -0600 Subject: [PATCH] feat: Adding findLoads service per account type (driver, shipper, carrier) --- v1/src/apps/private/loads/carrier.services.js | 216 ++++++++++++++++++ v1/src/apps/private/loads/driver.services.js | 185 +++++++++++++++ v1/src/apps/private/loads/routes.js | 1 - v1/src/apps/private/loads/services.js | 85 +++---- v1/src/apps/private/loads/shipper.services.js | 199 ++++++++++++++++ v1/src/lib/Handlers/Users.handler.js | 10 +- 6 files changed, 637 insertions(+), 59 deletions(-) create mode 100644 v1/src/apps/private/loads/carrier.services.js create mode 100644 v1/src/apps/private/loads/driver.services.js create mode 100644 v1/src/apps/private/loads/shipper.services.js diff --git a/v1/src/apps/private/loads/carrier.services.js b/v1/src/apps/private/loads/carrier.services.js new file mode 100644 index 0000000..1539b8c --- /dev/null +++ b/v1/src/apps/private/loads/carrier.services.js @@ -0,0 +1,216 @@ +"use strict"; +const { getModel } = require( '../../../lib/Models' ); +const { getPagination, normalizeDate } = require( '../../../lib/Misc.js' ); +const { GenericHandler } = require( '../../../lib/Handlers/Generic.handler.js' ); +const Model = getModel('loads'); +const CompanyModel = getModel('companies'); +const ProposalsModel = getModel('proposals'); +const companyGroupsModel = getModel('company_groups'); + +const carrier_projection = [ + 'company_name', + 'company_code', + 'createdAt', + 'rfc' +]; + +const vehicle_projection = [ + 'vehicle_code', + 'truck_type', + 'driver', + 'categories', + 'circulation_serial_number', + 'trailer_plate_1', + 'trailer_plate_2', + 'notes', + 'city', + 'available_in' +]; +const user_projection = ['first_name','last_name','middle_name']; +const populate_list = [ + 'product', + 'company', + 'categories', + 'origin_warehouse', + 'destination_warehouse', + {path:'carrier',select: carrier_projection }, + {path:'vehicle',select: vehicle_projection, populate : { path : 'categories' } }, + {path:'driver',select: user_projection }, + {path:'bidder',select: user_projection }, +]; +const generic = new GenericHandler( Model, null, populate_list ); + +function getAndFilterList( query ){ + const filter_list = []; + const { + company, + carrier, + vehicle, + driver, + status, + posted_by, + posted_by_name, + load_status, + published_date, + loaded_date, + transit_date, + categories, + product, + shipment_code, + origin_warehouse, + destination_warehouse, + est_loading_date, + est_unloading_date, + alert_list, + truck_type, + state, + city, + } = query; + + if( company ){ filter_list.push( { company } ); } + if( carrier ){ filter_list.push( { carrier } ); } + if( vehicle ){ filter_list.push( { vehicle } ); } + if( driver ){ filter_list.push( { driver } ); } + if( status ){ filter_list.push( { status } ); } + if( posted_by ) { filter_list.push({ posted_by }); } + if( posted_by_name ) { filter_list.push({ posted_by_name }); } + if( load_status ) { filter_list.push({ load_status }); } + if( published_date ) { filter_list.push({ published_date }); } + if( loaded_date ) { filter_list.push({ loaded_date }); } + if( transit_date ) { filter_list.push({ transit_date }); } + if( categories ) { filter_list.push({ categories }); } + if( product ) { filter_list.push({ product }); } + if( shipment_code ) { filter_list.push({ shipment_code }); } + if( origin_warehouse ) { filter_list.push({ origin_warehouse }); } + if( destination_warehouse ) { filter_list.push({ destination_warehouse }); } + if( alert_list ) { filter_list.push({ alert_list }); } + if( truck_type ) { filter_list.push({ truck_type }); } + + if( state ) { + filter_list.push({ + $or:[ + { "origin.state": state }, + { "destination.state": state }, + ] + }); + } + + if( city ) { + filter_list.push({ + $or:[ + { "origin.city": city }, + { "destination.city": city }, + ] + }); + } + + if( est_loading_date ) { + if( (est_loading_date.gte == undefined) || (est_loading_date.gte == null) ){ + throw "est_loading_date[gte] is required"; + } + if( (est_loading_date.lte == undefined) || (est_loading_date.lte == null) ){ + throw "est_loading_date[lte] is required"; + } + filter_list.push({ + "est_loading_date" : { + $gte : normalizeDate( est_loading_date["gte"] ), + $lte : normalizeDate( est_loading_date["lte"] ) + } + }); + } + + if( est_unloading_date ) { + if( (est_unloading_date.gte == undefined) || (est_unloading_date.gte == null) ){ + throw "est_unloading_date[gte] is required"; + } + if( (est_unloading_date.lte == undefined) || (est_unloading_date.lte == null) ){ + throw "est_unloading_date[lte] is required"; + } + filter_list.push({ + "est_unloading_date" : { + $gte : normalizeDate( est_unloading_date["gte"] ), + $lte : normalizeDate( est_unloading_date["lte"] ) + } + }); + } + + if( filter_list.length == 0 ){ + return null; + } + return filter_list; +} + +async function getCompanyIdListFromGroups( companyId ){ + const privateGroups = await companyGroupsModel.find({ + allowedCompanies: { $in: [companyId] } + }); + + if( !privateGroups ){ + return null; + } + + const companiesIds = privateGroups.map((group) => group.owner); + + return companiesIds; +} + +async function findLoads( companyId, query ){ + const { $sort, company_name } = query; + const { page, elements } = getPagination( query ); + const andFilterList = getAndFilterList( query ) || []; + + const { privacy } = query; + const privacyVal = ( privacy && ( privacy >= 1 || privacy.toLowerCase() === 'true' ))? true: false; + + let filter = {}; + + if( privacyVal ){ + const companiesIds = await getCompanyIdListFromGroups( companyId ) || []; + filter = { + company : { $in : companiesIds }, + privacy: true, + } + }else{ + filter = { + $or : [ + { privacy : false }, + { privacy : { $exists : false } } + ] + } + } + + if( company_name ){ + /* Populate list of company ids with match on the company_name */ + const company_list = await CompanyModel.find( { company_name }, [ "id" ] ); + const or_company_list = [] + company_list.forEach( (item) =>{ + or_company_list.push({"company" : item.id}); + }) + andFilterList.push({ + $or : or_company_list + }); + } + + if( andFilterList.length > 0 ){ + filter.$and = andFilterList; + } + + const { total , limit, skip, data } = await generic.getList( page , elements, filter, null, $sort ); + + const load_list = data; + + for(let i=0; i{ + or_company_list.push({"company" : item.id}); + }) + andFilterList.push({ + $or : or_company_list + }); + } + + if( andFilterList.length > 0 ){ + filter.$and = andFilterList; + } + + const { total , limit, skip, data } = await generic.getList( page , elements, filter, null, $sort ); + + const load_list = data; + + for(let i=0; i{ - or_company_list.push({"company" : item.id}); - }) - andFilterList.push({ - $or : or_company_list - }); - } - - if( andFilterList.length > 0 ){ - filter = { $and : andFilterList }; - }else{ - filter = null; - } - - const { total , limit, skip, data } = await generic.getList( page , elements, filter, null, $sort ); - - const load_list = data; - - for(let i=0; i { try{ const companyId = req.context.companyId; const query = req.query || {}; - const retVal = await findLoads( companyId, query ); + + let retVal; + + switch( req.context.user?.company?.company_type ){ + case "Shipper": + console.log("Shipper loads finder"); + retVal = await ShipperServices.findLoads( companyId, query ); + break; + case "Carrier": + if( req.context.user?.job_role === "driver" ){ + console.log("Driver loads finder"); + retVal = await DriverServices.findLoads( query ); + }else{ + console.log("Carrier load finder"); + retVal = await CarrierServices.findLoads( companyId, query ); + } + break; + default: + console.log( req.context.user.company.company_type ); + console.log( req.context.user.job_role ); + retVal = await CarrierServices.findLoads( companyId, query ); + break; + } res.send( retVal ); }catch(error){ console.error( error ); @@ -365,17 +349,6 @@ const findList = async(req, res) => { } }; -const findDriverList = async ( req, res ) => { - try{ - const query = req.query || {}; - const retVal = await findDriverLoads( companyId, query ); - res.send( retVal ); - }catch(error){ - console.error( error ); - return res.status( 500 ).send({ error }); - } -} - const getById = async(req, res) => { try{ const elementId = req.params.id; @@ -610,4 +583,4 @@ const deleteLoad = async(req, res) => { } }; -module.exports = { findCalendarList, findList, findDriverList, getById, patchLoad, postLoad, deleteLoad }; +module.exports = { findCalendarList, findList, getById, patchLoad, postLoad, deleteLoad }; diff --git a/v1/src/apps/private/loads/shipper.services.js b/v1/src/apps/private/loads/shipper.services.js new file mode 100644 index 0000000..fcb2f01 --- /dev/null +++ b/v1/src/apps/private/loads/shipper.services.js @@ -0,0 +1,199 @@ +"use strict"; +const { getModel } = require( '../../../lib/Models' ); +const { getPagination, genKey, normalizeDate } = require( '../../../lib/Misc.js' ); +const { GenericHandler } = require( '../../../lib/Handlers/Generic.handler.js' ); +const { onPatchEvent } = require('../../../lib/Handlers/Loads.handler'); +const Model = getModel('loads'); +const CompanyModel = getModel('companies'); +const ProposalsModel = getModel('proposals'); +const companyGroupsModel = getModel('company_groups'); + +const carrier_projection = [ + 'company_name', + 'company_code', + 'createdAt', + 'rfc' +]; + +const vehicle_projection = [ + 'vehicle_code', + 'truck_type', + 'driver', + 'categories', + 'circulation_serial_number', + 'trailer_plate_1', + 'trailer_plate_2', + 'notes', + 'city', + 'available_in' +]; +const user_projection = ['first_name','last_name','middle_name']; +const populate_list = [ + 'product', + 'company', + 'categories', + 'origin_warehouse', + 'destination_warehouse', + {path:'carrier',select: carrier_projection }, + {path:'vehicle',select: vehicle_projection, populate : { path : 'categories' } }, + {path:'driver',select: user_projection }, + {path:'bidder',select: user_projection }, +]; +const generic = new GenericHandler( Model, null, populate_list ); + +function getAndFilterList( query ){ + const filter_list = []; + const { + company, + carrier, + vehicle, + driver, + status, + posted_by, + posted_by_name, + load_status, + published_date, + loaded_date, + transit_date, + categories, + product, + shipment_code, + origin_warehouse, + destination_warehouse, + est_loading_date, + est_unloading_date, + alert_list, + truck_type, + state, + city, + } = query; + + if( company ){ filter_list.push( { company } ); } + if( carrier ){ filter_list.push( { carrier } ); } + if( vehicle ){ filter_list.push( { vehicle } ); } + if( driver ){ filter_list.push( { driver } ); } + if( status ){ filter_list.push( { status } ); } + if( posted_by ) { filter_list.push({ posted_by }); } + if( posted_by_name ) { filter_list.push({ posted_by_name }); } + if( load_status ) { filter_list.push({ load_status }); } + if( published_date ) { filter_list.push({ published_date }); } + if( loaded_date ) { filter_list.push({ loaded_date }); } + if( transit_date ) { filter_list.push({ transit_date }); } + if( categories ) { filter_list.push({ categories }); } + if( product ) { filter_list.push({ product }); } + if( shipment_code ) { filter_list.push({ shipment_code }); } + if( origin_warehouse ) { filter_list.push({ origin_warehouse }); } + if( destination_warehouse ) { filter_list.push({ destination_warehouse }); } + if( alert_list ) { filter_list.push({ alert_list }); } + if( truck_type ) { filter_list.push({ truck_type }); } + + if( state ) { + filter_list.push({ + $or:[ + { "origin.state": state }, + { "destination.state": state }, + ] + }); + } + + if( city ) { + filter_list.push({ + $or:[ + { "origin.city": city }, + { "destination.city": city }, + ] + }); + } + + if( est_loading_date ) { + if( (est_loading_date.gte == undefined) || (est_loading_date.gte == null) ){ + throw "est_loading_date[gte] is required"; + } + if( (est_loading_date.lte == undefined) || (est_loading_date.lte == null) ){ + throw "est_loading_date[lte] is required"; + } + filter_list.push({ + "est_loading_date" : { + $gte : normalizeDate( est_loading_date["gte"] ), + $lte : normalizeDate( est_loading_date["lte"] ) + } + }); + } + + if( est_unloading_date ) { + if( (est_unloading_date.gte == undefined) || (est_unloading_date.gte == null) ){ + throw "est_unloading_date[gte] is required"; + } + if( (est_unloading_date.lte == undefined) || (est_unloading_date.lte == null) ){ + throw "est_unloading_date[lte] is required"; + } + filter_list.push({ + "est_unloading_date" : { + $gte : normalizeDate( est_unloading_date["gte"] ), + $lte : normalizeDate( est_unloading_date["lte"] ) + } + }); + } + + if( filter_list.length == 0 ){ + return null; + } + return filter_list; +} + +async function getCompanyIdListFromGroups( companyId ){ + const privateGroups = await companyGroupsModel.find({ + allowedCompanies: { $in: [companyId] } + }); + + if( !privateGroups ){ + return null; + } + + const companiesIds = privateGroups.map((group) => group.owner); + + return companiesIds; +} + +async function findLoads( companyId, query ){ + const { $sort, company_name } = query; + const { page, elements } = getPagination( query ); + const andFilterList = getAndFilterList( query ) || []; + + let filter = {}; + + if( company_name ){ + /* Populate list of company ids with match on the company_name */ + const company_list = await CompanyModel.find( { company_name }, [ "id" ] ); + const or_company_list = [] + company_list.forEach( (item) =>{ + or_company_list.push({"company" : item.id}); + }) + andFilterList.push({ + $or : or_company_list + }); + } + + if( andFilterList.length > 0 ){ + filter.$and = andFilterList; + } + + const { total , limit, skip, data } = await generic.getList( page , elements, filter, null, $sort ); + + const load_list = data; + + for(let i=0; i