Skip to content

Commit

Permalink
Waitlists for program occurrences
Browse files Browse the repository at this point in the history
  • Loading branch information
htysc committed Mar 18, 2024
1 parent 63b4839 commit 1c99ac1
Show file tree
Hide file tree
Showing 18 changed files with 222 additions and 129 deletions.
4 changes: 0 additions & 4 deletions backend/models/program/programWaitlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@ const {GDBProgramOccurrenceModel} = require("./programOccurrence");
const {GDBProgramWaitlistEntryModel} = require("./programWaitlistEntry");

const GDBProgramWaitlistModel = createGraphDBModel({



waitlist: {type: [GDBProgramWaitlistEntryModel], internalKey: ':hasWaitlist'},
programOccurrence: {type: GDBProgramOccurrenceModel, internalKey: ':hasProgramOccurrence'},

},
{
rdfTypes: [':ProgramWaitlist'], name: 'programWaitlist'
Expand Down
3 changes: 1 addition & 2 deletions backend/models/program/programWaitlistEntry.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const {createGraphDBModel, DeleteType, Types} = require("graphdb-utils");
const { GDBProgramRegistrationModel } = require("../serviceRegistration");
const {GDBProgramRegistrationModel} = require("../programRegistration");

const GDBProgramWaitlistEntryModel = createGraphDBModel({

programRegistration: {type: GDBProgramRegistrationModel, internalKey: ':hasProgramRegistration'},
priority: {type: Number, internalKey: ':hasPriority'},
date: {type: Date, internalKey: ':hasDate'},
Expand Down
2 changes: 1 addition & 1 deletion backend/models/programRegistration.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const {createGraphDBModel, DeleteType, Types, getGraphDBModel} = require("graphdb-utils");
const {createGraphDBModel, DeleteType, Types} = require("graphdb-utils");
const {GDBProgramOccurrenceModel} = require("./program/programOccurrence");
const {GDBClientModel} = require("./ClientFunctionalities/client");
const {GDBReferralModel} = require("./referral");
Expand Down
8 changes: 2 additions & 6 deletions backend/models/service/serviceWaitlist.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,11 @@ const {createGraphDBModel, DeleteType, Types} = require("graphdb-utils");

//These might need tweaking, need to figure out what things we need for this model
const {GDBServiceOccurrenceModel} = require("./serviceOccurrence");
const {GDBWaitlistEntryModel} = require("./waitlistEntry");
const {GDBServiceWaitlistEntryModel} = require("./serviceWaitlistEntry");

const GDBServiceWaitlistModel = createGraphDBModel({



waitlist: {type: [GDBWaitlistEntryModel], internalKey: ':hasWaitlist'},
waitlist: {type: [GDBServiceWaitlistEntryModel], internalKey: ':hasWaitlist'},
serviceOccurrence: {type: GDBServiceOccurrenceModel, internalKey: ':hasServiceOccurrence'},

},
{
rdfTypes: [':ServiceWaitlist'], name: 'serviceWaitlist'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
const {createGraphDBModel, DeleteType, Types} = require("graphdb-utils");
const { GDBServiceRegistrationModel } = require("../serviceRegistration");

const GDBWaitlistEntryModel = createGraphDBModel({

const GDBServiceWaitlistEntryModel = createGraphDBModel({
serviceRegistration: {type: GDBServiceRegistrationModel, internalKey: ':hasServiceRegistration'},
priority: {type: Number, internalKey: ':hasPriority'},
date: {type: Date, internalKey: ':hasDate'},
},
{
rdfTypes: [':WaitlistEntry'], name: 'waitlistEntry'
rdfTypes: [':ServiceWaitlistEntry'], name: 'serviceWaitlistEntry'
}

);

module.exports = {
GDBWaitlistEntryModel
}
GDBServiceWaitlistEntryModel
}
29 changes: 11 additions & 18 deletions backend/services/characteristics/predefined/internalTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,6 @@ module.exports = [
}
},



// below are for service waitlist
{
name: 'waitlistForServiceWaitlist',
Expand All @@ -218,37 +216,35 @@ module.exports = [
label: 'Waitlist',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.MultiSelectField,
optionsFromClass: 'http://snmi#WaitlistEntry'
optionsFromClass: 'http://snmi#ServiceWaitlistEntry'
}
},
{
name: 'serviceOccurrenceForServiceWaitlist',
predefinedProperty: 'http://snmi#hasServiceOccurrence',
formType: 'serviceWaitlist',
implementation: {
label: 'ServiceOccurrence',
label: 'Service Occurrence',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.SingleSelectField,
optionsFromClass: 'http://snmi#ServiceOccurrence'
}
},

//below are for waitlist Entry
// below are for service waitlist entry
{
name: 'serviceRegistrationForWaitlistEntry',
name: 'serviceRegistrationForServiceWaitlistEntry',
predefinedProperty: 'http://snmi#hasServiceRegistration',
formType: 'waitlistEntry',
formType: 'serviceWaitlistEntry',
implementation: {
label: 'ServiceRegistration',
label: 'Service Registration',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.SingleSelectField,
optionsFromClass: 'http://snmi#ServiceRegistration'
}
},



// below are for service waitlist
// below are for program waitlist
{
name: 'waitlistForProgramWaitlist',
predefinedProperty: 'http://snmi#hasWaitlist',
Expand All @@ -265,29 +261,26 @@ module.exports = [
predefinedProperty: 'http://snmi#hasProgramOccurrence',
formType: 'programWaitlist',
implementation: {
label: 'ProgramOccurrence',
label: 'Program Occurrence',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.SingleSelectField,
optionsFromClass: 'http://snmi#ProramOccurrence'
optionsFromClass: 'http://snmi#ProgramOccurrence'
}
},

//below are for programWaitlistEntry
// below are for program waitlist entry
{
name: 'programRegistrationForProgramWaitlistEntry',
predefinedProperty: 'http://snmi#hasProgramRegistration',
formType: 'programWaitlistEntry',
implementation: {
label: 'ProgramRegistration',
label: 'Program Registration',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.SingleSelectField,
optionsFromClass: 'http://snmi#ProgramRegistration'
}
},




// below are for program Provision
{
name: 'needOccurrenceForProgramProvision',
Expand Down
54 changes: 21 additions & 33 deletions backend/services/genericData/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,23 @@ const {GDBAppointmentModel} = require("../../models/appointment");
const {GDBPersonModel} = require("../../models/person");
const {GDBServiceOccurrenceModel} = require("../../models/service/serviceOccurrence");
const {GDBProgramOccurrenceModel} = require("../../models/program/programOccurrence");

const {GDBServiceWaitlistModel} = require("../../models/service/serviceWaitlist");
const{GDBWaitlistEntryModel} = require("../../models/service/waitlistEntry");
const {GDBServiceWaitlistEntryModel} = require("../../models/service/serviceWaitlistEntry");
const {GDBProgramWaitlistModel} = require("../../models/program/programWaitlist");
const{GDBProgramWaitlistEntryModel} = require("../../models/program/programWaitlistEntry");


const {GDBProgramWaitlistEntryModel} = require("../../models/program/programWaitlistEntry");
const {GDBInternalTypeModel} = require("../../models/internalType");
const {noQuestion, checkCapacityNonNegative, setOccupancy, unsetOccupancy} = require('./checkers')
const {
serviceOccurrenceInternalTypeCreateTreater, serviceOccurrenceInternalTypeFetchTreater,
serviceOccurrenceInternalTypeUpdateTreater,
checkCapacityOnServiceOccurrenceUpdate
checkCapacityOnServiceOccurrenceUpdate,
afterCreateServiceOccurrence
} = require("./serviceOccurrenceInternalTypeTreater");
const {
programOccurrenceInternalTypeCreateTreater, programOccurrenceInternalTypeFetchTreater,
programOccurrenceInternalTypeUpdateTreater
programOccurrenceInternalTypeUpdateTreater,
afterCreateProgramOccurrence,
checkCapacityOnProgramOccurrenceUpdate
} = require("./programOccurrenceInternalTypeTreater");
const {
fetchCharacteristicQuestionsInternalTypesBasedOnForms,
Expand Down Expand Up @@ -78,7 +78,7 @@ const {
programRegistrationInternalTypeCreateTreater, programRegistrationInternalTypeFetchTreater,
programRegistrationInternalTypeUpdateTreater,
updateOccurrenceOccupancyOnProgramRegistrationCreate, updateOccurrenceOccupancyOnProgramRegistrationUpdate,
updateOccurrenceOccupancyOnProgramRegistrationDelete, checkProgramOccurrenceUnchanged,
updateOccurrenceOccupancyOnProgramRegistrationDelete, checkProgramOccurrenceUnchanged, afterCreateProgramRegistration,
} = require("./programRegistration");
const {
appointmentInternalTypeCreateTreater,
Expand Down Expand Up @@ -136,12 +136,10 @@ const {
} = require("./volunteerInternalTypeTreater");
const {GDBEligibilityModel} = require("../../models/eligibility");
const { serviceWaitlistInternalTypeCreateTreater, serviceWaitlistInternalTypeFetchTreater, serviceWaitlistInternalTypeUpdateTreater } = require("./serviceWaitlist");
const { waitlistEntryInternalTypeCreateTreater, waitlistEntryInternalTypeFetchTreater, waitlistEntryInternalTypeUpdateTreater } = require("./waitlistEntry");

const { serviceWaitlistEntryInternalTypeCreateTreater, serviceWaitlistEntryInternalTypeFetchTreater, serviceWaitlistEntryInternalTypeUpdateTreater } = require("./serviceWaitlistEntry");
const { programWaitlistInternalTypeCreateTreater, programWaitlistInternalTypeFetchTreater, programWaitlistInternalTypeUpdateTreater } = require("./programWaitlist");
const { programWaitlistEntryInternalTypeCreateTreater, programWaitlistEntryInternalTypeFetchTreater, programWaitlistEntryInternalTypeUpdateTreater } = require("./programWaitlistEntry");


const genericType2Model = {
'client': GDBClientModel,
'organization': GDBOrganizationModel,
Expand All @@ -151,7 +149,7 @@ const genericType2Model = {
'appointment': GDBAppointmentModel,
'serviceOccurrence': GDBServiceOccurrenceModel,
'serviceWaitlist': GDBServiceWaitlistModel,
'waitlistEntry' : GDBWaitlistEntryModel,
'serviceWaitlistEntry' : GDBServiceWaitlistEntryModel,
'programWaitlist': GDBProgramWaitlistModel,
'programWaitlistEntry' : GDBProgramWaitlistEntryModel,
'programOccurrence': GDBProgramOccurrenceModel,
Expand Down Expand Up @@ -180,11 +178,11 @@ const genericType2Populates = {
'service': ['serviceProvider.organization.address', 'serviceProvider.volunteer.address'],
'program': ['serviceProvider.organization.address', 'serviceProvider.volunteer.address', 'serviceProvider.organization', 'serviceProvider.volunteer', 'manager'],
'serviceOccurrence': ['address', 'occurrenceOf'],
'programOccurrence': ['address', 'occurrenceOf'],
'serviceWaitlist': ['waitlist', 'serviceOccurrence'],
'waitlistEntry': ['serviceRegistration', 'priority', 'date'],
'serviceWaitlistEntry': ['serviceRegistration', 'priority', 'date'],
'programWaitlist': ['waitlist', 'programOccurrence'],
'programWaitlistEntry': ['programRegistration', 'priority', 'date'],
'programOccurrence': ['address', 'occurrenceOf'],
'client': ['address', 'needs'],
'appointment': ['address', 'referral'],
'person': ['address'],
Expand All @@ -199,7 +197,7 @@ const genericType2BeforeCreateChecker = {
'programOccurrence': [noQuestion, checkCapacityNonNegative, setOccupancy],
'programRegistration': [updateOccurrenceOccupancyOnProgramRegistrationCreate],
'serviceWaitlist': [noQuestion],
'waitlistEntry': [noQuestion],
'serviceWaitlistEntry': [noQuestion],
'programWaitlist': [noQuestion],
'programWaitlistEntry': [noQuestion],
};
Expand All @@ -209,10 +207,10 @@ const genericType2BeforeUpdateChecker = {
'serviceOccurrence': [noQuestion, checkCapacityNonNegative, checkCapacityOnServiceOccurrenceUpdate, unsetOccupancy],
'serviceRegistration': [checkServiceOccurrenceUnchanged, updateOccurrenceOccupancyOnServiceRegistrationUpdate],
'program': [noQuestion],
'programOccurrence': [noQuestion, checkCapacityNonNegative, unsetOccupancy],
'programOccurrence': [noQuestion, checkCapacityNonNegative, checkCapacityOnProgramOccurrenceUpdate, unsetOccupancy],
'programRegistration': [checkProgramOccurrenceUnchanged, updateOccurrenceOccupancyOnProgramRegistrationUpdate],
'serviceWaitlist': [noQuestion],
'waitlistEntry' : [noQuestion],
'serviceWaitlistEntry' : [noQuestion],
'programWaitlist': [noQuestion],
'programWaitlistEntry' : [noQuestion],
};
Expand Down Expand Up @@ -255,7 +253,7 @@ const genericType2InternalTypeCreateTreater = {
'person': personInternalTypeCreateTreater,
'volunteer': volunteerInternalTypeCreateTreater,
'serviceWaitlist': serviceWaitlistInternalTypeCreateTreater,
'waitlistEntry': waitlistEntryInternalTypeCreateTreater,
'serviceWaitlistEntry': serviceWaitlistEntryInternalTypeCreateTreater,
'programWaitlist': programWaitlistInternalTypeCreateTreater,
'programWaitlistEntry': programWaitlistEntryInternalTypeCreateTreater
};
Expand All @@ -278,7 +276,7 @@ const genericType2InternalTypeFetchTreater = {
'person': personInternalTypeFetchTreater,
'volunteer': volunteerInternalTypeFetchTreater,
'serviceWaitlist': serviceWaitlistInternalTypeFetchTreater,
'waitlistEntry': waitlistEntryInternalTypeFetchTreater,
'serviceWaitlistEntry': serviceWaitlistEntryInternalTypeFetchTreater,
'programWaitlist': programWaitlistInternalTypeFetchTreater,
'programWaitlistEntry': programWaitlistEntryInternalTypeFetchTreater
};
Expand All @@ -301,7 +299,7 @@ const genericType2InternalTypeUpdateTreater = {
'person': personInternalTypeUpdateTreater,
'volunteer': volunteerInternalTypeUpdateTreater,
'serviceWaitlist': serviceWaitlistInternalTypeUpdateTreater,
'waitlistEntry' : waitlistEntryInternalTypeUpdateTreater,
'serviceWaitlistEntry' : serviceWaitlistEntryInternalTypeUpdateTreater,
'programWaitlist': programWaitlistInternalTypeUpdateTreater,
'programWaitlistEntry' : programWaitlistEntryInternalTypeUpdateTreater
};
Expand All @@ -311,6 +309,9 @@ const genericType2AfterCreateTreater = {
'service': afterCreateService,
'volunteer': afterCreateVolunteer,
'serviceRegistration': afterCreateServiceRegistration,
'programRegistration': afterCreateProgramRegistration,
'serviceOccurrence': afterCreateServiceOccurrence,
'programOccurrence': afterCreateProgramOccurrence,
}

const genericType2AfterUpdateTreater = {
Expand Down Expand Up @@ -556,19 +557,6 @@ const createSingleGeneric = async (req, res, next) => {
const newGeneric = genericType2Model[genericType](instanceData);
await newGeneric.save();

//create a new waitlist here that corresponds to the serviceOccurrence
if(genericType === 'serviceOccurrence'){
const occurrenceWaitlist = genericType2Model['serviceWaitlist']({'serviceOccurrence': newGeneric, 'waitlist':[]});
//pass in the serviceOccurrence that was just created ("newGeneric").
//and an empty list for the queue.
await occurrenceWaitlist.save();
}
//same thing as above, but for programOccurrences
if(genericType === 'programOccurrence'){
const occurrenceWaitlist = genericType2Model['programWaitlist']({'programOccurrence': newGeneric, 'waitlist':[]});
await occurrenceWaitlist.save();
}

if (genericType2AfterCreateTreater[genericType])
await genericType2AfterCreateTreater[genericType](data, req, newGeneric);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ const {GDBNeedSatisfierOccurrenceModel} = require("../../models/needSatisfierOcc
const {getPredefinedProperty, getInternalTypeValues} = require('./helperFunctions')
const {GDBInternalTypeModel} = require("../../models/internalType");
const {SPARQL} = require('graphdb-utils');
const {GDBProgramWaitlistModel} = require("../../models/program/programWaitlist");
const {getIndividualsInClass} = require("../dynamicForm");
const {PredefinedCharacteristics} = require("../characteristics");
const {popFromWaitlist} = require("../serviceWaitlist/serviceWaitlist");

const programOccurrenceInternalTypeCreateTreater = async (internalType, instanceData, value) => {
const property = getPredefinedProperty('programOccurrence', internalType);
Expand All @@ -21,4 +25,51 @@ const programOccurrenceInternalTypeUpdateTreater = async (internalType, value, r
await programOccurrenceInternalTypeCreateTreater(internalType, result, value);
}

module.exports = {programOccurrenceInternalTypeCreateTreater, programOccurrenceInternalTypeFetchTreater, programOccurrenceInternalTypeUpdateTreater, }
const checkCapacityOnProgramOccurrenceUpdate = async function (characteristics, questions, fields, oldGeneric) {
const capacityId = Object.keys(characteristics).find(id => characteristics[id].name === 'Capacity');
if (!capacityId)
return;
const capacity = fields['characteristic_' + capacityId];
if (capacity < oldGeneric.occupancy) {
throw new Error('The new capacity of this program occurrence is less than its current occupancy. Please unregister '
+ 'program registrations until the occupancy is below the desired capacity, and then try editing this program '
+ 'occurrence again.');
} else {
const statuses = await getIndividualsInClass(':RegistrationStatus');
const registeredStatus = Object.keys(statuses).find(status => statuses[status] === 'Registered');
const statusC = PredefinedCharacteristics['Registration Status'];
const occupancyC = PredefinedCharacteristics['Occupancy'];
const occupancyCO = oldGeneric.characteristicOccurrences.find(co => co.occurrenceOf === occupancyC._uri);
while (capacity > oldGeneric.occupancy) {
const registration = await popFromWaitlist(oldGeneric._id);
if (!!registration) {
// Make the registration's status be 'Registered' and save it
const statusCO = registration.characteristicOccurrences.find(co => co.occurrenceOf === statusC._uri);
registration.status = registeredStatus;
statusCO.dataStringValue = registeredStatus;
await registration.save();

oldGeneric.occupancy += 1;
occupancyCO.dataNumberValue += 1;
} else {
break;
}
}
await oldGeneric.save();
}
}

const afterCreateProgramOccurrence = async function (data, req, newGeneric) {
const occurrenceWaitlist = GDBProgramWaitlistModel({'programOccurrence': newGeneric, 'waitlist': []});
// pass in the programOccurrence that was just created ("newGeneric")
// and an empty list for the queue.
await occurrenceWaitlist.save();
}

module.exports = {
programOccurrenceInternalTypeCreateTreater,
programOccurrenceInternalTypeFetchTreater,
programOccurrenceInternalTypeUpdateTreater,
checkCapacityOnProgramOccurrenceUpdate,
afterCreateProgramOccurrence,
}
Loading

0 comments on commit 1c99ac1

Please sign in to comment.