Esempio n. 1
0
class Attachment(CacheClearingModel, TimeStampedModel):
    """
    A file attached to a submitted thing.
    """
    file = models.FileField(upload_to=timestamp_filename,
                            storage=AttachmentStorage())
    name = models.CharField(max_length=128, null=True, blank=True)
    thing = models.ForeignKey('SubmittedThing',
                              on_delete=models.CASCADE,
                              related_name='attachments')
    height = models.IntegerField(blank=True, null=True)
    width = models.IntegerField(blank=True, null=True)

    cache = cache.AttachmentCache()

    # previous_version = 'sa_api_v1.models.Attachment'

    def save(self, *args, **kwargs):
        try:
            image = Image.open(self.file)
            width, height = image.size
        except (ValueError, EOFError) as e:
            height = None
            width = None

        self.width = width
        self.height = height

        super(Attachment, self).save(*args, **kwargs)

    class Meta:
        app_label = 'sa_api_v2'
        db_table = 'sa_api_attachment'
Esempio n. 2
0
class Tag(models.Model):
    """ In geopaparrazi, Tags are actually form definitions, which are stored as JSON.
    This table keeps track of these JSON files.

    Future enhancement:  create a form for creating Tag files.
    """
    path = models.CharField(max_length=100, blank=True, default='')
    modifieddate = models.DateTimeField(auto_now_add=True)
    url = models.FileField(upload_to=tag_directory_path)
    size = models.CharField(max_length=30, blank=True, null=True)
    # add description and owner
    owner = models.ForeignKey('users.user',
                              to_field='id',
                              on_delete=models.CASCADE,
                              blank=True,
                              null=True)

    def save(self, *args, **kwargs):
        self.size = self.url.size
        super().save(*args, **kwargs)

    def __str__(self):
        return self.path

    class Meta:
        ordering = (
            'path',
            '-modifieddate',
        )
Esempio n. 3
0
class GentityFile(models.Model):
    # for db sync issues
    original_id = models.IntegerField(null=True, blank=True, editable=False)
    original_db = models.ForeignKey(Database, null=True, editable=False)
    last_modified = models.DateTimeField(auto_now=True,
                                         null=True,
                                         editable=False)

    gentity = models.ForeignKey(Gentity)
    date = models.DateField(blank=True, null=True)
    file_type = models.ForeignKey(FileType)
    content = models.FileField(upload_to='gentityfile')
    descr = models.CharField(max_length=100)
    remarks = models.TextField(blank=True)
    descr_alt = models.CharField(max_length=100)
    remarks_alt = models.TextField(blank=True)

    def __unicode__(self):
        return self.descr or self.descr_alt or str(self.id)

    @property
    def related_station(self):
        try:
            return Station.objects.get(id=self.gentity.id)
        except:
            return None
Esempio n. 4
0
class Attachment(ModifiableModel, AutoIdentifiedModel):
    name = models.CharField(verbose_name=_('Name'), max_length=200)
    attachment_file = models.FileField(verbose_name=_('File'),
                                       upload_to='attachment_files')

    def __str__(self):
        return self.name
Esempio n. 5
0
class File(models.Model):
    fileid = models.UUIDField(primary_key=True, default=uuid.uuid1)  # This field type is a guess.
    path = models.FileField(upload_to='uploadedfiles')

    class Meta:
        managed = True
        db_table = 'files'
Esempio n. 6
0
class Project(models.Model):
    """ A geopaparrazi project is a SQLite database, typically with a .gpap extension.
    This table keeps track of the blank projects that are provided to the app
    via the profile downloads.  Note that the path field defines where the file
    is stored on the mobile device.

    Future enhancements:
    -  The uploadurl field should be changed to reflect the URL endpoint for uploading
    UserProjects.
    - the size field should be automatically generated
    """
    path = models.CharField(max_length=100, blank=True, default='')
    modifieddate = models.DateTimeField(auto_now_add=True)
    url = models.FileField(upload_to='projects/')
    uploadurl = models.URLField(blank=True)
    size = models.CharField(max_length=30, blank=True, null=True)
    description = models.TextField(blank=True, null=True)

    def save(self, *args, **kwargs):
        """
        calculate the file size before saving
        """
        self.size = self.url.size
        super().save(*args, **kwargs)

    def __str__(self):
        return self.path

    class Meta:
        ordering = (
            'path',
            '-modifieddate',
        )
