feat: Private Groups + Load-Templates

Private Groups enabled based on the following assumptions:

* There is only one private group.
* The companies added to the private group is able to find private loads in the directory.
* The companies added to the private group is able to find private companies in the directory.
* The driver requires a new endpoint to read load resources no matter the privacy rules (as long as they are added to the load as driver).
* The private group can be updated by anyone within the company.
* The privacy is enabled on the company information by enabling `privacy=true`.
* The privacy is enabled on the loads information by enabling `privacy=true`.
* When looking for loads/companies by default the search is with `privacy=false` which returns public elements. When `privacy=true`is given, the results are limited to private elements only (not including public elements).

Load-Templates enabled based on the following assumptions:

* Anyone can CRUD the templates, there is no find feature (for now). It is assumed that the number of templates is limited.
This commit is contained in:
Josepablo Cruz Baas
2026-03-31 02:02:30 +00:00
parent 57cd47558a
commit 82c2ea74e8
18 changed files with 672 additions and 55 deletions

View File

@@ -0,0 +1,116 @@
"use strict";
const { getModel } = require( '../../../lib/Models' );
const { getPagination } = require( '../../../lib/Misc.js' );
const CompanyModel = getModel('companies');
const CompanyGroupModel = getModel('company_groups');
const company_projection = 'company_name rfc categories products truck_type company_city company_state';
async function getOrCreatePrivateGroup( owner ) {
let result = await CompanyGroupModel
.findOne({ owner: owner })
.populate({
path: 'allowedCompanies',
select: company_projection,
populate: {
path: 'categories',
select: '-_id name'
}
});
if( result ){
return result;
}
result = new CompanyGroupModel({
owner: owner,
list_name: "private"
});
await result.save();
return await CompanyGroupModel
.findOne({ owner: owner })
.populate({
path: 'allowedCompanies',
select: company_projection,
populate: {
path: 'categories',
select: '-_id name'
}
});
}
async function getPrivateGroup( req , res ) {
try{
const companyId = req.context.companyId;
const result = await getOrCreatePrivateGroup( companyId );
return res.send( result );
}catch( error ){
console.error( error );
return res.status( 500 ).send({ error });
}
}
async function addCompanyToGroup(req, res){
try{
const companyId = req.context.companyId;
const newEntryId = req.params.id;
if( newEntryId === companyId ){
return res.status(400).send({ error: "can't add yourself" });
}
const company = await CompanyModel.findById( newEntryId );
if( !company ){
return res.status(400).send({ error: "invalid entry id" });
}
let result = await getOrCreatePrivateGroup( companyId );
/// Add to the list only if it is not there already
if( ! result.allowedCompanies.some( entry => entry.id === newEntryId ) ){
await CompanyGroupModel.findByIdAndUpdate(result.id, {
$addToSet: { allowedCompanies: company.id }
});
}
result = await getOrCreatePrivateGroup( companyId );
return res.status(200).send( result );
}catch(error){
console.error( error );
return res.status( 500 ).send({ error });
}
}
async function removeCompanyFromGroup(req, res){
try{
const companyId = req.context.companyId;
const newEntryId = req.params.id;
if( newEntryId === companyId ){
return res.status(400).send({ error: "you are not at the list" });
}
let result = await getOrCreatePrivateGroup( companyId );
/// If the item belongs to the list remove it
if( result.allowedCompanies.some( entry => entry.id === newEntryId ) ){
await CompanyGroupModel.findByIdAndUpdate(result.id, {
$pull: { allowedCompanies: newEntryId }
});
}
result = await getOrCreatePrivateGroup( companyId );
return res.status(200).send( result );
}catch(error){
console.error( error );
return res.status( 500 ).send({ error });
}
}
module.exports = {
getPrivateGroup,
addCompanyToGroup,
removeCompanyFromGroup
};