365 lines
14 KiB
Python
Executable file
365 lines
14 KiB
Python
Executable file
# coding=utf-8
|
|
|
|
from django.db import models
|
|
|
|
# Create your models here.
|
|
|
|
|
|
class ICD9Diag(models.Model):
|
|
code = models.CharField(max_length=5, primary_key=True)
|
|
desc = models.CharField(max_length=50)
|
|
|
|
def __unicode__(self):
|
|
return "%s.%s %s" % (self.code[0:3], self.code[3:], self.desc)
|
|
|
|
|
|
class Activity(models.Model):
|
|
title = models.CharField(max_length=200)
|
|
|
|
def __unicode__(self):
|
|
return self.title
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
class Patient(models.Model):
|
|
GENDER_CHOICES = (
|
|
(1, 'Male'),
|
|
(2, 'Female'),
|
|
)
|
|
# STATUS_CHOICES = (
|
|
# ( 0, 'Male'),
|
|
# (10, 'Female'),
|
|
# )
|
|
name = models.CharField(max_length=200, verbose_name='姓名')
|
|
medical_records = models.CharField(max_length=200, unique=True)
|
|
gender = models.IntegerField(choices=GENDER_CHOICES)
|
|
birthday = models.DateField()
|
|
address = models.CharField(max_length=200)
|
|
phone = models.CharField(max_length=200)
|
|
id_cards = models.CharField(max_length=200, unique=True)
|
|
memo = models.CharField(max_length=200, blank=True, null=True)
|
|
dead = models.DateField(blank=True, null=True)
|
|
|
|
height = models.DecimalField(max_digits=4, decimal_places=1, null=True)
|
|
weight = models.DecimalField(max_digits=6, decimal_places=3, null=True)
|
|
native = models.CharField(max_length=200, blank=True, null=True)
|
|
past_and_family_history = models.TextField(blank=True, null=True)
|
|
|
|
# last_followup = models.DateField(blank=True, null=True)
|
|
# next_followup = models.DateField(blank=True, null=True)
|
|
|
|
timestamp = models.DateTimeField(auto_now=True)
|
|
|
|
def __unicode__(self):
|
|
return self.name
|
|
# return self.name+' '+str(self.medical_records)
|
|
|
|
class Admin:
|
|
pass
|
|
def get_absolute_url(self):
|
|
return "/patient/detail/%i/" % self.id
|
|
|
|
|
|
class Oncologist(models.Model):
|
|
name = models.CharField(max_length=200)
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
class Surgeon(models.Model):
|
|
name = models.CharField(max_length=200)
|
|
def __unicode__(self):
|
|
return self.name
|
|
|
|
class DiseaseStage(models.Model):
|
|
stage = models.CharField(max_length=200)
|
|
def __unicode__(self):
|
|
return self.stage
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
|
|
class PrimaryTumorSite(models.Model):
|
|
# id = models.IntegerField('ID', primary_key=True)
|
|
site = models.CharField(max_length=200)
|
|
|
|
def __unicode__(self):
|
|
return self.site
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
ACCOUNTING = (
|
|
(10, '健保'),
|
|
(20, '自費'),
|
|
(30, '內含'),
|
|
)
|
|
|
|
class Treatment(models.Model):
|
|
KARNOFSKY_SCORING = (
|
|
(100, '100% - normal, no complaints, no signs of disease'),
|
|
( 90, ' 90% - capable of normal activity, few symptoms or signs of disease'),
|
|
( 80, ' 80% - normal activity with some difficulty, some symptoms or signs'),
|
|
( 70, ' 70% - caring for self, not capable of normal activity or work'),
|
|
( 60, ' 60% - requiring some help, can take care of most personal requirements'),
|
|
( 50, ' 50% - requires help often, requires frequent medical care'),
|
|
( 40, ' 40% - disabled, requires special care and help'),
|
|
( 30, ' 30% - severely disabled, hospital admission indicated but no risk of death'),
|
|
( 20, ' 20% - very ill, urgently requiring admission, requires supportive measures or treatment'),
|
|
( 10, ' 10% - moribund, rapidly progressive fatal disease processes'),
|
|
( 0, ' 0% - death'),
|
|
)
|
|
|
|
IMAGE_GUIDANCE = (
|
|
(100, '6D Skull'),
|
|
(200, 'Xsight-Spine'),
|
|
(210, 'Xsight-Lung'),
|
|
(300, 'Fiducial'),
|
|
(400, 'Synchrony'),
|
|
)
|
|
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
bed = models.CharField(max_length=200, blank=True, null=True, verbose_name='病床號')
|
|
icd9 = models.ForeignKey(ICD9Diag, blank=True, null=True, verbose_name='ICD9診斷', on_delete=models.SET_NULL)
|
|
other_diagnosis = models.CharField(max_length=200, blank=True, null=True, verbose_name='其他診斷')
|
|
tracking_mode = models.IntegerField(choices=IMAGE_GUIDANCE, blank=True, null=True)
|
|
referral = models.CharField(max_length=200, blank=True, null=True, verbose_name='轉介醫師')
|
|
oncologist = models.ForeignKey(Oncologist, blank=True, null=True, on_delete=models.SET_NULL)
|
|
surgeon = models.ForeignKey(Surgeon, blank=True, null=True, on_delete=models.SET_NULL)
|
|
date_started = models.DateField(blank=True, null=True)
|
|
date_completed = models.DateField(blank=True, null=True)
|
|
accounting = models.IntegerField(choices=ACCOUNTING, blank=True, null=True, verbose_name='記帳別')
|
|
karnofsky_score = models.IntegerField(choices=KARNOFSKY_SCORING, blank=True, null=True)
|
|
disease_stage = models.ForeignKey(DiseaseStage, blank=True, null=True, on_delete=models.SET_NULL)
|
|
primary_tumor_site = models.ForeignKey(PrimaryTumorSite, blank=True, null=True, on_delete=models.SET_NULL)
|
|
input = models.ForeignKey(Activity, related_name='input', blank=True, null=True, verbose_name='已', on_delete=models.SET_NULL)
|
|
output = models.ForeignKey(Activity, related_name='output', blank=True, null=True, verbose_name='待', on_delete=models.SET_NULL)
|
|
complications = models.CharField(max_length=200, blank=True, null=True, verbose_name='併發症')
|
|
chief_complaint = models.TextField(blank=True, null=True)
|
|
|
|
memo = models.CharField(max_length=200, blank=True, null=True)
|
|
timestamp = models.DateTimeField(auto_now=True)
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
def get_absolute_url(self):
|
|
return "/treatment/detail/%i/" % self.id
|
|
|
|
class Price(models.Model):
|
|
code = models.CharField(max_length=200, blank=True, null=True)
|
|
identity = models.IntegerField(choices=ACCOUNTING)
|
|
name = models.CharField(max_length=200)
|
|
unit = models.CharField(max_length=200, blank=True, null=True)
|
|
address = models.IntegerField(blank=True, null=True)
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
def __unicode__(self):
|
|
return self.code + '-' + self.get_identity_display() + '-' + self.name
|
|
|
|
class VEVENT(models.Model):
|
|
# iCalendar
|
|
DTSTAMP = models.DateTimeField(auto_now=True)
|
|
DTSTART = models.DateTimeField()
|
|
DTEND = models.TimeField(blank=True)
|
|
DURATION = models.TimeField()
|
|
SUMMARY = models.CharField(max_length=200, blank=True, null=True)
|
|
CLASS = models.CharField(max_length=200, blank=True, null=True)
|
|
CATEGORIES = models.CharField(max_length=200, blank=True, null=True)
|
|
TRANSP = models.CharField(max_length=200, blank=True, null=True)
|
|
RRULE = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
DESCRIPTION = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
MODE_CHOICES = (
|
|
(110, 'Fiducial'),
|
|
(200, '固定器'),
|
|
(210, 'CT'),
|
|
(220, 'MRI'),
|
|
(230, 'Angio'),
|
|
(310, '治療'),
|
|
)
|
|
treatment = models.ForeignKey(Treatment, on_delete=models.CASCADE)
|
|
mode = models.IntegerField(choices=MODE_CHOICES)
|
|
price = models.ForeignKey(Price, blank=True, null=True, on_delete=models.SET_NULL)
|
|
|
|
break_frequency = models.IntegerField(blank=True)
|
|
system_err = models.IntegerField(blank=True)
|
|
shift = models.IntegerField(blank=True)
|
|
cone = models.IntegerField(blank=True)
|
|
path = models.IntegerField(blank=True)
|
|
|
|
def get_absolute_url(self):
|
|
return "/treatment/detail/%i/" % self.treatment.id
|
|
|
|
class TargetLocation(models.Model):
|
|
location = models.CharField(max_length=200)
|
|
|
|
def __unicode__(self):
|
|
return self.location
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
|
|
class Pathology(models.Model):
|
|
pathology = models.CharField(max_length=200, unique=True)
|
|
stage = models.ForeignKey(DiseaseStage, on_delete=models.CASCADE)
|
|
|
|
def __unicode__(self):
|
|
return self.pathology
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
|
|
class SubLocation(models.Model):
|
|
target_location = models.ForeignKey(TargetLocation, on_delete=models.CASCADE)
|
|
group = models.IntegerField()
|
|
sub_location = models.CharField(max_length=200)
|
|
pathology = models.ManyToManyField(Pathology)
|
|
|
|
def __unicode__(self):
|
|
# return TargetLocation.objects.get(id=self.target_location)+' - '+self.sub_location
|
|
return self.sub_location
|
|
|
|
class Admin:
|
|
pass
|
|
|
|
|
|
class Lesion(models.Model):
|
|
treatment = models.ForeignKey(Treatment, on_delete=models.CASCADE)
|
|
sub_location = models.ForeignKey(SubLocation, on_delete=models.CASCADE)
|
|
pathology = models.ForeignKey(Pathology, on_delete=models.CASCADE)
|
|
|
|
dimensions = models.CharField(max_length=200)
|
|
volume = models.DecimalField(max_digits=9, decimal_places=2)
|
|
|
|
plan_name = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
collimator = models.CharField(max_length=200)
|
|
path_no = models.IntegerField()
|
|
beam_no = models.IntegerField()
|
|
|
|
mu_max = models.DecimalField(max_digits=9, decimal_places=2)
|
|
mu_min = models.DecimalField(max_digits=9, decimal_places=2)
|
|
|
|
dose = models.IntegerField()
|
|
fractions = models.IntegerField()
|
|
iso_dose_curve = models.IntegerField()
|
|
|
|
dmin = models.DecimalField(max_digits=9, decimal_places=2)
|
|
dmax = models.DecimalField(max_digits=9, decimal_places=2)
|
|
|
|
coverage = models.DecimalField(max_digits=9, decimal_places=2)
|
|
ci = models.DecimalField(max_digits=9, decimal_places=2)
|
|
nci = models.DecimalField(max_digits=9, decimal_places=2)
|
|
|
|
start_date = models.DateField(blank=True, null=True)
|
|
end_date = models.DateField(blank=True, null=True)
|
|
|
|
memo = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
def get_absolute_url(self):
|
|
return "/treatment/detail/%i/" % self.treatment.id
|
|
|
|
def sub_location_target_location(self):
|
|
return self.sub_location.target_location
|
|
|
|
def treatment_id(self):
|
|
return treatment.id
|
|
|
|
class PriorTreatment(models.Model):
|
|
TREATMENT_CHOICES = (
|
|
(1, 'Surgery'),
|
|
(2, 'Biopsy'),
|
|
(3, 'RT'),
|
|
(4, 'Radiosurgery'),
|
|
(5, 'Chemotherapy'),
|
|
)
|
|
PERIOD_CHOICES = (
|
|
(1, 'Before'),
|
|
(2, 'Concurrent'),
|
|
(3, 'None'),
|
|
)
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
date = models.DateField()
|
|
treatment = models.IntegerField(choices=TREATMENT_CHOICES)
|
|
period = models.IntegerField(choices=PERIOD_CHOICES, blank=True, null=True)
|
|
dose = models.IntegerField(blank=True, null=True)
|
|
memo = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
def get_absolute_url(self):
|
|
return "/patient/detail/%i/" % self.patient.id
|
|
|
|
|
|
class PathExam(models.Model):
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
path_code = models.CharField(max_length=200, unique=True, verbose_name='病理號')
|
|
specimen_code = models.CharField(max_length=200, verbose_name='檢體')
|
|
specimen_get_date = models.DateField(verbose_name='收件日')
|
|
report_date = models.DateField(verbose_name='報告日')
|
|
division = models.CharField(max_length=200, verbose_name='科別')
|
|
bed = models.CharField(max_length=200, blank=True, null=True, verbose_name='病床')
|
|
report = models.TextField(blank=True, null=True, verbose_name='檢查報告')
|
|
|
|
|
|
class Followup(models.Model):
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
# date = models.DateField(auto_now_add=True)
|
|
date = models.DateField()
|
|
memo = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
def get_absolute_url(self):
|
|
return "/patient/detail/%i/" % self.patient.id
|
|
|
|
class PACSImage(models.Model):
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
|
|
PatChartNo = models.CharField(max_length=200, verbose_name='病歷號')
|
|
RequestSheetNo = models.CharField(max_length=200, verbose_name='單號')
|
|
ExamDate = models.DateField( verbose_name='檢查日')
|
|
LinkOrderName = models.CharField(max_length=200, verbose_name='檢查名稱')
|
|
Modality = models.CharField(max_length=200, verbose_name='儀器')
|
|
VerifiedStateString = models.CharField(max_length=200, verbose_name='狀態')
|
|
|
|
SAVED_CHOICES = (
|
|
(0 , '待處理'),
|
|
(10, '有輸入'),
|
|
(15, '已確認'),
|
|
(20, '不適用'),
|
|
)
|
|
# Saved = models.BooleanField()
|
|
Saved = models.IntegerField(choices=SAVED_CHOICES, verbose_name='保存')
|
|
|
|
|
|
class LesionFollow(models.Model):
|
|
Lesion = models.ForeignKey(Lesion, on_delete=models.CASCADE)
|
|
Date = models.DateField(null=False, verbose_name='追蹤日期')
|
|
Volume = models.FloatField(null=True, verbose_name='體積(mm3)')
|
|
A = models.FloatField(null=True, verbose_name='長(mm)')
|
|
B = models.FloatField(null=True, verbose_name='寬(mm)')
|
|
C = models.FloatField(null=True, verbose_name='高(mm)')
|
|
Memo = models.CharField(max_length=200, blank=True, null=True)
|
|
|
|
|
|
class MedicalRecord(models.Model):
|
|
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
|
|
|
|
Record = models.CharField(max_length=200, null=True) # 住急門
|
|
|
|
HospName = models.CharField(max_length=200, null=True)
|
|
DeptName = models.CharField(max_length=200, null=True, verbose_name='科')
|
|
InDate = models.DateField( null=False, verbose_name='入')
|
|
OutDate = models.DateField( null=True, verbose_name='出')
|
|
WardName = models.CharField(max_length=200, null=True, verbose_name='房')
|
|
RoomName = models.CharField(max_length=200, null=True, verbose_name='室')
|
|
BedName = models.CharField(max_length=200, null=True, verbose_name='床')
|
|
MainDrName = models.CharField(max_length=200, null=True, verbose_name='主治')
|
|
MainDiagnosisName = models.CharField(max_length=200, null=True, verbose_name='診斷')
|
|
StatusName = models.CharField(max_length=200, null=True, verbose_name='狀態')
|
|
|
|
SpecialCureName = models.CharField(max_length=200, null=True, verbose_name='行為')
|