NMDSdevopsServiceAdm/SopraSteria-SFC

View on GitHub
backend/server/models/establishment.js

Summary

Maintainability
F
3 wks
Test Coverage
File `establishment.js` has 2331 lines of code (exceeds 250 allowed). Consider refactoring.
const { Op } = require('sequelize');
const moment = require('moment');
 
Function `exports` has 2327 lines of code (exceeds 25 allowed). Consider refactoring.
Function `exports` has a Cognitive Complexity of 50 (exceeds 5 allowed). Consider refactoring.
module.exports = function (sequelize, DataTypes) {
const Establishment = sequelize.define(
'establishment',
{
id: {
type: DataTypes.INTEGER,
allowNull: false,
primaryKey: true,
autoIncrement: true,
field: '"EstablishmentID"',
},
uid: {
type: DataTypes.UUID,
allowNull: false,
unique: true,
field: '"EstablishmentUID"',
},
ustatus: {
type: DataTypes.ENUM,
values: ['PENDING', 'IN PROGRESS', 'REJECTED'],
allowNull: true,
field: '"Status"',
},
address1: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address1"',
},
Address1SavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address1SavedAt"',
},
Address1ChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address1ChangedAt"',
},
Address1SavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address1SavedBy"',
},
Address1ChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address1ChangedBy"',
},
address2: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address2"',
},
Address2SavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address2SavedAt"',
},
Address2ChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address2ChangedAt"',
},
Address2SavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address2SavedBy"',
},
Address2ChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address2ChangedBy"',
},
address3: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address3"',
},
Address3SavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address3SavedAt"',
},
Address3ChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"Address3ChangedAt"',
},
Address3SavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address3SavedBy"',
},
Address3ChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Address3ChangedBy"',
},
town: {
type: DataTypes.TEXT,
allowNull: true,
field: '"Town"',
},
TownSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"TownSavedAt"',
},
TownChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"TownChangedAt"',
},
TownSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"TownSavedBy"',
},
TownChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"TownChangedBy"',
},
county: {
type: DataTypes.TEXT,
allowNull: true,
field: '"County"',
},
CountySavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"CountySavedAt"',
},
CountyChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"CountyChangedAt"',
},
CountySavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"CountySavedBy"',
},
CountyChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"CountyChangedBy"',
},
locationId: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"LocationID"',
},
LocationIdSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LocationIdSavedAt"',
},
LocationIdChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LocationIdChangedAt"',
},
LocationIdSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LocationIdSavedBy"',
},
LocationIdChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LocationIdChangedBy"',
},
provId: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"ProvID"',
},
postcode: {
type: DataTypes.TEXT,
allowNull: false,
field: '"PostCode"',
},
PostcodeSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"PostcodeSavedAt"',
},
PostcodeChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"PostcodeChangedAt"',
},
PostcodeSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"PostcodeSavedBy"',
},
PostcodeChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"PostcodeChangedBy"',
},
isRegulated: {
type: DataTypes.BOOLEAN,
allowNull: false,
field: '"IsRegulated"',
},
IsRegulatedSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"IsRegulatedSavedAt"',
},
IsRegulatedChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"IsRegulatedChangedAt"',
},
IsRegulatedSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"IsRegulatedSavedBy"',
},
IsRegulatedChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"IsRegulatedChangedBy"',
},
overallWdfEligibility: {
type: DataTypes.DATE,
allowNull: true,
field: '"OverallWdfEligibility"',
},
establishmentWdfEligibility: {
type: DataTypes.DATE,
allowNull: true,
field: '"EstablishmentWdfEligibility"',
},
staffWdfEligibility: {
type: DataTypes.DATE,
allowNull: true,
field: '"StaffWdfEligibility"',
},
lastWdfEligibility: {
type: DataTypes.DATE,
allowNull: true,
field: '"LastWdfEligibility"',
},
isParent: {
type: DataTypes.BOOLEAN,
allowNull: false,
default: false,
field: '"IsParent"',
},
parentId: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"ParentID"',
},
parentUid: {
type: DataTypes.UUID,
allowNull: true,
field: '"ParentUID"',
},
dataOwner: {
type: DataTypes.ENUM,
allowNull: false,
values: ['Workplace', 'Parent'],
field: '"DataOwner"',
default: 'Workplace',
},
dataPermissions: {
type: DataTypes.ENUM,
allowNull: true,
values: ['Workplace', 'Workplace and Staff', 'None'],
field: '"DataPermissions"',
},
NameValue: {
type: DataTypes.TEXT,
allowNull: false,
unique: true,
field: '"NameValue"',
},
NameSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"NameSavedAt"',
},
NameChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"NameChangedAt"',
},
NameSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"NameSavedBy"',
},
NameChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"NameChangedBy"',
},
MainServiceFKValue: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"MainServiceFKValue"',
},
MainServiceFKSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"MainServiceFKSavedAt"',
},
MainServiceFKChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"MainServiceFKChangedAt"',
},
MainServiceFKSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"MainServiceFKSavedBy"',
},
MainServiceFKChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"MainServiceFKChangedBy"',
},
MainServiceFkOther: {
type: DataTypes.TEXT,
allowNull: true,
primaryKey: false,
field: '"MainServiceFkOther"',
},
EmployerTypeValue: {
type: DataTypes.ENUM,
allowNull: true,
values: [
'Private Sector',
'Voluntary / Charity',
'Other',
'Local Authority (generic/other)',
'Local Authority (adult services)',
],
field: '"EmployerTypeValue"',
},
EmployerTypeSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"EmployerTypeSavedAt"',
},
EmployerTypeChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"EmployerTypeChangedAt"',
},
EmployerTypeSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"EmployerTypeSavedBy"',
},
EmployerTypeChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"EmployerTypeChangedBy"',
},
EmployerTypeOther: {
type: DataTypes.TEXT,
allowNull: true,
primaryKey: false,
field: '"EmployerTypeOther"',
},
NumberOfStaffValue: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"NumberOfStaffValue"',
},
NumberOfStaffSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"NumberOfStaffSavedAt"',
},
NumberOfStaffChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"NumberOfStaffChangedAt"',
},
NumberOfStaffSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"NumberOfStaffSavedBy"',
},
NumberOfStaffChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"NumberOfStaffChangedBy"',
},
otherServicesValue: {
type: DataTypes.ENUM,
allowNull: true,
field: '"OtherServicesValue"',
values: ['No', 'Yes'],
},
OtherServicesSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"OtherServicesSavedAt"',
},
OtherServicesChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"OtherServicesChangedAt"',
},
OtherServicesSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"OtherServicesSavedBy"',
},
OtherServicesChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"OtherServicesChangedBy"',
},
ServiceUsersSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"ServiceUsersSavedAt"',
},
ServiceUsersChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"ServiceUsersChangedAt"',
},
ServiceUsersSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"ServiceUsersSavedBy"',
},
ServiceUsersChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"ServiceUsersChangedBy"',
},
CapacityServicesSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"CapacityServicesSavedAt"',
},
CapacityServicesChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"CapacityServicesChangedAt"',
},
CapacityServicesSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"CapacityServicesSavedBy"',
},
CapacityServicesChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"CapacityServicesChangedBy"',
},
ShareDataSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"ShareDataSavedAt"',
},
ShareDataChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"ShareDataChangedAt"',
},
ShareDataSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"ShareDataSavedBy"',
},
ShareDataChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"ShareDataChangedBy"',
},
shareWithCQC: {
type: DataTypes.BOOLEAN,
allowNull: true,
field: '"ShareDataWithCQC"',
},
shareWithLA: {
type: DataTypes.BOOLEAN,
allowNull: true,
field: '"ShareDataWithLA"',
},
VacanciesValue: {
type: DataTypes.ENUM,
allowNull: true,
values: ['None', "Don't know", 'With Jobs'],
field: '"VacanciesValue"',
},
VacanciesSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"VacanciesSavedAt"',
},
VacanciesChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"VacanciesChangedAt"',
},
VacanciesSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"VacanciesSavedBy"',
},
VacanciesChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"VacanciesChangedBy"',
},
StartersValue: {
type: DataTypes.ENUM,
allowNull: true,
values: ['None', "Don't know", 'With Jobs'],
field: '"StartersValue"',
},
StartersSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"StartersSavedAt"',
},
StartersChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"StartersChangedAt"',
},
StartersSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"StartersSavedBy"',
},
StartersChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"StartersChangedBy"',
},
LeaversValue: {
type: DataTypes.ENUM,
allowNull: true,
values: ['None', "Don't know", 'With Jobs'],
field: '"LeaversValue"',
},
LeaversSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LeaversSavedAt"',
},
LeaversChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LeaversChangedAt"',
},
LeaversSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LeaversSavedBy"',
},
LeaversChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LeaversChangedBy"',
},
LocalIdentifierValue: {
type: DataTypes.TEXT,
allowNull: true,
unique: true,
field: '"LocalIdentifierValue"',
},
LocalIdentifierSavedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LocalIdentifierSavedAt"',
},
LocalIdentifierChangedAt: {
type: DataTypes.DATE,
allowNull: true,
field: '"LocalIdentifierChangedAt"',
},
LocalIdentifierSavedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LocalIdentifierSavedBy"',
},
LocalIdentifierChangedBy: {
type: DataTypes.TEXT,
allowNull: true,
field: '"LocalIdentifierChangedBy"',
},
archived: {
type: DataTypes.BOOLEAN,
allowNull: false,
field: '"Archived"',
defaultValue: false,
},
nmdsId: {
type: DataTypes.TEXT,
allowNull: false,
field: '"NmdsID"',
},
source: {
type: DataTypes.ENUM,
allowNull: false,
values: ['Online', 'Bulk'],
default: 'Online',
field: '"DataSource"',
},
lastBulkUploaded: {
type: DataTypes.DATE,
allowNull: true,
field: '"LastBulkUploaded"',
},
dataOwnershipRequested: {
type: DataTypes.DATE,
allowNull: true,
field: '"DataOwnershipRequested"',
},
linkToParentRequested: {
type: DataTypes.DATE,
allowNull: true,
field: '"LinkToParentRequested"',
},
reasonsForLeaving: {
type: DataTypes.TEXT,
allowNull: true,
field: '"ReasonsForLeaving"',
},
created: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
field: 'created',
},
updated: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: DataTypes.NOW,
field: 'updated',
},
updatedBy: {
type: DataTypes.TEXT,
allowNull: false,
field: 'updatedby',
},
laReportLockHeld: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'LaReportLockHeld',
},
eightWeeksFromFirstLogin: {
type: DataTypes.DATE,
allowNull: true,
field: 'eightWeeksFromFirstLogin',
},
reviewer: {
type: DataTypes.TEXT,
allowNull: true,
field: 'Reviewer',
},
inReview: {
type: DataTypes.BOOLEAN,
allowNull: true,
defaultValue: false,
field: 'InReview',
},
showSharingPermissionsBanner: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'ShowSharingPermissionsBanner',
},
expiresSoonAlertDate: {
type: DataTypes.ENUM,
allowNull: false,
values: ['90', '60', '30'],
default: '90',
field: 'ExpiresSoonAlertDate',
},
dataChangesLastUpdated: {
type: DataTypes.DATE,
allowNull: true,
field: 'DataChangesLastUpdated',
},
isNationalOrg: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'IsNationalOrg',
},
peopleInterviewedInTheLastFourWeeks: {
type: DataTypes.TEXT,
allowNull: true,
field: '"PeopleInterviewedInTheLastFourWeeks"',
},
moneySpentOnAdvertisingInTheLastFourWeeks: {
type: DataTypes.TEXT,
allowNull: true,
field: '"MoneySpentOnAdvertisingInTheLastFourWeeks"',
},
doNewStartersRepeatMandatoryTrainingFromPreviousEmployment: {
type: DataTypes.ENUM,
allowNull: true,
values: ['Yes, always', 'Yes, very often', 'Yes, but not very often', 'No, never'],
field: '"DoNewStartersRepeatMandatoryTrainingFromPreviousEmployment"',
},
wouldYouAcceptCareCertificatesFromPreviousEmployment: {
type: DataTypes.ENUM,
allowNull: true,
values: ['Yes, always', 'Yes, very often', 'Yes, but not very often', 'No, never'],
field: '"WouldYouAcceptCareCertificatesFromPreviousEmployment"',
},
recruitmentJourneyExistingUserBanner: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false,
field: 'RecruitmentJourneyExistingUserBanner',
},
showAddWorkplaceDetailsBanner: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: true,
field: 'ShowAddWorkplaceDetailsBanner',
},
careWorkersLeaveDaysPerYear: {
type: DataTypes.TEXT,
allowNull: true,
field: 'CareWorkersLeaveDaysPerYear',
},
careWorkersCashLoyaltyForFirstTwoYears: {
type: DataTypes.TEXT,
allowNull: true,
field: 'CareWorkersCashLoyaltyForFirstTwoYears',
},
pensionContribution: {
type: DataTypes.ENUM,
allowNull: true,
values: ['Yes', 'No', "Don't know"],
field: 'PensionContribution',
},
sickPay: {
type: DataTypes.ENUM,
allowNull: true,
values: ['Yes', 'No', "Don't know"],
field: 'SickPay',
},
isParentApprovedBannerViewed: {
type: DataTypes.BOOLEAN,
allowNull: true,
field: 'IsParentApprovedBannerViewed',
},
cssrId: {
type: DataTypes.INTEGER,
allowNull: true,
field: '"CssrID"',
},
},
{
defaultScope: {
where: {
archived: false,
},
},
scopes: {
noUstatus: {
where: {
ustatus: {
[Op.is]: null,
},
},
},
noLocalIdentifier: {
where: {
LocalIdentifierValue: {
[Op.is]: null,
},
},
},
parentAndChildWorkplaces: function (establishmentId) {
return {
where: {
[Op.or]: [
{
id: establishmentId,
},
{
parentId: establishmentId,
dataOwner: 'Parent',
},
],
},
};
},
withEstablishmentId: function (establishmentId) {
return {
where: {
id: establishmentId,
},
};
},
},
tableName: '"Establishment"',
schema: 'cqc',
createdAt: false,
updatedAt: false,
},
);
 
