I want to create a status timeline. Similar to what we have with Uber or Lyft and I have my model schema to update so that I can keep track.
New request, Driver accepts, arrives, starts trip and ends trip.
I am keeping track of all these by updating the database and putting the time of update.
The problem I have now is it is possible to enter same entry eg
arrive pickup twice with different timestamp.
I do not want this to happen.
Once you arrive pickup, you cannot arrive pickup again, the most you can do should be able to return to the previous stage new request.
Here is my Schema
const StatusDataSchema = new Schema({
status: {
type: SchemaTypes.String,
enum: [
'new',
'acknowledged',
'assigned',
'start',
'arrived',
'end',
'rejected',
'cancelled',
'completed'
],
unique: true,
default: 'new'
},
message: {
type: SchemaTypes.String,
default: 'You created a new request'
},
createdAt: {
type: SchemaTypes.String,
required: false,
default: Date.now.toString()
},
updatedAt: {
type: SchemaTypes.Date,
required: false,
default: null
}
},
{
toJSON: {
virtuals: true,
versionKey: false,
transform: function (_, ret, __) {
const { _id, __v, ...rest } = ret;
return rest;
}
}
});
const DeliverySchema = SchemaFactory({
pickup: { type: PickupSchema, required: true },
dropoff: { type: DestinationSchema, required: true },
status: {
type: SchemaTypes.String,
enum: [
'new',
'acknowledged',
'assigned',
'toPickup',
'arrived',
'start',
'end',
'rejected',
'cancelled',
'completed'
],
unique: true,
default: 'new'
},
statusData: [StatusDataSchema],
})
Then I create like this
public async createReq(user: string, body: TripDTO) {
if (user !== body.user.id)
throw new ActionNotAllowedError(
'You cannot create a trip on the behalf of another user'
);
const data = await this.create({
...body
});
return data;
}
and I update like this
public async updateReq(id: string, body: StatusDeliveryDTO) {
var message = '';
var cancelReason = null;
var rejectReason = null;
var name = '';
if (body.driver == null) {
// do something
name = 'System';
} else {
name = body.driver.firstName;
}
if (body.status == 'assigned') {
message = `${name} has been assigned to you`;
} else if (body.status == 'new') {
message = 'You created a new request';
} else if (body.status == 'toPickup') {
message = `${name} is heading to your pickup location`;
} else if (body.status == 'arrived') {
message = `${name} has arrived your pickup`;
} else if (body.status == 'pickup') {
message = `${name} has picked`;
} else if (body.status == 'start') {
message = `${name} started`;
} else if (body.status == 'arrived') {
message = `${name} has arrived`;
} else if (body.status == 'completed') {
message = `${name} has completed`;
} else if (body.status == 'rejected') {
message = `${name} has rejected your request`;
rejectReason = body.reason;
} else if (body.status == 'cancelled') {
message = `${name} has canceled your request`;
cancelReason = body.reason;
} else {
message = body.status;
}
const data = await this.updateWithOperators(id, {
$push: {
statusData: {
status: body.status,
message: message,
createdAt: Date.now().toString()
}
},
cancelReason: cancelReason,
rejectReason: rejectReason,
...body
});
await NotificationService.dispatchTimeline(data.user.id, message);
return data;
}
The create function uses mongoose model.create while update uses model.findOneAndUpdate
How can I avoid the duplicate and keep a streamlined timeline.
Further code can be provided on request.