feat: Simplify proposals events and add warehouse events
This commit is contained in:
@@ -1,14 +1,28 @@
|
|||||||
|
/* global use, db */
|
||||||
// MongoDB Playground
|
// MongoDB Playground
|
||||||
// Use Ctrl+Space inside a snippet or a string literal to trigger completions.
|
// Use Ctrl+Space inside a snippet or a string literal to trigger completions.
|
||||||
|
|
||||||
// The current database to use.
|
// The current database to use.
|
||||||
use('enrutaviaporte');
|
use('enrutaviaporte');
|
||||||
|
|
||||||
// Create a new document in the collection.
|
// Search for documents in the current collection.
|
||||||
db.getCollection('notifications').insertOne({
|
db.getCollection('loads')
|
||||||
"owner" : ObjectId("65eeadb8ed616b897ca4c4cd"),
|
.find(
|
||||||
"title":"Notification title",
|
{
|
||||||
"description":"Notification description",
|
_id : ObjectId('66c151a1299e3cfe8fa4a1dc')
|
||||||
"tag":"category",
|
},
|
||||||
"deleted":false
|
{
|
||||||
|
/*
|
||||||
|
* Projection
|
||||||
|
* _id: 0, // exclude _id
|
||||||
|
* fieldA: 1 // include field
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.sort({
|
||||||
|
/*
|
||||||
|
* fieldA: 1 // ascending
|
||||||
|
* fieldB: -1 // descending
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
90
v1/src/lib/Handlers/Events/Proposals/index.js
Normal file
90
v1/src/lib/Handlers/Events/Proposals/index.js
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
'user strict';
|
||||||
|
const { getModel } = require( '../../../Models' );
|
||||||
|
|
||||||
|
const onAcceptedEvents = require('./onAccepted');
|
||||||
|
|
||||||
|
const branchesModel = getModel('branches')
|
||||||
|
const vehiclesModel = getModel('vehicles');
|
||||||
|
const proposalsModel = getModel('proposals');
|
||||||
|
const loadsModel = getModel('loads');
|
||||||
|
const usersModel = getModel('users');
|
||||||
|
const companiesModel = getModel('companies');
|
||||||
|
const notificationsModel = getModel('notifications');
|
||||||
|
const productsModel = getModel('products');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When the proposal is created then the load owner should be notified
|
||||||
|
*/
|
||||||
|
async function onProposalCreate( proposal_id ){
|
||||||
|
const proposal = await proposalsModel.findById( proposal_id );
|
||||||
|
const load = await loadsModel.findById( proposal.load );
|
||||||
|
const user = await usersModel.findById( load.posted_by );
|
||||||
|
|
||||||
|
const notification = new notificationsModel({
|
||||||
|
"owner": user.id,
|
||||||
|
"title": "New proposal",
|
||||||
|
"description": `${load.shipment_code}`,
|
||||||
|
"tag":"new_proposal",
|
||||||
|
"deleted":false
|
||||||
|
});
|
||||||
|
|
||||||
|
await notification.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a proposal is removed from the load, it is considered as rejected
|
||||||
|
*/
|
||||||
|
async function onProposalRejected( proposal_id ){
|
||||||
|
const proposal = await proposalsModel.findById( proposal_id );
|
||||||
|
|
||||||
|
/// Update Proposal:
|
||||||
|
/// Remove shipper
|
||||||
|
await proposalsModel.findByIdAndUpdate( id , {
|
||||||
|
shipper : null
|
||||||
|
} );
|
||||||
|
|
||||||
|
/// Update Load:
|
||||||
|
/// Remove carrier, driver and vehicle
|
||||||
|
await loadsModel.findByIdAndUpdate( proposal.load, {
|
||||||
|
carrier : null,
|
||||||
|
driver : null,
|
||||||
|
vehicle : null,
|
||||||
|
bidder : null
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a proposal is accepted by the shipper
|
||||||
|
*/
|
||||||
|
async function onProposalAccepted( proposal_id ){
|
||||||
|
const proposal = await proposalsModel.findById( proposal_id );
|
||||||
|
const shipper_user = await usersModel.findById( proposal.accepted_by );
|
||||||
|
const shipper = await companiesModel.findById( shipper_user.company );
|
||||||
|
const vehicle = await vehiclesModel.findById( proposal.vehicle );
|
||||||
|
const load = await loadsModel.findById( proposal.load );
|
||||||
|
|
||||||
|
/// Update Proposal:
|
||||||
|
/// Adding shipper to proposal
|
||||||
|
await proposalsModel.findByIdAndUpdate( proposal_id , {
|
||||||
|
shipper : shipper.id
|
||||||
|
} );
|
||||||
|
|
||||||
|
/// Update Load:
|
||||||
|
/// Add carrier, driver and vehicle
|
||||||
|
await loadsModel.findByIdAndUpdate( proposal.load, {
|
||||||
|
carrier : proposal.carrier,
|
||||||
|
driver : vehicle.driver,
|
||||||
|
vehicle : proposal.vehicle,
|
||||||
|
bidder : proposal.bidder // Who created the proposal (carrier user)
|
||||||
|
} );
|
||||||
|
|
||||||
|
const carrier = await companiesModel.findById( load.carrier );
|
||||||
|
const product = await productsModel.findById( load.product );
|
||||||
|
const driver = await usersModel.findById( load.driver );
|
||||||
|
const warehouse = await branchesModel.findById( load.shipper_warehouse );
|
||||||
|
|
||||||
|
await onAcceptedEvents.sendNotification( proposal, load );
|
||||||
|
await onAcceptedEvents.sendWarehouseEmail( warehouse, load, carrier, product, vehicle, driver );
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { onProposalCreate, onProposalRejected, onProposalAccepted };
|
||||||
29
v1/src/lib/Handlers/Events/Proposals/onAccepted.js
Normal file
29
v1/src/lib/Handlers/Events/Proposals/onAccepted.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
'user strict';
|
||||||
|
const { getModel } = require( '../../../Models' );
|
||||||
|
const warehouseEvents = require('../Warehouse');
|
||||||
|
const notificationsModel = getModel('notifications');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a platform notification to the
|
||||||
|
* @param {*} proposal
|
||||||
|
* @param {*} shipper
|
||||||
|
* @param {*} vehicle
|
||||||
|
* @param {*} load
|
||||||
|
*/
|
||||||
|
async function sendNotification( proposal, load ){
|
||||||
|
const notification = new notificationsModel({
|
||||||
|
"owner": proposal.bidder,
|
||||||
|
"title": `Your proposal has been accepted!`,
|
||||||
|
"description": `${load.shipment_code}`,
|
||||||
|
"tag":"accepted_proposal",
|
||||||
|
"deleted":false
|
||||||
|
});
|
||||||
|
|
||||||
|
await notification.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendWarehouseEmail( warehouse, load, carrier, product, vehicle, driver ){
|
||||||
|
await warehouseEvents.onProposalAccepted( warehouse, load, carrier, product, vehicle, driver );
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { sendNotification, sendWarehouseEmail };
|
||||||
36
v1/src/lib/Handlers/Events/Warehouse/index.js
Normal file
36
v1/src/lib/Handlers/Events/Warehouse/index.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
'user strict';
|
||||||
|
const { getModel } = require( '../../../Models' );
|
||||||
|
const { emailEvent , EMAIL_EVENTS } = require( '../../MailClient' );
|
||||||
|
|
||||||
|
const usersModel = getModel('users');
|
||||||
|
|
||||||
|
async function onProposalAccepted( warehouse, load, carrier, product, vehicle, driver ){
|
||||||
|
const driver_name = `${driver.first_name} ${driver.last_name}`;
|
||||||
|
|
||||||
|
const list_of_warehouse_responsibles = await usersModel.find(
|
||||||
|
{
|
||||||
|
branch: warehouse.id,
|
||||||
|
job_role: 'warehouse'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
for( const entry of list_of_warehouse_responsibles ){
|
||||||
|
warehouse_email = entry.email;
|
||||||
|
emailEvent(
|
||||||
|
EMAIL_EVENTS.WAREHOUSE_DRIVER_ASSIGNED,
|
||||||
|
warehouse_email,
|
||||||
|
{
|
||||||
|
code : load.shipment_code,
|
||||||
|
date : new Date( load.est_loading_date ).toLocaleString("es-MX",{year: 'numeric', month: '2-digit', day: '2-digit'}),
|
||||||
|
company: carrier.company_name,
|
||||||
|
product: product.name,
|
||||||
|
plate: vehicle.circulation_serial_number,
|
||||||
|
truck_type: vehicle.truck_type,
|
||||||
|
driver: driver_name,
|
||||||
|
note: load.notes,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { onProposalAccepted };
|
||||||
@@ -88,4 +88,11 @@ async function ContactEmail( receiver, content ){
|
|||||||
return await sendMailTemplate( receiver, subject, html );
|
return await sendMailTemplate( receiver, subject, html );
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail };
|
async function WarehouseDriverAssignedNotification( receiver, content ){
|
||||||
|
const subject = "[ETA] Warehouse Notification";
|
||||||
|
const { code, date, company, product, plate, truck_type, driver, note } = content;
|
||||||
|
const html = warehouseNotificationTemplate( code, date, company, product, plate, truck_type, driver, note );
|
||||||
|
return await sendMailTemplate( receiver, subject, html );
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail, WarehouseDriverAssignedNotification };
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
'user strict';
|
'user strict';
|
||||||
const { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail } = require('./StandAlone.handler');
|
const { AccountVerifyEmail, AccountConfirmed, AccountPwdResetEmail, ContactEmail, StandAloneContactEmail, WarehouseDriverAssignedNotification } = require('./StandAlone.handler');
|
||||||
|
|
||||||
const EMAIL_EVENTS={
|
const EMAIL_EVENTS={
|
||||||
ACCOUNT_VERIFY:1,
|
ACCOUNT_VERIFY:1,
|
||||||
ACCOUNT_CONFIRMED:2,
|
ACCOUNT_CONFIRMED:2,
|
||||||
ACCOUNT_PWD_RESET:3,
|
ACCOUNT_PWD_RESET:3,
|
||||||
CONTACT_EMAIL:4,
|
CONTACT_EMAIL:4,
|
||||||
|
WAREHOUSE_DRIVER_ASSIGNED:5,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,6 +38,11 @@ async function emailEvent( eventId, receiver , content ){
|
|||||||
return await ContactEmail( receiver, content );
|
return await ContactEmail( receiver, content );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case EMAIL_EVENTS.WAREHOUSE_DRIVER_ASSIGNED:
|
||||||
|
{
|
||||||
|
return await WarehouseDriverAssignedNotification( receiver, content );
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
throw new Error(`Email event not defined ${eventId}`);
|
throw new Error(`Email event not defined ${eventId}`);
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
'user strict';
|
'user strict';
|
||||||
const { getModel } = require( '../Models' );
|
const { getModel } = require( '../Models' );
|
||||||
const vehiclesModel = require('../Models/vehicles.model');
|
const ProposalsEvents = require( './Events/Proposals' );
|
||||||
|
|
||||||
|
const vehiclesModel = getModel('vehicles');
|
||||||
const proposalsModel = getModel('proposals');
|
const proposalsModel = getModel('proposals');
|
||||||
const loadsModel = getModel('loads');
|
const loadsModel = getModel('loads');
|
||||||
const usersModel = getModel('users');
|
const usersModel = getModel('users');
|
||||||
@@ -16,19 +17,8 @@ const notificationsModel = getModel('notifications');
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function onPostEvent( id , newProposalData ){
|
async function onPostEvent( id , newProposalData ){
|
||||||
const proposal = await proposalsModel.findById( id );
|
/// When a post event happens it is assumed that a proposal is created
|
||||||
const load = await loadsModel.findById( proposal.load );
|
ProposalsEvents.onProposalCreate( id );
|
||||||
const user = await usersModel.findById( load.posted_by );
|
|
||||||
|
|
||||||
const notification = new notificationsModel({
|
|
||||||
"owner": user.id,
|
|
||||||
"title": "New proposal",
|
|
||||||
"description": `${load.shipment_code}`,
|
|
||||||
"tag":"new_proposal",
|
|
||||||
"deleted":false
|
|
||||||
});
|
|
||||||
|
|
||||||
await notification.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,51 +29,10 @@ async function onPostEvent( id , newProposalData ){
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async function onPatchEvent( id , newProposalData ){
|
async function onPatchEvent( id , newProposalData ){
|
||||||
const proposal = await proposalsModel.findById( id );
|
|
||||||
if( !newProposalData.is_accepted ){
|
if( !newProposalData.is_accepted ){
|
||||||
/// Update Proposal:
|
ProposalsEvents.onProposalRejected( id );
|
||||||
/// Remove shipper
|
|
||||||
await proposalsModel.findByIdAndUpdate( id , {
|
|
||||||
shipper : null
|
|
||||||
} );
|
|
||||||
|
|
||||||
/// Update Load:
|
|
||||||
/// Remove carrier, driver and vehicle
|
|
||||||
await loadsModel.findByIdAndUpdate( proposal.load, {
|
|
||||||
carrier : null,
|
|
||||||
driver : null,
|
|
||||||
vehicle : null,
|
|
||||||
bidder : null
|
|
||||||
} );
|
|
||||||
}else{
|
}else{
|
||||||
const shipper_user = await usersModel.findById( proposal.accepted_by );
|
ProposalsEvents.onProposalAccepted( id );
|
||||||
const shipper = await companiesModel.findById( shipper_user.company );
|
|
||||||
const vehicle = await vehiclesModel.findById( proposal.vehicle );
|
|
||||||
const load = await loadsModel.findById( proposal.load );
|
|
||||||
/// Update Proposal:
|
|
||||||
/// Adding shipper to proposal
|
|
||||||
await proposalsModel.findByIdAndUpdate( id , {
|
|
||||||
shipper : shipper.id
|
|
||||||
} );
|
|
||||||
|
|
||||||
/// Update Load:
|
|
||||||
/// Add carrier, driver and vehicle
|
|
||||||
await loadsModel.findByIdAndUpdate( proposal.load, {
|
|
||||||
carrier : proposal.carrier,
|
|
||||||
driver : vehicle.driver,
|
|
||||||
vehicle : proposal.vehicle,
|
|
||||||
bidder : proposal.bidder
|
|
||||||
} );
|
|
||||||
|
|
||||||
const notification = new notificationsModel({
|
|
||||||
"owner": proposal.bidder,
|
|
||||||
"title": `Your proposal has been accepted!`,
|
|
||||||
"description": `${load.shipment_code}`,
|
|
||||||
"tag":"accepted_proposal",
|
|
||||||
"deleted":false
|
|
||||||
});
|
|
||||||
|
|
||||||
await notification.save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ const schema = new Schema({
|
|||||||
driver: { type: Schema.Types.ObjectId, ref: 'users' },
|
driver: { type: Schema.Types.ObjectId, ref: 'users' },
|
||||||
posted_by: { type: Schema.Types.ObjectId, ref: 'users' }, // shipper
|
posted_by: { type: Schema.Types.ObjectId, ref: 'users' }, // shipper
|
||||||
posted_by_name: { type: String }, // search purpose
|
posted_by_name: { type: String }, // search purpose
|
||||||
bidder: { type: Schema.Types.ObjectId, ref: 'users' },
|
bidder: { type: Schema.Types.ObjectId, ref: 'users' }, // who sent the proposal (carrier user)
|
||||||
|
|
||||||
shipper_warehouse : { type: Schema.Types.ObjectId, ref: 'branches' },
|
shipper_warehouse : { type: Schema.Types.ObjectId, ref: 'branches' },
|
||||||
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ const schema = new Schema({
|
|||||||
carrier: { type: Schema.Types.ObjectId, ref: 'companies' }, // who transport the load
|
carrier: { type: Schema.Types.ObjectId, ref: 'companies' }, // who transport the load
|
||||||
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
|
vehicle: { type: Schema.Types.ObjectId, ref: 'vehicles' },
|
||||||
|
|
||||||
bidder: { type: Schema.Types.ObjectId, ref: 'users' },
|
bidder: { type: Schema.Types.ObjectId, ref: 'users' }, // who sends the proposal (proposal author, carrier)
|
||||||
|
|
||||||
comment: { type: String },
|
comment: { type: String },
|
||||||
|
|
||||||
accepted_by: { type: Schema.Types.ObjectId, ref: 'users' },
|
accepted_by: { type: Schema.Types.ObjectId, ref: 'users' }, // who accepts the proposal (shipper)
|
||||||
accepted_date: { type: Date },
|
accepted_date: { type: Date },
|
||||||
|
|
||||||
is_withdrawn: { type: Boolean, default: false },
|
is_withdrawn: { type: Boolean, default: false },
|
||||||
|
|||||||
Reference in New Issue
Block a user