Esempio n. 7
0
class ChatMessage(models.Model):
    """
    Модель отвечает за сообщение пользователя
    user - автор сообщения
    message_chat - чат в который было отправлено сообщение
    message_text - текст сообщения
    message_file - файл в сообщении (необязательное поле)
    """
    # message author
    user = models.ForeignKey(FitnessUser, on_delete=models.CASCADE)
    # chat
    message_chat = models.ForeignKey(Chat, on_delete=models.CASCADE)
    # message text
    message_text = models.TextField(max_length=1000)
    # message creating datetime
    message_datetime = models.DateTimeField(default=now)
    # message read status
    message_readed = models.BooleanField(default=False)
    # message file
    message_file = models.FileField(blank=True,
                                    null=True,
                                    upload_to=chat_directory_path)

    def __str__(self):
        return f'User: {self.user.user.username}; Chat: {self.message_chat.users_list()}; ' \
               f'Message: {self.short_message()}'

    def short_message(self):
        return self.message_text if len(
            self.message_text) < 30 else self.message_text[:30] + ' ...'
Esempio n. 8
0
File: models.py Progetto: zokis/TG
class Categoria(models.Model):
    ESTILO = {
        'graphicWidth': 32,
        'graphicHeight': 32,
        'externalGraphic': 'http://104.131.23.39/media/markers/C_3674.png',
    }

    nome = models.CharField('nome', max_length=75)
    descricao = models.CharField(u'Descrição', max_length=200)
    marker = models.FileField(upload_to=marker_rename, blank=True, null=True)
    estilo = JSONField(default=dumps(ESTILO), blank=True, null=True)
    perigosa = models.BooleanField(default=False)

    def get_estilo(self):
        if self.estilo:
            try:
                estilo = loads(self.estilo)
            except TypeError:
                estilo = None

        if not self.estilo or not estilo:
            estilo = self.ESTILO.copy()

        if self.marker:
            estilo['externalGraphic'] = self.marker.url
        return estilo

    def get_estilo_json(self):
        if self.estilo:
            return self.estilo
        else:
            return dumps(self.get_estilo())

    def __unicode__(self):
        return u'%s' % (self.nome)
Esempio n. 9
0
class FileDataSource(DataSource):
    """DataSource with a source_file field and processing statuses."""
    class Statuses(object):
        PENDING = 'pending'
        UPLOADING = 'uploading'
        UPLOADED = 'uploaded'
        PROCESSING = 'processing'
        DOWNLOADING = 'downloading'
        WAITING_USER_INPUT = 'waiting_input'
        VALIDATING = 'validating'
        IMPORTING = 'importing'
        COMPLETE = 'complete'
        WARNING = 'warning'
        ERROR = 'error'
        CHOICES = (
            (PENDING, _(u'Pending')),
            (UPLOADING, _(u'Uploading')),
            (UPLOADED, _(u'Uploaded')),
            (PROCESSING, _(u'Processing')),
            (DOWNLOADING, _(u'Downloading')),
            (IMPORTING, _(u'Importing')),
            (WAITING_USER_INPUT, _(u'Waiting for User Input')),
            (VALIDATING, _(u'Validating')),
            (COMPLETE, _(u'Complete')),
            (WARNING, _(u'Warning')),
            (ERROR, _(u'Error')),
        )

    source_file = models.FileField()
    status = models.CharField(max_length=16,
                              default=Statuses.PENDING,
                              choices=Statuses.CHOICES)

    class Meta(object):
        abstract = True
