Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Capacities and occupancies for service and program occurrences #117

Open
wants to merge 46 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0a2ca21
Changes to list overview in Clients and Need Occurences
Damon-D-Ma Jan 15, 2024
830c727
Revert local backend index.js changes
Damon-D-Ma Jan 15, 2024
735256f
Base Code for Service Waitlist Type
Damon-D-Ma Feb 2, 2024
e91597d
Completed Service Waitlist Feature
Damon-D-Ma Feb 12, 2024
1739f27
Add capacity to service and program occurrences
htysc Feb 25, 2024
a1ec584
Add occupancy to service and program occurrences
htysc Mar 1, 2024
9910ac4
Add occurrence status (string for now)
htysc Mar 2, 2024
69de1f4
Use options for program and service occurrences
htysc Mar 2, 2024
92e6d45
Let capacities be unlimited
htysc Mar 2, 2024
6b2e375
Set occupancy to 0 on creation
htysc Mar 2, 2024
2839427
Bugfix on NumberField & partial CO deletion.
LesterLyu Mar 4, 2024
193163b
Registration statuses
htysc Mar 5, 2024
dd34179
Customized service registration status options
htysc Mar 5, 2024
652e572
Customized program registration status options
htysc Mar 5, 2024
d95b58a
Registration status option fixes
htysc Mar 5, 2024
74adf7a
Service registration status backend (except for waitlists)
htysc Mar 6, 2024
76a096f
Merge branch 'master' into capacities
htysc Mar 6, 2024
fa09dde
Fix bugs
htysc Mar 6, 2024
07bb558
Program registration status backend (except for waitlists)
htysc Mar 6, 2024
0f232af
Fix bugs
htysc Mar 6, 2024
a660b8d
Update waitlist TODOs
htysc Mar 6, 2024
00dd1f3
Updates to Waitlist + New Entry Model
Damon-D-Ma Mar 6, 2024
708cbf0
Added Required Functions to Manipulate Service Waitlists
Damon-D-Ma Mar 7, 2024
f926dc1
Fix occupancy update bug
htysc Mar 11, 2024
ea4ef26
Added auto-create waitlist for serviceOccurrence
Damon-D-Ma Mar 12, 2024
1e55e15
Updated waitlistEntryModel
Damon-D-Ma Mar 12, 2024
fa466b4
Forgot to fix import statements
Damon-D-Ma Mar 12, 2024
cb0d9dd
Changes to backend waitlistEntry Components
Damon-D-Ma Mar 12, 2024
cf4e8a6
Changes to waitlistEntry Structure
Damon-D-Ma Mar 12, 2024
45ce943
Forgot to Rename serviceWaitlist Attribute
Damon-D-Ma Mar 12, 2024
b34b528
Updated waitlist functions
Damon-D-Ma Mar 12, 2024
23f989b
Implemented Changes From Code Review
Damon-D-Ma Mar 15, 2024
5b67143
More Fixes From Code Review
Damon-D-Ma Mar 15, 2024
ca862ae
Created Models for program waitlists + entries
Damon-D-Ma Mar 15, 2024
bc88bed
Added Program Waitlists
Damon-D-Ma Mar 15, 2024
2eb86a4
Use waitlist functions (not fully tested yet)
htysc Mar 15, 2024
e19c7b6
Fix bugs
htysc Mar 18, 2024
63b4839
Implement service occurrence capacity change checks
htysc Mar 18, 2024
1c99ac1
Waitlists for program occurrences
htysc Mar 18, 2024
5c40d5f
Fix bug
htysc Mar 18, 2024
8c1a524
Added functionality for programWaitlist, code style changes
Damon-D-Ma Mar 20, 2024
ec1832e
Fix bugs
htysc Mar 20, 2024
5422bce
Prevent updating a registration's occurrence
htysc Mar 20, 2024
194de23
Added New General FAQ Guide for Codebase Newcomers
Damon-D-Ma Mar 22, 2024
8c94e97
Guide got ignored by gitignore for some reason
Damon-D-Ma Mar 22, 2024
6d91055
Merge branch 'master' into capacities
LesterLyu Mar 25, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ if (isProduction)