Function `associate` has 81 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.associate = (models) => {
Establishment.belongsTo(models.establishment, {
as: 'Parent',
foreignKey: 'ParentID',
targetKey: 'id',
});
Establishment.belongsTo(models.lastUpdatedEstablishmentsView, {
as: 'LastUpdated',
foreignKey: 'id',
targetKey: 'id',
});
Establishment.belongsTo(models.establishmentLastActivityView, {
as: 'LastActivity',
foreignKey: 'id',
targetKey: 'id',
});
 
Establishment.hasMany(models.user, {
foreignKey: 'establishmentId',
sourceKey: 'id',
as: 'users',
});
Establishment.belongsTo(models.services, {
foreignKey: 'MainServiceFKValue',
targetKey: 'id',
as: 'mainService',
});
Establishment.belongsToMany(models.services, {
through: 'establishmentServices',
foreignKey: 'establishmentId',
targetKey: 'id',
as: 'otherServices',
});
Establishment.belongsToMany(models.serviceUsers, {
through: 'establishmentServiceUsers',
foreignKey: 'establishmentId',
targetKey: 'id',
as: 'serviceUsers',
});
Establishment.hasMany(models.establishmentCapacity, {
foreignKey: 'establishmentId',
sourceKey: 'id',
as: 'capacity',
});
Establishment.hasMany(models.establishmentJobs, {
foreignKey: 'establishmentId',
sourceKey: 'id',
as: 'jobs',
});
Establishment.hasMany(models.establishmentAudit, {
foreignKey: 'establishmentFk',
sourceKey: 'id',
as: 'auditEvents',
hooks: true,
onDelete: 'CASCADE',
});
Establishment.hasMany(models.worker, {
foreignKey: 'establishmentFk',
sourceKey: 'id',
as: 'workers',
onDelete: 'CASCADE',
});
Establishment.hasMany(models.notes, {
foreignKey: 'establishmentFk',
sourceKey: 'id',
as: 'notes',
onDelete: 'CASCADE',
});
Establishment.hasMany(models.establishment, {
foreignKey: 'parentId',
sourceKey: 'id',
as: 'Subsidiaries',
});
Establishment.hasMany(models.Approvals, {
foreignKey: 'ID',
sourceKey: 'id',
as: 'Approvals',
});
Establishment.hasMany(models.MandatoryTraining, {
foreignKey: 'establishmentFK',
sourceKey: 'id',
as: 'MandatoryTraining',
});
};
 