Esempio n. 10
0
class UploadedFile(models.Model):
    title = models.CharField(max_length=255, blank=True)
    file = models.FileField(upload_to='uploads/')
    uploaded_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        managed = True
Esempio n. 11
0
class DigitalObject(models.Model):
    name = models.CharField(max_length=500)
    description = models.TextField(null=True, blank=True)
    digital_format = models.ForeignKey(DigitalFormat)
    file = models.FileField(upload_to="portal/%Y/%m/%d/",
                            null=True,
                            blank=True)
    url = models.URLField(null=True, blank=True)
    source = models.CharField(max_length=500, null=True, blank=True)

    audience = models.ManyToManyField(Audience, null=True, blank=True)
    facet = models.ManyToManyField(Facet)
    tag = models.ManyToManyField(Tag, null=True, blank=True)

    created_date = models.DateTimeField('created_date', default=datetime.now)
    modified_date = models.DateTimeField('modified_date', default=datetime.now)

    markup = models.TextField(null=True, blank=True)

    def __unicode__(self):
        return self.name

    class Meta:
        verbose_name = "Digital Object"
        ordering = ['name']
Esempio n. 12
0
class LeaseAreaAttachment(TimeStampedSafeDeleteModel):
    """
    In Finnish: Liitetiedosto (Vuokra-alue)
    """

    lease_area = models.ForeignKey(LeaseArea,
                                   related_name="attachments",
                                   on_delete=models.PROTECT)

    # In Finnish: Tyyppi
    type = EnumField(LeaseAreaAttachmentType,
                     verbose_name=_("Type"),
                     max_length=30)

    # In Finnish: Tiedosto
    file = models.FileField(upload_to=get_attachment_file_upload_to,
                            blank=False,
                            null=False)

    # In Finnish: Lataaja
    uploader = models.ForeignKey(User,
                                 verbose_name=_("Uploader"),
                                 related_name="+",
                                 on_delete=models.PROTECT)

    # In Finnish: Latausaika
    uploaded_at = models.DateTimeField(auto_now_add=True,
                                       verbose_name=_("Time uploaded"))

    recursive_get_related_skip_relations = ["lease_area", "uploader"]

    class Meta:
        verbose_name = pgettext_lazy("Model name", "Lease area attachment")
        verbose_name_plural = pgettext_lazy("Model name",
                                            "Lease area attachments")
Esempio n. 13
0
class NamedMask(models.Model):
    name = models.CharField(_('name'), max_length=100)
    projection = models.IntegerField(_('projection'), help_text=_('EPSG code'))
    mask = models.FileField(_('mask'),
                            upload_to=get_named_mask_upload_path,
                            storage=namedMaskStorage)
    mask_path = models.CharField(_('mask path'),
                                 max_length=255,
                                 null=True,
                                 blank=True)

    # TODO: override save() and check if name has changed -> rename directory
    def save(self, *args, **kwargs):
        super(NamedMask, self).save(*args, **kwargs)
        target_path = extract_zipfile(self.mask.path)
        shape = find_shapefile(target_path)
        self.mask_path = shape
        super(NamedMask, self).save(*args, **kwargs)

    def __str__(self):
        return "%s (%s)" % (self.name, self.projection)

    class Meta:
        verbose_name = _('Mask')
        verbose_name_plural = _('Masks')
Esempio n. 14
0
class Attachment(AnnotationAbstract):
    def attachement_dir(instance, filename):
        return "user_{0}/attachements/{1}".format(instance.author.pk, filename)

    title = models.CharField('Titre', max_length=128)

    info = models.TextField('Info', blank=True, null=True)

    object_type = models.CharField("Type d'objet concerné",
                                   choices=RELATED_MODELS,
                                   max_length=50)

    # TODO@cbenhabib: valider L'extension + Taille du fichier?
    attachment_file = models.FileField('Pièce jointe',
                                       upload_to=attachement_dir)

    # TODO@cbenhabib: si suppression d'un commentaire?
    comment = models.ForeignKey("geocontrib.Comment",
                                on_delete=models.SET_NULL,
                                blank=True,
                                null=True)

    class Meta:
        verbose_name = "Pièce jointe"
        verbose_name_plural = "Pièces jointes"

    def __str__(self):
        if self.title:
            return self.title

    @property
    def extension(self):
        name, extension = os.path.splitext(self.attachment_file.name)
        return extension
