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

Add Plugin Support #2036

Merged
merged 14 commits into from
Apr 12, 2024
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,4 @@ secrets.sh
/.idea/misc.xml
/.idea/modules.xml
/.idea/vcs.xml
/.idea/ruff.xml
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ werkzeug = "==2.3.8"
[docs]
furo = "==2023.9.10"
sphinx = "==7.2.6"
myst-parser = "==2.0.0"

[requires]
python_version = "3.11"
94 changes: 92 additions & 2 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions care/facility/migrations/0426_alter_fileupload_file_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 4.2.10 on 2024-04-12 12:10

from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("facility", "0425_merge_20240403_2055"),
]

operations = [
migrations.AlterField(
model_name="fileupload",
name="file_type",
field=models.IntegerField(
choices=[
(0, "OTHER"),
(1, "PATIENT"),
(2, "CONSULTATION"),
(3, "SAMPLE_MANAGEMENT"),
(4, "CLAIM"),
(5, "DISCHARGE_SUMMARY"),
(6, "COMMUNICATION"),
(7, "CONSENT_RECORD"),
],
default=1,
),
),
]
133 changes: 78 additions & 55 deletions care/facility/models/file_upload.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,53 @@
import enum
import time
from uuid import uuid4

import boto3
from django.contrib.auth import get_user_model
from django.db import models

from care.facility.models import FacilityBaseModel
from care.users.models import User
from care.utils.csp.config import BucketType, get_client_config
from care.utils.models.base import BaseManager

User = get_user_model()

class FileUpload(FacilityBaseModel):
"""
Stores data about all file uploads
the file can belong to any type ie Patient , Consultation , Daily Round and so on ...
the file will be uploaded to the corresponding folders
the file name will be randomised and converted into an internal name before storing in S3
all data will be private and file access will be given on a NEED TO BASIS ONLY
"""

# TODO : Periodic tasks that removes files that were never uploaded

class FileType(enum.Enum):
PATIENT = 1
CONSULTATION = 2
SAMPLE_MANAGEMENT = 3
CLAIM = 4
DISCHARGE_SUMMARY = 5
COMMUNICATION = 6
CONSENT_RECORD = 7
class BaseFileUpload(models.Model):
class FileCategory(models.TextChoices):
UNSPECIFIED = "UNSPECIFIED", "UNSPECIFIED"
XRAY = "XRAY", "XRAY"
AUDIO = "AUDIO", "AUDIO"
IDENTITY_PROOF = "IDENTITY_PROOF", "IDENTITY_PROOF"

class FileCategory(enum.Enum):
UNSPECIFIED = "UNSPECIFIED"
XRAY = "XRAY"
AUDIO = "AUDIO"
IDENTITY_PROOF = "IDENTITY_PROOF"

FileTypeChoices = [(e.value, e.name) for e in FileType]
FileCategoryChoices = [(e.value, e.name) for e in FileCategory]
external_id = models.UUIDField(default=uuid4, unique=True, db_index=True)

name = models.CharField(max_length=2000) # name should not contain file extension
internal_name = models.CharField(
max_length=2000
) # internal_name should include file extension
associating_id = models.CharField(max_length=100, blank=False, null=False)
upload_completed = models.BooleanField(default=False)
is_archived = models.BooleanField(default=False)
archive_reason = models.TextField(blank=True)
uploaded_by = models.ForeignKey(
User,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name="uploaded_by",
)
archived_by = models.ForeignKey(
User,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name="archived_by",
)
archived_datetime = models.DateTimeField(blank=True, null=True)
file_type = models.IntegerField(
choices=FileTypeChoices, default=FileType.PATIENT.value
)
file_type = models.IntegerField(default=0)
file_category = models.CharField(
choices=FileCategoryChoices,
default=FileCategory.UNSPECIFIED.value,
choices=FileCategory.choices,
default=FileCategory.UNSPECIFIED,
max_length=100,
)
created_date = models.DateTimeField(
auto_now_add=True, null=True, blank=True, db_index=True
sainak marked this conversation as resolved.
Show resolved Hide resolved
)
modified_date = models.DateTimeField(
auto_now=True, null=True, blank=True, db_index=True
)
upload_completed = models.BooleanField(default=False)
deleted = models.BooleanField(default=False, db_index=True)

def get_extension(self):
parts = self.internal_name.split(".")
return f".{parts[-1]}" if len(parts) > 1 else ""
objects = BaseManager()

class Meta:
abstract = True

def delete(self, *args):
self.deleted = True
self.save(update_fields=["deleted"])

def save(self, *args, **kwargs):
if "force_insert" in kwargs or (not self.internal_name):
Expand All @@ -85,6 +59,10 @@ def save(self, *args, **kwargs):
self.internal_name = internal_name
return super().save(*args, **kwargs)

def get_extension(self):
parts = self.internal_name.split(".")
return f".{parts[-1]}" if len(parts) > 1 else ""

def signed_url(
self, duration=60 * 60, mime_type=None, bucket_type=BucketType.PATIENT
):
Expand Down Expand Up @@ -138,3 +116,48 @@ def file_contents(self):
content_type = response["ContentType"]
content = response["Body"].read()
return content_type, content


class FileUpload(BaseFileUpload):
"""
Stores data about all file uploads
the file can belong to any type ie Patient , Consultation , Daily Round and so on ...
the file will be uploaded to the corresponding folders
the file name will be randomised and converted into an internal name before storing in S3
all data will be private and file access will be given on a NEED TO BASIS ONLY
"""

# TODO : Periodic tasks that removes files that were never uploaded

class FileType(models.IntegerChoices):
OTHER = 0, "OTHER"
PATIENT = 1, "PATIENT"
CONSULTATION = 2, "CONSULTATION"
SAMPLE_MANAGEMENT = 3, "SAMPLE_MANAGEMENT"
CLAIM = 4, "CLAIM"
DISCHARGE_SUMMARY = 5, "DISCHARGE_SUMMARY"
COMMUNICATION = 6, "COMMUNICATION"
CONSENT_RECORD = 7, "CONSENT_RECORD"

file_type = models.IntegerField(choices=FileType.choices, default=FileType.PATIENT)
is_archived = models.BooleanField(default=False)
archive_reason = models.TextField(blank=True)
uploaded_by = models.ForeignKey(
User,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name="uploaded_by",
)
archived_by = models.ForeignKey(
User,
on_delete=models.PROTECT,
null=True,
blank=True,
related_name="archived_by",
)
archived_datetime = models.DateTimeField(blank=True, null=True)

# TODO: switch to Choices.choices
FileTypeChoices = [(x.value, x.name) for x in FileType]
FileCategoryChoices = [(x.value, x.name) for x in BaseFileUpload.FileCategory]
Loading
Loading