Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
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
4 changes: 4 additions & 0 deletions backend/python/app/models/child.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from . import db
from .base_mixin import BaseMixin
from .child_providers import child_providers
from .children_child_behaviors import children_child_behaviors


Expand All @@ -20,6 +21,9 @@ class Child(db.Model, BaseMixin):
intake = db.relationship("Intake")
daytime_contact = db.relationship("DaytimeContact")
behaviors = db.relationship("ChildBehavior", secondary=children_child_behaviors)
providers = db.relationship(
"Provider", backref="children", secondary=child_providers
)
visit_cadences = db.relationship(
"VisitCadence", backref="associated_child", cascade="all, delete"
)
8 changes: 8 additions & 0 deletions backend/python/app/models/child_providers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from . import db

child_providers = db.Table(
"child_providers",
db.metadata,
db.Column("child_id", db.ForeignKey("children.id")),
db.Column("providers_id", db.ForeignKey("providers.id")),
)
3 changes: 1 addition & 2 deletions backend/python/app/models/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class Provider(db.Model, BaseMixin):
__tablename__ = "providers"

id = db.Column(db.Integer, primary_key=True)
intake_id = db.Column(db.Integer, db.ForeignKey("intakes.id"), nullable=True)
name = db.Column(db.String, nullable=False)
file_number = db.Column(db.String, nullable=False)
primary_phone_number = db.Column(db.String, nullable=False)
Expand All @@ -14,5 +15,3 @@ class Provider(db.Model, BaseMixin):
address = db.Column(db.String, nullable=False)
relationship_to_child = db.Column(db.String, nullable=False)
additional_contact_notes = db.Column(db.String, nullable=True)
child_id = db.Column(db.Integer, db.ForeignKey("children.id"), nullable=False)
child = db.relationship("Child", backref="providers")
2 changes: 1 addition & 1 deletion backend/python/app/resources/provider_dto.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
class ProviderDTO:
def __init__(self, **kwargs):
self.id = kwargs.get("id")
self.intake_id = kwargs.get("intake_id")
self.name = kwargs.get("name")
self.file_number = kwargs.get("file_number")
self.primary_phone_number = kwargs.get("primary_phone_number")
Expand All @@ -12,7 +13,6 @@ def __init__(self, **kwargs):
self.address = kwargs.get("address")
self.relationship_to_child = kwargs.get("relationship_to_child")
self.additional_contact_notes = kwargs.get("additional_contact_notes")
self.child_id = kwargs.get("child_id")