const config = {
graphdb: {
addr: isProduction ? 'http://localhost:7200' : `http://${isDocker ? 'host.docker.internal' : 'localhost'}:7200`,
addr: isProduction ? 'http://127.0.0.1:7200' : `http://${isDocker ? 'host.docker.internal' : '127.0.0.1'}:7200`,
},
mongodb: {
addr: isProduction ? 'mongodb://localhost:27017/snmi' : `mongodb://localhost:27017/${process.env.test ? "snmiTest" : "snmi"}`
Expand Down
26 changes: 26 additions & 0 deletions backend/models/service/serviceWaitlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const {createGraphDBModel, DeleteType, Types} = require("graphdb-utils");




//These might need tweaking, need to figure out what things we need for this model
const {GDBServiceModel} = require("./service");
const {GDBClientModel} = require("../ClientFunctionalities/client");
const { GDBCOModel } = require("../ClientFunctionalities/characteristicOccurrence");


const GDBServiceWaitlistModel = createGraphDBModel({

clients: {type: [GDBClientModel], internalKey: ':hasClient'},
service: {type: GDBServiceModel, internalKey: ':hasService'},
characteristicOccurences: {type: [GDBCOModel], internalKey: ':hasCharacteristicOccurence'}

},
{
rdfTypes: [':ServiceWaitlist'], name: 'serviceWaitlist'
}

);
module.exports = {
GDBServiceWaitlistModel
}
29 changes: 29 additions & 0 deletions backend/services/characteristics/predefined/internalTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,35 @@ module.exports = [
}
},



// below are for servic waitlist
{
name: 'clientForServiceWaitlist',
predefinedProperty: 'http://snmi#hasClient',
formType: 'serviceWaitlist',
implementation: {
label: 'Client',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.MultiSelectField,
optionsFromClass: 'http://snmi#Client'
}
},
{
name: 'serviceForServiceWaitlist',
predefinedProperty: 'http://snmi#hasService',
formType: 'serviceWaitlist',
implementation: {
label: 'Service',
valueDataType: 'owl:NamedIndividual',
fieldType: FieldTypes.SingleSelectField,
optionsFromClass: 'http://snmi#Service'
}
},




// below are for program Provision
{
name: 'needOccurrenceForProgramProvision',
Expand Down
25 changes: 18 additions & 7 deletions backend/services/genericData/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ 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 {GDBInternalTypeModel} = require("../../models/internalType");
const {noQuestion} = require('./checkers')
const {
Expand Down Expand Up @@ -123,6 +126,7 @@ const {
afterDeleteVolunteer
} = require("./volunteerInternalTypeTreater");
const {GDBEligibilityModel} = require("../../models/eligibility");
const { serviceWaitlistInternalTypeCreateTreater, serviceWaitlistInternalTypeFetchTreater, serviceWaitlistInternalTypeUpdateTreater } = require("./serviceWaitlist");
const genericType2Model = {
'client': GDBClientModel,
'organization': GDBOrganizationModel,
Expand All @@ -131,6 +135,7 @@ const genericType2Model = {
'program': GDBProgramModel,
'appointment': GDBAppointmentModel,
'serviceOccurrence': GDBServiceOccurrenceModel,
'serviceWaitlist': GDBServiceWaitlistModel,
'programOccurrence': GDBProgramOccurrenceModel,
'referral': GDBReferralModel,
'serviceRegistration': GDBServiceRegistrationModel,
Expand All @@ -157,6 +162,7 @@ const genericType2Populates = {
'service': ['serviceProvider.organization.address', 'serviceProvider.volunteer.address'],
'program': ['serviceProvider.organization.address', 'serviceProvider.volunteer.address', 'serviceProvider.organization', 'serviceProvider.volunteer', 'manager'],
'serviceOccurrence': ['address', 'occurrenceOf'],
'serviceWaitlist': ['service', 'clients'],
'programOccurrence': ['address', 'occurrenceOf'],
'client': ['address', 'needs'],
'appointment': ['address', 'referral'],
Expand All @@ -165,10 +171,11 @@ const genericType2Populates = {
};

const genericType2Checker = {
'service': noQuestion,
'serviceOccurrence': noQuestion,
'programOccurrence': noQuestion,
'program': noQuestion
'service': noQuestion,
'serviceOccurrence': noQuestion,
'programOccurrence': noQuestion,
'program' : noQuestion,
'serviceWaitlist': noQuestion
};


Expand Down Expand Up @@ -203,7 +210,8 @@ const genericType2InternalTypeCreateTreater = {
'outcomeOccurrence': outcomeOccurrenceInternalTypeCreateTreater,
'clientAssessment': clientAssessmentInternalTypeCreateTreater,
'person': personInternalTypeCreateTreater,
'volunteer': volunteerInternalTypeCreateTreater
'volunteer': volunteerInternalTypeCreateTreater,
'serviceWaitlist': serviceWaitlistInternalTypeCreateTreater
};

const genericType2InternalTypeFetchTreater = {
Expand All @@ -222,7 +230,9 @@ const genericType2InternalTypeFetchTreater = {
'outcomeOccurrence': outcomeOccurrenceInternalTypeFetchTreater,
'clientAssessment': clientAssessmentInternalTypeFetchTreater,
'person': personInternalTypeFetchTreater,
'volunteer': volunteerInternalTypeFetchTreater
'volunteer': volunteerInternalTypeFetchTreater,
'serviceWaitlist': serviceWaitlistInternalTypeFetchTreater

};

const genericType2InternalTypeUpdateTreater = {
Expand All @@ -241,7 +251,8 @@ const genericType2InternalTypeUpdateTreater = {
'outcomeOccurrence': outcomeOccurrenceInternalTypeUpdateTreater,
'clientAssessment': clientAssessmentInternalTypeUpdateTreater,
'person': personInternalTypeUpdateTreater,
'volunteer': volunteerInternalTypeUpdateTreater
'volunteer': volunteerInternalTypeUpdateTreater,
'serviceWaitlist': serviceWaitlistInternalTypeUpdateTreater
};

const genericType2AfterCreateTreater = {
Expand Down
34 changes: 34 additions & 0 deletions backend/services/genericData/serviceWaitlist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const {getPredefinedProperty} = require("./helperFunctions");
const {GDBInternalTypeModel} = require("../../models/internalType");
const {SPARQL} = require("graphdb-utils");
const FORMTYPE = 'serviceWaitlist'

const serviceWaitlistInternalTypeCreateTreater = async (internalType, instanceData, value) => {
//get the property name from the internalType
const property = getPredefinedProperty(FORMTYPE, internalType);
//if the property is client, person or user, then set the value to the instanceData
if (property === 'clients' || property === 'service'){
instanceData[property] = value;
}
};

const serviceWaitlistInternalTypeFetchTreater = async (data) => {
const result = {};
const schema = data.schema;
// for each property in data, if the property is client, person or user, then set the value to the result
for (const property in data) {
if (property === 'clients' || property === 'service') {
const internalType = await GDBInternalTypeModel.findOne({predefinedProperty: schema[property].internalKey, formType: FORMTYPE});
result[ 'internalType_'+ internalType._id] = SPARQL.ensureFullURI(data[property]);
}
}
return result;
};


const serviceWaitlistInternalTypeUpdateTreater = async (internalType, value, result) => {
await serviceWaitlistInternalTypeCreateTreater(internalType, result, value);
}


module.exports = {serviceWaitlistInternalTypeCreateTreater, serviceWaitlistInternalTypeFetchTreater, serviceWaitlistInternalTypeUpdateTreater}
69 changes: 69 additions & 0 deletions frontend/src/components/ServiceWaitlists.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React from 'react';
import { Link } from './shared';
import { GenericPage } from "./shared";
import { deleteSingleGeneric, fetchMultipleGeneric, fetchSingleGeneric } from "../api/genericDataApi";
import {getAddressCharacteristicId} from "./shared/CharacteristicIds";

const TYPE = 'serviceWaitlist';

const columnsWithoutOptions = [
{
label: 'Service Name',
body: ({service}) => <Link color to={`/${TYPE}/${service?._id}/edit`}>{service?.name}</Link>

},
{
label: 'Clients Waitlisted',
body: ({clients}) => clients ? clients.length : 0
},
// {
// label: 'Category',
// body: ({category}) => category
// }
];

export default function ServiceWaitlists() {

const nameFormatter = serviceWaitlist => {
if (serviceWaitlist.description) {
return serviceWaitlist.description;
} else {
return 'Service Waitlist ' + serviceWaitlist._id;
}
}

const linkFormatter = serviceWaitlist => `/${TYPE}/${serviceWaitlist._id}`;

const fetchData = async () => {
const addressCharacteristicId = await getAddressCharacteristicId();
const serviceWaitlists = (await fetchMultipleGeneric(TYPE)).data;
console.log(serviceWaitlists)
const data = [];
for (const serviceWaitlist of serviceWaitlists) {
const serviceWaitlistData = {_id: serviceWaitlist._id};
if (serviceWaitlist.clients)
serviceWaitlistData.clients = serviceWaitlist.clients;
if (serviceWaitlist.service)
serviceWaitlistData.service = serviceWaitlist.service;
data.push(serviceWaitlistData);
}
return data;
};

const deleteService = (id) => deleteSingleGeneric('serviceWaitlist', id);

return (
<GenericPage
type={TYPE}
title={"Service Waitlists"}
columnsWithoutOptions={columnsWithoutOptions}
fetchData={fetchData}
deleteItem={deleteService}
nameFormatter={nameFormatter}
linkFormatter={linkFormatter}
tableOptions={{
idField: '_id'
}}
/>
);
}
7 changes: 7 additions & 0 deletions frontend/src/components/layouts/TopNavbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@ function TopNavBar() {
<Typography variant="inherit">Service Occurrences</Typography>
</MenuItem>

<MenuItem onClick={handleLink(`/serviceWaitlists`)}>
<ListItemIcon>
<LocationCityIcon fontSize="medium" sx={{color: 'black'}}/>
</ListItemIcon>
<Typography variant="inherit">Service Waitlists</Typography>
</MenuItem>

<MenuItem onClick={handleLink(`/appointments`)}>
<ListItemIcon>
<BusinessCenterIcon fontSize="medium" sx={{color: 'black'}}/>
Expand Down
24 changes: 24 additions & 0 deletions frontend/src/components/serviceWaitlist/ServiceWaitlist.js
htysc marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, {useEffect, useState} from 'react';
import GenericForm from "../shared/GenericForm";
import {fetchInternalTypeByFormType} from "../../api/internalTypeApi";
import {ServiceAndNeedSatisfierField} from "../serviceOccurrence/ServiceAndNeedSatisfierField";

export default function ServiceWaitlistForm() {
const formType = 'serviceWaitlist';

const [internalTypes, setInternalTypes] = useState({});
useEffect(() => {
fetchInternalTypeByFormType(formType).then(({internalTypes}) => {
const data = {}
for (const {implementation, name, _id} of internalTypes) {
data[name] = {implementation, _id}
}
setInternalTypes(data);
console.log('serviceWaitlist internalTypes', data);
});
}, []);

return (
<GenericForm name={formType} mainPage={'/serviceWaitlists'}/>
);
};
24 changes: 24 additions & 0 deletions frontend/src/components/serviceWaitlist/serviceWaitlistForm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React, {useEffect, useState} from 'react';
import GenericForm from "../shared/GenericForm";
import {fetchInternalTypeByFormType} from "../../api/internalTypeApi";
import {ServiceAndNeedSatisfierField} from "./ServiceAndNeedSatisfierField";

export default function ServiceWaitlistForm() {
const formType = 'serviceWaitlist';

const [internalTypes, setInternalTypes] = useState({});
useEffect(() => {
fetchInternalTypeByFormType(formType).then(({internalTypes}) => {
const data = {}
for (const {implementation, name, _id} of internalTypes) {
data[name] = {implementation, _id}
}
setInternalTypes(data);
console.log('serviceWaitlist internalTypes', data);
});
}, []);

return (
<GenericForm name={formType} mainPage={'/serviceWaitlists'}/>
);
};
Loading