Esempio n. 15
0
class GeoLayer(models.Model):
    organization = models.ForeignKey(Organization,
                                     related_name='geo_layers',
                                     on_delete=models.CASCADE)
    level = models.IntegerField(default=1)
    title = models.CharField(max_length=255)
    title_prop = models.CharField(max_length=255, blank=True)
    code_prop = models.CharField(max_length=255, blank=True)
    geo_shape_file = models.FileField(upload_to='geo_layers/')
    stale_areas = models.BooleanField(default=True)
    tolerance = models.FloatField(default=0.0001)

    class Meta:
        ordering = ['title', 'level']

    def __unicode__(self):
        return self.title

    def save(self, *args, **kwargs):
        from .loader import load_areas

        super(GeoLayer, self).save(*args, **kwargs)

        if self.stale_areas:
            load_areas(self)
Esempio n. 16
0
class Record(models.Model):
    """This model represents a record that needs to be saved for
    future reference. It also records metadata and optional text content to be
    indexed for search.
    """
    DOC_CATEGORY_CHOICES = Choices(
        (1, 'consent', ('Landowner consent')),
        (2, 'deed', ('Deed')),
        (3, 'assessment', ('Assessment report')),
        (4, 'referee_response', ('Referee response')),
        (5, 'lodgement', ('Lodgement document')),
        (6, 'draft', ('Draft document')),
        (7, 'final', ('Final document')),
        (8, 'determination', ('Determination document')),
        (9, 'completion', ('Completed document')),
    )

    upload = models.FileField(max_length=512, upload_to='uploads/%Y/%m/%d')
    name = models.CharField(max_length=256)
    category = models.IntegerField(choices=DOC_CATEGORY_CHOICES,
                                   null=True,
                                   blank=True)
    metadata = JSONField(null=True, blank=True)
    text_content = models.TextField(null=True, blank=True,
                                    editable=False)  # Text for indexing

    def __str__(self):
        if self.category:
            return '{} ({})'.format(self.name, self.get_category_display())
        return self.name
Esempio n. 17
0
class Transaction(models.Model):

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

    total_amount = models.IntegerField(null=True)

    PAYMENT_STATUS = [
        ('OK', 'Successful'),
        ('FL', 'Failed'),
        ('PD', 'Pending'),

        ('NA', 'Not Available')
    ]

    transaction_type = models.CharField(max_length=255, blank=True, null=True)
    transaction_message = models.CharField(max_length=255, blank=True, null=True)
    card_holder = models.CharField(max_length=255, blank=True, null=True)
    card_no_mask = models.CharField(max_length=255, blank=True, null=True)
    
    payment_status = models.CharField(choices=PAYMENT_STATUS, max_length=2, default='PD')    
    payment_gateway_update_date = models.DateTimeField(null=True) 

    PAYMENT_METHOD = [
        ('CC', 'Credit Card'),
        ('DD', 'Direct Debit'),
        ('WA', 'e-Wallet'),
        ('NA', 'Not Available')
    ]
    payment_method = models.CharField(choices=PAYMENT_METHOD, max_length=2, null=True)

    name = models.CharField(max_length=512, null=True)
    organisation = models.CharField(max_length=512, null=True) 
    address1 = models.CharField(max_length=512, null=True) 
    address2 = models.CharField(max_length=512, null=True) 
    address3 = models.CharField(max_length=512, null=True) 
    postcode = models.CharField(max_length=512, null=True) 
    state = models.CharField(max_length=512, null=True) 
    city = models.CharField(max_length=512, null=True) 
    country = models.CharField(max_length=512, null=True) 
    email_address = models.CharField(max_length=512, null=True) 
    phone_number = models.CharField(max_length=512, null=True) 

    reference =  models.CharField(max_length=512, null=True)     

    cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)

    payment_gateway_order_id = models.IntegerField(default=0)

    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
    reference_no = models.CharField(max_length=512, null=True)
    transaction_id = models.CharField(max_length=512, null=True)
    receipt_no = models.CharField(max_length=512, null=True)
    receipt = models.FileField(null=True, upload_to=PathAndRename('transaction-receipt'))

    created_date = models.DateTimeField(auto_now_add=True)
    modified_date = models.DateTimeField(auto_now=True)

    class Meta:
       ordering = ['-payment_gateway_update_date']