Establishment.turnoverAndVacanciesData = function (establishmentId) {
return this.findByPk(establishmentId, {
attributes: ['id', 'NumberOfStaffValue', 'LeaversValue', 'VacanciesValue'],
});
};
 
Establishment.turnoverData = function (establishmentId) {
return this.findByPk(establishmentId, {
attributes: ['id', 'NumberOfStaffValue', 'LeaversValue'],
});
};
 
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.updateCssrIdsByPostcode = async function (postcode, cssrId) {
return await this.update(
{ cssrId: cssrId },
{
where: {
postcode: postcode,
},
},
);
};
 
Establishment.findWithWorkersAndTraining = function (establishmentId) {
return this.findByPk(establishmentId, {
attributes: ['id'],
include: {
model: sequelize.models.worker,
attributes: ['id', 'uid', 'NameOrIdValue'],
as: 'workers',
where: {
archived: false,
},
include: [
{
model: sequelize.models.job,
as: 'mainJob',
attributes: ['id', 'title'],
required: false,
},
{
model: sequelize.models.workerTraining,
as: 'workerTraining',
attributes: ['id', 'uid', 'title', 'expires', 'categoryFk'],
},
],
},
});
};
 
Establishment.findbyId = async function (id) {
return await this.findOne({
where: {
id,
},
});
};
 
Establishment.findAllbyId = async function (id) {
return await this.findAll({
where: {
id,
},
});
};
 
Establishment.findbyIdWithMainService = async function (id) {
return await this.findOne({
where: {
id,
},
include: {
model: sequelize.models.services,
as: 'mainService',
},
});
};
 
Establishment.findByUid = async function (uid, isRegistration = false) {
return await this.findOne({
where: {
uid,
archived: isRegistration ? { [Op.or]: [true, false] } : false,
},
});
};
 
Establishment.findEstablishmentWithSameNmdsId = async function (uid, nmdsId) {
return await this.findOne({
where: {
uid: {
[Op.ne]: uid,
},
nmdsId: nmdsId,
},
attributes: ['id'],
});
};
 
Establishment.find = async function (where) {
return await this.findOne({
where: {
archived: false,
...where,
},
attributes: [
'id',
'uid',
'ustatus',
'locationId',
'provId',
'isRegulated',
'isParent',
'parentId',
'NameValue',
'nmdsId',
],
});
};
 
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.closeLock = async function (LockHeldTitle, establishmentId) {
return await this.update(
{
[LockHeldTitle]: true,
},
{
where: {
id: establishmentId,
[LockHeldTitle]: false,
},
},
);
};
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.openLock = async function (LockHeldTitle, establishmentId) {
return await this.update(
{
[LockHeldTitle]: false,
},
{
where: {
id: establishmentId,
},
},
);
};
 
