class Job(models.Model): STATES = Choices("queued", "running", "completed") name = models.CharField(max_length=320, unique=True) args = models.TextField(null=True, blank=True) output = models.TextField(null=True, blank=True) state = models.CharField(choices=STATES, default=STATES.queued, max_length=64) class Meta: app_label = 'swingers'
class Token(models.Model): link = models.ForeignKey(ApplicationLink) user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="%(app_label)s_%(class)s_user", help_text="User token authenticates as") url = models.TextField(help_text="Suburl this token is restricted to, " "relative e.g. (/my/single/service/entrypoint)", default="/") secret = models.CharField(max_length=320, help_text="Token Secret", unique=True) modified = models.DateTimeField(default=timezone.now, editable=False) timeout = models.IntegerField(default=600, help_text="Timeout token in " "seconds, 0 means never times out") class Meta: app_label = 'swingers' def save(self, *args, **kwargs): try: revision.unregister(self.__class__) except: pass super(Token, self).save(*args, **kwargs) def natural_key(self): return (self.secret, ) def get_by_natural_key(self, secret): return self.get(secret=secret) def __str__(self): return "{0} - {1}:{2}@{3}".format(self.pk, self.user, self.secret, self.link.client_name)[:320]
class Acknowledgement(models.Model): burn = models.ForeignKey('PrescribedBurn', related_name='acknowledgements', on_delete=models.PROTECT) user = models.ForeignKey(User, help_text="User", null=True, blank=True, on_delete=models.PROTECT) acknow_type = models.CharField(max_length=64, null=True, blank=True) acknow_date = models.DateTimeField(auto_now_add=True, null=True, blank=True) fmt = "%d/%m/%Y %H:%M" @property def record(self): username = '******'.format(self.user.first_name[0], self.user.last_name) return "{} {}".format( username, self.acknow_date.astimezone(tz.tzlocal()).strftime(self.fmt)) def remove(self): self.delete() def __str__(self): return "{} - {} - {}".format(self.burn, self.acknow_type, self.record)
class FireTenure(models.Model): name = models.CharField(max_length=50) class Meta: ordering = ['name'] def __str__(self): return self.name
class ExternalAssist(models.Model): name = models.CharField(max_length=25) class Meta: ordering = ['name'] def __str__(self): return self.name
class DocumentTag(models.Model): name = models.CharField(verbose_name="Document Tag", max_length=200) category = models.ForeignKey(DocumentCategory, on_delete=models.PROTECT) objects = CategoryManager() class Meta: ordering = ['name'] def __str__(self): return self.name
class IgnitionType(models.Model): """ """ name = models.CharField(max_length=64, unique=True) objects = IgnitionTypeManager() def __str__(self): return self.name def natural_key(self): return (self.name, )
class DocumentCategory(models.Model): name = models.CharField(max_length=200) order = models.PositiveSmallIntegerField(default=0) class Meta: verbose_name = "Document Category" verbose_name_plural = "Document Categories" ordering = ['name'] def __str__(self): return self.name
class TrafficControlDiagram(models.Model): """ """ name = models.CharField(max_length=64, unique=True) path = models.FileField(storage=trafficdiagram_storage, upload_to=".") display_order = models.IntegerField(default=1) objects = TrafficControlDiagramManager() @property def dimensions(self): """width, height = subprocess.check_output([ "identify", "-format", "%Wx%H,", self.document.path ]).split(",")[0].strip().split("x") return {"width": width, "height": height} """ dimensions_info = get_dimensions(self.document.path) logger.info( str({ "width": dimensions_info.width, "height": dimensions_info.height })) return { "width": dimensions_info.width, "height": dimensions_info.height } @property def document(self): return self.path @property def descriptor(self): return self.name @property def modified(self): return False @property def filename(self): return os.path.basename(self.path.path) def __str__(self): return self.name def natural_key(self): return (self.name, ) class Meta: ordering = ['id'] verbose_name = "Traffic Control Diagram" verbose_name_plural = "Traffic Control Diagrams"
class PostBurnChecklist(Audit): prescription = models.ForeignKey(Prescription, blank=True, null=True, on_delete=models.PROTECT) action = models.CharField(max_length=320) relevant = models.BooleanField(default=False) completed_on = models.DateField(default=timezone.now, blank=True, null=True) completed_by = models.TextField(verbose_name="Action completed by (name)", blank=True, null=True) _required_fields = ('completed_on', 'completed_by') def __str__(self): return self.action def clean_completed_on(self): if self.completed_on is not None: # The following line was causing validation failure before 0800. # Jira ref: PBS-1454 #if self.completed_on > timezone.now().date(): if self.completed_on > datetime.now().date(): raise ValidationError("This action could not be completed " "in the future.") if (self.prescription.approval_status_modified is None or self.completed_on < self.prescription.approval_status_modified.date()): raise ValidationError("This action could not be completed " "before its prescription was approved.") def clean(self, *args, **kwargs): super(PostBurnChecklist, self).clean(*args, **kwargs) if self.completed_on is not None and not self.completed_by: raise ValidationError("Please specify who completed this action.") if self.completed_by and self.completed_on is None: raise ValidationError("Please specify when was this action " "completed.") class Meta: ordering = ["pk"] verbose_name = "post burn checklist item" verbose_name_plural = "post burn checklist"
class RegionAbstract(Audit, ActiveModel): """ Abstract model to represent DEC regions and district areas, for use within other DEC corporate applications. """ name = models.CharField(max_length=320, unique=True) description = models.TextField(null=True, blank=True) slug = models.SlugField(unique=True, help_text='Must be unique.') class Meta: abstract = True ordering = ['name'] def __unicode__(self): return unicode(self.name) search_fields = ('name', 'slug', 'description')
class Way(Audit): prescription = models.ForeignKey( Prescription, help_text="Prescription this belongs to.", on_delete=models.PROTECT) name = models.CharField(max_length=300) signs_installed = models.DateField( verbose_name="Signs Installed", null=True, blank=True) signs_removed = models.DateField( verbose_name="Signs Removed", null=True, blank=True) def __str__(self): return self.name def clean_signs_removed(self): if ((self.signs_removed and self.signs_installed and self.signs_removed < self.signs_installed)): raise ValidationError('Signs cannot be removed earlier than the ' 'install date.')
class AnnualIndicativeBurnProgram(models.Model): objectid = models.IntegerField(primary_key=True) wkb_geometry = models.MultiPolygonField(srid=4326, blank=True, null=True) region = models.CharField(max_length=35, blank=True) district = models.CharField(max_length=35, blank=True) burnid = models.CharField(max_length=30, blank=True) fin_yr = models.CharField(verbose_name='Fin Year', max_length=9, blank=True, null=True) location = models.CharField(max_length=254, blank=True) status = models.CharField(max_length=254, blank=True) priority = models.DecimalField(max_digits=9, decimal_places=0, blank=True, null=True) #content = models.CharField(max_length=254, blank=True) #issues = models.CharField(max_length=254, blank=True) treatment = models.DecimalField(max_digits=9, decimal_places=0, blank=True, null=True) #purpose_1 = models.CharField(max_length=254, blank=True) #program = models.CharField(max_length=254, blank=True) #acb = models.CharField(max_length=254, blank=True) trtd_area = models.CharField(max_length=254, blank=True) #yslb = models.CharField(max_length=254, blank=True) area_ha = models.DecimalField(max_digits=19, decimal_places=11, blank=True, null=True) perim_km = models.DecimalField(max_digits=19, decimal_places=11, blank=True, null=True) longitude = models.DecimalField(max_digits=19, decimal_places=11, blank=True, null=True) latitude = models.DecimalField(max_digits=19, decimal_places=11, blank=True, null=True) objects = models.GeoManager() class Meta: managed = False
class BurnState(models.Model): prescription = models.ForeignKey(Prescription, related_name='burnstate', on_delete=models.PROTECT) user = models.ForeignKey(User, help_text="User", on_delete=models.PROTECT) review_type = models.CharField(max_length=64) review_date = models.DateTimeField(auto_now_add=True) fmt = "%d/%m/%Y %H:%M:%S" @property def record(self): username = '******'.format(self.user.first_name[0], self.user.last_name) return "{} {}".format( username, self.review_date.astimezone(tz.tzlocal()).strftime(self.fmt)) def __str__(self): return "{} - {} - {}".format(self.prescription, self.review_type, self.record)
class GrandParentDuck(Audit): """A parent duck.""" name = models.CharField(max_length=20) duck = models.ForeignKey(ParentDuck) objects = Manager()
class PrescribedBurn(Audit): BURN_ACTIVE = 1 BURN_INACTIVE = 2 BURN_MONITORED = 3 BURN_CHOICES = ( (BURN_ACTIVE, 'Yes'), (BURN_INACTIVE, 'No'), (BURN_MONITORED, 'Monitored'), ) IGNITION_STATUS_REQUIRED = 1 IGNITION_STATUS_COMPLETED = 2 IGNITION_STATUS_CHOICES = ( (IGNITION_STATUS_REQUIRED, 'Further ignitions required'), (IGNITION_STATUS_COMPLETED, 'Ignition now complete'), ) APPROVAL_DRAFT = 'DRAFT' APPROVAL_SUBMITTED = 'USER' APPROVAL_ENDORSED = 'SRM' APPROVAL_APPROVED = 'SDO' APPROVAL_CHOICES = ( (APPROVAL_DRAFT, 'Draft'), (APPROVAL_SUBMITTED, 'District Submitted'), (APPROVAL_ENDORSED, 'Region Endorsed'), (APPROVAL_APPROVED, 'State Approved'), ) FORM_268A = 1 FORM_268B = 2 FORM_NAME_CHOICES = ( (FORM_268A, 'Form 268a'), (FORM_268B, 'Form 268b'), ) ''' BUSHFIRE_DISTRICT_ALIASES can be used to override the District's original code from the model. Usage e.g.: BUSHFIRE_DISTRICT_ALIASES = { 'PHS' : 'PH', 'SWC' : 'SC', } ''' BUSHFIRE_DISTRICT_ALIASES = {} fmt = "%Y-%m-%d %H:%M" prescription = models.ForeignKey(Prescription, verbose_name="Burn ID", related_name='prescribed_burn', null=True, blank=True, on_delete=models.PROTECT) # prescription = ChainedForeignKey( # Prescription, chained_field="region", chained_model_field="region", # show_all=False, auto_choose=True, blank=True, null=True) # Required for Fire records fire_id = models.CharField(verbose_name="Fire Number", max_length=15, null=True, blank=True) fire_name = models.TextField(verbose_name="Name", null=True, blank=True) region = models.PositiveSmallIntegerField(choices=[ (r.id, r.name) for r in Region.objects.all() ], null=True, blank=True) district = ChainedForeignKey(District, chained_field="region", chained_model_field="region", show_all=False, auto_choose=True, blank=True, null=True, on_delete=models.PROTECT) fire_tenures = models.ManyToManyField(FireTenure, verbose_name="Tenures", blank=True) date = models.DateField(auto_now_add=False) form_name = models.PositiveSmallIntegerField( verbose_name="Form Name (268a / 268b)", choices=FORM_NAME_CHOICES, editable=True) status = models.PositiveSmallIntegerField(verbose_name="Active", choices=BURN_CHOICES, null=True, blank=True) ignition_status = models.PositiveSmallIntegerField( verbose_name="Ignition Status", choices=IGNITION_STATUS_CHOICES, null=True, blank=True) external_assist = models.ManyToManyField( ExternalAssist, verbose_name="Assistance received from", blank=True) planned_area = models.DecimalField( verbose_name="Today's treatment area (ha)", max_digits=12, decimal_places=1, validators=[MinValueValidator(0.0)], null=True, blank=True) area = models.DecimalField(verbose_name="Yesterday's treatment area (ha)", max_digits=12, decimal_places=1, validators=[MinValueValidator(0.0)], null=True, blank=True) planned_distance = models.DecimalField( verbose_name="Today's treatment distance (km)", max_digits=12, decimal_places=1, validators=[MinValueValidator(0.0)], null=True, blank=True) distance = models.DecimalField( verbose_name="Yesterday's treatment distance (km)", max_digits=12, decimal_places=1, validators=[MinValueValidator(0.0)], null=True, blank=True) tenures = models.TextField(verbose_name="Tenure") location = models.TextField(verbose_name="Location", null=True, blank=True) est_start = models.TimeField('Estimated Start Time', null=True, blank=True) conditions = models.TextField(verbose_name='SDO Special Conditions', null=True, blank=True) rolled = models.BooleanField(verbose_name="Fire Rolled from yesterday", editable=False, default=False) latitude = models.FloatField(default=0.0) longitude = models.FloatField(default=0.0) #aircraft_burn = models.BooleanField(verbose_name="Aircraft Burn", default=False) def clean(self): if not self.form_name: if self.prescription and self.area == None and self.distance == None: self.form_name = 1 else: self.form_name = 2 if self.prescription and not (self.region and self.district): self.region = self.prescription.region.id self.district = self.prescription.district def clean_fire_id(self): # set the Lat/Long to Zero, since Bushfire is not assigning these required fields self.latitude = 0.0 self.longitude = 0.0 # def clean_date(self): # today = date.today() # tomorrow = today + timedelta(days=1) # if not self.pk and (self.date < today or self.date > tomorrow): # raise ValidationError("You must enter burn plans for today or tommorow's date only.") def clean_planned_distance(self): if self.planned_area == None and self.planned_distance == None: raise ValidationError( "Must input at least one of Area or Distance") def clean_distance(self): if self.area == None and self.distance == None: raise ValidationError( "Must input at least one of Area or Distance") @property def is_acknowledged(self): if all(x in [i.acknow_type for i in self.acknowledgements.all()] for x in ['SDO_A', 'SDO_B']): return True else: return False @property def user_a_record(self): ack = self.acknowledgements.filter(acknow_type='USER_A') return ack[0].record if ack else None @property def srm_a_record(self): ack = self.acknowledgements.filter(acknow_type='SRM_A') return ack[0].record if ack else None @property def sdo_a_record(self): ack = self.acknowledgements.filter(acknow_type='SDO_A') return ack[0].record if ack else None @property def user_b_record(self): ack = self.acknowledgements.filter(acknow_type='USER_B') return ack[0].record if ack else None @property def srm_b_record(self): ack = self.acknowledgements.filter(acknow_type='SRM_B') return ack[0].record if ack else None @property def sdo_b_record(self): ack = self.acknowledgements.filter(acknow_type='SDO_B') return ack[0].record if ack else None @property def formA_isDraft(self): return not any( x in [i.acknow_type for i in self.acknowledgements.all()] for x in ['USER_A', 'SRM_A', 'SDO_A']) @property def formB_isDraft(self): return not any( x in [i.acknow_type for i in self.acknowledgements.all()] for x in ['USER_B', 'SRM_B', 'SDO_B']) @property def formA_user_acknowledged(self): return True if self.user_a_record else False @property def formA_srm_acknowledged(self): return True if self.srm_a_record else False @property def formA_sdo_acknowledged(self): return True if self.sdo_a_record else False @property def formB_user_acknowledged(self): return True if self.user_b_record else False @property def formB_srm_acknowledged(self): return True if self.srm_b_record else False @property def formB_sdo_acknowledged(self): return True if self.sdo_b_record else False @property def fire_type(self): return "Burn" if self.prescription else "Fire" @property def fire_idd(self): if self.prescription: return self.prescription.burn_id else: return self.fire_id @property def further_ignitions_req(self): if self.ignition_status == self.IGNITION_STATUS_REQUIRED: return True elif self.ignition_status == self.IGNITION_STATUS_COMPLETED: return False return None @property def active(self): # if self.status==self.BURN_ACTIVE: if self.status == self.BURN_ACTIVE or self.status == self.BURN_MONITORED: return True elif self.status == self.BURN_INACTIVE: return False return None @property def has_conditions(self): if self.conditions: return True return False @property def planned_area_str(self): _str = '' if self.planned_area: _str += str(self.planned_area) + " ha {} ".format( '-' if self.planned_distance else '') if self.planned_distance: _str += str(self.planned_distance) + " km" return _str @property def area_str(self): _str = '' if self.area >= 0: _str += str( self.area) + " ha {} ".format('-' if self.distance else '') if self.distance >= 0: _str += str(self.distance) + " km" return _str @property def tenures_str(self): if self.prescription: return self.tenures #', '.join([t.name for t in self.tenures.all()]) else: return ', '.join([i.name for i in self.fire_tenures.all()]) @property def had_external_assist(self): if self.external_assist.all().count() > 0: return True return False @property def external_assist_str(self): return ', '.join([i.name for i in self.external_assist.all()]) @property def name(self): if self.prescription: return self.prescription.name else: return self.fire_name @property def get_region(self): return self.prescription.region if self.prescription else self.region @property def get_district(self): return self.prescription.district if self.prescription else self.district @property def can_endorse(self): return (self.status == self.APPROVAL_SUBMITTED) @property def can_approve(self): return (self.status == self.APPROVAL_ENDORSED) @property def last_ignition(self): if self.prescription: area_achievements = self.prescription.areaachievement_set.all() if area_achievements: return max([i.ignition for i in area_achievements]) return None def short_str(self): return self.prescription.burn_id if self.prescription else self.fire_id def copy_ongoing_records(self, dt): """ Copy today's 'active' records to tomorrow 268b - (Automatically) copy all records from yesterday that were Active when 268a Region Endorsement occurs, except for Active and Area Burnt Yesterday dt = from date, copied to dt+1 """ tomorrow = dt + timedelta(days=1) # relative to dt #objects = [obj for obj in PrescribedBurn.objects.filter(date=dt, status=PrescribedBurn.BURN_ACTIVE)] objects = [self] now = timezone.now() admin = User.objects.get(username='******') count = 0 for obj in objects: if obj.fire_id and PrescribedBurn.objects.filter( fire_id=obj.fire_id, date=tomorrow, form_name=PrescribedBurn.FORM_268B): # don't copy if already exists - since record is unique on Prescription (not fire_id) logger.info( 'Ongoing Record Already Exists (Fire) - not copied (268b today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) continue if obj.prescription and PrescribedBurn.objects.filter( prescription__burn_id=obj.prescription.burn_id, date=tomorrow, form_name=PrescribedBurn.FORM_268B, location=obj.location): # don't copy if already exists - since record is unique on Prescription (not fire_id) logger.info( 'Ongoing Record Already Exists (Burn) - not copied (268b today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) continue try: obj.pk = None obj.date = tomorrow obj.area = None obj.status = None obj.approval_268a_status = PrescribedBurn.APPROVAL_DRAFT obj.approval_268a_status_modified = now obj.approval_268b_status = PrescribedBurn.APPROVAL_DRAFT obj.approval_268b_status_modified = now obj.acknowledgements.all().delete() obj.rolled = True obj.save() count += 1 logger.info( 'Ongoing Record copied (268b today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) except: # records already exist - pk (pres, date) will not allow overwrite, so ignore the exception logger.warn( 'Ongoing Record not copied. Record {} already exists on day {}' .format(obj.fire_idd, tomorrow)) def copy_planned_approved_records_adhoc(self, dt): """ Copy today's 'planned' records (268a), that have been SDO approved. to tomorrow ongoing (268b) set Active and Area Burnt fields to None dt = from date, copied to dt+1 """ tomorrow = dt + timedelta(days=1) # relative to dt if not self.formA_sdo_acknowledged: logger.info( 'Only SDO Acknowledged record can be copied from dt {} to tomorrow {}' .format(dt, tomorrow)) return #objects = PrescribedBurn.objects.filter(date=dt, acknowledgements__acknow_type__in=['SDO_A'], form_name=PrescribedBurn.FORM_268A) objects = [self] now = timezone.now() count = 0 for obj in objects: if obj.fire_id and PrescribedBurn.objects.filter( fire_id=obj.fire_id, date=tomorrow, form_name=PrescribedBurn.FORM_268B): # don't copy if already exists - since record is unique on Prescription (not fire_id) logger.info( 'Planned Approved Record Already Exists (Fire) - not copied (268a today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) continue if obj.prescription and PrescribedBurn.objects.filter( prescription__burn_id=obj.prescription.burn_id, date=tomorrow, form_name=PrescribedBurn.FORM_268B, location=obj.location): # don't copy if already exists - since record is unique on Prescription (not fire_id) logger.info( 'Planned Approved Record Already Exists (Burn) - not copied (268a today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) continue try: obj.pk = None obj.date = tomorrow obj.area = None obj.distance = None obj.status = None obj.approval_268a_status = PrescribedBurn.APPROVAL_DRAFT obj.approval_268a_status_modified = now obj.approval_268b_status = PrescribedBurn.APPROVAL_DRAFT obj.approval_268b_status_modified = now #obj.acknowledgements.all().delete() obj.form_name = PrescribedBurn.FORM_268B obj.rolled = True obj.save() count += 1 logger.info( 'Planned Approved Record copied (268a today to 268b tomorrow). Record {}, today {}, tomorrow {}' .format(obj.fire_idd, dt, tomorrow)) except: # records already exist - pk (pres, date) will not allow overwrite, so ignore the exception logger.warn( 'Planned Approved Record not copied. Record {} already exists on day {}' .format(obj.fire_idd, tomorrow)) def __str__(self): return self.prescription.burn_id + ' (Burn)' if self.prescription else self.fire_id + ' (Fire)' class Meta: unique_together = ('prescription', 'date', 'form_name', 'location') verbose_name = 'Prescribed Burn or Bushfire' verbose_name_plural = 'Prescribed Burns and Bushfires' permissions = ( ("can_endorse", "Can endorse burns"), ("can_approve", "Can approve burns"), )
class Document(Audit): prescription = models.ForeignKey( Prescription, null=True, help_text="Prescription that this document belongs to", on_delete=models.PROTECT) category = models.ForeignKey(DocumentCategory, related_name="documents", on_delete=models.PROTECT) tag = ChainedForeignKey( DocumentTag, chained_field="category", chained_model_field="category", show_all=False, auto_choose=True, verbose_name="Descriptor", on_delete=models.PROTECT) custom_tag = models.CharField( max_length=64, blank=True, verbose_name="Custom Descriptor") document = ContentTypeRestrictedFileField( upload_to=content_file_name, max_length=200, content_types=['application/pdf', 'image/tiff', 'image/tif', 'image/jpeg', 'image/jpg', 'image/gif', 'image/png', 'application/zip', 'application/x-zip-compressed'], help_text='Acceptable file types: pdf, tiff, jpg, gif, png, zip') document_created = models.DateTimeField( verbose_name="Date Document Created", default=timezone.now, editable=True, null=True, blank=True) document_archived = models.BooleanField(default=False, verbose_name="Archived Document") objects = TagManager() def save(self, *args, **kwargs): super(Document, self).save(*args, **kwargs) # confirm that file is written to filesystem, if not remove the record if not self.exists: fname = self.document.name Document.objects.get(id=self.id).delete() raise Exception('ERROR: File not created on filesystem {}'.format(fname)) return @property def descriptor(self): if self.custom_tag: return "Other ({0})".format(self.custom_tag) else: return self.tag.name @property def dimensions(self): return get_dimensions(self.document.path) @property def filename(self): try: return os.path.basename(self.document.path) except: return None @property def exists(self): """ Check if file exists on the file system """ try: return os.path.exists(self.document.file.name) except: return False @property def is_zipped(self): return self.filename.endswith('.zip') class Meta: ordering = ['tag', 'document'] permissions = ( ("archive_document", "Can archive documents") ) def __str__(self): return "{0} - {1}".format(self.prescription, self.document.name)
class ApplicationLink(models.Audit): AUTH_METHOD = Choices('basic', 'md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512') client_name = models.CharField( max_length=320, help_text="project/host of client, this app is {0}".format( settings.SITE_NAME)) server_name = models.CharField( max_length=320, help_text="project/host of server, this app is {0}".format( settings.SITE_NAME)) server_url = models.TextField( help_text="URL service backend requests should be made to") identifier = models.CharField( max_length=320, null=True, blank=True, help_text="IP or Hostname, optional for added security") secret = models.CharField(max_length=320, help_text="Application secret") timeout = models.IntegerField(default=600, help_text="Timeout of oauth tokens in " "seconds") auth_method = models.CharField(choices=AUTH_METHOD, default=AUTH_METHOD.sha256, max_length=20) class Meta(Audit.Meta): unique_together = ("client_name", "server_name") app_label = 'swingers' def natural_key(self): return (self.client_name, self.server_name) def get_by_natural_key(self, client_name, server_name): return self.get(client_name=client_name, server_name=server_name) def get_access_token(self, user_id, expires=600): """ Returns an access token for with the current user. Note: uses a hardcoded URL when determining where to send the request. """ url = self.server_url + "/api/swingers/v1/{0}/request_token" nonce = make_nonce() r = requests.get(url.format(self.server_name), params={ "user_id": user_id, "nonce": nonce, "client_secret": self.get_client_secret(user_id, nonce), "client_id": self.client_name, "expires": expires }) if r.ok: return r.content else: r.raise_for_status() def get_client_secret(self, user_id, nonce): """ Returns the client secret based on a user and a nonce. """ stringtohash = "{0}{1}{2}".format(self.secret, user_id, nonce) return getattr(hashlib, self.auth_method)(stringtohash).hexdigest()
class ActiveDuck(ActiveModel): """An active duck.""" name = models.CharField(max_length=20)
class AreaAchievement(Audit): prescription = models.ForeignKey(Prescription, on_delete=models.PROTECT) #Jira issue PBS-1407 ignition = models.DateField(verbose_name="Ignition Date", ) # default=lambda: timezone.now().date()) ignition_types = models.ManyToManyField(IgnitionType) area_treated = models.DecimalField( verbose_name="Area where treatment is complete (ha)", validators=[MinValueValidator(0)], default=0, decimal_places=1, max_digits=12) area_estimate = models.DecimalField(verbose_name="Area treated today (ha)", validators=[MinValueValidator(0)], default=0, decimal_places=1, max_digits=12) edging_length = models.DecimalField( verbose_name="Length of Successful Edging (kms)", validators=[MinValueValidator(0)], default=0, decimal_places=1, max_digits=12) edging_depth_estimate = models.DecimalField( verbose_name="Estimated Depth of Edging (m)", validators=[MinValueValidator(0)], default=0, decimal_places=1, max_digits=12) dpaw_fire_no = models.CharField(verbose_name="DPaW Fire Number", max_length=64, blank=True) dfes_fire_no = models.CharField(verbose_name="DFES Fire Number", max_length=64, blank=True) date_escaped = models.DateField(verbose_name="Date of Escape", null=True, blank=True) _required_fields = ('ignition', 'ignition_types', 'area_treated', 'area_estimate') class Meta: ordering = ['-ignition'] get_latest_by = 'ignition' verbose_name = "Day of Burn Achievement" verbose_name_plural = "Day of Burn Achievements" def __str__(self): return "%s %d ha %d kms" % (self.ignition, self.area_estimate, self.edging_length) def clean_ignition(self): if self.ignition and self.ignition > timezone.now().date(): raise ValidationError("Ignition date cannot be in the future.") def clean_date_escaped(self): if self.date_escaped: if self.date_escaped > timezone.now().date(): raise ValidationError("Date of escape cannot be in the " "future.") if not self.dpaw_fire_no and not self.dfes_fire_no: raise ValidationError("If there is a date of escape, there " "must also be a DPaW or DFES fire no.") def save(self, **kwargs): super(AreaAchievement, self).save(**kwargs) self.prescription.save() def delete(self, **kwargs): super(AreaAchievement, self).delete(**kwargs) obj = self.prescription if obj.areaachievement_set.all().count() == 0: obj.ignition_completed_date = None obj.save()
class Duck(Audit): """A duck.""" name = models.CharField(max_length=20) objects = Manager()