Esempio n. 18
0
class Record(models.Model):
    """This model represents a record that needs to be saved for
    future reference. It also records metadata and optional text content to be
    indexed for search.
    """
    DOC_CATEGORY_CHOICES = Choices(
        (1, 'consent', ('Landowner consent')),
        (2, 'deed', ('Deed')),
        (3, 'assessment', ('Assessment report')),
        (4, 'referee_response', ('Referee response')),
        (5, 'lodgement', ('Lodgement document')),
        (6, 'draft', ('Draft document')),
        (7, 'final', ('Final document')),
        (8, 'determination', ('Determination document')),
        (9, 'completion', ('Completed document')),
    )

    FILE_GROUP = Choices(
        (1, 'permit', ('Permit')), (2, 'licence', ('Licence/permit')),
        (3, 'part5', ('Part 5')), (4, 'emergency', ('Emergency works')),
        (5, 'part5cr', ('Part 5 - Amendment Request')),
        (6, 'part5amend', ('Part 5 - Amendment Application')),
        (7, 'test', ('Test - Application')), (8, 'permitamend',
                                              ('Amend Permit')),
        (9, 'licenceamend', ('Amend Licence')), (10, 'permitrenew',
                                                 ('Renew Permit')),
        (11, 'licencerenew', ('Renew Licence')), (2001, 'person', ('Person')),
        (2002, 'organisation', ('Organistion')),
        (2003, 'application_comms',
         ('Application Communication Logs')), (2004, 'account_comms',
                                               ('Account Communication Logs')),
        (2005, 'approval', ('Approval')), (2006, 'compliance', ('Compliance')),
        (2007, 'approval_comms', ('Approval Communication Logs')))

    upload = models.FileField(max_length=512,
                              upload_to='uploads/%Y/%m/%d',
                              storage=upload_storage)
    name = models.CharField(max_length=256)
    category = models.IntegerField(choices=DOC_CATEGORY_CHOICES,
                                   null=True,
                                   blank=True)
    metadata = JSONField(null=True, blank=True)
    text_content = models.TextField(null=True, blank=True,
                                    editable=False)  # Text for indexing
    file_group = models.IntegerField(choices=FILE_GROUP, null=True, blank=True)
    file_group_ref_id = models.IntegerField(null=True, blank=True)
    extension = models.CharField(max_length=5, null=True, blank=True)
    created = models.DateTimeField(auto_now_add=True, null=True, blank=True)

    def file_url(self):
        if self.extension is None:
            self.extension = ''
        return settings.PRIVATE_MEDIA_URL + str(
            self.pk) + '-file' + self.extension

    def __str__(self):
        if self.category:
            return '{} ({})'.format(self.name, self.get_category_display())
        return self.name