Establishment.workers = async function (establishmentId, where, attribute) {
return this.findOne({
attributes: ['id'],
include: {
model: sequelize.models.worker,
attributes: ['id', 'uid', ...attribute],
as: 'workers',
where,
},
where: {
id: establishmentId,
},
});
};
 
Function `searchEstablishments` has 70 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.searchEstablishments = async function (where) {
return await this.findAll({
attributes: [
'id',
'uid',
'NameValue',
'nmdsId',
'isRegulated',
'isParent',
'address1',
'address2',
'town',
'county',
'postcode',
'locationId',
'dataOwner',
'updated',
'provId',
'EmployerTypeValue',
'EmployerTypeOther',
],
where: {
ustatus: {
[Op.is]: null,
},
...where,
},
order: [['NameValue', 'ASC']],
include: [
{
model: sequelize.models.establishment,
attributes: ['id', 'uid', 'nmdsId'],
as: 'Parent',
required: false,
},
{
model: sequelize.models.establishment,
attributes: ['NameValue'],
as: 'Subsidiaries',
required: false,
},
{
model: sequelize.models.user,
attributes: ['id', 'uid', 'FullNameValue', 'SecurityQuestionValue', 'SecurityQuestionAnswerValue'],
as: 'users',
required: false,
where: {
UserRoleValue: 'Edit',
archived: false,
},
include: [
{
model: sequelize.models.login,
attributes: ['username', 'isActive'],
},
],
},
{
model: sequelize.models.notes,
attributes: ['note', 'createdAt', 'noteType'],
as: 'notes',
include: [
{
model: sequelize.models.user,
attributes: ['FullNameValue'],
as: 'user',
},
],
},
],
});
};
 
Function `generateDeleteReportData` has 65 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.generateDeleteReportData = async function (lastUpdatedDate) {
await sequelize.query('REFRESH MATERIALIZED VIEW cqc."EstablishmentLastActivity"');
 
const date = new Date(lastUpdatedDate).toISOString();
const whereCondition = sequelize.literal(`NOT EXISTS
(
SELECT s."EstablishmentID" AS EstablishmentID
FROM cqc."EstablishmentLastActivity" s
WHERE s."IsParent" = true AND EXISTS
(
SELECT c."EstablishmentID"
FROM cqc."EstablishmentLastActivity" c
WHERE s."EstablishmentID" = c."ParentID"
AND c."LastLogin" > '${date}'
AND c."LastUpdated" > '${date}'
AND c."IsParent"= false
) AND s."EstablishmentID" = establishment."EstablishmentID")`);
 
return await this.findAll({
attributes: [
'uid',
'id',
'NameValue',
'nmdsId',
'isRegulated',
'address1',
'address2',
'address3',
'town',
'county',
'postcode',
'locationId',
'EmployerTypeValue',
'EmployerTypeOther',
],
order: [['NameValue', 'ASC']],
include: [
{
model: sequelize.models.establishmentLastActivityView,
as: 'LastActivity',
attributes: ['id', 'dataOwner', 'lastUpdated', 'lastLogin'],
where: {
lastUpdated: {
[Op.lte]: lastUpdatedDate,
},
lastLogin: {
[Op.or]: {
[Op.lte]: lastUpdatedDate,
[Op.is]: null,
},
},
whereCondition,
},
order: [['lastUpdated', 'DESC']],
},
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['name'],
},
{
model: sequelize.models.establishment,
as: 'Parent',
attributes: ['NameValue'],
required: false,
},
],
});
};
 
Establishment.getMissingEstablishmentRefCount = async function (establishmentId, isParent) {
const scopes = ['defaultScope', 'noUstatus', 'noLocalIdentifier'];
 
Identical blocks of code found in 3 locations. Consider refactoring.
if (isParent) {
scopes.push({ method: ['parentAndChildWorkplaces', establishmentId] });
} else {
scopes.push({ method: ['withEstablishmentId', establishmentId] });
}
return await this.scope(scopes).count();
};
 
Function `getEstablishmentWithPrimaryUser` has 59 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getEstablishmentWithPrimaryUser = async function (uid, isRegistration = false) {
return await this.findOne({
attributes: [
'NameValue',
'IsRegulated',
'LocationID',
'ProvID',
'Address1',
'Address2',
'Address3',
'Town',
'County',
'PostCode',
'NmdsID',
'EstablishmentID',
'ParentID',
'ParentUID',
'created',
'updatedBy',
'Status',
'EstablishmentUID',
'Reviewer',
'InReview',
'EmployerTypeValue',
'EmployerTypeOther',
],
where: {
uid,
archived: isRegistration ? { [Op.or]: [true, false] } : false,
},
include: [
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['id', 'name'],
},
{
model: sequelize.models.user,
as: 'users',
attributes: [
'EmailValue',
'PhoneValue',
'FullNameValue',
'SecurityQuestionValue',
'SecurityQuestionAnswerValue',
'created',
],
where: {
isPrimary: true,
},
required: false,
include: [
{
model: sequelize.models.login,
attributes: ['id', 'username'],
},
],
},
],
});
};
 
Establishment.getEstablishmentRegistrationsByStatus = async function (isRejection) {
const params = isRejection
? { ustatus: 'REJECTED', archived: true }
: { ustatus: { [Op.or]: ['PENDING', 'IN PROGRESS'] } };
 
return await this.findAll({
attributes: [
'NameValue',
'PostCode',
'ParentID',
'ParentUID',
'created',
'updated',
'Status',
'EstablishmentUID',
'IsRegulated',
],
where: params,
order: [['created', 'DESC']],
});
};
 
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.getNmdsIdUsingEstablishmentId = async function (id) {
return await this.findOne({
where: {
id: id,
},
attributes: ['NmdsID'],
});
};
 
Establishment.getEstablishmentsWithMissingWorkerRef = async function (establishmentId, isParent) {
const scopes = ['defaultScope', 'noUstatus'];
 
Identical blocks of code found in 3 locations. Consider refactoring.
if (isParent) {
scopes.push({ method: ['parentAndChildWorkplaces', establishmentId] });
} else {
scopes.push({ method: ['withEstablishmentId', establishmentId] });
}
 
return this.scope(scopes).findAll({
attributes: ['uid', 'NameValue'],
include: {
attributes: ['id'],
model: sequelize.models.worker.scope('active', 'noLocalIdentifier'),
as: 'workers',
},
});
};
 
