You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
252 lines
6.4 KiB
252 lines
6.4 KiB
// client.js
|
|
// Copyright (C) 2024 DTP Technologies, LLC
|
|
// All Rights Reserved
|
|
|
|
'use strict';
|
|
|
|
import mongoose from 'mongoose';
|
|
const Client = mongoose.model('Client');
|
|
const ClientProject = mongoose.model('ClientProject');
|
|
|
|
import { SiteService/*, SiteError*/ } from '../../lib/site-lib.js';
|
|
|
|
export default class ClientService extends SiteService {
|
|
|
|
static get name ( ) { return 'ClientService'; }
|
|
static get slug () { return 'client'; }
|
|
|
|
constructor (dtp) {
|
|
super(dtp, ClientService);
|
|
}
|
|
|
|
async start ( ) {
|
|
const { user: userService } = this.dtp.services;
|
|
|
|
this.populateClient = [
|
|
{
|
|
path: 'user',
|
|
select: userService.USER_SELECT,
|
|
},
|
|
];
|
|
|
|
this.populateClientProject = [
|
|
{
|
|
path: 'user',
|
|
select: userService.USER_SELECT,
|
|
},
|
|
{
|
|
path: 'client',
|
|
populate: this.populateClient,
|
|
},
|
|
];
|
|
}
|
|
|
|
async createClient (user, clientDefinition) {
|
|
const { text: textService } = this.dtp.services;
|
|
|
|
const client = new Client();
|
|
client.user = user._id;
|
|
client.name = textService.filter(clientDefinition.name);
|
|
if (clientDefinition.description && clientDefinition.description.length > 0) {
|
|
client.description = textService.filter(clientDefinition.description);
|
|
}
|
|
client.hoursLimit = clientDefinition.hoursLimit;
|
|
|
|
await client.save();
|
|
|
|
return client.toObject();
|
|
}
|
|
|
|
async updateClient (client, clientDefinition) {
|
|
const { text: textService } = this.dtp.services;
|
|
const update = { $set: { }, $unset: { } };
|
|
|
|
let changed = false;
|
|
|
|
if (clientDefinition.name !== client.name) {
|
|
update.$set.name = textService.filter(clientDefinition.name);
|
|
changed = true;
|
|
}
|
|
|
|
if (clientDefinition.description && (clientDefinition.description.length > 0)) {
|
|
if (clientDefinition.description !== client.description) {
|
|
update.$set.description = textService.filter(clientDefinition.description);
|
|
changed = true;
|
|
}
|
|
} else {
|
|
update.$unset.description = 1;
|
|
changed = true;
|
|
}
|
|
|
|
if (clientDefinition.hoursLimit !== client.hoursLimit) {
|
|
update.$set.hoursLimit = clientDefinition.hoursLimit;
|
|
changed = true;
|
|
}
|
|
|
|
if (!changed) {
|
|
return;
|
|
}
|
|
|
|
await Client.updateOne({ _id: client._id }, update);
|
|
}
|
|
|
|
async getClientById (clientId) {
|
|
const client = Client
|
|
.findOne({ _id: clientId })
|
|
.populate(this.populateClient)
|
|
.lean();
|
|
return client;
|
|
}
|
|
|
|
async getClientsForUser (user) {
|
|
const clients = Client
|
|
.find({ user: user._id })
|
|
.sort({ name: 1 })
|
|
.populate(this.populateClient)
|
|
.lean();
|
|
return clients;
|
|
}
|
|
|
|
async createProject (client, projectDefinition) {
|
|
const { text: textService } = this.dtp.services;
|
|
|
|
const project = new ClientProject();
|
|
project.user = client.user._id;
|
|
project.client = client._id;
|
|
|
|
project.name = textService.filter(projectDefinition.name);
|
|
if (projectDefinition.description && (projectDefinition.description.length > 0)) {
|
|
project.description = textService.filter(projectDefinition.description);
|
|
}
|
|
|
|
project.hourlyRate = projectDefinition.hourlyRate;
|
|
|
|
await project.save();
|
|
|
|
return project.toObject();
|
|
}
|
|
|
|
async updateProject (project, projectDefinition) {
|
|
const { text: textService } = this.dtp.services;
|
|
const update = { $set: { }, $unset: { } };
|
|
let changed = false;
|
|
|
|
if (projectDefinition.name !== project.name) {
|
|
update.$set.name = textService.filter(projectDefinition.name);
|
|
changed = true;
|
|
}
|
|
if (projectDefinition.description !== project.description) {
|
|
update.$set.description = textService.filter(projectDefinition.description);
|
|
changed = true;
|
|
}
|
|
|
|
if (projectDefinition.hourlyRate !== project.hourlyRate) {
|
|
update.$set.hourlyRate = projectDefinition.hourlyRate;
|
|
changed = true;
|
|
}
|
|
|
|
if (!changed) {
|
|
return;
|
|
}
|
|
|
|
await ClientProject.updateOne({ _id: project._id }, update);
|
|
}
|
|
|
|
async getProjectById (projectId) {
|
|
const project = ClientProject
|
|
.findOne({ _id: projectId })
|
|
.populate(this.populateClientProject)
|
|
.lean();
|
|
return project;
|
|
}
|
|
|
|
async getProjectsForUser (user) {
|
|
const projects = ClientProject
|
|
.find({ user: user._id })
|
|
.sort({ created: -1 })
|
|
.populate(this.populateClientProject)
|
|
.lean();
|
|
return projects;
|
|
}
|
|
|
|
async getProjectsForClient (client) {
|
|
const projects = ClientProject
|
|
.find({ client: client._id })
|
|
.sort({ created: -1 })
|
|
.populate(this.populateClientProject)
|
|
.lean();
|
|
return projects;
|
|
}
|
|
|
|
async addTimeWorked (client, duration) {
|
|
const { task: taskService } = this.dtp.services;
|
|
|
|
const durationLimit = client.hoursLimit * 3600;
|
|
if ((client.weeklyTotals.timeWorked + duration) > durationLimit) {
|
|
this.log.alert('clamping time worked to weekly hours limit', {
|
|
user: {
|
|
_id: client.user._id,
|
|
username: client.user.username,
|
|
},
|
|
client: {
|
|
_id: client._id,
|
|
hoursLimit: client.hoursLimit,
|
|
},
|
|
});
|
|
await Client.updateOne(
|
|
{ _id: client._id },
|
|
{
|
|
$set: { 'weeklyTotals.timeWorked': durationLimit },
|
|
},
|
|
);
|
|
|
|
this.log.alert('Ending work sessions for user due to hours limit reached', {
|
|
user: {
|
|
_id: client.user._id,
|
|
username: client.user.username,
|
|
},
|
|
client: {
|
|
_id: client._id,
|
|
hoursLimit: client.hoursLimit,
|
|
},
|
|
});
|
|
await taskService.closeTaskSessionForUser(client.user);
|
|
|
|
const displayList = this.createDisplayList('session-control');
|
|
displayList.showNotification(
|
|
'Hours limit reached. The task work session has been closed.',
|
|
'danger',
|
|
'bottom-center',
|
|
5000,
|
|
);
|
|
|
|
this.dtp.emitter
|
|
.to(client.user._id.toString())
|
|
.emit('session-control', {
|
|
cmd: 'end-session',
|
|
displayList,
|
|
});
|
|
|
|
return;
|
|
}
|
|
|
|
this.log.info('adding time worked to client weekly totals', {
|
|
user: {
|
|
_id: client.user._id,
|
|
username: client.user.username,
|
|
},
|
|
client: {
|
|
_id: client._id,
|
|
hoursLimit: client.hoursLimit,
|
|
currentHours: client.weeklyTotals.timeWorked / 3600,
|
|
},
|
|
hours: duration / 3600,
|
|
});
|
|
await Client.updateOne(
|
|
{ _id: client._id },
|
|
{
|
|
$inc: { 'weeklyTotals.timeWorked': duration },
|
|
},
|
|
);
|
|
}
|
|
}
|