from django.db import models
from django.utils import timezone


class TimeTrackedModel(models.Model):
    created_at = models.DateTimeField(editable=False)
    updated_at = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.id:
            self.created_at = timezone.now()
        self.updated_at = timezone.now()
        return super(TimeTrackedModel, self).save(*args, **kwargs)

    class Meta:
        abstract = True


# This model is still has a prototypical status, but I needed something to
# test with and it's at least in the right ballpark
class Batch(TimeTrackedModel):
    source_type = models.CharField(max_length=256)
    size_in_bytes = models.IntegerField()
    download_url = models.CharField(max_length=256)
    raw_format = models.CharField(max_length=256)
    processed_format = models.CharField(max_length=256)
    processor_required = models.IntegerField()
    accession_code = models.CharField(max_length=256)

    # This field where denote where in our system the file can be found
    internal_location = models.CharField(max_length=256)

    # This will at some be a meaningful integer->organism lookup thing
    organism = models.IntegerField()

    STATUSES = (
        ("NEW", "New"),
        ("DOWNLOADED", "Downloaded"),
        ("PROCESSED", "Proccessed"),
    )
    status = models.CharField(max_length=10, choices=STATUSES)

@@ -645,24 +645,70 @@
 ckedModel):%0A
+    survey_job = models.ForeignKey(SurveyJob)%0A
     source_t
@@ -955,16 +955,15 @@
    p
-rocessor
+ipeline
 _req
@@ -973,37 +973,48 @@
 ed = models.
-Intege
+Cha
 rField(
+max_length=256
 )%0A    access
@@ -1044,35 +1044,34 @@
 ield(max_length=
+3
 2
-56
 )%0A%0A    # This fi
@@ -1211,16 +1211,22 @@
 at some 
+point 
 be a mea
@@ -1365,130 +1365,2160 @@
 LOAD
-ED%22, %22Downloaded%22),%0A        (%22PROCESSED%22, %22Proccessed%22),%0A    )%0A    status = models.CharField(max_length=10, choices=STATUSES)
+ING%22, %22Downloading%22),%0A        (%22DOWNLOADED%22, %22Downloaded%22),%0A        (%22PROCESSING%22, %22Processing%22),%0A        (%22PROCESSED%22, %22Proccessed%22),%0A    )%0A    status = models.CharField(max_length=10, choices=STATUSES)%0A%0A    class Meta:%0A        db_table = %22batches%22%0A%0A%0A# This table is used for tacking fields onto a Batch record that would%0A# be sparsly populated if it was its own column.%0A# I.e. one source may have an extra field or two that are worth tracking%0A# but are specific to that source.%0Aclass BatchKeyValue(TimeTrackedModel):%0A    batch_id = models.ForeignKey(Batch, on_delete=models.CASCADE)%0A    key = models.CharField(max_length=256)%0A    value = models.CharField(max_length=256)%0A%0A    class Meta:%0A        db_table = %22batch_key_values%22%0A%0A%0Aclass ProcessorJob(TimeTrackedModel):%0A    batch_id = models.ForeignKey(Batch, on_delete=models.CASCADE)%0A    pipeline_applied = models.CharField(max_length=256)%0A    start_time = models.DateTimeField()%0A    end_time = models.DateTimeField()%0A    success = models.NullBooleanField()%0A    num_retries = models.IntegerField()%0A%0A    # This point of this field is to identify what worker ran the job.%0A    # A few fields may actually be required or something other than just an id.%0A    worker_id = models.CharField(max_length=256)%0A%0A    class Meta:%0A        db_table = %22processor_jobs%22%0A%0A%0Aclass DownloaderJob(TimeTrackedModel):%0A    batch_id = models.ForeignKey(Batch, on_delete=models.CASCADE)%0A    start_time = models.DateTimeField()%0A    end_time = models.DateTimeField()%0A    success = models.NullBooleanField()%0A    num_retries = models.IntegerField()%0A    worker_id = models.CharField(max_length=256)%0A%0A    class Meta:%0A        db_table = %22downloader_jobs%22%0A%0A%0Aclass SurveyJob(TimeTrackedModel):%0A    source_type = models.CharField(max_length=256)%0A%0A    # The start time of the query used to replicate%0A    replication_started_at = models.DateTimeField()%0A%0A    # The end time of the query used to replicate%0A    replication_ended_at = models.DateTimeField()%0A%0A    # The start time of the job%0A    start_time = models.DateTimeField()%0A%0A    # The end time of the job%0A    end_time = models.DateTimeField()%0A%0A    class Meta:%0A        db_table = %22survey_jobs%22
 %0A

Write out all the tables. No tests yet because I want to see what migrations are generated first.