Establishment.getMissingWorkerRefCount = async function (establishmentId, isParent) {
const scopes = ['defaultScope', 'noUstatus'];
 
Identical blocks of code found in 3 locations. Consider refactoring.
if (isParent) {
scopes.push({ method: ['parentAndChildWorkplaces', establishmentId] });
} else {
scopes.push({ method: ['withEstablishmentId', establishmentId] });
}
return await this.scope(scopes).count({
include: {
model: sequelize.models.worker.scope('active', 'noLocalIdentifier'),
as: 'workers',
},
});
};
 
Function `downloadEstablishments` has 94 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.downloadEstablishments = async function (establishmentId) {
return await this.findAll({
attributes: [
'LocalIdentifierValue',
'id',
'NameValue',
'address1',
'address2',
'address3',
'town',
'postcode',
'EmployerTypeValue',
'EmployerTypeOther',
'isRegulated',
'shareWithCQC',
'shareWithLA',
'provId',
'locationId',
'NumberOfStaffValue',
'VacanciesValue',
'StartersValue',
'LeaversValue',
'reasonsForLeaving',
'moneySpentOnAdvertisingInTheLastFourWeeks',
'peopleInterviewedInTheLastFourWeeks',
'doNewStartersRepeatMandatoryTrainingFromPreviousEmployment',
'wouldYouAcceptCareCertificatesFromPreviousEmployment',
'careWorkersLeaveDaysPerYear',
'careWorkersCashLoyaltyForFirstTwoYears',
'sickPay',
'pensionContribution',
],
Identical blocks of code found in 3 locations. Consider refactoring.
where: {
[Op.or]: [
{
id: establishmentId,
dataOwner: 'Workplace',
},
{
parentId: establishmentId,
dataOwner: 'Parent',
},
],
archived: false,
ustatus: {
[Op.is]: null,
},
},
include: [
{
model: sequelize.models.establishment,
attributes: ['id', 'uid', 'nmdsId'],
as: 'Parent',
required: false,
},
{
model: sequelize.models.services,
attributes: ['id', 'reportingID'],
as: 'mainService',
},
{
model: sequelize.models.services,
attributes: ['id', 'reportingID'],
as: 'otherServices',
},
{
model: sequelize.models.serviceUsers,
as: 'serviceUsers',
},
{
model: sequelize.models.establishmentCapacity,
attributes: ['id', 'serviceCapacityId', 'answer'],
as: 'capacity',
include: [
{
model: sequelize.models.serviceCapacity,
as: 'reference',
attributes: ['id', 'question', 'type'],
include: [
{
model: sequelize.models.services,
attributes: ['id', 'reportingID'],
as: 'service',
},
],
},
],
},
{
model: sequelize.models.establishmentJobs,
attributes: ['jobId', 'type', 'total'],
as: 'jobs',
},
],
});
};
 
Function `downloadWorkers` has 108 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.downloadWorkers = async function (establishmentId) {
return await this.findAll({
attributes: ['LocalIdentifierValue', 'id'],
Identical blocks of code found in 3 locations. Consider refactoring.
where: {
[Op.or]: [
{
id: establishmentId,
dataOwner: 'Workplace',
},
{
parentId: establishmentId,
dataOwner: 'Parent',
},
],
archived: false,
ustatus: {
[Op.is]: null,
},
},
include: [
{
model: sequelize.models.worker,
attributes: [
'id',
'uid',
'LocalIdentifierValue',
'NameOrIdValue',
'NationalInsuranceNumberValue',
'PostcodeValue',
'DateOfBirthValue',
'GenderValue',
'NationalityValue',
'BritishCitizenshipValue',
'CountryOfBirthValue',
'YearArrivedValue',
'YearArrivedYear',
'DisabilityValue',
'CareCertificateValue',
'RecruitedFromValue',
'MainJobStartDateValue',
'SocialCareStartDateValue',
'SocialCareStartDateYear',
'ApprenticeshipTrainingValue',
'ContractValue',
'ZeroHoursContractValue',
'DaysSickValue',
'DaysSickDays',
'AnnualHourlyPayValue',
'AnnualHourlyPayRate',
'MainJobFkOther',
'WeeklyHoursContractedValue',
'WeeklyHoursContractedHours',
'WeeklyHoursAverageValue',
'WeeklyHoursAverageHours',
'NurseSpecialismsValue',
'RegisteredNurseValue',
'ApprovedMentalHealthWorkerValue',
'QualificationInSocialCareValue',
'OtherQualificationsValue',
],
as: 'workers',
where: {
archived: false,
},
include: [
{
model: sequelize.models.ethnicity,
as: 'ethnicity',
},
{
model: sequelize.models.nationality,
as: 'nationality',
},
{
model: sequelize.models.country,
as: 'countryOfBirth',
},
{
model: sequelize.models.recruitedFrom,
as: 'recruitedFrom',
},
{
model: sequelize.models.job,
as: 'mainJob',
},
{
model: sequelize.models.qualification,
as: 'highestQualification',
},
{
model: sequelize.models.qualification,
as: 'socialCareQualification',
},
{
model: sequelize.models.workerNurseSpecialism,
as: 'nurseSpecialisms',
},
{
model: sequelize.models.workerQualifications,
as: 'qualifications',
include: {
model: sequelize.models.workerAvailableQualifications,
as: 'qualification',
},
},
],
},
],
});
};
 
Function `downloadTrainingRecords` has 40 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.downloadTrainingRecords = async function (establishmentId) {
return await this.findAll({
attributes: ['LocalIdentifierValue', 'id'],
Identical blocks of code found in 3 locations. Consider refactoring.
where: {
[Op.or]: [
{
id: establishmentId,
dataOwner: 'Workplace',
},
{
parentId: establishmentId,
dataOwner: 'Parent',
},
],
archived: false,
ustatus: {
[Op.is]: null,
},
},
include: [
{
model: sequelize.models.worker,
attributes: ['LocalIdentifierValue', 'id'],
as: 'workers',
where: {
archived: false,
},
include: [
{
attributes: ['title', 'completed', 'expires', 'accredited', 'notes'],
model: sequelize.models.workerTraining,
as: 'workerTraining',
include: {
model: sequelize.models.workerTrainingCategories,
as: 'category',
},
},
],
},
],
});
};
 
