Example #1
0
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("#")
Example #2
0
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()
Example #3
0
class TrainStation(models.Model):
    train = models.ForeignKey(Train)
    station = models.ForeignKey(Station)
    serial = models.IntegerField()
    time = models.TimeField()        
Example #4
0
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)
Example #5
0
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)
Example #6
0
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
Example #7
0
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"
Example #8
0
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
Example #10
0
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()]
        }
Example #11
0
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
Example #12
0
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
Example #13
0
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 ''
Example #14
0
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'
Example #15
0
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]
Example #16
0
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
Example #17
0
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()
Example #18
0
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)
Example #19
0
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'])
Example #20
0
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
Example #21
0
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',
        ]
Example #22
0
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)
Example #23
0
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
Example #24
0
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]
Example #25
0
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