Esempio n. 19
0
class AbstractWMS(AbstractMap):
    local = models.BooleanField(default=False) # locally hosted on geoserver
    sourceFile = models.FileField(upload_to=settings.XGDS_MAP_SERVER_GEOTIFF_SUBDIR, max_length=256,
                                  null=True, blank=True)
    projectionName = models.CharField(null=True, max_length=32, blank=True)
    wmsUrl = models.CharField(null=True, max_length=512)
    layers = models.CharField(null=True, max_length=64, db_index=True)
    # geoserver specific stuff
    workspaceName = models.CharField(null=True, max_length=32, blank=True)
    storeName = models.CharField(null=True, max_length=32, blank=True)
    format = models.CharField(max_length=16, default="image/png")  # the format on geoserver
    tileWidth = models.IntegerField(default=256)
    tileHeight = models.IntegerField(default=256)
    minLevel = models.IntegerField(default=0)
    maxLevel = models.IntegerField(null=True, blank=True)
    wmsVersion = models.CharField(default='1.1.1', max_length=16)  # wms version, 1.1.1, or could be 1.3.0
    srs = models.CharField(null=True, blank=True, max_length=32)  # srs or crs if we are wms version 1.3.0 or higher
    hasTime = models.BooleanField(default=False) #whether or not this supports time ie lunaserv time wms
    start = models.DateTimeField(null=True, blank=True, db_index=True)
    end = models.DateTimeField(null=True, blank=True, db_index=True)
    interval = models.FloatField(null=True, blank=True)


    def getUrl(self):
        return self.wmsUrl

    def get_tree_json(self):
        """ Get the json block that the fancy tree needs to render this node """
        result = super(AbstractWMS, self).get_tree_json()
        result["data"]["tileURL"] = self.getUrl()
        result["data"]["format"] = self.format
        result["data"]["layers"] = self.layers
        result["data"]["tileWidth"] = self.tileWidth
        result["data"]["tileHeight"] = self.tileHeight
        result["data"]["wmsVersion"] = self.wmsVersion
        result["data"]["srs"] = self.srs
        result["data"]["hasTime"] = self.hasTime
        if self.hasTime:
            result["data"]["start"] = self.start
            result["data"]["end"] = self.end
            result["data"]["interval"] = self.interval

        if self.minLevel > 0:
            result["data"]["minLevel"] = self.minLevel
        if self.maxLevel:
            result["data"]["maxLevel"] = self.maxLevel
        if self.projectionName:
            result["data"]["projectionName"] = self.projectionName

        if self.minLat:
            result['data']['miny'] = self.minLat
            result['data']['minx'] = self.minLon
            result['data']['maxy'] = self.maxLat
            result['data']['maxx'] = self.maxLon

        return result

    class Meta:
        abstract = True
Esempio n. 20
0
class Propriedade(models.Model):
    nome = models.CharField(max_length=50)
    valor = models.DecimalField(decimal_places=2, max_digits=12)
    tipo = models.ForeignKey('imovel.Tipo', on_delete=models.PROTECT)
    foto = models.FileField()
    posicao = models.PointField('posicao', srid=4326, null=True)
    criado_em = models.DateTimeField(auto_now_add=True)
    modificado_em = models.DateTimeField(auto_now=True)
class Attachment(DatedModel):

    feature_layer = models.ForeignKey(FeatureLayer)
    feature_id = models.CharField(max_length=300)
    attachment = models.FileField(upload_to=attachment_upload,
                                  storage=upload_storage)
    name = models.CharField(max_length=300)
    content_type = models.CharField(max_length=200)
Esempio n. 22
0
class File(models.Model):
    fileid = models.UUIDField(primary_key=True, default=uuid.uuid1)  # This field type is a guess.
    path = models.FileField(upload_to="uploadedfiles")
    tile = models.ForeignKey("TileModel", db_column="tileid", null=True, on_delete=models.CASCADE)

    class Meta:
        managed = True
        db_table = "files"
Esempio n. 23
0
class Housevideo(models.Model):
    HouseID = models.ForeignKey(House,
                                to_field='HouseID',
                                on_delete=models.CASCADE)
    Video = models.FileField(null=True, blank=True)

    def __str__(self):
        return "%s" % (self.HouseID)