// DO NOT USE if property is tracked (updatedBy, audit logs etc.)
Establishment.updateEstablishment = async function (establishmentId, updatedEstablishment) {
return await this.update(updatedEstablishment, {
where: {
id: establishmentId,
},
});
};
 
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.findByLocationID = async function (locationID) {
return await this.findAll({
where: {
locationId: locationID,
},
attributes: ['locationId'],
});
};
 
Establishment.findEstablishmentsByLocationID = async function (locationIDs) {
return await this.findAll({
where: {
locationId: {
[Op.or]: locationIDs,
},
},
attributes: ['locationId'],
});
};
 
Function `workersAndTraining` has 188 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.workersAndTraining = async function (
Function `workersAndTraining` has 7 arguments (exceeds 4 allowed). Consider refactoring.
establishmentId,
includeMandatoryTrainingBreakdown = false,
isParent = false,
limit = 0,
pageIndex = 0,
sortBy = 'staffNameAsc',
searchTerm = '',
) {
const currentDate = moment().toISOString();
const expiresSoonAlertDate = await this.getExpiresSoonAlertDate(establishmentId);
const expiresSoon = moment().add(expiresSoonAlertDate.get('ExpiresSoonAlertDate'), 'days').toISOString();
const offset = pageIndex * limit;
 
let attributes = [
'id',
'uid',
'LocalIdentifierValue',
'NameOrIdValue',
'ContractValue',
'CompletedValue',
'created',
'updated',
'updatedBy',
'lastWdfEligibility',
'wdfEligible',
[
sequelize.literal('(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID")'),
'trainingCount',
],
[
sequelize.literal('(SELECT COUNT(0) FROM cqc."WorkerQualifications" WHERE "WorkerFK" = "workers"."ID")'),
'qualificationCount',
],
[
sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND "Expires" < '${currentDate}')`,
),
'expiredTrainingCount',
],
[
sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND "Expires" BETWEEN '${currentDate}' AND '${expiresSoon}')`,
),
'expiringTrainingCount',
],
[
sequelize.literal(
`
(
SELECT
COUNT(0)
FROM cqc."MandatoryTraining"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
AND "TrainingCategoryFK" NOT IN (
SELECT
DISTINCT "CategoryFK"
FROM cqc."WorkerTraining"
WHERE "WorkerFK" = "workers"."ID"
)
)
`,
),
'missingMandatoryTrainingCount',
],
[
sequelize.literal('(SELECT MAX("updated") FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID")'),
'trainingLastUpdated',
],
[
sequelize.literal('(SELECT MAX("updated") FROM cqc."WorkerQualifications" WHERE "WorkerFK" = "workers"."ID")'),
'qualificationsLastUpdated',
],
'LongTermAbsence',
];
 
