class NotamAirspace(gis_models.Model): geom = gis_models.PolygonField() # objects = gis_models.GeoManager() objects = GeoManager() date_created = gis_models.DateTimeField(auto_now_add=True) date_modified = gis_models.DateTimeField(auto_now=True) start_day = gis_models.DateField(default=date.today, validators=[validate_start_date]) start_time = gis_models.TimeField(help_text="HH:MM:SS") end = gis_models.TimeField(help_text="HH:MM:SS") created_by = gis_models.ForeignKey(User, on_delete=gis_models.CASCADE) notam_number = gis_models.CharField(max_length=255, blank=True, null=True) notam_file = gis_models.FileField(upload_to="uploads/%Y/%m/%d/", blank=True, null=True) PENDING = 0 ACTIVE = 1 STATUS = ((PENDING, "PENDING"), (ACTIVE, "ACTIVE")) status = gis_models.IntegerField(default=0, choices=STATUS, blank=True, null=True) reason = gis_models.CharField(max_length=255, blank=True, null=True, help_text=" Reason for NOTAM") centroid = gis_models.PointField(blank=True, null=True) expiry = gis_models.BooleanField(default=False) def save(self, *args, **kwargs): self.centroid = self.geom.centroid super(NotamAirspace, self).save(*args, **kwargs) x = "NOTAM/CAA/2018/" y = self.pk self.notam_number = x + str(y) super(NotamAirspace, self).save(*args, **kwargs) def clean(self): super(NotamAirspace, self).clean() if self.start_time and self.end: booking_time = datetime.combine(date.min, self.end) - datetime.combine( date.min, self.start_time) c = booking_time.total_seconds() if (c / 3600) > 3: raise ValidationError( "Cannot create Notam Airspace for more three hours!") elif (c / 3600) < 0: raise ValidationError("You can not start a Notam at " "{:%H:%M:%S}".format(self.start_time) + " and then end it at " + "{:%H:%M:%S}".format(self.end)) if self.geom: from applications.models import ReserveAirspace notam_qs = (NotamAirspace.objects.all().exclude(pk=self.pk).filter( geom__intersects=self.geom)) reserve_qs = ReserveAirspace.objects.filter( geom__intersects=self.geom) if notam_qs or reserve_qs: e = [] for qs in notam_qs: if self.start_time and self.end: booking_time_start = datetime.combine( self.start_day, self.start_time) booking_time_end = datetime.combine( self.start_day, self.end) booking_time_qs_start = datetime.combine( qs.start_day, qs.start_time) booking_time_qs_end = datetime.combine( qs.start_day, qs.end) if (booking_time_qs_start < booking_time_start < booking_time_qs_end): error = str( qs.notam_number + " " + "(Kindly book after the curent NOTAM ends, try from " + qs.get_start_day + " " + booking_time_qs_end.strftime("%H:%M:%S")) e.append(error) # TODO: NOTAM SEND NOTIFICATION/EMAIL/MESSAGE: this is in clean, does it mean if its OK but the above is wrong its sends all the time? # Can this be send into save()? as there is no validationError raised anyway? for (qs) in ( reserve_qs ): # TODO: qs in reserve_qs: is qs a single object or qs? if not rename if self.start_time and self.end: booking_time_qs_start = datetime.combine( qs.start_day, qs.start_time) booking_time_qs_end = datetime.combine( qs.start_day, qs.end) notam_start = datetime.combine(self.start_day, self.start_time) notam_end = datetime.combine(self.start_day, self.end) if (notam_start < booking_time_qs_start < notam_end or notam_start < booking_time_qs_end < notam_end): from notifications.models import Notifications as n n.objects.create(title="Notam Alert", receiver=qs.created_by) # from notifications.send_a_notification import send_a_notification # send_a_notification(qs.created_by, "Notam Alert", str(self.reason)) if e: raise ValidationError(((mark_safe( "Cannot book airspace in this zone!!" + "You have intersected the following notam(s) occuring at the same day and time" + "<hr>" + "<p></p>" + "<b>" + str(e) + "<br> " + "<hr>" + '<a href="/applications/airspace/">Go To Airspace</a>') ))) def get_area(self): x = self.geom.area * 12365.1613 return x # sq km def get_perimeter(self): x = self.geom.length return x * 111 def __str__(self): return str(self.notam_number) def get_start_datetime(self): booking_schedule = datetime.combine(self.start_day, self.start_time) return booking_schedule def get_absolute_url(self): return reverse("view_airspace") @property def get_start_day(self): from django.contrib.humanize.templatetags.humanize import naturalday natural_day = naturalday(self.start_day) return str(natural_day) @property def get_file_url(self): if self.notam_file: file_url = self.notam_file.url return str(file_url) else: return str("#")
class Person(models.Model): gender = models.CharField(max_length=1, choices=GENDER_CH) happy = models.BooleanField(default=True) unhappy = models.BooleanField(default=False) bipolar = models.BooleanField(default=False) name = models.CharField(max_length=30) nickname = models.SlugField(max_length=36) age = models.IntegerField() bio = models.TextField() birthday = models.DateField() birth_time = models.TimeField() appointment = models.DateTimeField() blog = models.URLField() occupation = models.CharField(max_length=10, choices=OCCUPATION_CHOCIES) try: uuid = models.UUIDField(primary_key=False) except AttributeError: # New at Django 1.9 pass try: name_hash = models.BinaryField(max_length=16) except AttributeError: # We can't test the binary field if it is not supported # (django < 1,6) pass try: from django.contrib.postgres.fields import ArrayField acquaintances = ArrayField(models.IntegerField()) except ImportError: # New at Django 1.9 pass try: from django.contrib.postgres.fields import JSONField data = JSONField() except ImportError: # New at Django 1.9 pass try: from django.contrib.postgres.fields import HStoreField hstore_data = HStoreField() except ImportError: # New at Django 1.8 pass # backward compatibility with Django 1.1 try: wanted_games_qtd = models.BigIntegerField() except AttributeError: wanted_games_qtd = models.IntegerField() try: duration_of_sleep = models.DurationField() except AttributeError: pass if MOMMY_GIS: geom = models.GeometryField() point = models.PointField() line_string = models.LineStringField() polygon = models.PolygonField() multi_point = models.MultiPointField() multi_line_string = models.MultiLineStringField() multi_polygon = models.MultiPolygonField() geom_collection = models.GeometryCollectionField()
class TrainStation(models.Model): train = models.ForeignKey(Train) station = models.ForeignKey(Station) serial = models.IntegerField() time = models.TimeField()
class Meeting(models.Model): SUNDAY = 1 MONDAY = 2 TUESDAY = 3 WEDNESDAY = 4 THURSDAY = 5 FRIDAY = 6 SATURDAY = 7 WEEKDAY_CHOICES = ( (SUNDAY, 'Sunday'), (MONDAY, 'Monday'), (TUESDAY, 'Tuesday'), (WEDNESDAY, 'Wednesday'), (THURSDAY, 'Thursday'), (FRIDAY, 'Friday'), (SATURDAY, 'Saturday'), ) VALID_WEEKDAY_INTS = [day[0] for day in WEEKDAY_CHOICES] id = models.BigAutoField(primary_key=True) source_id = models.BigIntegerField() root_server = models.ForeignKey(RootServer, on_delete=models.CASCADE) service_body = models.ForeignKey(ServiceBody, on_delete=models.CASCADE) name = models.CharField(max_length=255) weekday = models.SmallIntegerField(choices=WEEKDAY_CHOICES) venue_type = models.SmallIntegerField(null=True) start_time = models.TimeField(null=True) duration = models.DurationField(null=True) formats = models.ManyToManyField(Format) language = models.CharField(max_length=7, null=True) latitude = models.DecimalField(max_digits=15, decimal_places=12) longitude = models.DecimalField(max_digits=15, decimal_places=12) point = models.PointField(null=True, geography=True) published = models.BooleanField(default=False) deleted = models.BooleanField(default=False) class Meta: indexes = [models.Index(fields=['deleted', 'published'])] @staticmethod def import_from_bmlt_objects(root_server, bmlt_meetings): logger = logging.getLogger('django') try: meeting_ids = [int(m['id_bigint']) for m in bmlt_meetings] Meeting.objects.filter(root_server=root_server).exclude(source_id__in=meeting_ids).delete() except Exception as e: message = 'Error deleting old meetings: {}'.format(str(e)) logger.error(message) ImportProblem.objects.create(root_server=root_server, message=message) for bmlt_meeting in bmlt_meetings: try: bmlt_meeting = Meeting.validate_bmlt_object(root_server, bmlt_meeting) except ImportException as e: logger.warning('Error parsing meeting: {}'.format(str(e))) ImportProblem.objects.create(root_server=root_server, message=str(e), data=str(e.bmlt_object)) continue try: try: qs = Meeting.objects.select_related('meetinginfo', 'service_body', 'root_server') qs = qs.prefetch_related('formats', 'formats__translatedformats') meeting = qs.get(root_server=root_server, source_id=bmlt_meeting.get('source_id')) except Meeting.DoesNotExist: meeting = Meeting(root_server=root_server, source_id=bmlt_meeting.get('source_id')) dirty = False field_names = ('service_body', 'name', 'weekday', 'start_time', 'duration', 'language', 'latitude', 'longitude', 'published', 'deleted', 'venue_type') changed_fields = [] for field_name in field_names: if set_if_changed(meeting, field_name, bmlt_meeting[field_name]): changed_fields.append(field_name) dirty = True if meeting.longitude and meeting.latitude: point = Point(float(meeting.longitude), float(meeting.latitude), srid=4326) if meeting.point != point: meeting.point = point dirty = True if dirty: meeting.save() try: meeting.meetinginfo except MeetingInfo.DoesNotExist: meeting.meetinginfo = MeetingInfo.objects.create(meeting=meeting) meeting.save() dirty = False for field_name in bmlt_meeting['meetinginfo'].keys(): if set_if_changed(meeting.meetinginfo, field_name, bmlt_meeting['meetinginfo'][field_name]): changed_fields.append(field_name) dirty = True if dirty: meeting.meetinginfo.save() if bmlt_meeting['formats']: if meeting.formats != bmlt_meeting['formats']: meeting.formats.set(bmlt_meeting['formats']) elif meeting.formats.exists(): meeting.formats.clear() except Exception as e: message = 'Error saving meeting: {}'.format(str(e)) logger.error(message) ImportProblem.objects.create(root_server=root_server, message=message, data=str(bmlt_meeting)) @staticmethod def validate_bmlt_object(root_server, bmlt_meeting): try: format_source_ids = bmlt_meeting.get('format_shared_id_list') if format_source_ids: try: format_source_ids = [int(id) for id in format_source_ids.split(',')] except ValueError: raise ImportException('Malformed format_shared_id_list', bmlt_meeting) formats = Format.objects.filter(root_server=root_server, source_id__in=format_source_ids) else: format_key_strings = [fks for fks in bmlt_meeting.get('formats').split(',') if fks.strip()] if not format_key_strings: formats = Format.objects.none() else: formats = Format.objects.filter( root_server=root_server, translatedformat__key_string__in=format_key_strings, translatedformat__language=bmlt_meeting.get('lang_enum') ) seen_key_strings = set() unique_formats = list() for fmt in formats: for tf in fmt.translatedformats.filter(language=bmlt_meeting.get('lang_enum')): if tf.key_string in seen_key_strings: break seen_key_strings.add(tf.key_string) else: unique_formats.append(fmt) formats = unique_formats venue_type = bmlt_meeting.get('venue_type') if venue_type: try: venue_type = int(venue_type) except ValueError: raise ImportException('Malformed venue_type', bmlt_meeting) else: venue_type = None return { 'source_id': get_int(bmlt_meeting, 'id_bigint'), 'service_body': ServiceBody.objects.get(root_server=root_server, source_id=get_int(bmlt_meeting, 'service_body_bigint')), 'name': get_required_str(bmlt_meeting, 'meeting_name'), 'weekday': get_int(bmlt_meeting, 'weekday_tinyint', valid_choices=Meeting.VALID_WEEKDAY_INTS), 'venue_type': venue_type, 'start_time': get_time(bmlt_meeting, 'start_time'), 'duration': get_timedelta(bmlt_meeting, 'duration_time'), 'language': bmlt_meeting.get('lang_enum', 'en'), 'latitude': get_decimal(bmlt_meeting, 'latitude'), 'longitude': get_decimal(bmlt_meeting, 'longitude'), 'published': bmlt_meeting.get('published', '0') == '1', 'deleted': bmlt_meeting.get('deleted', False), 'formats': formats, 'meetinginfo': { 'email': bmlt_meeting.get('email_contact', None), 'location_text': bmlt_meeting.get('location_text', None), 'location_info': bmlt_meeting.get('location_info', None), 'location_street': bmlt_meeting.get('location_street', None), 'location_city_subsection': bmlt_meeting.get('location_city_subsection', None), 'location_neighborhood': bmlt_meeting.get('location_neighborhood', None), 'location_municipality': bmlt_meeting.get('location_municipality', None), 'location_sub_province': bmlt_meeting.get('location_sub_province', None), 'location_province': bmlt_meeting.get('location_province', None), 'location_postal_code_1': bmlt_meeting.get('location_postal_code_1', None), 'location_nation': bmlt_meeting.get('location_nation', None), 'train_lines': bmlt_meeting.get('train_lines', None), 'bus_lines': bmlt_meeting.get('bus_lines', None), 'world_id': bmlt_meeting.get('worldid_mixed', None), 'comments': bmlt_meeting.get('comments', None), 'virtual_meeting_link': bmlt_meeting.get('virtual_meeting_link', None), 'phone_meeting_number': bmlt_meeting.get('phone_meeting_number', None), 'virtual_meeting_additional_info': bmlt_meeting.get('virtual_meeting_additional_info', None) } } except ServiceBody.DoesNotExist: raise ImportException('Invalid service_body', bmlt_meeting) def __str__(self): return '{} | {} | {} | {}'.format(self.id, self.root_server, self.service_body, self.name)
class graphdata(models.Model): graphname = models.TextField() graphid = models.TextField() datestamp = models.DateField(auto_now_add=True, blank=True) timestamp = models.TimeField(auto_now_add=True, blank=True)
class Campground(models.Model): CAMPGROUND_TYPE_CHOICES = ( (0, 'Bookable Online'), (1, 'Not Bookable Online'), (2, 'Other Accomodation'), ) CAMPGROUND_PRICE_LEVEL_CHOICES = ( (0, 'Campground level'), (1, 'Campsite Class level'), (2, 'Campsite level'), ) SITE_TYPE_CHOICES = ((0, 'Bookable Per Site'), (1, 'Bookable Per Site Type')) name = models.CharField(max_length=255, null=True) park = models.ForeignKey('Park', on_delete=models.PROTECT, related_name='campgrounds') ratis_id = models.IntegerField(default=-1) contact = models.ForeignKey('Contact', on_delete=models.PROTECT, blank=True, null=True) campground_type = models.SmallIntegerField(choices=CAMPGROUND_TYPE_CHOICES, default=0) promo_area = models.ForeignKey('PromoArea', on_delete=models.PROTECT, blank=True, null=True) site_type = models.SmallIntegerField(choices=SITE_TYPE_CHOICES, default=0) address = JSONField(null=True) features = models.ManyToManyField('Feature') description = models.TextField(blank=True, null=True) area_activities = models.TextField(blank=True, null=True) # Tags for communications methods available and access type tags = TaggableManager(blank=True) driving_directions = models.TextField(blank=True, null=True) fees = models.TextField(blank=True, null=True) othertransport = models.TextField(blank=True, null=True) key = models.CharField(max_length=255, blank=True, null=True) price_level = models.SmallIntegerField( choices=CAMPGROUND_PRICE_LEVEL_CHOICES, default=0) customer_contact = models.ForeignKey('CustomerContact', blank=True, null=True, on_delete=models.PROTECT) wkb_geometry = models.PointField(srid=4326, blank=True, null=True) dog_permitted = models.BooleanField(default=False) check_in = models.TimeField(default=time(14)) check_out = models.TimeField(default=time(10)) def __str__(self): return self.name class Meta: unique_together = (('name', 'park'), ) # Properties # ======================================= @property def region(self): return self.park.district.region.name @property def active(self): return self._is_open(datetime.now().date()) @property def current_closure(self): closure = self._get_current_closure() if closure: return 'Start: {} End: {}'.format(closure.range_start, closure.range_end) @property def dog_permitted(self): try: self.features.get(name='NO DOGS') return False except Feature.DoesNotExist: return True @property def campfires_allowed(self): try: self.features.get(name='NO CAMPFIRES') return False except Feature.DoesNotExist: return True # Methods # ======================================= def _is_open(self, period): '''Check if the campground is open on a specified datetime ''' open_ranges, closed_ranges = None, None # Get all booking ranges try: open_ranges = self.booking_ranges.filter( Q(status=0), Q(range_start__lte=period), Q(range_end__gte=period) | Q(range_end__isnull=True)).latest('updated_on') except CampgroundBookingRange.DoesNotExist: pass try: closed_ranges = self.booking_ranges.filter( Q(range_start__lte=period), ~Q(status=0), Q(range_end__gte=period) | Q(range_end__isnull=True)).latest('updated_on') except CampgroundBookingRange.DoesNotExist: return True if open_ranges else False if not open_ranges: return False if open_ranges.updated_on > closed_ranges.updated_on: return True return False def _get_current_closure(self): closure_period = None period = datetime.now().date() if not self.active: closure = self.booking_ranges.get( Q(range_start__lte=period), ~Q(status=0), Q(range_end__isnull=True) | Q(range_end__gte=period)) closure_period = closure return closure_period def open(self, data): if self.active: raise ValidationError('This campground is already open.') b = CampgroundBookingRange(**data) try: within = CampgroundBookingRange.objects.filter( Q(campground=b.campground), Q(status=0), Q(range_start__lte=b.range_start), Q(range_end__gte=b.range_start) | Q(range_end__isnull=True)).latest('updated_on') if within: within.updated_on = timezone.now() within.save(skip_validation=True) except CampgroundBookingRange.DoesNotExist: #if (self.__get_current_closure().range_start <= b.range_start and not self.__get_current_closure().range_end) or (self.__get_current_closure().range_start <= b.range_start <= self.__get_current_closure().range_end): # self.__get_current_closure().delete() b.save() def close(self, data): if not self.active: raise ValidationError('This campground is already closed.') b = CampgroundBookingRange(**data) try: within = CampgroundBookingRange.objects.filter( Q(campground=b.campground), ~Q(status=0), Q(range_start__lte=b.range_start), Q(range_end__gte=b.range_start) | Q(range_end__isnull=True)).latest('updated_on') if within: within.updated_on = timezone.now() within.save(skip_validation=True) except CampgroundBookingRange.DoesNotExist: b.save() def createCampsitePriceHistory(self, data): '''Create Multiple campsite rates ''' try: with transaction.atomic(): for c in self.campsites.all(): cr = CampsiteRate(**data) cr.campsite = c cr.save() except Exception as e: raise def updatePriceHistory(self, original, _new): '''Update Multiple campsite rates ''' try: rates = CampsiteRate.objects.filter(**original) campsites = self.campsites.all() with transaction.atomic(): for r in rates: if r.campsite in campsites and r.update_level == 0: r.update(_new) except Exception as e: raise def deletePriceHistory(self, data): '''Delete Multiple campsite rates ''' try: rates = CampsiteRate.objects.filter(**data) campsites = self.campsites.all() with transaction.atomic(): for r in rates: if r.campsite in campsites and r.update_level == 0: r.delete() except Exception as e: raise
class Schedule(models.Model): id = models.IntegerField(primary_key=True) arrival = models.TimeField(blank=True, null=True) departure = models.TimeField(blank=True, null=True) halt = models.IntegerField(blank=True, null=True) stop_number = models.IntegerField() minor_stop_number = models.IntegerField() station = models.ForeignKey(Station, blank=True, null=True) train = models.ForeignKey(Train, blank=True, null=True) day = models.IntegerField() distance_from_previous = models.IntegerField(null=True, blank=True) distance_travelled = models.IntegerField(blank=True, null=True) is_suspicious = models.BooleanField(default=False) class Meta: ordering = ['stop_number', 'minor_stop_number'] def __unicode__(self): return str(self.id) def get_geojson(self): if not self.station.point: return None station_geojson = self.station.get_geojson() station_geojson['properties']['stop_number'] = self.stop_number station_geojson['properties'][ 'minor_stop_number'] = self.minor_stop_number station_geojson['properties']['day'] = self.day station_geojson['properties']['time'] = self.get_time() return station_geojson def get_time(self): if self.arrival: return str(self.arrival) else: return str(self.departure) @classmethod def import_from_json(kls, path_to_json): station_errors = [] train_errors = [] schedules = json.load(open(path_to_json)) for s in schedules: stop_number_split = s['stop_number'].split('.') stop_number = stop_number_split[0] if len(stop_number_split) > 1: minor_stop_number = stop_number_split[1] else: minor_stop_number = 0 s['stop_number'] = stop_number s['minor_stop_number'] = minor_stop_number if s['arrival'] == '': s['arrival'] = None if s['departure'] == '': s['departure'] = None if s['halt'] == '': s['halt'] = None if s['halt']: s['halt'] = ''.join([d for d in s['halt'] if d.isdigit()]) try: s['station'] = Station.objects.get(code=s['station_code']) except: s['station'] = None station_errors.append(s) try: s['train'] = Train.objects.get(number=s['train_number']) except: s['train'] = None train_errors.append(s) s.pop('station_code') s.pop('station_name') s.pop('train_number') schedule = Schedule(**s) schedule.save() print unicode(schedule) station_errors_file = open('station_errors.json', "w") station_errors_file.write(json.dumps(station_errors)) train_errors_file = open('train_errors.json', "w") train_errors_file.write(json.dumps(train_error)) station_errors_file.close() train_errors_file.close() print "done"
class Person(models.Model): gender = models.CharField(max_length=1, choices=GENDER_CHOICES) # Jards Macalé is an amazing brazilian musician! =] enjoy_jards_macale = models.BooleanField(default=True) like_metal_music = models.BooleanField(default=False) name = models.CharField(max_length=30) nickname = models.SlugField(max_length=36) age = models.IntegerField() bio = models.TextField() birthday = models.DateField() birth_time = models.TimeField() appointment = models.DateTimeField() blog = models.URLField() occupation = models.CharField(max_length=10, choices=OCCUPATION_CHOICES) uuid = models.UUIDField(primary_key=False) name_hash = models.BinaryField(max_length=16) days_since_last_login = models.BigIntegerField() duration_of_sleep = models.DurationField() email = models.EmailField() id_document = models.CharField(unique=True, max_length=10) try: from django.db.models import JSONField data = JSONField() except ImportError: # Skip JSONField-related fields pass try: from django.contrib.postgres.fields import ArrayField, HStoreField from django.contrib.postgres.fields import JSONField as PostgresJSONField from django.contrib.postgres.fields.citext import ( CICharField, CIEmailField, CITextField, ) from django.contrib.postgres.fields.ranges import ( BigIntegerRangeField, DateRangeField, DateTimeRangeField, IntegerRangeField, ) if settings.USING_POSTGRES: acquaintances = ArrayField(models.IntegerField()) postgres_data = PostgresJSONField() hstore_data = HStoreField() ci_char = CICharField(max_length=30) ci_email = CIEmailField() ci_text = CITextField() int_range = IntegerRangeField() bigint_range = BigIntegerRangeField() date_range = DateRangeField() datetime_range = DateTimeRangeField() except ImportError: # Skip PostgreSQL-related fields pass try: from django.contrib.postgres.fields.ranges import FloatRangeField if settings.USING_POSTGRES: float_range = FloatRangeField() except ImportError: # Django version greater or equal than 3.1 pass try: from django.contrib.postgres.fields.ranges import DecimalRangeField if settings.USING_POSTGRES: decimal_range = DecimalRangeField() except ImportError: # Django version lower than 2.2 pass if BAKER_GIS: geom = models.GeometryField() point = models.PointField() line_string = models.LineStringField() polygon = models.PolygonField() multi_point = models.MultiPointField() multi_line_string = models.MultiLineStringField() multi_polygon = models.MultiPolygonField() geom_collection = models.GeometryCollectionField()
class HabitatComplexityObsSQLModel(BaseSUSQLModel): _se_fields = ", ".join([f"se.{f}" for f in BaseSUSQLModel.se_fields]) _su_fields = BaseSUSQLModel.su_fields_sql sql = f""" WITH se AS ( {sample_event_sql_template} ) SELECT o.id, pseudosu_id, {_se_fields}, {_su_fields}, se.data_policy_habitatcomplexity, su.number AS transect_number, su.len_surveyed AS transect_len_surveyed, rs.name AS reef_slope, tt.interval_size, o."interval", s.val AS score, s.name AS score_name, o.notes AS observation_notes FROM obs_habitatcomplexity o INNER JOIN api_habitatcomplexityscore s ON (o.score_id = s.id) INNER JOIN transectmethod_habitatcomplexity tt ON o.habitatcomplexity_id = tt.transectmethod_ptr_id INNER JOIN transect_benthic su ON tt.transect_id = su.id LEFT JOIN api_current c ON su.current_id = c.id LEFT JOIN api_tide t ON su.tide_id = t.id LEFT JOIN api_visibility v ON su.visibility_id = v.id LEFT JOIN api_relativedepth r ON su.relative_depth_id = r.id LEFT JOIN api_reefslope rs ON su.reef_slope_id = rs.id JOIN ( SELECT tt_1.transect_id, jsonb_agg(jsonb_build_object('id', p.id, 'name', (COALESCE(p.first_name, ''::character varying)::text || ' '::text) || COALESCE(p.last_name, ''::character varying)::text)) AS observers FROM observer o1 JOIN profile p ON o1.profile_id = p.id JOIN transectmethod tm ON o1.transectmethod_id = tm.id JOIN transectmethod_habitatcomplexity tt_1 ON tm.id = tt_1.transectmethod_ptr_id GROUP BY tt_1.transect_id ) observers ON su.id = observers.transect_id JOIN se ON su.sample_event_id = se.sample_event_id INNER JOIN ( SELECT pseudosu_id, UNNEST(sample_unit_ids) AS sample_unit_id FROM ( SELECT uuid_generate_v4() AS pseudosu_id, array_agg(DISTINCT su.id) AS sample_unit_ids FROM transect_benthic su GROUP BY {", ".join(BaseSUSQLModel.transect_su_fields)} ) pseudosu ) pseudosu_su ON (su.id = pseudosu_su.sample_unit_id) """ sql_args = dict(project_id=SQLTableArg(required=True)) objects = SQLTableManager() sample_unit_id = models.UUIDField() sample_time = models.TimeField() transect_number = models.PositiveSmallIntegerField() transect_len_surveyed = models.PositiveSmallIntegerField( verbose_name=_("transect length surveyed (m)")) reef_slope = models.CharField(max_length=50) interval_size = models.DecimalField(max_digits=4, decimal_places=2, default=0.5, verbose_name=_("interval size (m)")) interval = models.DecimalField(max_digits=7, decimal_places=2) observation_notes = models.TextField(blank=True) score = models.PositiveSmallIntegerField() score_name = models.CharField(max_length=100) data_policy_habitatcomplexity = models.CharField(max_length=50) class Meta: db_table = "habitatcomplexity_obs_sm" managed = False
class Train(models.Model): id = models.IntegerField(primary_key=True) data_id = models.IntegerField(db_index=True) name = models.CharField(max_length=512) number = models.CharField(max_length=64, db_index=True) return_train = models.CharField(max_length=64, db_index=True, blank=True, null=True) duration_h = models.IntegerField() duration_m = models.IntegerField() zone = models.CharField(max_length=16, blank=True) date_from = models.CharField(max_length=32, blank=True) date_to = models.CharField(max_length=32, blank=True) from_station = models.ForeignKey("Station", related_name="trains_from") to_station = models.ForeignKey("Station", related_name="trains_to") number_of_halts = models.IntegerField(null=True) typ = models.CharField(max_length=16, blank=True) departure = models.TimeField(null=True, blank=True) arrival = models.TimeField(null=True, blank=True) distance = models.IntegerField() departure_days = models.CharField(max_length=16, blank=True) monday = models.BooleanField() tuesday = models.BooleanField() wednesday = models.BooleanField() thursday = models.BooleanField() friday = models.BooleanField() saturday = models.BooleanField() sunday = models.BooleanField() classes = models.CharField(max_length=32, blank=True) chair_car = models.BooleanField() sleeper = models.BooleanField() first_class = models.BooleanField() third_ac = models.BooleanField() second_ac = models.BooleanField() first_ac = models.BooleanField() def __unicode__(self): return "%s: %s" % (self.number, self.name) def get_line_geojson(self): schedules = self.schedule_set.filter( is_suspicious=False).select_related('station') line_coords = [] for schedule in schedules: station = schedule.station if not station or not station.point: continue line_coords.append([station.point.x, station.point.y]) properties = {'number': self.number, 'name': self.name} return { 'type': 'Feature', 'geometry': { 'type': 'LineString', 'coordinates': line_coords }, 'properties': properties } def set_schedule_distance(self): schedules = self.schedule_set.all().values('id', 'distance_travelled') first_sched = Schedule.objects.get(id=schedules[0]['id']) first_sched.distance_from_previous = 0 first_sched.save() for i, schedule in enumerate(schedules, start=0): if i == 0: continue previous = schedules[i - 1] if schedule['distance_travelled'] and previous[ 'distance_travelled']: distance = schedule['distance_travelled'] - previous[ 'distance_travelled'] else: distance = 10 #UGLY!!!!!! sched = Schedule.objects.get(id=schedule['id']) sched.distance_from_previous = distance # print sched.id sched.save() def flag_suspicious_schedules(self): schedules = list(self.schedule_set.all().select_related('station')) previous_point = None previous_distance = 0 suspicions = [] for i, schedule in enumerate(schedules): if schedule.station.point: has_point = True else: has_point = False if not has_point: previous_distance = previous_distance + schedule.distance_from_previous continue else: if previous_point is None: previous_distance += schedule.distance_from_previous previous_point = schedule.station.point continue expected_distance = previous_distance + schedule.distance_from_previous actual_distance = distance(previous_point, schedule.station.point).km distance_buffer = expected_distance if distance_buffer < 25: distance_buffer = 25 if actual_distance > expected_distance + distance_buffer: schedule.is_suspicious = True suspicion = { 'id': schedule.id, 'expected_distance': expected_distance, 'actual_distance': actual_distance } suspicions.append(suspicion) print suspicion schedule.save() previous_distance = 0 previous_point = schedule.station.point # out = open("suspicious_schedules.json", "w") # out.write(json.dumps(suspicions)) # out.close() def get_stations_geojson(self): schedules = self.schedule_set.filter( minor_stop_number=0).select_related('station') features = [ s.get_geojson() for s in schedules if s.station.point is not None ] return {'type': 'FeatureCollection', 'features': features} @classmethod def import_from_csv(kls, path_to_csv): trains = csv.DictReader(open(path_to_csv)) for t in trains: if t['return_train'] == '': t['return_train'] = None train = Train(**t) train.save() print train.name @classmethod def get_featurecollection(kls, path_to_file): return { 'type': 'FeatureCollection', 'features': [t.get_line_geojson() for t in Train.objects.all()] }
class Resource(models.Model, WithNameSlug): """ Individual services rendered, supplies distributed or other resources """ name = models.CharField(max_length=500) description = RichTextField() # Contact Info phone_number = PhoneNumberField(null=True, blank=True) email = models.EmailField(null=True, blank=True) website = models.URLField(null=True, blank=True) # Categorization categories = models.ManyToManyField('ResourceCategory', related_name='resources') populations_served = models.ManyToManyField('Population', related_name='resources') # Locations assets = models.ManyToManyField("assets.Asset", related_name='resources', blank=True) other_locations = models.ManyToManyField("assets.Location", related_name='resources', blank=True) virtual_only = models.BooleanField() # Timing recurrence = RecurrenceField(null=True, blank=True) all_day = models.BooleanField(default=False) start_time = models.TimeField( help_text='If you selected "all day," you can leave this blank.', null=True, blank=True ) end_time = models.TimeField( help_text='If you selected "all day," you can leave this blank.', null=True, blank=True ) # Publishing info priority = models.IntegerField( help_text="This helps determine the order in which resources are listed.", choices=Priority.choices, default=Priority.MEDIUM, ) published = models.BooleanField(help_text="When checked, activity will show up on the site.", default=False) start_publish_date = models.DateField( "Start displaying on", help_text="After this date, the resource will show up on the site (default is today)", default=timezone.now ) stop_publish_date = models.DateField( "Stop displaying after", help_text="After this date, the resource will stop showing up on the site (leave blank to keep up indefinitely)", null=True, blank=True ) @property def virtual_only(self): return not len(self.assets.all()) and not len(self.other_locations.all()) @property def publishable(self): return self.published and (self.start_date <= timezone.now() < self.stop_date) @property def locations(self): return Location.objects.filter(asset__in=self.assets.all()) | self.other_locations.all() class Meta: ordering = ('priority',) def __str__(self): return self.name
class VehicleJourney(models.Model): id = models.CharField(max_length=255, primary_key=True, db_index=True) journey_pattern = models.ForeignKey(JourneyPattern, related_name='journeys', on_delete=models.CASCADE) departure_time = models.TimeField() days_of_week = models.CharField(max_length=100, null=True, blank=True) nonoperation_bank_holidays = models.CharField(max_length=200, null=True, blank=True) operation_bank_holidays = models.CharField(max_length=200, null=True, blank=True) order = models.IntegerField() last_modified = models.DateTimeField(auto_now=True) def generate_timetable(self): departure_time = datetime.datetime.combine(datetime.date(1, 1, 1), self.departure_time) timing_links = self.journey_pattern.section.timing_links.order_by('stop_from_sequence_number')\ .select_related("stop_from") order = 1 timetable_objects = [] if timing_links: for timing_link in timing_links: timetable_objects.append( Timetable(vehicle_journey=self, stop_id=timing_link.stop_from.atco_code, time=departure_time.time(), order=order)) departure_time += timing_link.run_time if timing_link.wait_time: departure_time += timing_link.wait_time order += 1 timetable_objects.append( Timetable(vehicle_journey=self, stop_id=timing_links.last().stop_to.atco_code, time=departure_time.time(), order=order, last_stop=True)) return timetable_objects def get_timetable(self): return Timetable.objects.filter(vehicle_journey=self).order_by('order') @property def timetable(self): timetable = [] for time in Timetable.objects.filter( vehicle_journey=self).order_by('order'): timetable.append({ 'stop': time.stop.atco_code, 'time': time.time, 'order': time.order }) return timetable def get_timetable_prefetch(self): return self.get_timetable().select_related('stop') def get_stops_list(self): return Timetable.objects.filter( vehicle_journey=self).order_by('order').values('stop') @python_2_unicode_compatible def __str__(self): return self.id
class library(models.Model): name = models.CharField(max_length=50) location = models.PointField(srid=4326, geography=True) owner = models.ForeignKey(User, on_delete=models.CASCADE) owner_fname = models.CharField(max_length=50) owner_lname = models.CharField(max_length=50) email = models.EmailField() mobile_no = models.CharField(max_length=15) addr1 = models.CharField(max_length=50) addr2 = models.CharField(max_length=50) city = models.CharField(max_length=50) pincode = models.CharField(max_length=6) state = models.CharField(max_length=50) landline = models.CharField(max_length=12, blank=True, null=True) amenities = models.ManyToManyField(ammenities, blank=True) library_description = models.TextField(max_length=500) past_record_of_students = models.TextField(max_length=500, blank=True, null=True) payment_methods = models.ManyToManyField(payment_methods) fb_url = models.CharField(max_length=200, blank=True, null=True) insta = models.CharField(max_length=100, blank=True, null=True) google_map = models.CharField(max_length=100, blank=True, null=True) website = models.CharField(max_length=50, blank=True, null=True) main_image = models.ImageField() no_of_seats = models.PositiveSmallIntegerField() opening_days = models.ManyToManyField(weekday) opening_time = models.TimeField() closing_time = models.TimeField() non_refundable_charges = models.PositiveSmallIntegerField(blank=True, null=True) refund_policy = models.CharField(max_length=3, choices=refund_policy_choices) min_price_range = models.PositiveSmallIntegerField(blank=True, null=True) max_price_range = models.PositiveSmallIntegerField(blank=True, null=True) verified = models.BooleanField(default=False) visible = models.BooleanField(default=True) views = models.PositiveSmallIntegerField(default=0) rejected = models.BooleanField(default=False) rejection_reason = models.CharField(max_length=200, blank=True, null=True) def __str__(self): return self.name class Meta: verbose_name_plural = 'Libraries' def get_images(self): images = library_images.objects.filter(library=self) return images def get_rating(self): ratings = library_ratings.objects.filter(library=self) if ratings.exists(): total_rating = 0 total = 0 for rating_qs in ratings: total += 1 total_rating += rating_qs.rating avg = total_rating / total return str(avg) else: return ''
class Llamada(models.Model): fecha = models.DateField(auto_now_add=True) hora_inicio = models.TimeField() hora_fin = models.TimeField() f = models.CharField(max_length=4096, blank=True, null=True) debilidades = models.CharField(max_length=4096, blank=True, null=True) amenazas = models.CharField(max_length=4096, blank=True, null=True) recursos = models.CharField(max_length=4096, blank=True, null=True) intervencion = models.CharField(max_length=4096, blank=True, null=True) posible_solucion = models.CharField(max_length=4096, blank=True, null=True) vida_en_riesgo = models.BooleanField(default=False) calificacion = models.FloatField(null=True, blank=True) devolver_llamada = models.BooleanField(default=False) num_llamada = models.PositiveIntegerField() consejero = models.ForeignKey('Consejero', models.DO_NOTHING) victima = models.ForeignKey('Victima', models.DO_NOTHING) medio_contacto = models.ForeignKey('MedioContacto', models.DO_NOTHING) violentometro = models.ForeignKey('Violentometro', models.DO_NOTHING, blank=True, null=True) tipo_violencia = models.ForeignKey('TipoViolencia', models.DO_NOTHING, blank=True, null=True) tipo_llamada = models.ForeignKey('TipoLlamada', models.DO_NOTHING, blank=True, null=True) motivo = models.ForeignKey('MotivoLLamada', models.DO_NOTHING, blank=True, null=True) nivel_riesgo = models.ForeignKey('NivelRiesgo', models.DO_NOTHING, blank=True, null=True) fase_cambio = models.ForeignKey('FaseCambio', models.DO_NOTHING, blank=True, null=True) modalidad_violencia = models.ForeignKey('ModalidadViolencia', models.DO_NOTHING, blank=True, null=True) victima_involucrada = models.ForeignKey('VictimaInvolucrada', models.DO_NOTHING, blank=True, null=True) agresor = models.ForeignKey('Agresor', models.DO_NOTHING, blank=True, null=True) como_se_entero = models.ForeignKey('ComoSeEntero', models.DO_NOTHING, blank=True, null=True) linea_negocio = models.ForeignKey('LineaNegocio', models.DO_NOTHING, blank=True, null=True) aliado = models.ForeignKey('Aliado', models.DO_NOTHING, blank=True, null=True) tareas = models.ManyToManyField('TareaLLamada', related_name='tareas') duracion_servicio = models.BigIntegerField() transferencia = models.BooleanField(default=False) recibido = models.BooleanField(default=False) class Meta: managed = True db_table = 'llamada'
class TouristicEvent(AddPropertyMixin, PublishableMixin, MapEntityMixin, StructureRelated, PicturesMixin, TimeStampedModelMixin, NoDeleteMixin): """ A touristic event (conference, workshop, etc.) in the park """ description_teaser = models.TextField(verbose_name=_("Description teaser"), blank=True, help_text=_("A brief summary")) description = models.TextField(verbose_name=_("Description"), blank=True, help_text=_("Complete description")) themes = models.ManyToManyField(Theme, related_name="touristic_events", blank=True, verbose_name=_("Themes"), help_text=_("Main theme(s)")) geom = models.PointField(verbose_name=_("Location"), srid=settings.SRID) begin_date = models.DateField(blank=True, null=True, verbose_name=_("Begin date")) end_date = models.DateField(blank=True, null=True, verbose_name=_("End date")) duration = models.CharField(verbose_name=_("Duration"), max_length=64, blank=True, help_text=_("3 days, season, ...")) meeting_point = models.CharField(verbose_name=_("Meeting point"), max_length=256, blank=True, help_text=_("Where exactly ?")) meeting_time = models.TimeField(verbose_name=_("Meeting time"), blank=True, null=True, help_text=_("11:00, 23:30")) contact = models.TextField(verbose_name=_("Contact"), blank=True) email = models.EmailField(verbose_name=_("Email"), max_length=256, blank=True, null=True) website = models.URLField(verbose_name=_("Website"), max_length=256, blank=True, null=True) organizer = models.CharField(verbose_name=_("Organizer"), max_length=256, blank=True) speaker = models.CharField(verbose_name=_("Speaker"), max_length=256, blank=True) type = models.ForeignKey(TouristicEventType, verbose_name=_("Type"), blank=True, null=True, on_delete=models.CASCADE) accessibility = models.CharField(verbose_name=_("Accessibility"), max_length=256, blank=True) participant_number = models.CharField( verbose_name=_("Number of participants"), max_length=256, blank=True) booking = models.TextField(verbose_name=_("Booking"), blank=True) target_audience = models.CharField(verbose_name=_("Target audience"), max_length=128, blank=True, null=True) practical_info = models.TextField( verbose_name=_("Practical info"), blank=True, help_text=_("Recommandations / To plan / Advices")) source = models.ManyToManyField('common.RecordSource', blank=True, related_name='touristicevents', verbose_name=_("Source")) portal = models.ManyToManyField('common.TargetPortal', blank=True, related_name='touristicevents', verbose_name=_("Portal")) eid = models.CharField(verbose_name=_("External id"), max_length=1024, blank=True, null=True) approved = models.BooleanField(verbose_name=_("Approved"), default=False) id_prefix = 'E' class Meta: verbose_name = _("Touristic event") verbose_name_plural = _("Touristic events") ordering = ['-begin_date'] def __str__(self): return self.name @property def type1(self): return [self.type] if self.type else [] @property def districts_display(self): return ', '.join([str(d) for d in self.districts]) @property def dates_display(self): if not self.begin_date and not self.end_date: return "" elif not self.end_date: return _("starting from {begin}").format( begin=date_format(self.begin_date, 'SHORT_DATE_FORMAT')) elif not self.begin_date: return _("up to {end}").format( end=date_format(self.end_date, 'SHORT_DATE_FORMAT')) elif self.begin_date == self.end_date: return date_format(self.begin_date, 'SHORT_DATE_FORMAT') else: return _("from {begin} to {end}").format( begin=date_format(self.begin_date, 'SHORT_DATE_FORMAT'), end=date_format(self.end_date, 'SHORT_DATE_FORMAT')) @property def prefixed_category_id(self): return self.id_prefix def distance(self, to_cls): return settings.TOURISM_INTERSECTION_MARGIN @property def rando_url(self): category_slug = _('touristic-event') return '{}/{}/'.format(category_slug, self.slug) @property def meta_description(self): return plain_text(self.description_teaser or self.description)[:500]
class Product(models.Model): CHARGE_UNIT_CHOICES = ( ('day', 'Day'), ('half-day', 'Half-Day'), ('hour', 'Hour'), ) EXPERIENCE_UNIT_CHOICES = ( ('day', 'Day'), ('week', 'Week'), ('hour', 'Hour'), ) ALLOW_RENTAL_CHOICES = ( ('meet-cr', 'Guests who meet Coastal\'s requirements'), ('no-one', 'No one. I will read and approve every request within 72 hours'), ) STATUS_CHOICES = (('draft', 'Draft'), ('published', 'Published'), ('cancelled', 'Cancelled')) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='draft') category = models.ForeignKey(Category) for_rental = models.BooleanField() for_sale = models.BooleanField() owner = models.ForeignKey(User, related_name='properties') # address info country = models.CharField(max_length=100) administrative_area_level_1 = models.CharField('State', max_length=100, blank=True, null=True) administrative_area_level_2 = models.CharField('County', max_length=100, blank=True, null=True) locality = models.CharField('City', max_length=100, blank=True, null=True) sublocality = models.CharField('District', max_length=100, blank=True, null=True) city = models.CharField('City v1', max_length=100, blank=True, null=True) address = models.CharField(max_length=255, blank=True) city_address = models.CharField(max_length=255, blank=True) point = models.PointField(blank=True, null=True) timezone = models.CharField(max_length=100, blank=True, default='') # basic info max_guests = models.PositiveSmallIntegerField(blank=True, null=True) beds = models.PositiveSmallIntegerField(blank=True, null=True) bathrooms = models.PositiveSmallIntegerField(blank=True, null=True) sleeps = models.PositiveSmallIntegerField(blank=True, null=True) rooms = models.PositiveSmallIntegerField(blank=True, null=True) marina = models.CharField(max_length=255, blank=True) basin = models.CharField(max_length=255, blank=True) stall = models.CharField(max_length=255, blank=True) length = models.PositiveSmallIntegerField(blank=True, null=True) depth = models.PositiveSmallIntegerField(blank=True, null=True) cabins = models.PositiveSmallIntegerField(blank=True, null=True) year = models.PositiveSmallIntegerField(blank=True, null=True) speed = models.PositiveSmallIntegerField(blank=True, null=True) rank = models.PositiveSmallIntegerField(blank=True, null=True, default=0) currency = models.CharField(max_length=3, default='USD', blank=True) distance_from_coastal = models.FloatField(max_length=32, blank=True, null=True, editable=False) # rental info rental_price = models.FloatField(help_text='here is the price per day', null=True, blank=True) rental_usd_price = models.FloatField('Rental USD Price', null=True, blank=True) rental_unit = models.CharField(max_length=32, choices=CHARGE_UNIT_CHOICES, blank=True) rental_type = models.CharField(max_length=32, choices=ALLOW_RENTAL_CHOICES, blank=True, help_text='Who can book instantly') rental_rule = models.TextField(blank=True) discount_weekly = models.IntegerField( null=True, blank=True, help_text="The unit is %. e.g. 60 means 60%") discount_monthly = models.IntegerField( null=True, blank=True, help_text="The unit is %. e.g. 60 means 60%") # sale info sale_price = models.FloatField(default=0, null=True, blank=True) sale_usd_price = models.FloatField('Sale USD Price', default=0, null=True, blank=True) # experience info exp_time_unit = models.CharField(max_length=32, choices=EXPERIENCE_UNIT_CHOICES, blank=True) exp_time_length = models.PositiveSmallIntegerField(blank=True, null=True) exp_start_time = models.TimeField(blank=True, null=True) exp_end_time = models.TimeField(blank=True, null=True) # description name = models.CharField(max_length=255, null=True, blank=True) description = models.TextField(null=True, blank=True) amenities = models.ManyToManyField('Amenity', blank=True) desc_about_it = models.TextField(null=True, blank=True) desc_guest_access = models.TextField(null=True, blank=True) desc_interaction = models.TextField(null=True, blank=True) desc_getting_around = models.TextField(null=True, blank=True) desc_other_to_note = models.TextField(null=True, blank=True) # score score = models.PositiveIntegerField(default=0) active_product = models.DateTimeField(null=True, blank=True) def __str__(self): return self.name @cached_property def short_desc(self): if self.category_id in (defs.CATEGORY_HOUSE, defs.CATEGORY_APARTMENT): short_desc = 'Entire %s with %s rooms' % (self.category.name, self.rooms) elif self.category_id == defs.CATEGORY_ROOM: short_desc = 'Private Room' elif self.category_id in (defs.CATEGORY_YACHT, defs.CATEGORY_BOAT_SLIP, defs.CATEGORY_JET): short_desc = '%s ft. %s' % (self.length, self.category.name) else: short_desc = self.category.name return short_desc def get_amenities_display(self): return ', '.join(self.amenities.values_list('name', flat=True)) def publish(self): self.status = 'published' def validate_publish_data(self): if not self.productimage_set: return False if not (self.for_sale or self.for_rental ) and self.category_id != defs.CATEGORY_ADVENTURE: return False if self.category_id == defs.CATEGORY_ADVENTURE: if not (self.rental_price and self.rental_type and self.currency): return False elif self.for_rental: if not (self.rental_price and self.rental_unit and self.rental_type and self.currency): return False if self.for_sale: if not self.currency: return False if self.category_id == defs.CATEGORY_JET: if not (self.cabins and self.beds and self.sleeps and self.bathrooms and self.length and self.year): return False elif self.category_id == defs.CATEGORY_ADVENTURE: if self.exp_start_time is None or self.exp_end_time is None or not self.exp_time_length or not self.exp_time_unit: return False elif self.category_id in (defs.CATEGORY_HOUSE, defs.CATEGORY_APARTMENT): if not (self.rooms and self.sleeps and self.beds and self.bathrooms): return False elif self.category_id == defs.CATEGORY_ROOM: if not (self.sleeps and self.beds and self.bathrooms): return False elif self.category_id == defs.CATEGORY_YACHT: if not (self.cabins and self.beds and self.sleeps and self.bathrooms and self.length and self.year and self.speed): return False elif self.category_id == defs.CATEGORY_BOAT_SLIP: if not (self.marina and self.basin and self.stall): return False return True def cancel(self): self.status = 'cancelled' @property def is_no_one(self): return self.rental_type == 'no-one' def get_price(self, unit): unit_mapping = {'day': 24, 'half-day': 6, 'hour': 1, 'week': 7 * 24} return unit_mapping[unit] / unit_mapping[ self.rental_unit] * self.rental_price def get_rental_price_display(self): return price_display(self.rental_price, self.currency) def new_rental_unit(self): if self.category_id == defs.CATEGORY_ADVENTURE: return 'Person (%s)' % self.get_exp_time_display() return self.get_rental_unit_display() def get_sale_price_display(self): return price_display(self.sale_price, self.currency) def get_exp_time_display(self): return '%s %s%s' % (self.exp_time_length, self.get_exp_time_unit_display(), self.exp_time_length > 1 and 's' or '') def get_product_type(self): if self.for_rental and self.for_sale: return 'both' if self.for_sale: return 'sale' return 'rental' def _product_images(self): cache_key = 'product_images|%s' % self.id image_info = cache.get(cache_key) if image_info is not None: return image_info image_info = {'images': [], 'images_360': []} images = self.productimage_set.exclude( image_type=ProductImage.CAPTION_360) for img in images: image_info['images'].append({ 'image_id': img.id, 'url': img.image.url }) images_360 = self.productimage_set.filter( image_type=ProductImage.CAPTION_360) for img in images_360: image_info['images_360'].append({ 'image_id': img.id, 'url': img.image.url }) cache.set(cache_key, image_info, 60) return image_info def get_main_image(self): image_info = self._product_images() return image_info['images'] and image_info['images'][0]['url'] or '' def save(self, force_insert=False, force_update=False, using=None, update_fields=None): currency_rate = get_exchange_rate(self.currency) if self.currency and self.rental_unit and self.rental_price: self.rental_usd_price = math.ceil( self.get_price('day') / currency_rate) if self.currency and self.sale_price: self.sale_usd_price = math.ceil(self.sale_price / currency_rate) if self.category_id == defs.CATEGORY_ADVENTURE and self.rental_price: self.rental_usd_price = math.ceil(self.rental_price / currency_rate) super(Product, self).save() def check_exp_end_time(self): return self.exp_end_time == datetime.time(hour=23, minute=59) def has_remain_end_time(self, end_datetime): if end_datetime.hour == 23 and end_datetime.minute == 59: end_datetime_hour = 24 else: end_datetime_hour = end_datetime.hour if self.exp_end_time.hour == 23 and self.exp_end_time.minute == 59: actual_exp_end_time_hour = 24 else: actual_exp_end_time_hour = self.exp_end_time.hour return end_datetime_hour + self.exp_time_length > actual_exp_end_time_hour def has_remain_start_time(self, start_datetime): return start_datetime.hour - self.exp_time_length < self.exp_start_time.hour
class Company(models.Model): user = models.ForeignKey(User, null=True, on_delete=models.SET_NULL) name = models.CharField(max_length=100) name_en = models.CharField(max_length=100) description = models.CharField(max_length=3000, null=True) logo = models.CharField(max_length=200, null=True) cover = models.CharField(max_length=200, null=True) industry = models.ForeignKey(Industry, on_delete=models.CASCADE) founded = models.DateField(null=True, blank=True) company_slug = models.SlugField(max_length=255, unique=True, db_index=True) benefit = models.ManyToManyField(Benefit, blank=True) size = models.CharField(choices=settings.OFFICE_SIZE_CHOICES, max_length=2) is_deleted = models.BooleanField(default=False) has_legal_issue = models.BooleanField(default=False) created = models.DateTimeField(auto_now=True) approved = models.BooleanField(default=False) user_generated = models.BooleanField(default=False) city = models.ForeignKey(City, on_delete=models.CASCADE) tell = models.CharField(max_length=14, blank=True) site = models.CharField(max_length=100, blank=True) address = models.CharField(max_length=200, blank=True) location_point = LocationField(based_fields=['city'], zoom=7, default=Point(0, 0), null=True, blank=True) working_hours_start = models.TimeField(null=True) working_hours_stop = models.TimeField(null=True) work_life_balance = models.FloatField(default=0) salary_benefit = models.FloatField(default=0) security = models.FloatField(default=0) management = models.IntegerField( default=0) culture = models.FloatField(default=0) over_all_rate = models.FloatField(default=0) salary_avg = models.FloatField(default=0) salary_max = models.FloatField(default=0) salary_min = models.FloatField(default=0) recommend_to_friend = models.IntegerField(default=0) total_review = models.IntegerField(default=0) total_interview = models.IntegerField(default=0) view = models.ManyToManyField(User, related_name='company_views') total_view = models.IntegerField(default=0) is_cheater = models.BooleanField(default=False) # for company that try to cheat and advertise, 1 point in best company is_famous = models.BooleanField(default=False) # 2 points in best company has_panel_moderator = models.BooleanField(default=False) # 1 point is_big_company = models.BooleanField(default=False) # 1 point company_score = models.FloatField(default=0) # company rate for best company def __str__(self): return self.name def save(self, *args, **kwargs): cache.delete(settings.BEST_COMPANY_LIST) cache.delete(settings.DISCUSSED_COMPANY_LIST) cache.delete(settings.TOTAL_COMPANY) self.is_big_company = False if self.size in ['VS', 'S'] else True self.handle_company_score() for review in self.companyreview_set.all(): review.has_legal_issue = self.has_legal_issue review.save() for interview in self.interview_set.all(): interview.has_legal_issue = self.has_legal_issue interview.save() super().save(*args, **kwargs) def handle_company_score(self): review_count = self.companyreview_set.filter(is_deleted=False, approved=True).count() interview_count = self.interview_set.filter(is_deleted=False, approved=True).count() review_point = (review_count + interview_count) review_point = 20 if review_point > 20 else review_point review_point /= 4 # max must be 5 bool_point = (2*self.is_famous) + self.has_panel_moderator + self.is_big_company + (not self.is_cheater) over_all_rate = self.companyreview_set.filter(is_deleted=False, approved=True). \ aggregate(models.Avg('over_all_rate')) over_all_rate = over_all_rate['over_all_rate__avg'] if over_all_rate['over_all_rate__avg'] else 0 self.company_score = round((bool_point + review_point + over_all_rate)/3, 1) @property def get_media(self): return self.logo def get_absolute_url(self): return '/company/{}'.format(self.company_slug) def handle_company_review_statics(self): result_company_review = self.companyreview_set.filter(is_deleted=False, approved=True).exclude(salary=0). \ aggregate(models.Avg('salary'), models.Max('salary'), models.Min('salary'), models.Avg('work_life_balance'), models.Avg('salary_benefit'), models.Avg('security'), models.Avg('management'), models.Avg('culture'), models.Avg('over_all_rate')) result_list = self.companyreview_set.filter(is_deleted=False, approved=True).values_list('recommend_to_friend') total_result_list = len(result_list) total_result_list_true = len(list(filter(lambda x: x[0], result_list))) temp_data = { 'total_review': total_result_list, 'salary_avg': result_company_review['salary__avg'], 'salary_max': result_company_review['salary__max'], 'salary_min': result_company_review['salary__min'], 'work_life_balance': result_company_review['work_life_balance__avg'], 'salary_benefit': result_company_review['salary_benefit__avg'], 'security': result_company_review['security__avg'], 'management': result_company_review['management__avg'], 'culture': result_company_review['culture__avg'], 'over_all_rate': result_company_review['over_all_rate__avg'], 'recommend_to_friend': round(total_result_list_true / total_result_list) * 100 if total_result_list else 0, } self.total_review = temp_data['total_review'] self.salary_avg = round(temp_data['salary_avg']/1000000, 1) if temp_data['salary_avg'] else 0 self.salary_max = round(temp_data['salary_max']/1000000, 1) if temp_data['salary_max'] else 0 self.salary_min = round(temp_data['salary_min']/1000000, 1) if temp_data['salary_min'] else 0 self.work_life_balance = round(temp_data['work_life_balance'], 1) if temp_data['work_life_balance'] else 0 self.salary_benefit = round(temp_data['salary_benefit'], 1) if temp_data['salary_benefit'] else 0 self.security = round(temp_data['security'], 1) if temp_data['security'] else 0 self.management = round(temp_data['management'], 1) if temp_data['management'] else 0 self.culture = round(temp_data['culture'], 1) if temp_data['culture'] else 0 self.over_all_rate = round(temp_data['over_all_rate'], 1) if temp_data['over_all_rate'] else 0 self.recommend_to_friend = round(temp_data['recommend_to_friend'], 2) if temp_data['recommend_to_friend'] else 0 self.handle_company_score() self.save() def handle_company_interview_statics(self): self.total_interview = self.interview_set.filter(is_deleted=False, approved=True).count() self.handle_company_score() self.save()
class CateringOrder(TimeStampedModel): provider = models.ForeignKey(CateringProvider, verbose_name=_('Catering provider'), related_name='catering_orders', on_delete=models.PROTECT) reservation = models.ForeignKey(Reservation, verbose_name=_('Reservation'), related_name='catering_orders', on_delete=models.CASCADE) invoicing_data = models.TextField(verbose_name=_('Invoicing data')) message = models.TextField(verbose_name=_('Message'), blank=True) serving_time = models.TimeField(verbose_name=_('Serving time'), blank=True, null=True) objects = CateringOrderQuerySet.as_manager() class Meta: verbose_name = _('Catering order') verbose_name_plural = _('Catering orders') ordering = ('id', ) def __str__(self): return 'catering order for %s' % self.reservation def get_provider(self): return self.provider def get_notification_context(self, language_code): with translation.override(language_code): serving_time = self.serving_time if not serving_time: serving_time = self.reservation.begin.astimezone( self.reservation.resource.unit.get_tz()) context = { 'resource': self.reservation.resource.name, 'reservation': self.reservation, 'unit': self.reservation.resource.unit.name if self.reservation.resource.unit else '', 'serving_time': formats.date_format(serving_time, 'TIME_FORMAT'), 'invoicing_data': self.invoicing_data, 'message': self.message, 'order_lines': [], } for order_line in self.order_lines.all(): context['order_lines'].append({ 'product': order_line.product.name, 'quantity': order_line.quantity, 'category': order_line.product.category.name, }) return context def _send_notification(self, notification_type, request=None): provider = self.get_provider() email = provider.notification_email if provider else None if not email: return context = self.get_notification_context(DEFAULT_LANG) try: rendered_notification = render_notification_template( notification_type, context, DEFAULT_LANG) except NotificationTemplateException as e: logger.error(e, exc_info=True, extra={'request': request}) return send_respa_mail(email, rendered_notification['subject'], rendered_notification['body']) def send_created_notification(self, request=None): self._send_notification(NotificationType.CATERING_ORDER_CREATED, request) def send_modified_notification(self, request=None): self._send_notification(NotificationType.CATERING_ORDER_MODIFIED, request) def send_deleted_notification(self, request=None): self._send_notification(NotificationType.CATERING_ORDER_DELETED, request)
class Account(UserenaBaseProfile, FacebookProfileModel, AccountSettingsMixin): user = models.OneToOneField(User, unique=True, verbose_name=_('user'), related_name='my_profile') tax_origin_confirmed = models.BooleanField(default=False) not_from_canada = models.BooleanField(default=False) native_region = models.ForeignKey(Region, blank=True, null=True, related_name="native_for_accounts") website = models.URLField(blank=True, null=True, default='') # Reminder # remind options # remind time before event reminder_time_before_event = models.TimeField(blank=True, null=True) reminder_days_before_event = models.IntegerField(blank=True, null=True) reminder_hours_before_event = models.IntegerField(blank=True, null=True) # remind on week day reminder_on_week_day = models.CharField(max_length=1, choices=DAYS_OF_WEEK, blank=True, null=True, default=0) reminder_on_week_day_at_time = models.TimeField(blank=True, null=True) # remind each day, starting from reminder_each_day_from = models.IntegerField(blank=True, null=True) reminder_each_day_at_time = models.TimeField(blank=True, null=True) reminder_type_state = models.IntegerField( blank=True, null=False, default=REMINDER_TYPES['HOURS']['id']) # remind types reminder_with_website = models.BooleanField(default=True) reminder_with_email = models.BooleanField(default=True) reminder_with_sms = models.BooleanField(default=False) reminder_email = models.EmailField(blank=True, null=True) reminder_phonenumber = models.CharField(max_length=15, blank=True, null=True) # single events for remind reminder_single_events = models.ManyToManyField('event.SingleEvent', blank=True, null=True) in_the_loop_tags = TaggableManager(blank=True) # In the Loop in_the_loop_with_website = models.BooleanField(default=True) in_the_loop_with_email = models.BooleanField(default=True) in_the_loop_with_sms = models.BooleanField(default=False) in_the_loop_email = models.EmailField(blank=True, null=True) in_the_loop_phonenumber = models.CharField(max_length=15, blank=True, null=True) all_of_canada = models.BooleanField() regions = models.ManyToManyField(Region) cities = models.ManyToManyField(City) bonus_budget = MoneyField(max_digits=10, decimal_places=2, default_currency='CAD') fb_pages = models.TextField(blank=True, null=True) objects = models.Manager() accounts = money_manager(models.Manager()) def future_events(self): return SingleEvent.future_events.filter(event__owner_id=self.user.id) def featured_events(self): return FeaturedEvent.objects.filter(owner__id=self.id) def archived_events(self): return SingleEvent.archived_events.filter(event__owner_id=self.id) def in_the_loop_events(self): region_ids = self.regions.all().values_list("id", flat=True) city_ids = self.cities.all().values_list("id", flat=True) if self.all_of_canada: location_query = Q(event__venue__country__name="Canada") else: location_query = Q(event__venue__city__id__in=city_ids) | Q( event__venue__city__region__id__in=region_ids) | Q( event__venue__city__subregion__id__in=region_ids) return SingleEvent.future_events.filter( Q(event__tagged_items__tag__name__in=self.in_the_loop_tags.all(). values_list("name", flat=True)), location_query).annotate(Count("id")) def reminder_single_events_in_future(self): return SingleEvent.future_events.filter( id__in=self.reminder_single_events.values_list('id', flat=True)) def ads(self): return Advertising.objects.filter(campaign__account__id=self.id) def campaigns(self): return AdvertisingCampaign.objects.filter(account__id=self.id) def taxes(self): if self.native_region: return AccountTax.objects.filter(regions__id=self.native_region.id) else: return [] def reminder_weekday(self): return "%s" % dict(DAYS_OF_WEEK)[self.reminder_on_week_day] def in_the_loop_tag_names(self): return self.in_the_loop_tags.all().values_list("name", flat=True) def advertising_region(self): if self.not_from_canada: return None return self.native_region def shared_campaigns(self): return AdvertisingCampaign.objects.filter( Q(account=self) | Q(shareadvertisingcampaign__account=self)) def notices(self): return Notice.objects.filter(user__id=self.user.id, read=False).order_by('-id') def notices_history(self): return Notice.objects.filter(user__id=self.user.id).order_by('-id') def venues(self): return Venue.objects.filter(user=self.user, suggested=True) def check_reminder_type_state(self, type, state=None): if not state: state = self.reminder_type_state return bool(state & REMINDER_TYPES[type]['id'])
class Service(NameInCurrentLanguageMixin, models.Model): provider = models.ForeignKey( Provider, verbose_name=_("provider"), ) name_en = models.CharField( # Translators: Service name _("name in English"), max_length=256, default='', blank=True, ) name_ar = models.CharField( # Translators: Service name _("name in Arabic"), max_length=256, default='', blank=True, ) name_fr = models.CharField( # Translators: Service name _("name in French"), max_length=256, default='', blank=True, ) area_of_service = models.ForeignKey( ServiceArea, verbose_name=_("area of service"), ) description_en = models.TextField( # Translators: Service description _("description in English"), default='', blank=True, ) description_ar = models.TextField( # Translators: Service description _("description in Arabic"), default='', blank=True, ) description_fr = models.TextField( # Translators: Service description _("description in French"), default='', blank=True, ) additional_info_en = models.TextField( _("additional information in English"), blank=True, default='', ) additional_info_ar = models.TextField( _("additional information in Arabic"), blank=True, default='', ) additional_info_fr = models.TextField( _("additional information in French"), blank=True, default='', ) cost_of_service = models.TextField( _("cost of service"), blank=True, default='', ) is_mobile = models.BooleanField( _("mobile service"), blank=True, default=False, ) # Note: we don't let multiple non-archived versions of a service record pile up # there should be no more than two, one in current status and/or one in some other # status. STATUS_DRAFT = 'draft' STATUS_CURRENT = 'current' STATUS_REJECTED = 'rejected' STATUS_CANCELED = 'canceled' STATUS_ARCHIVED = 'archived' STATUS_CHOICES = ( # New service or edit of existing service is pending approval (STATUS_DRAFT, _('draft')), # This Service has been approved and not superseded. Only services with # status 'current' appear in the public interface. (STATUS_CURRENT, _('current')), # The staff has rejected the service submission or edit (STATUS_REJECTED, _('rejected')), # The provider has canceled service. They can do this on draft or current services. # It no longer appears in the public interface. (STATUS_CANCELED, _('canceled')), # The record is obsolete and we don't want to see it anymore (STATUS_ARCHIVED, _('archived')), ) status = models.CharField( _('status'), max_length=10, choices=STATUS_CHOICES, default=STATUS_DRAFT, ) update_of = models.ForeignKey( 'self', help_text=_( 'If a service record represents a modification of another service ' 'record, this field links to that other record.'), null=True, blank=True, related_name='updates', ) location = models.PointField( _('location'), blank=True, null=True, ) # Open & close hours by day. If None, service is closed that day. sunday_open = models.TimeField(null=True, blank=True) sunday_close = models.TimeField(null=True, blank=True) monday_open = models.TimeField(null=True, blank=True) monday_close = models.TimeField(null=True, blank=True) tuesday_open = models.TimeField(null=True, blank=True) tuesday_close = models.TimeField(null=True, blank=True) wednesday_open = models.TimeField(null=True, blank=True) wednesday_close = models.TimeField(null=True, blank=True) thursday_open = models.TimeField(null=True, blank=True) thursday_close = models.TimeField(null=True, blank=True) friday_open = models.TimeField(null=True, blank=True) friday_close = models.TimeField(null=True, blank=True) saturday_open = models.TimeField(null=True, blank=True) saturday_close = models.TimeField(null=True, blank=True) type = models.ForeignKey( ServiceType, verbose_name=_("type"), ) objects = models.GeoManager() def get_api_url(self): return reverse('service-detail', args=[self.id]) def get_provider_fetch_url(self): # For convenience of the serializer return self.provider.get_fetch_url() def get_admin_edit_url(self): return reverse('admin:services_service_change', args=[self.id]) def email_provider_about_approval(self): """Schedule a task to send an email to the provider""" email_provider_about_service_approval_task.delay(self.pk) def may_approve(self): return self.status == self.STATUS_DRAFT def may_reject(self): return self.status == self.STATUS_DRAFT def cancel(self): """ Cancel a pending service update, or withdraw a current service from the directory. """ # First cancel any pending changes to this service for pending_change in self.updates.filter(status=Service.STATUS_DRAFT): pending_change.cancel() previous_status = self.status self.status = Service.STATUS_CANCELED self.save() if previous_status == Service.STATUS_DRAFT: JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.CANCEL_DRAFT_SERVICE) elif previous_status == Service.STATUS_CURRENT: JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.CANCEL_CURRENT_SERVICE) def save(self, *args, **kwargs): new_service = self.pk is None superseded_draft = None with atomic(): # All or none of this if (new_service and self.status == Service.STATUS_DRAFT and self.update_of and self.update_of.status == Service.STATUS_DRAFT): # Any edit of a record that's still in review means we're # superseding one draft with another. superseded_draft = self.update_of # Bump this one up a level - we're replacing a pending change. self.update_of = superseded_draft.update_of # If it's mobile, force the location to the center of the area if self.is_mobile: self.location = self.area_of_service.centroid super().save(*args, **kwargs) if new_service: # Now we've safely saved this new record. # Did we replace an existing draft? Archive the previous one. if superseded_draft: superseded_draft.status = Service.STATUS_ARCHIVED superseded_draft.save() JiraUpdateRecord.objects.create( service=self, superseded_draft=superseded_draft, update_type=JiraUpdateRecord.SUPERSEDED_DRAFT) elif self.update_of: # Submitted a proposed change to an existing service JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.CHANGE_SERVICE) else: # Submitted a new service JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.NEW_SERVICE) def validate_for_approval(self): """ Raise a ValidationError if this service's data doesn't look valid to be a current, approved service. Current checks: * self.full_clean() * .location must be set * at least one language field for each of several translated fields must be set * status must be DRAFT """ try: self.full_clean() except ValidationError as e: errs = e.error_dict else: errs = {} if not self.location: errs['location'] = [_('This field is required.')] for field in ['name', 'description']: if not any([ getattr(self, '%s_%s' % (field, lang)) for lang in ['en', 'ar', 'fr'] ]): errs[field] = [_('This field is required.')] if self.status != Service.STATUS_DRAFT: errs['status'] = [ _('Only services in draft status may be approved.') ] if errs: raise ValidationError(errs) def staff_approve(self, staff_user): """ Staff approving the service (new or changed). :param staff_user: The user who approved :raises: ValidationErrror """ # Make sure it's ready self.validate_for_approval() # if there's already a current record, archive it if self.update_of and self.update_of.status == Service.STATUS_CURRENT: self.update_of.status = Service.STATUS_ARCHIVED self.update_of.save() self.status = Service.STATUS_CURRENT self.save() self.email_provider_about_approval() JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.APPROVE_SERVICE, by=staff_user) def validate_for_rejecting(self): """ Raise a ValidationError if this service's data doesn't look valid to be rejected. Current checks: * self.full_clean() * status must be DRAFT """ try: self.full_clean() except ValidationError as e: errs = e.error_dict else: errs = {} if self.status != Service.STATUS_DRAFT: errs['status'] = [ _('Only services in draft status may be rejected.') ] if errs: raise ValidationError(errs) def staff_reject(self, staff_user): """ Staff rejecting the service (new or changed) :param staff_user: The user who rejected """ # Make sure it's ready self.validate_for_rejecting() self.status = Service.STATUS_REJECTED self.save() JiraUpdateRecord.objects.create( service=self, update_type=JiraUpdateRecord.REJECT_SERVICE, by=staff_user) @property def longitude(self): if self.location: return self.location[0] @longitude.setter def longitude(self, value): if self.location is None: self.location = Point(0, 0) self.location[0] = value @property def latitude(self): if self.location: return self.location[1] @latitude.setter def latitude(self, value): if self.location is None: self.location = Point(0, 0) self.location[1] = value
class PlaEvent(gismodel.Model): eventid = gismodel.IntegerField(_('Event ID')) title = gismodel.CharField(_('Title'), max_length=255) description = gismodel.TextField(_('Description'), null=True, blank=True) club_name = gismodel.CharField(_('Club name'), max_length=255, blank=True, null=True) club_location = gismodel.PointField(_('Club location'), blank=True, null=True) from_name = gismodel.CharField(_('Location From Name'), max_length=255, blank=True, null=True) from_location = gismodel.PointField(_('From location'), blank=True, null=True) from_description = gismodel.TextField(_('From description'), blank=True, null=True) from_date = gismodel.DateField(_('From Date'), blank=True, null=True) from_time = gismodel.TimeField(_('From Time'), blank=True, null=True) to_name = gismodel.CharField(_('Location To Name'), max_length=255, blank=True, null=True) to_location = gismodel.PointField(_('To location'), blank=True, null=True) to_description = gismodel.TextField(_('To description'), blank=True, null=True) to_date = gismodel.DateField(_('To Date'), blank=True, null=True) to_time = gismodel.TimeField(_('To Time'), blank=True, null=True) river_closure = gismodel.NullBooleanField(_('River Closure'), default=None) link = gismodel.CharField(_('Link'), max_length=255, blank=True, null=True) group_type = gismodel.CharField(_('Type'), max_length=255, blank=True, null=True) district_name_one = gismodel.CharField(_('District name one'), max_length=255, null=True, blank=True) district_description_one = gismodel.CharField( _('District description one'), max_length=255, null=True, blank=True) district_name_two = gismodel.CharField(_('District name two'), max_length=255, null=True, blank=True) district_description_two = gismodel.CharField( _('District description two'), max_length=255, null=True, blank=True) district_name_three = gismodel.CharField(_('District name three'), max_length=255, null=True, blank=True) district_description_three = gismodel.CharField( _('District description three'), max_length=255, null=True, blank=True) status_name = gismodel.CharField(_('Status name'), max_length=255, null=True, blank=True) status_description = gismodel.CharField(_('Status description'), max_length=255, null=True, blank=True) calendar = gismodel.ManyToManyField(Calendar, null=True, blank=True) created = CreationDateTimeField() modified = ModificationDateTimeField() def __unicode__(self): return "{0} - {1}".format(self.eventid, self.title) def __str__(self): return "{0} - {1}".format(self.eventid, self.title) class Meta: verbose_name = 'PLA Event' verbose_name_plural = 'PLA Events' ordering = [ 'eventid', ]
class Schedule(models.Model): owner = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('owner'), on_delete=models.PROTECT) name = models.CharField( _('name'), max_length=100, help_text=_('Name your test schedule, must be unique')) url = models.URLField(_('URL'), db_index=True, help_text=_('The URL you want to test')) trillians = models.ManyToManyField( Trillian, verbose_name=_('Trillians'), help_text=_( 'The data centres from where you want this URL to be tested')) time = models.TimeField( _('time'), help_text=_( 'The time of day in UTC when you want the tests to be scheduled')) start = models.DateField( _('start'), default=date.today, help_text=_('The first day that you want the tests to be run')) end = models.DateField( _('end'), blank=True, null=True, help_text=_('The last day that you want the tests to be run')) frequency = models.CharField( _('frequency'), max_length=1, choices=[ ('D', _('Every day')), ('W', _('Every week')), ('M', _('Every month')), ], help_text= _('Frequency to schedule the tests. Can be "D" (daily), "W" (weekly) or "M" (monthly)' )) is_public = models.BooleanField( _('is public'), default=True, help_text=_('Whether the test results should be publicly visible')) class Meta: verbose_name = _('schedule') verbose_name_plural = _('schedules') ordering = ('start', 'end') unique_together = (('owner', 'name'), ) def __str__(self): return self.name def first_testrun(self): return self.testruns.order_by('requested').values_list( 'requested', flat=True).first() first_testrun.short_description = _('first testrun') first_testrun = property(first_testrun) def last_testrun(self): return self.testruns.order_by('-requested').values_list( 'requested', flat=True).first() last_testrun.short_description = _('last testrun') last_testrun = property(last_testrun) def is_active(self): # Check if it started already if datetime.datetime.combine(self.start, self.time, timezone.utc) > timezone.now(): return False # No end means it's still active if not self.end: return True return datetime.datetime.combine(self.end, self.time, timezone.utc) >= timezone.now() is_active.short_description = _('is active') is_active = property(is_active)
class AerialFrame(models.Model): """Aerial photo frames. Not aerial imagery. Metadata pertaining to the aerial photography collection. These images are sourced from http://retrolens.nz, and are in various stages of georeference. The name field is provided as an alternative identifier to the survey/run/frame identifiers. The description text field is intended to hold georeferencing notes. """ STATUS = ( (None, '-'), ('for reference', 'for reference'), ('polynomial', 'polynomial'), ('thin plate spline', 'thin plate spline'), ) FILESPACE = os.path.join(settings.BASE_FILESPACE, 'airphoto_historic') STATIC_URL = os.path.join(settings.STATIC_URL, 'geolib/airphoto_historic') latitude = None longitude = None azimuth = None altitude = None run = models.ForeignKey(AerialRun, related_name='frames') identifier = models.CharField(max_length=16) ordinal = models.IntegerField(blank=True, null=True) date_flown = models.DateField(blank=True, null=True) time_flown = models.TimeField(blank=True, null=True) alt_ft = models.PositiveIntegerField(blank=True, null=True) alt_m = models.PositiveIntegerField(blank=True, null=True) focal_length = models.CharField(max_length=16, blank=True, null=True) aperture = models.CharField(max_length=32, blank=True, null=True) status = models.CharField( max_length=255, choices=STATUS, default=None, blank=True, null=True) name = models.CharField(max_length=255, blank=True, null=True) description = models.TextField(blank=True, null=True) georef_notes = models.TextField(blank=True, null=True) source_url = models.CharField(max_length=2014, blank=True, null=True) coverage = models.CharField(max_length=255, blank=True, null=True) provenance = models.TextField(blank=True, null=True) rights = models.CharField(max_length=255, blank=True, null=True) geom = models.PolygonField(srid=2193, blank=True, null=True) class Meta: ordering = ('run', 'ordinal') def save(self, *args, **kwargs): if not os.path.isdir(self.filespace()): os.mkdir(self.filespace()) self.ordinal = self.find_ordinal() super(AerialFrame, self).save(*args, **kwargs) def __unicode__(self): return self.identifier def get_absolute_url(self): return os.path.join(self.run.url, self.fn()) url = property(get_absolute_url) def _get_identifier(self): """Return a string identifier. """ identifier = 'unknown' if self.survey and self.run and self.frame: identifier = ( str(self.survey) + '/' + str(self.run) + '/' + str(self.frame) ) return identifier def filespace(self): return os.path.join(self.run.survey.FILESPACE, self.identifier) def find_ordinal(self): """Return an integer ordinal.""" survey, run, frame = self.identifier.split('/') try: ordinal = int(frame) except ValueError: ordinal = None return ordinal def fn(self): parts = self.identifier.split('/') return parts[-1] def lidar_set(self): if not self.geom: return None if self.lidar_tiles().count(): return self.lidar_tiles()[0].series return None def lidar_tiles(self): """Lidar tiles intersecting with this photo.""" if not self.geom: return None return LidarTile.objects.filter( geom__intersects=self.geom) def ortho(self): """Orthophoto tiles intersecting with this tile.""" if not self.geom: return None return OrthoTile.objects.filter( geom__intersects=self.geom) def sites(self): """NZAA sites within the footprint of this frame.""" if not self.geom: return None return nzaa.models.Site.objects.filter(geom__intersects=self.geom) def ephemera(self): """Return solar azimuth and altitude. These values are computed on the day and time the frame was taken. They can be used to generate hillshade images with the same lighting values as the photograph, to aid in georeferencing. """ if not self.geom: return None p = self.geom.centroid p.transform(4326) self.latitude = p.y self.longitude = p.x if not self.date_flown: return None if not self.time_flown: return None O = ephem.Observer() O.lon, O.lat = str(p.x), str(p.y) date = datetime.datetime( self.date_flown.year, self.date_flown.month, self.date_flown.day, self.time_flown.hour, self.time_flown.minute, self.time_flown.second, ) shift = datetime.timedelta(0, 0, 0, 0, 0, 12) date = date - shift O.date = date S = ephem.Sun() S.compute(O) self.azimuth = S.az self.altitude = ephem.degrees(S.alt) return None def lat(self): if self.latitude: return self.latitude self.ephemera() return self.latitude def lon(self): if self.longitude: return self.longitude self.ephemera() return self.longitude def az(self): if self.azimuth: return self.azimuth self.ephemera() return self.azimuth def alt(self): if self.altitude: return self.altitude self.ephemera() return self.altitude def dms2dd(self, dms): """Degrees, minutes, seconds to digital degrees. Accepts an Angle object from the ephem package. This is encoded as a float containing an angle in radians. The conversion is done using the standard formula for converting radians into degrees. """ if dms: return dms * (180 / math.pi) return None def alt_dd(self): """Altitude as digital degrees (float).""" return self.dms2dd(self.alt()) def az_dd(self): """Azimuth as digital degrees (float).""" return self.dms2dd(self.az()) def thumbnail(self): """Return an image link tuple to the thumbnail image.""" fname = self.run.survey.sn() + '_' + self.run.rn() fname += '-' + self.fn() + '_512.jpg' src = os.path.join( self.STATIC_URL, self.identifier, fname ) alt = self.identifier return (src, alt) def retrolens(self): """Return a list of link tuples to original files. """ url = self.get_retrolens_url() links = [ (os.path.join(url, 'High.jpg'), "High resolution"), (os.path.join(url, 'Med.jpg'), "Medium resolution"), ] return links def get_retrolens_url(self): """Return string being the address of the original image file.""" url = self.run.survey.RETROLENS + 'SN' + self.run.survey.sn() url += '/Crown_' + self.run.survey.sn() + '_' url += self.run.rn() + '_' + self.fn() + '/' return url def files_available(self): """True if retrolens has files available.""" base_url = self.get_retrolens_url() high = os.path.join(base_url, 'High.jpg') med = os.path.join(base_url, 'Med.jpg') try: response = urllib2.urlopen(med) except urllib2.HTTPError: return False return True def download_source_files(self): """Go get copies of the photo from from Retrolensnz.""" base_url = self.get_retrolens_url() high = os.path.join(base_url, 'High.jpg') med = os.path.join(base_url, 'Med.jpg') fname = self.run.survey.id.replace('SN', '') fname += '_' + self.run.rn() + '-' fname += self.fn() fname_med = fname + '_med.jpg' dest_med = os.path.join(self.filespace(), fname_med) try: response = urllib2.urlopen(med) except urllib2.HTTPError: pass f_med = open(dest_med, 'w') f_med.write(response.read()) f_med.close() response.close() fname_high = fname + '.jpg' dest_high = os.path.join(self.filespace(), fname_high) try: response = urllib2.urlopen(high) except urllib2.HTTPError: pass f_high = open(dest_high, 'w') f_high.write(response.read()) f_high.close() response.close() def write_exif(self): """Produce an exif compatable structure to write into a file. """ return None def thumbnails(self): """List of links to the 512px thumbnails held in filespace.""" thumbs = [] for f in sorted(os.listdir(self.filespace())): if "_512" in f: alt = f src = os.path.join( settings.STATIC_URL, self.STATIC_URL, self.identifier, f, ) thumbs.append((src, alt)) return thumbs
class TouristicEvent(AddPropertyMixin, PublishableMixin, MapEntityMixin, StructureRelated, PicturesMixin, TimeStampedModelMixin, NoDeleteMixin): """ A touristic event (conference, workshop, etc.) in the park """ description_teaser = models.TextField(verbose_name=_(u"Description teaser"), blank=True, help_text=_(u"A brief summary"), db_column='chapeau') description = models.TextField(verbose_name=_(u"Description"), blank=True, db_column='description', help_text=_(u"Complete description")) themes = models.ManyToManyField(Theme, related_name="touristic_events", db_table="t_r_evenement_touristique_theme", blank=True, verbose_name=_(u"Themes"), help_text=_(u"Main theme(s)")) geom = models.PointField(verbose_name=_(u"Location"), srid=settings.SRID) begin_date = models.DateField(blank=True, null=True, verbose_name=_(u"Begin date"), db_column='date_debut') end_date = models.DateField(blank=True, null=True, verbose_name=_(u"End date"), db_column='date_fin') duration = models.CharField(verbose_name=_(u"Duration"), max_length=64, blank=True, db_column='duree', help_text=_(u"3 days, season, ...")) meeting_point = models.CharField(verbose_name=_(u"Meeting point"), max_length=256, blank=True, db_column='point_rdv', help_text=_(u"Where exactly ?")) meeting_time = models.TimeField(verbose_name=_(u"Meeting time"), blank=True, null=True, db_column='heure_rdv', help_text=_(u"11:00, 23:30")) contact = models.TextField(verbose_name=_(u"Contact"), blank=True, db_column='contact') email = models.EmailField(verbose_name=_(u"Email"), max_length=256, db_column='email', blank=True, null=True) website = models.URLField(verbose_name=_(u"Website"), max_length=256, db_column='website', blank=True, null=True) organizer = models.CharField(verbose_name=_(u"Organizer"), max_length=256, blank=True, db_column='organisateur') speaker = models.CharField(verbose_name=_(u"Speaker"), max_length=256, blank=True, db_column='intervenant') type = models.ForeignKey(TouristicEventType, verbose_name=_(u"Type"), blank=True, null=True, db_column='type') accessibility = models.CharField(verbose_name=_(u"Accessibility"), max_length=256, blank=True, db_column='accessibilite') participant_number = models.CharField(verbose_name=_(u"Number of participants"), max_length=256, blank=True, db_column='nb_places') booking = models.TextField(verbose_name=_(u"Booking"), blank=True, db_column='reservation') target_audience = models.CharField(verbose_name=_(u"Target audience"), max_length=128, blank=True, null=True, db_column='public_vise') practical_info = models.TextField(verbose_name=_(u"Practical info"), blank=True, db_column='infos_pratiques', help_text=_(u"Recommandations / To plan / Advices")) source = models.ManyToManyField('common.RecordSource', blank=True, related_name='touristicevents', verbose_name=_("Source"), db_table='t_r_evenement_touristique_source') portal = models.ManyToManyField('common.TargetPortal', blank=True, related_name='touristicevents', verbose_name=_("Portal"), db_table='t_r_evenement_touristique_portal') eid = models.CharField(verbose_name=_(u"External id"), max_length=1024, blank=True, null=True, db_column='id_externe') approved = models.BooleanField(verbose_name=_(u"Approved"), default=False, db_column='labellise') objects = NoDeleteMixin.get_manager_cls(models.GeoManager)() category_id_prefix = 'E' class Meta: db_table = 't_t_evenement_touristique' verbose_name = _(u"Touristic event") verbose_name_plural = _(u"Touristic events") ordering = ['-begin_date'] def __unicode__(self): return self.name @property def type1(self): return [self.type] if self.type else [] @property def type2(self): return [] @property def districts_display(self): return ', '.join([unicode(d) for d in self.districts]) @property def dates_display(self): if not self.begin_date and not self.end_date: return u"" elif not self.end_date: return _(u"starting from {begin}").format( begin=date_format(self.begin_date, 'SHORT_DATE_FORMAT')) elif not self.begin_date: return _(u"up to {end}").format( end=date_format(self.end_date, 'SHORT_DATE_FORMAT')) elif self.begin_date == self.end_date: return date_format(self.begin_date, 'SHORT_DATE_FORMAT') else: return _(u"from {begin} to {end}").format( begin=date_format(self.begin_date, 'SHORT_DATE_FORMAT'), end=date_format(self.end_date, 'SHORT_DATE_FORMAT')) @property def prefixed_category_id(self): return self.category_id_prefix def distance(self, to_cls): return settings.TOURISM_INTERSECTION_MARGIN @property def portal_display(self): return ', '.join([unicode(portal) for portal in self.portal.all()]) @property def source_display(self): return ', '.join([unicode(source) for source in self.source.all()]) @property def themes_display(self): return ','.join([unicode(source) for source in self.themes.all()]) @property def rando_url(self): category_slug = _(u'touristic-event') return '{}/{}/'.format(category_slug, self.slug) @property def meta_description(self): return plain_text(self.description_teaser or self.description)[:500]
class BaseSUSQLModel(BaseSQLModel): # Unique combination of these fields defines a single (pseudo) sample unit. # Corresponds to *SUSQLModel.su_fields transect_su_fields = [ "sample_event_id", "depth", "number", "len_surveyed", ] qc_su_fields = [ "sample_event_id", "depth", "quadrat_size", ] # SU sql common to all obs-level views su_fields_sql = """ su.id AS sample_unit_id, su.depth, su.label, r.name AS relative_depth, su.sample_time, observers.observers, c.name AS current_name, t.name AS tide_name, v.name AS visibility_name """ # SU aggregation SQL common to all SU-level views su_aggfields_sql = """ string_agg(DISTINCT label::text, ', '::text ORDER BY (label::text)) AS label, string_agg(DISTINCT relative_depth::text, ', '::text ORDER BY (relative_depth::text)) AS relative_depth, string_agg(DISTINCT sample_time::text, ', '::text ORDER BY (sample_time::text)) AS sample_time, string_agg(DISTINCT current_name::text, ', '::text ORDER BY (current_name::text)) AS current_name, string_agg(DISTINCT tide_name::text, ', '::text ORDER BY (tide_name::text)) AS tide_name, string_agg(DISTINCT visibility_name::text, ', '::text ORDER BY (visibility_name::text)) AS visibility_name """ # Fields common to all SUs that are actually SU properties (that make SUs distinct) depth = models.DecimalField(max_digits=3, decimal_places=1, verbose_name=_("depth (m)")) # Fields common to all SUs that are aggregated from actual SUs into pseudo-SUs agg_su_fields = [ "sample_unit_ids", "label", "relative_depth", "sample_time", "observers", "current_name", "tide_name", "visibility_name", ] # SU-level BaseSUSQLModel inheritors should instantiate sample_unit_ids; obs-level inheritors shouldn't label = models.CharField(max_length=50, blank=True) relative_depth = models.CharField(max_length=50) sample_time = models.TimeField() observers = JSONField(null=True, blank=True) current_name = models.CharField(max_length=50) tide_name = models.CharField(max_length=50) visibility_name = models.CharField(max_length=50) class Meta: abstract = True