Esempio n. 24
0
class Wellphoto(models.Model):
    WellID = models.ForeignKey(Well,
                               to_field='WellID',
                               on_delete=models.CASCADE)
    Photo = models.FileField(null=True, blank=True)

    def __str__(self):
        return "%s" % (self.WellID)
Esempio n. 25
0
class Farmphoto(models.Model):
    FarmID = models.ForeignKey(Farm,
                               to_field='FarmID',
                               on_delete=models.CASCADE)
    Photo = models.FileField(null=True, blank=True)

    def __str__(self):
        return "%s" % (self.FarmID)
Esempio n. 26
0
class Dataset(models.Model):
    id = models.CharField(unique=True, primary_key=True, max_length=20)
    file = models.FileField(null=True, blank=True)
    label = models.CharField(null=True, max_length=500)
    type = models.CharField(null=True, max_length=10)

    def __str__(self):
        return self.id
Esempio n. 27
0
class EventAttachment(models.Model):
    event = models.ForeignKey(Event, blank=False, null=False)
    attachment = models.FileField(upload_to=attachment_file_path,
                                  blank=True,
                                  null=True)

    def filename(self):
        return os.path.basename(self.attachment.name)
Esempio n. 28
0
File: models.py Progetto: rossi1/RES
class Estate(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='user')
    description = models.TextField()
    topic = models.CharField(max_length=250)
    document = models.FileField()
    
    def __str__(self):
        return str(self.user)
Esempio n. 29
0
class Pheno(models.Model):
    name = models.CharField(max_length=200)
    description = models.TextField(blank=True, null=True)
    order = models.PositiveIntegerField(default=0)
    image = models.FileField("Image", upload_to="pheno", null=True, blank=True, help_text="Upload phase image")

    def __unicode__(self):
        return u"%s" % (self.name)
Esempio n. 30
0
class AggregationLayer(models.Model):
    """
    Source data for aggregation layers and meta information.
    """
    UNPROCESSED = 'Unprocessed'
    PENDING = 'Pending'
    PROCESSING = 'Processing'
    FINISHED = 'Finished'
    FAILED = 'Failed'
    ST_STATUS_CHOICES = (
        (UNPROCESSED, UNPROCESSED),
        (PENDING, PENDING),
        (PROCESSING, PROCESSING),
        (FINISHED, FINISHED),
        (FAILED, FAILED),
    )
    name = models.CharField(max_length=100, blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    shapefile = models.FileField(upload_to='shapefiles/aggregationlayers',
                                 blank=True,
                                 null=True)
    name_column = models.CharField(max_length=10, default='', blank=True)
    fields = HStoreField(blank=True, default=dict)
    min_zoom_level = models.IntegerField(default=0)
    max_zoom_level = models.IntegerField(default=18)
    simplification_tolerance = models.FloatField(default=0.01)
    parse_log = models.TextField(blank=True, null=True, default='')
    extent = models.PolygonField(srid=WEB_MERCATOR_SRID,
                                 editable=False,
                                 null=True)
    nr_of_areas = models.IntegerField(default=0, editable=False)
    modified = models.DateTimeField(auto_now=True)
    status = models.CharField(max_length=20,
                              choices=ST_STATUS_CHOICES,
                              default=UNPROCESSED)

    def __str__(self):
        return '{name} ({count} divisions | {status})'.format(
            name=self.name,
            count=self.aggregationarea_set.all().count(),
            status=self.status,
        )

    def log(self, msg, status=None):
        """
        Write a message to the parse log of the aggregationlayer instance.
        """
        # Prepare datetime stamp for log
        now = '[{0}] '.format(datetime.datetime.now().strftime('%Y-%m-%d %T'))
        # Update status if requested.
        if status:
            self.status = status
        # Ensure log is not null.
        if not self.parse_log:
            self.parse_log = ''
        # Write log message.
        self.parse_log += '\n' + now + msg
        self.save()