if (includeMandatoryTrainingBreakdown) {
const mandatoryTrainingAttributes = [
[
sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND "Expires" < '${currentDate}' AND "CategoryFK" IN
(
SELECT DISTINCT "TrainingCategoryFK" FROM cqc."MandatoryTraining"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
)
)`,
),
'expiredMandatoryTrainingCount',
],
[
sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND "CategoryFK" IN
(
SELECT DISTINCT "TrainingCategoryFK" FROM cqc."MandatoryTraining"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
)
)`,
),
'mandatoryTrainingCount',
],
[
sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND "Expires" BETWEEN '${currentDate}' AND '${expiresSoon}' AND "CategoryFK" IN
(
SELECT DISTINCT "TrainingCategoryFK" FROM cqc."MandatoryTraining"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
)
)`,
),
'expiringMandatoryTrainingCount',
],
];
 
attributes = [...attributes, ...mandatoryTrainingAttributes];
}
 
let subsidiaries = [];
if (isParent) {
subsidiaries = [
{
parentId: establishmentId,
dataOwner: 'Parent',
},
{
parentId: establishmentId,
dataOwner: 'Workplace',
dataPermissions: 'Workplace and Staff',
},
];
}
 
const workerPagination = {
subQuery: false,
limit,
offset,
};
 
const order = {
staffNameAsc: [['workers', 'NameOrIdValue', 'ASC']],
staffNameDesc: [['workers', 'NameOrIdValue', 'DESC']],
jobRoleAsc: [[sequelize.literal('"workers.mainJob.jobRoleName"'), 'ASC']],
jobRoleDesc: [[sequelize.literal('"workers.mainJob.jobRoleName"'), 'DESC']],
wdfMeeting: [['workers', 'wdfEligible', 'DESC']],
wdfNotMeeting: [['workers', 'wdfEligible', 'ASC']],
trainingExpiringSoon: [
[sequelize.literal('"workers.expiringTrainingCount"'), 'DESC'],
['workers', 'NameOrIdValue', 'ASC'],
],
trainingExpired: [
[sequelize.literal('"workers.expiredTrainingCount"'), 'DESC'],
['workers', 'NameOrIdValue', 'ASC'],
],
trainingMissing: [
[sequelize.literal('"workers.missingMandatoryTrainingCount"'), 'DESC'],
['workers', 'NameOrIdValue', 'ASC'],
],
}[sortBy] || [['workers', 'NameOrIdValue', 'ASC']];
 
return this.findAndCountAll({
attributes: ['id', 'NameValue'],
where: {
[Op.or]: [
{
id: establishmentId,
},
...subsidiaries,
],
},
include: [
{
model: sequelize.models.worker,
as: 'workers',
attributes,
Similar blocks of code found in 2 locations. Consider refactoring.
where: {
archived: false,
...(searchTerm ? { NameOrIdValue: { [Op.iLike]: `%${searchTerm}%` } } : {}),
},
required: true,
include: [
{
model: sequelize.models.job,
as: 'mainJob',
attributes: [
'id',
'title',
[
sequelize.literal(
'(SELECT CASE WHEN "workers"."MainJobFkOther" IS NOT NULL THEN "workers"."MainJobFkOther" ELSE "JobName" END)',
),
'jobRoleName',
],
],
required: false,
},
],
},
],
order,
...(limit ? workerPagination : {}),
});
};
 
Function `getEstablishmentTrainingRecords` has 78 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getEstablishmentTrainingRecords = async function (establishmentId, isParent = false) {
let attributes = [
'id',
'NameOrIdValue',
[
sequelize.literal(
`
(
SELECT json_agg(cqc."TrainingCategories"."Category")
FROM cqc."MandatoryTraining"
RIGHT JOIN cqc."TrainingCategories" ON
"TrainingCategoryFK" = cqc."TrainingCategories"."ID"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
)
`,
),
'mandatoryTrainingCategories',
],
'LongTermAbsence',
];
let subsidiaries = [];
if (isParent) {
subsidiaries = [
{
parentId: establishmentId,
dataOwner: 'Parent',
},
{
parentId: establishmentId,
dataOwner: 'Workplace',
dataPermissions: 'Workplace and Staff',
},
];
}
return this.findAll({
attributes: ['id', 'NameValue', 'ExpiresSoonAlertDate'],
where: {
[Op.or]: [
{
id: establishmentId,
},
...subsidiaries,
],
},
include: [
{
model: sequelize.models.worker,
as: 'workers',
attributes,
where: {
archived: false,
},
required: false,
include: [
{
model: sequelize.models.job,
as: 'mainJob',
attributes: ['id', 'title'],
required: false,
},
{
model: sequelize.models.workerTraining,
as: 'workerTraining',
attributes: ['CategoryFK', 'Title', 'Expires', 'Completed', 'Accredited'],
required: false,
include: [
{
model: sequelize.models.workerTrainingCategories,
as: 'category',
attributes: ['category'],
required: false,
},
],
},
],
},
],
});
};
 
Function `getWorkerQualifications` has 57 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getWorkerQualifications = async function (establishmentId, isParent = false) {
let subsidiaries = [];
if (isParent) {
subsidiaries = [
{
parentId: establishmentId,
dataOwner: 'Parent',
},
{
parentId: establishmentId,
dataOwner: 'Workplace',
dataPermissions: 'Workplace and Staff',
},
];
}
 
return this.findAll({
attributes: ['NameValue'],
where: {
[Op.or]: [
{
id: establishmentId,
},
...subsidiaries,
],
},
include: [
{
model: sequelize.models.worker,
as: 'workers',
attributes: ['NameOrIdValue'],
where: {
archived: false,
},
required: false,
include: [
{
model: sequelize.models.job,
as: 'mainJob',
attributes: ['id', 'title'],
required: false,
},
{
model: sequelize.models.workerQualifications,
as: 'qualifications',
attributes: ['Year'],
include: [
{
model: sequelize.models.workerAvailableQualifications,
as: 'qualification',
attributes: ['group', 'title', 'level'],
required: false,
},
],
},
],
},
],
});
};
 
Function `getWorkersWithCareCertificateStatus` has 45 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getWorkersWithCareCertificateStatus = async function (establishmentId, isParent = false) {
let subsidiaries = [];
 
if (isParent) {
subsidiaries = [
{
parentId: establishmentId,
dataOwner: 'Parent',
},
{
parentId: establishmentId,
dataOwner: 'Workplace',
dataPermissions: 'Workplace and Staff',
},
];
}
 
return this.findAll({
attributes: ['id', 'NameValue'],
where: {
[Op.or]: [
{
id: establishmentId,
},
...subsidiaries,
],
},
include: [
{
model: sequelize.models.worker,
as: 'workers',
attributes: ['NameOrIdValue', 'CareCertificateValue'],
where: {
CareCertificateValue: { [Op.ne]: null },
archived: false,
},
required: false,
include: [
{
model: sequelize.models.job,
as: 'mainJob',
attributes: ['id', 'title'],
required: false,
},
],
},
],
});
};
 
Establishment.getExpiresSoonAlertDate = async function (establishmentId) {
return this.findOne({
attributes: ['ExpiresSoonAlertDate'],
where: {
id: establishmentId,
},
});
};
 
Function `getInfoForPermissions` has 56 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getInfoForPermissions = async function (establishmentId) {
return this.findOne({
attributes: [
'IsRegulated',
[
sequelize.literal(`
CASE WHEN "establishment"."ParentID" IS NULL THEN
false
ELSE
true
END
`),
'hasParent',
],
[
sequelize.literal(`
CASE WHEN "establishment"."DataOwnershipRequested" IS NULL THEN
false
ELSE
true
END
`),
'dataOwnershipRequested',
],
[
sequelize.literal(`
CASE WHEN COUNT("Approvals"."ID") = 0 THEN
false
ELSE
true
END
`),
'hasRequestedToBecomeAParent',
],
],
where: {
id: establishmentId,
},
include: [
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['id'],
},
{
model: sequelize.models.Approvals,
as: 'Approvals',
where: {
Status: 'Pending',
ApprovalType: 'BecomeAParent',
},
attributes: ['ID'],
required: false,
},
],
group: ['establishment.EstablishmentID', 'mainService.id', 'Approvals.ID'],
});
};
 
Similar blocks of code found in 2 locations. Consider refactoring.
Establishment.updateDataChangesLastUpdatedDate = async function (establishmentId, lastUpdated) {
return await this.update(
{
dataChangesLastUpdated: lastUpdated,
},
{
where: {
id: establishmentId,
},
},
);
};
 
Establishment.getdataChangesLastUpdated = async function (establishmentId) {
return await this.findOne({
attributes: ['DataChangesLastUpdated'],
where: {
id: establishmentId,
},
});
};
 
Establishment.authenticateEstablishment = async function (where) {
return await this.findOne({
attributes: ['id', 'dataPermissions', 'dataOwner', 'parentId', 'nmdsId', 'isParent'],
where,
});
};
 
Function `getChildWorkplaces` has 54 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getChildWorkplaces = async function (
Function `getChildWorkplaces` has 5 arguments (exceeds 4 allowed). Consider refactoring.
establishmentUid,
limit = 0,
pageIndex = 0,
searchTerm = '',
getPendingWorkplaces,
) {
const offset = pageIndex * limit;
let ustatus;
 
if (getPendingWorkplaces) {
ustatus = {
[Op.or]: {
[Op.ne]: 'REJECTED',
[Op.is]: null,
},
};
} else {
ustatus = {
[Op.is]: null,
};
}
 
const data = await this.findAndCountAll({
attributes: [
'uid',
'updated',
'NameValue',
'dataOwner',
'dataPermissions',
'dataOwnershipRequested',
'ustatus',
'postcode',
'locationId',
],
include: [
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['name'],
},
],
where: {
ParentUID: establishmentUid,
ustatus,
...(searchTerm ? { NameValue: { [Op.iLike]: `%${searchTerm}%` } } : {}),
},
order: [
[sequelize.literal("\"Status\" IN ('PENDING', 'IN PROGRESS')"), 'ASC'],
['NameValue', 'ASC'],
],
...(limit ? { limit } : {}),
offset,
});
 
const pendingCount = await Establishment.count({
where: {
ParentUID: establishmentUid,
ustatus: {
[Op.or]: [['PENDING', 'IN PROGRESS']],
},
},
});
 
return { ...data, pendingCount };
};
 
Function `getRegistrationIdsForArchiving` has 38 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getRegistrationIdsForArchiving = async function (establishmentIds, transaction) {
const lastMonth = moment().subtract(1, 'months').endOf('month');
const twentyFourLastMonths = lastMonth.clone().subtract(24, 'months').format('YYYY-MM-DD');
return await sequelize.query(
`
SELECT
u."RegistrationID"
FROM
cqc."EstablishmentLastActivity" e
inner join cqc."User" u on e."EstablishmentID" = u."EstablishmentID"
inner join cqc."Login" l on u."RegistrationID" = l."RegistrationID"
WHERE
e."LastLogin" <= :twentyFourLastMonths
AND e."LastUpdated" <= :twentyFourLastMonths
AND NOT EXISTS
(
SELECT s."EstablishmentID" AS EstablishmentID
FROM cqc."EstablishmentLastActivity" s
WHERE s."IsParent" = true AND EXISTS
(
SELECT c."EstablishmentID"
FROM cqc."EstablishmentLastActivity" c
WHERE s."EstablishmentID" = c."ParentID"
AND c."LastLogin" > :twentyFourLastMonths
AND c."LastUpdated" > :twentyFourLastMonths
AND c."IsParent"= false
) AND s."EstablishmentID" = e."EstablishmentID"
)
 