class CreateProviderDTO(ProviderDTO):
Expand Down
61 changes: 37 additions & 24 deletions backend/python/app/rest/intake_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def get_all_intakes():
just_children = child_service.get_children_by_intake_id(intake.id)
new_children = []
for child in just_children:
providers = provider_service.get_providers_by_child_id(child.id)
providers = provider_service.get_providers_by_child(child.id)
child_info = {
"name": f"{child.first_name} {child.last_name}",
"dateOfBirth": child.date_of_birth,
Expand Down Expand Up @@ -325,7 +325,10 @@ def run_undos():
run_undos()
return jsonify(error), 400

children_providers = {}
all_providers = []
children = request.json["children"]
# children
for child in children:
# daytime contact
daytimeContact = child["daytimeContact"]
Expand Down Expand Up @@ -369,29 +372,15 @@ def run_undos():
return jsonify(error), 400

# provider
providers = child["provider"]
for provider in providers:
provider_obj = {
"name": provider["name"],
"file_number": provider["fileNumber"],
"primary_phone_number": provider["primaryPhoneNumber"],
"secondary_phone_number": provider["secondaryPhoneNumber"],
"email": provider["email"],
"address": provider["address"],
"relationship_to_child": provider["relationshipToChild"],
"additional_contact_notes": provider["additionalContactNotes"],
"child_id": child_response.id,
}
try:
provider_response = provider_service.create_new_provider(
CreateProviderDTO(**provider_obj)
)
undos.append(
(provider_service, "delete_provider", provider_response.id)
)
except Exception as error:
run_undos()
return jsonify(error), 400
providers_by_child = child["provider"]
for provider in providers_by_child:
if provider.providerId in children_providers:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i c wat ur going for here, but when the user POSTs the intake obj, the provider obj within it has no field providerId (see intake frontend<>backend for more info)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While working on the changes, I added a providerId which is now included in the provider interface apart of ProviderDetails, so it should work. It's present in this file: .\frontend\src\components\intake\NewProviderModal.tsx and is defined across all components working with ProviderDetails

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provider["providerId"]

children_providers[provider["providerId"]].append(child_response.id)
else:
children_providers[provider["providerId"]] = [child_response.id]

if not any(x.providerId == provider.providerId for x in all_providers):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

provider["providerId"]

all_providers.append(provider)

# concerns
concerns = child["childInfo"]["concerns"]
Expand All @@ -415,6 +404,30 @@ def run_undos():
run_undos()
return jsonify(error), 400

# create providers
for provider in all_providers:
provider_obj = {
"name": provider["name"],
"intake_id": new_intake.id,
"file_number": provider["fileNumber"],
"primary_phone_number": provider["primaryPhoneNumber"],
"secondary_phone_number": provider["secondaryPhoneNumber"],
"email": provider["email"],
"address": provider["address"],
"relationship_to_child": provider["relationshipToChild"],
"additional_contact_notes": provider["additionalContactNotes"],
}

try:
provider_response = provider_service.create_new_provider(
CreateProviderDTO(**provider_obj),
children_providers[provider["providerId"]],
Comment on lines +422 to +424
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm, just looked into this—it seems like the create_new_provider function doesn't work when it takes in children_ids as a param..
for now (until we fix this), keep the arg for create_new_provider as

provider_response = provider_service.create_new_provider(
    CreateProviderDTO(**provider_obj)
)

you're going to have to change some of your providers_by_child logic, since atm the POST request doesn't save providers properly

)
undos.append((provider_service, "delete_provider", provider_response.id))
except Exception as error:
run_undos()
return jsonify(error), 400

Check warning

Code scanning / CodeQL

Information exposure through an exception

[Stack trace information](1) flows to this location and may be exposed to an external user.

return jsonify(new_intake.__dict__), 201


Expand Down
27 changes: 21 additions & 6 deletions backend/python/app/services/implementations/provider_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from ...models import db
from ...models.child import Child
from ...models.provider import Provider
from ...resources.child_dto import ChildDTO
from ...resources.provider_dto import CreateProviderDTO, ProviderDTO
from ..interfaces.provider_service import IProviderService

Expand All @@ -20,7 +21,7 @@ def get_all_providers(self):
self.logger.error(str(error))
raise error

def create_new_provider(self, provider):
def create_new_provider(self, provider, children_ids):
try:
if not provider:
raise Exception(
Expand All @@ -33,6 +34,11 @@ def create_new_provider(self, provider):
raise Exception(error_list)

new_provider_entry = Provider(**provider.__dict__)

for child_id in children_ids:
child = Child.query.filter_by(id=child_id)
new_provider_entry.children.append(child)

db.session.add(new_provider_entry)
db.session.commit()

Expand All @@ -53,13 +59,22 @@ def delete_provider(self, provider_id):
db.session.rollback()
raise error

def get_providers_by_child_id(self, child_id):
def get_children_by_provider(self, provider_id):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think it makes more sense to have this function within child_service.py

try:
providers = Provider.query.filter_by(child_id=child_id)
providers_dto = [
ProviderDTO(**provider.to_dict()) for provider in providers
provider = Provider.query.filter_by(id=provider_id).first()
children_dto = [ChildDTO(**child.to_dict()) for child in provider.children]
return children_dto
except Exception as error:
self.logger.error(str(error))
raise error

def get_providers_by_child(self, child_id):
try:
child = Child.query.filter_by(id=child_id).first()
provider_dto = [
ProviderDTO(**provider.to_dict()) for provider in child.providers
]
return providers_dto
return provider_dto
except Exception as error:
self.logger.error(str(error))
raise error
13 changes: 12 additions & 1 deletion backend/python/app/services/interfaces/provider_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,18 @@ def delete_provider(self, provider_id):
pass

@abstractmethod
def get_providers_by_child_id(self, child_id):
def get_children_by_provider(self, id):
"""Returns all children associated with a provider's ID
:param id: the ID of the provider
:type id: int
:return: list of ChildDTO
:rtype: list of ChildDTO
:raises Exception: if an error occurs at the database level
"""
pass

@abstractmethod
def get_providers_by_child(self, child_id):
"""Returns all providers associated with a child's ID
:param child_id: the ID of the child
:type child_id: int
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""change child-provider relationship

Revision ID: 05393a9f6f23
Revises: 2e3a95429cdf
Create Date: 2023-11-11 18:52:37.274933

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "05393a9f6f23"
down_revision = "2e3a95429cdf"
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table(
"child_providers",
sa.Column("child_id", sa.Integer(), nullable=True),
sa.Column("providers_id", sa.Integer(), nullable=True),
sa.ForeignKeyConstraint(
["child_id"],
["children.id"],
),
sa.ForeignKeyConstraint(
["providers_id"],
["providers.id"],
),
)
op.add_column("providers", sa.Column("intake_id", sa.Integer(), nullable=True))
op.drop_constraint("providers_child_id_fkey", "providers", type_="foreignkey")
op.create_foreign_key(None, "providers", "intakes", ["intake_id"], ["id"])
op.drop_column("providers", "child_id")
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column(
"providers",
sa.Column("child_id", sa.INTEGER(), autoincrement=False, nullable=False),
)
op.drop_constraint(None, "providers", type_="foreignkey")
op.create_foreign_key(
"providers_child_id_fkey", "providers", "children", ["child_id"], ["id"]
)
op.drop_column("providers", "intake_id")
op.drop_table("child_providers")
# ### end Alembic commands ###
9 changes: 0 additions & 9 deletions backend/python/tools/db_seed.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,6 @@ def insert_test_data():
insert_values(db, "other_permitted_individuals", ("name", "phone_number", "relationship_to_child", "notes", "intake_id"), value)


# Providers
values = [
('Provider One', '111', '555-555-5555', '777-777-7777', '[email protected]', 'address', 'KINSHIP_PROVIDER', 'NULL', 1),
('Provider Two', '222', '777-777-7777', '555-555-5555', '[email protected]', 'address', 'KINSHIP_PROVIDER', 'NULL', 1)
]

for value in values:
insert_values(db, "providers", ("name", "file_number", "primary_phone_number", "secondary_phone_number", "email", "address", "relationship_to_child", "additional_contact_notes", "child_id"), value)

# fmt: on

# fmt: off
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/components/intake/NewProviderModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export type ProviderDetails = {
contactNotes?: string;
address: string;
relationship: string;
providerId: number;
};

export type Providers = ProviderDetails[];
Expand All @@ -23,13 +24,15 @@ type NewProviderProps = {
onClick: (newProvider: ProviderDetails) => void;
onClose: () => void;
provider: ProviderDetails;
providerId: number;
};

const NewProviderModal = ({
isOpen,
onClick,
onClose,
provider,
providerId,
}: NewProviderProps): React.ReactElement => {
const [providerName, setProviderName] = useState("");
const [providerFileNo, setProviderFileNo] = useState("");
Expand Down Expand Up @@ -234,6 +237,7 @@ const NewProviderModal = ({
relationship: relationshipChanged
? relationship
: provider.relationship,
providerId,
};
onClick(newProvider);
handleClose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ const ChildProviderForm = ({
contactNotes: "",
address: "",
relationship: "",
providerId: 0,
};

return (
Expand Down Expand Up @@ -110,6 +111,9 @@ const ChildProviderForm = ({
provider={
selectedIndex >= 0 ? providers[selectedIndex] : emptyProvider
}
providerId={
selectedIndex >= 0 ? selectedIndex : allProviders.length - 1
}
/>
</Box>
</VStack>
Expand Down