and e."EstablishmentID" IN(:establishmentIds)
`,
{
type: sequelize.QueryTypes.SELECT,
replacements: {
twentyFourLastMonths,
establishmentIds,
},
},
{ transaction },
);
};
 
Function `archiveInactiveWorkplaces` has 47 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.archiveInactiveWorkplaces = async function (establishmentIds) {
try {
return await sequelize.transaction(async (t) => {
await Establishment.update(
{
archived: true,
},
{
where: {
id: establishmentIds,
},
transaction: t,
},
);
 
await sequelize.models.user.update(
{
archived: true,
FullNameValue: 'inactive',
EmailValue: 'inactive',
},
{
where: {
establishmentId: establishmentIds,
},
transaction: t,
},
);
const registrationIds = await Establishment.getRegistrationIdsForArchiving(establishmentIds, t);
 
const promises = registrationIds.map((registration) => {
return sequelize.models.login.update(
{
isActive: false,
username: 'inactive' + registration.RegistrationID,
status: 'inactive',
},
{
where: {
registrationId: registration.RegistrationID,
},
transaction: t,
},
);
});
return await Promise.all(promises);
});
} catch (error) {
console.log({ error });
}
};
 
Function `getWorkerWithExpiredExpiringOrMissingTraining` has 55 lines of code (exceeds 25 allowed). Consider refactoring.
Establishment.getWorkerWithExpiredExpiringOrMissingTraining = async function (
Function `getWorkerWithExpiredExpiringOrMissingTraining` has 6 arguments (exceeds 4 allowed). Consider refactoring.
establishmentId,
status,
limit = 0,
pageIndex = 0,
sortBy = '',
searchTerm = '',
) {
const currentDate = moment().toISOString();
const expiresSoonAlertDate = await this.getExpiresSoonAlertDate(establishmentId);
const expiresSoon = moment().add(expiresSoonAlertDate.get('ExpiresSoonAlertDate'), 'days').toISOString();
const offset = pageIndex * limit;
 
const pagination = {
subQuery: false,
limit,
offset,
};
 
let trainingCount;
 
if (status === 'missing') {
trainingCount = sequelize.literal(`(
SELECT
COUNT(0)
FROM cqc."MandatoryTraining"
WHERE "EstablishmentFK" = "workers"."EstablishmentFK"
AND "JobFK" = "workers"."MainJobFKValue"
AND "TrainingCategoryFK" NOT IN (
SELECT
DISTINCT "CategoryFK"
FROM cqc."WorkerTraining"
WHERE "WorkerFK" = "workers"."ID"
)
)`);
} else {
const conditionalSQL =
status === 'expiring'
? `"Expires" BETWEEN '${currentDate}' AND '${expiresSoon}'`
: `"Expires" < '${currentDate}'`;
 
trainingCount = sequelize.literal(
`(SELECT COUNT(0) FROM cqc."WorkerTraining" WHERE "WorkerFK" = "workers"."ID" AND ${conditionalSQL})`,
);
}
 
const order = {
staffNameAsc: [['workers', 'NameOrIdValue', 'ASC']],
staffNameDesc: [['workers', 'NameOrIdValue', 'DESC']],
}[sortBy] || [['workers', 'NameOrIdValue', 'ASC']];
 
return await this.findAndCountAll({
where: {
id: establishmentId,
col1: sequelize.where(trainingCount, '>', 0),
},
attributes: ['NameValue'],
include: {
model: sequelize.models.worker,
attributes: ['id', 'uid', 'NameOrIdValue'],
as: 'workers',
Similar blocks of code found in 2 locations. Consider refactoring.
where: {
archived: false,
...(searchTerm ? { NameOrIdValue: { [Op.iLike]: `%${searchTerm}%` } } : {}),
},
},
order,
...(limit ? pagination : {}),
});
};
 
const nhsBsaAttributes = [
'id',
'nmdsId',
'NameValue',
'address1',
'locationId',
'town',
'postcode',
'isParent',
'dataOwner',
'NumberOfStaffValue',
'parentId',
];
 
Establishment.getNhsBsaApiDataByWorkplaceId = async function (where) {
return await this.findOne({
nhsBsaAttributes,
as: 'establishment',
 
where: {
archived: false,
...where,
},
include: [
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['name', 'category'],
required: true,
},
],
});
};
 
Establishment.getNhsBsaApiDataForSubs = async function (establishmentId) {
return await this.findAll({
nhsBsaAttributes,
as: 'establishment',
 
where: {
archived: false,
parentId: establishmentId,
},
 
include: [
{
model: sequelize.models.services,
as: 'mainService',
attributes: ['name', 'category'],
required: true,
},
],
});
};
 
return Establishment;
};