Пример #1
0
class Initiative(models.Model):
    """Model to represent Initiative objects"""

    name = models.CharField(
        _('Nombre de la iniciativa'),
        max_length=200,
        blank=False,
        null=True,
        help_text=_('¿Cuál es el nombre de tu iniciativa?'))
    slug = models.SlugField(editable=False, blank=True)
    creation_date = models.DateField(editable=False, default=timezone.now)
    featured = models.BooleanField(
        _('Destacado'),
        blank=True,
        default=False,
        help_text=_('Indica si es una iniciativa destacada'))
    user = models.ForeignKey(User,
                             verbose_name=_('Gestor'),
                             blank=True,
                             null=True,
                             on_delete=models.SET_NULL)
    image = models.ImageField(
        _("Imagen"),
        blank=True,
        validators=[validate_image_size, validate_image_type],
        upload_to=initiatives_images_path,
        help_text=
        _("Sube una imagen representativa de la iniciativa haciendo click en la imagen inferior. "
          "La imagen ha de tener ancho mínimo de 300 píxeles y máximo de 1920, y altura mínima "
          "de 300 píxeles y máxima de 1280. Formatos permitidos: PNG, JPG, JPEG."
          ))
    image_medium = ImageSpecField(
        source="image",
        processors=[processors.ResizeToFill(600, 300)],
        format='JPEG',
        options={'quality': 90})
    video = models.CharField(
        _('Video'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('Inserta la url de un video de Youtube o Vimeo'))
    description = models.TextField(
        _('Descripción de la iniciativa'),
        blank=False,
        null=True,
        help_text=_('Describe los objetivos y actividad de la iniciativa.'))
    website = models.URLField(
        _('Website'),
        blank=True,
        null=True,
        help_text=_(
            'Especifica opcionalmente una web para conocer mejor la iniciativa.'
        ))
    twitter = models.CharField(
        _('Twitter'),
        blank=True,
        null=True,
        max_length=128,
        help_text=_(
            'Si tienes una cuenta de Twitter, pon aquí el nombre de usuario.'))
    facebook = models.URLField(
        _('Facebook'),
        blank=True,
        null=True,
        help_text=
        _('Si tienes un perfil de Facebook pon aquí el enlace completo a la misma.'
          ))
    email = models.EmailField(
        _('Correo electrónico'),
        blank=False,
        null=True,
        help_text=_('Especifica un correo de contacto para la iniciativa.'))
    topic = models.CharField(_('Tema'),
                             blank=False,
                             null=False,
                             default='DC',
                             max_length=2,
                             choices=categories.TOPICS,
                             help_text=_('El tema de la iniciativa'))
    space = models.CharField(
        _('Tipo de espacio'),
        blank=False,
        null=False,
        default='CC',
        max_length=2,
        choices=categories.SPACES,
        help_text=_('El tipo de espacio asociado a la iniciativa'))
    agent = models.CharField(
        _('tipo de agente'),
        blank=False,
        null=False,
        default='IM',
        max_length=2,
        choices=categories.AGENTS,
        help_text=_('El tipo de agente involucrado en la iniciativa'))
    city = models.ForeignKey(
        City,
        verbose_name=_('Ciudad'),
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        help_text=
        _('Ciudad donde se encuentra la iniciativa. Si no encuentras la ciudad en el desplegable usa el botón inferior para añadir una nueva ciudad y seleccionarla'
          ))
    address = models.CharField(
        _('Dirección'),
        max_length=200,
        blank=False,
        null=True,
        help_text=
        _('Dirección de la iniciativa. No es necesario que vuelvas a introducir la ciudad de la iniciativa.'
          ))
    district = models.CharField(
        _('Distrito'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('¿En qué barrio de la ciudad se sitúa la iniciativa?'))
    position = PointField(
        _("Ubicación"),
        blank=False,
        null=True,
        help_text=
        _("Tras añadir ciudad y dirección puedes ubicar la iniciativa pulsando el botón inferior y ajustando la posición del marcador posteriormente."
          ))

    class Meta:
        verbose_name = _('Iniciativa')
        verbose_name_plural = _('Iniciativas')

    def __str__(self):
        """String representation of this model objects."""
        return self.name or '---'

    @property
    def translated_name(self):
        print(self.request)

    @property
    def external_url(self):
        """Returns the first occurence of an external url related to the initiative"""
        if self.website:
            return self.website
        elif self.facebook:
            return self.facebook
        return "https://twitter.com/" + self.twitter

    def save(self, *args, **kwargs):
        """Populate automatically 'slug' field"""
        self.slug = slugify(self.name)
        # Notify by mail, only when creating new content
        if not self.id:
            send_mail(
                'Creada la iniciativa \"' + self.name + "\"",
                'Creada el ' + self.creation_date.strftime("%d/%b/%Y") +
                ' por ' + self.user.username + '\n---\n' + self.name + ' (' +
                self.email + '):\n' + self.description + '\n---\n' +
                'Ciudad: ' + self.city.name,
                'civics.cc <*****@*****.**>',
                settings.NOTIFICATIONS_EMAILS,
                fail_silently=False,
            )
        super(Initiative, self).save(*args, **kwargs)

    def edit_permissions(self, user):
        """Returns users allowed to edit an instance of this model."""
        if user.is_staff or (self.user and self.user == user):
            return True
        return False
Пример #2
0
class Record(models.Model):
    class Meta:
        verbose_name = "HRD Record"

    def __unicode__(self):
        return "%s (%s)" % (self.person_id, self.name)

    # Additional model valiation

    def clean(self):
        super(Record, self).clean()

        if self.date_govreply and not self.govreply_content:
            raise ValidationError(
                'With a government reply date set, a reply content is required'
            )
        if self.date_govaction and not self.govreply_action:
            raise ValidationError(
                'With a government reply date set, a reply content is required'
            )
        if self.type_intervention == 'JUA' or self.type_intervention == 'JAL':
            if not self.joint_with or (len(self.joint_with) == 1
                                       and not self.joint_with[0]):
                raise ValidationError(
                    'Select joint intervention type, required for JUA and JAL.'
                )

        # Communication dates: check for sensible time order
        if self.date_govreply and self.date_intervention and self.date_govreply < self.date_intervention:
            raise ValidationError(
                'Date of government reply has to be past the date of intervention.'
            )
        if self.date_intervention and self.date_incident and self.date_intervention < self.date_incident:
            raise ValidationError(
                'Date of intervention has to be past the date of the incident.'
            )
        if self.date_govreply and self.date_incident and self.date_govreply < self.date_incident:
            raise ValidationError(
                'Date of government reply has to be past the date of the incident.'
            )

        # Violations: Auto-add top-level entries when sub-cat is selected
        if not "AD" in self.violations:
            if any(True for x in self.violations if x in ["IC", "PC", "RT"]):
                self.violations.append("AD")
        if not "KA" in self.violations:
            if any(True for x in self.violations if x in ["KK", "K"]):
                self.violations.append("KA")
        if not "P" in self.violations:
            if any(True for x in self.violations if x in ["UT", "C"]):
                self.violations.append("P")

        if not "AD" in self.violations2:
            if any(True for x in self.violations2 if x in ["IC", "PC", "RT"]):
                self.violations2.append("AD")
        if not "KA" in self.violations2:
            if any(True for x in self.violations2 if x in ["KK", "K"]):
                self.violations2.append("KA")
        if not "P" in self.violations2:
            if any(True for x in self.violations2 if x in ["UT", "C"]):
                self.violations2.append("P")

        if not "AD" in self.violations3:
            if any(True for x in self.violations3 if x in ["IC", "PC", "RT"]):
                self.violations3.append("AD")
        if not "KA" in self.violations3:
            if any(True for x in self.violations3 if x in ["KK", "K"]):
                self.violations3.append("KA")
        if not "P" in self.violations3:
            if any(True for x in self.violations3 if x in ["UT", "C"]):
                self.violations3.append("P")

        if not "AD" in self.violations4:
            if any(True for x in self.violations4 if x in ["IC", "PC", "RT"]):
                self.violations4.append("AD")
        if not "KA" in self.violations4:
            if any(True for x in self.violations4 if x in ["KK", "K"]):
                self.violations4.append("KA")
        if not "P" in self.violations4:
            if any(True for x in self.violations4 if x in ["UT", "C"]):
                self.violations4.append("P")

        # Fill geolocation:
        self.get_coordinates()

    def save(self, *args, **kwargs):
        self.clean()
        super(Record, self).save(*args,
                                 **kwargs)  # Call the "real" save() method.

    # Choices for select boxes

    GENDER_CHOICES = ((0, _("Male")), (1, _("Female")), (2, _("Trans/inter*")),
                      (3, _("Gender unclear")))

    ISSUE_CHOICES = (
        ("?", _("N/A")),
        ("WR", _("Women's rights")),
        ("CRS", _("Children's rights")),
        ("IPR", _("Indigenous peoples' rights")),
        ("LGBTI", _("LGBTI issues")),
        ("MRR", _("Migrants'/refugees'/IDP's rights")),
        ("MR", _("Ethnic minorities' rights")),
        ("LR", _("Labour rights")),
        ("POV", _("Poverty/social welfare")),
        ("RTF", _("Right to food/water")),
        ("HI", _("Health issues")),
        ("RE", _("Right to education")),
        ("HRFE", _("Housing rights/forced evictions")),
        ("LNR", _("Land rights/environment")),
        ("CR", _("Cultural rights")),
        ("RF", _("Religious freedom")),
        ("PR", _("Prisoner's rights")),
        ("AT", _("Torture")),
        ("DP", _("Death penalty")),
        ("ED", _("Enforced disappearance")),
        ("H", _("Homocide")),
        ("PV", _("Police/military violence")),
        ("NSV", _("Non-state violence")),
        ("AC", _("Corruption")),
        ("DV", _("Democratic/voting rights")),
        ("JI", _("Judicial independence")),
        ("IF", _("Internet freedom")),
        ("HRE", _("Human rights education")),
        ("TJ", _("Transitional justice")),
        ("PA", _("Peace activism")),
        ("AR", _("Anti-racism")),
        ("RP", _("Right to privacy")),
    )

    ACTIVITIES_CHOICES = (
        ("?", _("N/A")),
        ("CSA", _("Civil society activist")),
        ("TUA", _("Trade union activist")),
        ("RA", _("Religious association")),
        ("PM", _("Politician/Party member")),
        ("CL", _("Community leader")),
        ("L", _("Lawyer/Judge/Attorney")),
        ("J", _("Journalist/Editor")),
        ("CA", _("Cyberactivist")),
        ("A", _("Artist/Writer")),
        ("S", _("Student")),
        ("T", _("Teacher/Professor/Scientist")),
        ("MP", _("Medical professional")),
        ("HW", _("Humanitarian worker")),
        ("V", _("Victim/witness of HR violations")),
        ("OP", _("Ombudsperson/Procuraduria/NHRI")),
        ("UN", _("UN official")),
        ("GAS", _("Government/Army/Security forces")),
        ("I", _("Investigation against officials")),
        ("PC", _("Participation in conference/meeting")),
        ("PP", _("Participation in public protest/rally")),
    )

    COOPERATION_CHOICES = (
        (0, _("Not mentioned")),
        (1, _("UN")),
        (2, _("INGO/other IO")),
    )

    LOCATION_CHOICES = (("C", _("Capital")), ("T", _("City/Town")),
                        ("R", _("Rural area")), ("A", _("Abroad")),
                        ("?", _("Unknown")))

    VIOLATION_FAMILY_CHOICES = (
        (0, _("Only HRD")),
        (1, _("against relative")),
        (2, _("against both")),
    )

    VIOLATIONS_CHOICES = (
        ("?", _("N/A")),
        ("AD", _("Arrest/Detention")),
        ("IC", _("Incommunicado")),
        ("PC", _("Held in poor conditions")),
        ("RT", _("Risk of torture")),
        ("TI", _("Torture/Ill-treatment")),
        ("ED", _("Enforced disappearance")),
        ("KA", _("Physical attack")),
        ("KK", _("Killing attempt")),
        ("K", _("Killing")),
        ("DI", _("Kidnapping")),
        ("P", _("Trial")),
        ("UT", _("Unfair trial")),
        ("C", _("Conviction")),
        ("T", _("Threats")),
        ("S", _("Surveillance")),
        ("R", _("Office/home raided")),
        ("PD", _("Property stolen/confiscated/destroyed")),
        ("DC", _("Defamation campaign")),
        ("DP", _("Disciplinary proceedings")),
        ("B", _("Travel restrictions")),
        ("A", _("Access denied")),
        ("VD", _("Expulsion/Visa denied")),
        ("AH", _("Administrative harassment")),
        ("FI", _("Failure to intervene/protect")),
        ("CR", _("Citizenship revoked")),
    )

    PERPETRATOR_CHOICES = (
        ("U", _("Unknown")),
        ("P", _("Police/security forces")),
        ("CS", _("Public official/administration/judiciary")),
        ("A", _("Army")),
        ("AO", _("Armed opposition")),
        ("B", _("Business/landholder")),
        ("M", _("Mob")),
        ("PM", _("Paramilitary group")),
        ("PP", _("Private person")),
        ("RA", _("Religious authority")),
    )

    INTERVENTION_CHOICES = (
        ("?", _("N/A")),
        ("UA", _("UA")),
        ("JUA", _("JUA")),
        ("AL", _("AL")),
        ("JAL", _("JAL")),
        ("PR", _("PR")),
    )

    JOINT_CHOICES = (
        ("FrASSEM", _("FrASSEM")),
        ("FrEXPRESS", _("FrEXPRESS")),
        ("TORTURE", _("TORTURE")),
        ("WGAD", _("WGAD")),
        ("WGED", _("WGED")),
        ("SumEXECU", _("SumEXECU")),
        ("WOMEN", _("WOMEN")),
        ("FrRELIGION", _("FrRELIGION")),
        ("JUDGES", _("JUDGES")),
        ("INDIGENOUS", _("INDIGENOUS")),
        ("TERRORISM", _("TERRORISM")),
        ("BUSINESS", _("BUSINESS")),
        ("HEALTH", _("HEALTH")),
        ("ENVIR", _("ENVIR")),
        ("FOOD", _("FOOD")),
        ("CHILD", _("CHILD")),
        ("RACISM", _("RACISM")),
        ("HOUSING", _("HOUSING")),
        ("MINORITY", _("MINORITY")),
        ("EDUCATION", _("EDUCATION")),
        ("MIGRANTS", _("MIGRANTS")),
        ("WASTE", _("WASTE")),
        ("IDPs", _("IDPs")),
        ("WG_WOMEN", _("WG_WOMEN")),
        ("MERCENARIES", _("MERCENARIES")),
        ("TRUTH", _("TRUTH")),
        ("POVERTY", _("POVERTY")),
        ("CULTURE", _("CULTURE")),
        ("ELDERLY", _("ELDERLY")),
        ("SLAVERY", _("SLAVERY")),
        ("WATER", _("WATER")),
        ("AFRICAN", _("AFRICAN")),
        ("DISCAPA", _("DISCAPA")),
        ("SOLIDAR", _("SOLIDAR")),
        ("INTORDER", _("INT'ORDER")),
        ("TRAFFIC", _("TRAFFIC")),
        ("PRIVACY", _("PRIVACY")),
        ("DEBT", _("DEBT")),
        ("SOGI", _("SOGI")),
        ("specific", _("Country-specific")),
    )

    CONCERN_CHOICES = (
        ("CV", _("Concern over violation")),
        ("PV", _("Concern: Pattern of violation")),
        ("PM", _("Demand: Protection measures")),
        ("II", _("Demand: Independent investigation")),
        ("PI", _("Demand: Provide information")),
        ("RD", _("Demand: Release detainee")),
    )

    GOV_REPLY_CHOICES = (
        ("reject", _("Violation rejected")),
        ("incomp", _("Reponsive but incomplete")),
        ("immat", _("Immaterial response")),
        ("react", _("Steps taken to address")),
        ("transl", _("In translation")),
        ("na", _("File not available")),
    )

    GOV_ACTION_CHOICES = (
        ("protect", _("Protection measures granted")),
        ("release", _("Individual released early")),
        ("notrial", _("Individual released without trial")),
        ("improve", _("Improved prison conditions")),
        ("investigate", _("Investigation opened")),
        ("prosecuted", _("Perpetrator suspended/prosecuted")),
        ("issued", _("Travel documents issued")),
        ("other", _("Other")),
    )

    SOURCES_CHOICES = (
        ("NGO", _("INGO")),
        ("RNGO", _("RNGO")),
        ("LNGO", _("LNGO")),
        ("GOV", _("GOV")),
        ("IO", _("IO")),
        ("IND", _("Indiv.")),
    )

    # Data model implementation

    person_id = models.CharField(
        max_length=13,
        verbose_name=_("Person ID"),
        unique=True,
        validators=[
            int_list_validator(sep='-', message=None, code='invalid'),
            MinLengthValidator(13, message=None)
        ],
        help_text=
        _("Form YYYY-CCCC-PPP, where YYYY is the year of publication, CCCC is the paragraph number given in the report, and PPP the person number within the communication"
          ))
    ohchr_case = models.CharField(max_length=20,
                                  blank=True,
                                  verbose_name=_("OHCHR case no."))
    country = CountryField(blank_label=_('(select country)'),
                           verbose_name=_("Country"))
    date_intervention = models.DateField(
        verbose_name=_("Date of the intervention"),
        help_text=_("Format YYYY-MM-DD"),
        blank=True,
        null=True)
    type_intervention = models.CharField(
        max_length=3,
        choices=INTERVENTION_CHOICES,
        verbose_name=_("Type of intervention"))
    joint_with = SelectMultipleField(
        max_length=200,
        choices=JOINT_CHOICES,
        blank=True,
        verbose_name=_("Joint with"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"))
    name = models.CharField(max_length=500, verbose_name=_("Name of HRD"))
    gender = models.IntegerField(choices=GENDER_CHOICES,
                                 verbose_name=_("Gender"))
    follow_up_case = models.BooleanField(
        default=False, verbose_name=_("Follow-up on UN case"))
    follow_ups = models.ManyToManyField('self',
                                        default=None,
                                        blank=True,
                                        verbose_name="Follow-up Person IDs")
    earlier_coms = models.CharField(blank=True,
                                    max_length=500,
                                    verbose_name=_("Date(s) of earlier coms"))
    regional_case = models.BooleanField(
        default=False, verbose_name=_("Regional mechanism case"))
    issue_area = SelectMultipleField(
        max_length=20,
        choices=ISSUE_CHOICES,
        max_choices=3,
        default="?",
        verbose_name=_("Issue area"),
        help_text=_("Select maximum 3 items with <i>Ctrl+Click</i>"))
    relevant_activities = SelectMultipleField(
        max_length=15,
        choices=ACTIVITIES_CHOICES,
        max_choices=3,
        default="?",
        verbose_name=_("Relevant activities"),
        help_text=_("Select maximum 3 items with <i>Ctrl+Click</i>"))
    affiliation = models.CharField(blank=True,
                                   max_length=500,
                                   verbose_name=_("Affiliation"))
    further_info = models.TextField(
        blank=True,
        verbose_name=_("Further information"),
        help_text=
        _("Name of NGO or party, title of conference, object of investigation etc."
          ))
    foreign_national = models.BooleanField(default=False,
                                           verbose_name=_("Foreign national"))
    international_cooperation = models.IntegerField(
        choices=COOPERATION_CHOICES,
        default=0,
        verbose_name=_("International cooperation"))
    location = models.CharField(max_length=1,
                                choices=LOCATION_CHOICES,
                                default="?",
                                verbose_name=_("Location"))
    name_area = models.CharField(max_length=500,
                                 blank=True,
                                 verbose_name=_("Name of City / Area"))
    violation_family = models.IntegerField(
        choices=VIOLATION_FAMILY_CHOICES,
        default=0,
        verbose_name=_("Violation against HRD or family member?"))
    violation_family_who = models.CharField(
        max_length=500, blank=True, verbose_name=_("Concerned family member"))
    violations = SelectMultipleField(
        max_length=50,
        choices=VIOLATIONS_CHOICES,
        default="?",
        verbose_name=_("Violation(s)"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"))
    perpetrator = SelectMultipleField(
        max_length=10,
        choices=PERPETRATOR_CHOICES,
        default="U",
        verbose_name=_("Alleged perpetrator"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"))
    violations2 = SelectMultipleField(
        max_length=50,
        choices=VIOLATIONS_CHOICES,
        verbose_name=_("Violation(s) #2"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    perpetrator2 = SelectMultipleField(
        max_length=10,
        choices=PERPETRATOR_CHOICES,
        verbose_name=_("Alleged perpetrator #2"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    violations3 = SelectMultipleField(
        max_length=50,
        choices=VIOLATIONS_CHOICES,
        verbose_name=_("Violation(s) #3"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    perpetrator3 = SelectMultipleField(
        max_length=10,
        choices=PERPETRATOR_CHOICES,
        verbose_name=_("Alleged perpetrator #3"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    violations4 = SelectMultipleField(
        max_length=50,
        choices=VIOLATIONS_CHOICES,
        verbose_name=_("Violation(s) #4"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    perpetrator4 = SelectMultipleField(
        max_length=10,
        choices=PERPETRATOR_CHOICES,
        verbose_name=_("Alleged perpetrator #4"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)
    date_incident = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Date of the latest incident"),
        help_text=_("Format YYYY-MM-DD"))
    date_incident_unspecific = models.CharField(
        max_length=500, blank=True, verbose_name=_("If unspecific"))
    concern_expressed = models.CharField(
        max_length=2,
        choices=CONCERN_CHOICES,
        verbose_name=_("Concern/demand expressed in intervention"),
        blank=True)
    is_released = models.BooleanField(default=False,
                                      verbose_name=_("If arrested: released?"))

    ##########################

    date_govreply = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Date of government reply"),
        help_text=_('Format YYYY-MM-DD, leave empty for "No response"'))
    date_govreply_further = models.CharField(
        max_length=500,
        blank=True,
        verbose_name=_("Date(s) of further replies"))
    govreply_content = models.CharField(
        max_length=6,
        choices=GOV_REPLY_CHOICES,
        verbose_name=_("Content of government reply"),
        help_text=_("According to rating criteria by Piccone (2012)"),
        blank=True)
    date_govaction = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Date of action according to reply"),
        help_text=_("Format YYYY-MM-DD"))
    govreply_action = models.CharField(
        max_length=11,
        choices=GOV_ACTION_CHOICES,
        verbose_name=_("Action taken according to reply"),
        blank=True)

    ##########################

    further_comments = models.TextField(
        blank=True,
        verbose_name=_("Further comments"),
        help_text=_(
            "Observations that might be relevant but don't fit elsewhere"))

    feedback = models.TextField(
        blank=True,
        verbose_name=_("Feedback"),
        help_text=_("Direct feedback on the coding of this particular case"))

    upload = models.FileField(upload_to=update_filename,
                              null=True,
                              blank=True,
                              verbose_name=_("Uploads"))

    analyst = models.ForeignKey(
        User,
        blank=True,
        null=True,
        verbose_name=_("Analyst"),
        help_text=_("User responsible for this record"))

    is_final = models.BooleanField(default=False, verbose_name=_("Final"))

    business_case = models.BooleanField(
        default=False, verbose_name=_("Business-related case"))

    business_company = models.CharField(blank=True,
                                        max_length=500,
                                        verbose_name=_("Name of company"))

    sources_number = models.CharField(blank=True,
                                      max_length=50,
                                      verbose_name=_("Number of sources"))

    sources_type = SelectMultipleField(
        max_length=50,
        choices=SOURCES_CHOICES,
        verbose_name=_("Type of sources"),
        help_text=_("Select multiple items with <i>Ctrl+Click</i>"),
        blank=True)

    complaint_sent = models.DateField(null=True,
                                      blank=True,
                                      verbose_name=_("Complaint sent on"),
                                      help_text=_("Format YYYY-MM-DD"))

    complaint_received = models.DateField(
        null=True,
        blank=True,
        verbose_name=_("Complaint received on"),
        help_text=_("Format YYYY-MM-DD"))

    coords = PointField(blank=True,
                        null=True,
                        editable=False,
                        verbose_name=_("Coordinates"))

    def has_related_object(self):
        return hasattr(self, 'followup')

    def get_geoname(self):
        return "%s" % (
            self.country.name
        ) if not self.name_area or self.location == 'A' else "%s, %s" % (
            self.name_area, self.country.name)

    def get_coordinates(self):
        geolocator = Nominatim()
        try:
            loc = geolocator.geocode(self.get_geoname())
            tmp = PointField()
            tmp = {
                "type": "Point",
                "coordinates": [float(loc.longitude),
                                float(loc.latitude)]
            }

            #if tmp != self.coords:
            #print "Updated record %s: %s -> %s" % (self.person_id, "none" if not self.coords else self.coords['coordinates'], tmp['coordinates'])

            self.coords = tmp
            #print "Located record %s (%s)" % (self.person_id, unicode(self.name)) + " with: " + unicode(self.get_geoname()) + " " + str(loc.longitude) + " " + str(loc.latitude)
        except AttributeError:
            #print "Could not locate record %s (%s)" % (self.person_id, unicode(self.name)) + " with: " + unicode(self.get_geoname())
            pass
        except GeocoderServiceError:
            #print "Geocoder service error on record %s (%s)" % (self.person_id, unicode(self.name))
            pass

    # Produce list with field items:
    def get_field_list(self):
        thisrow = list()
        for field in self._meta.get_fields():
            try:
                if isinstance(field, models.ManyToManyField):
                    thisrow.append("\"" + force_bytes(
                        [p.person_id
                         for p in getattr(self, field.name).all()]) + "\"")
                elif isinstance(field, CountryField):
                    thisrow.append(
                        "\"" + force_bytes(getattr(self, field.name).alpha3) +
                        "\"")
                else:
                    thisrow.append("\"" +
                                   force_bytes(getattr(self, field.name)) +
                                   "\"")
            except:
                thisrow.append("\"\"")
        return thisrow

    def as_geojson_dict(self):
        """
        Method to return each feature in the DB as a geojson object.
        """
        if self.coords is not None:
            place = self.get_geoname()
            as_dict = {
                "type": "Feature",
                "geometry": self.coords,
                "properties": {
                    "date":
                    dateformat.format(self.date_intervention, 'F j, Y')
                    if self.date_intervention else "unknown",
                    "type":
                    self.type_intervention,
                    "location":
                    place,
                    "id":
                    self.id
                }
            }
        else:
            as_dict = {}
        return as_dict
Пример #3
0
class Property(models.Model):
    """
    Property where you find one or more trees for harvesting.
    """
    is_active = models.BooleanField(
        verbose_name=_("Is active"),
        help_text=_("This property exists and may be able to host a pick"),
        default=True)

    authorized = models.NullBooleanField(
        verbose_name=_("Authorized for this season"),
        help_text=
        _("Harvest in this property has been authorized for the current season by its owner"
          ),
        default=None)

    pending = models.BooleanField(
        verbose_name=_("Pending"),
        help_text=
        _("This property was created through a public form and needs to be validated by an administrator"
          ),
        default=True)

    pending_contact_name = models.CharField(
        verbose_name=_("Contact name"),
        help_text=_("Name of the person to be contacted for confirmation"),
        max_length=50)

    pending_contact_phone = models.CharField(
        verbose_name=_("Contact phone number"),
        help_text=_("Phone number to be used for confirmation"),
        max_length=50)

    pending_contact_email = models.EmailField(
        verbose_name=_("Contact email"),
        help_text=_("Email address to be used for confirmation"),
        null=True,
        blank=True,
    )

    pending_newsletter = models.BooleanField(
        verbose_name=_("Newsletter subscription"), default=False)

    pending_recurring = models.BooleanField(
        verbose_name=_("Recurring property signup"), default=False)

    geom = PointField(null=True, blank=True)

    owner = models.ForeignKey('member.Actor',
                              null=True,
                              blank=True,
                              verbose_name=_("Owner"))

    # FIXME: add help_text in forms.py
    trees = models.ManyToManyField(
        'TreeType',
        verbose_name=_("Fruit tree/vine type(s)"),
        help_text=
        _('Select multiple fruit types if applicable. Unknown fruit type or colour can be mentioned in the additional comments at the bottom.'
          ),
    )

    trees_location = models.CharField(verbose_name=_("Trees location"),
                                      help_text=_("Front yard or backyard?"),
                                      null=True,
                                      blank=True,
                                      max_length=200)

    trees_accessibility = models.CharField(
        verbose_name=_("Trees accessibility"),
        help_text=_("Any info on how to access the tree (eg. key, gate etc)"),
        null=True,
        blank=True,
        max_length=200)

    avg_nb_required_pickers = models.PositiveIntegerField(
        verbose_name=_("Required pickers on average"), null=True, default=1)

    public_access = models.BooleanField(
        verbose_name=_("Publicly accessible"),
        default=False,
    )

    neighbor_access = models.BooleanField(
        verbose_name=_("Access to neighboring terrain if needed"),
        default=False,
    )

    compost_bin = models.BooleanField(
        verbose_name=_("Compost bin closeby"),
        default=False,
    )

    ladder_available = models.BooleanField(
        verbose_name=_("There is a ladder available in the property"),
        default=False,
    )

    ladder_available_for_outside_picks = models.BooleanField(
        verbose_name=
        _("A ladder is available in the property and can be used for nearby picks"
          ),
        default=False,
    )

    harvest_every_year = models.BooleanField(
        verbose_name=_("Produces fruits every year"),
        default=False,
    )

    number_of_trees = models.PositiveIntegerField(
        verbose_name=_("Total number of trees/vines on this property"),
        blank=True,
        null=True)

    approximative_maturity_date = models.DateField(
        verbose_name=_("Approximative maturity date"),
        help_text=_("When is the tree commonly ready to be harvested?"),
        blank=True,
        null=True)

    fruits_height = models.PositiveIntegerField(
        verbose_name=_("Height of lowest fruits"), blank=True, null=True)

    street_number = models.CharField(verbose_name=_("Number"),
                                     max_length=10,
                                     null=True,
                                     blank=True)

    street = models.CharField(verbose_name=_("Street"),
                              max_length=50,
                              null=True,
                              blank=True)

    complement = models.CharField(verbose_name=_("Complement"),
                                  max_length=150,
                                  null=True,
                                  blank=True)

    postal_code = models.CharField(verbose_name=_("Postal code"),
                                   max_length=10,
                                   null=True,
                                   blank=True)

    publishable_location = models.CharField(
        verbose_name=_("Publishable location"),
        help_text=
        _("Aproximative location to be used in public communications (not the actual address)"
          ),
        max_length=50,
        null=True,
        blank=True)

    neighborhood = models.ForeignKey('member.Neighborhood',
                                     verbose_name=_("Neighborhood"),
                                     null=True)

    city = models.ForeignKey('member.City',
                             verbose_name=_("City"),
                             null=True,
                             default=1)

    state = models.ForeignKey('member.State',
                              verbose_name=_("Province"),
                              null=True,
                              default=1)

    country = models.ForeignKey('member.Country',
                                verbose_name=_("Country"),
                                null=True,
                                default=1)

    longitude = models.FloatField(verbose_name=_("Longitude"),
                                  null=True,
                                  blank=True)

    latitude = models.FloatField(verbose_name=_("Latitude"),
                                 null=True,
                                 blank=True)

    additional_info = models.CharField(
        verbose_name=_("Additional information"),
        help_text=_("Any additional information that we should be aware of"),
        max_length=1000,
        null=True,
        blank=True)

    changed_by = models.ForeignKey('member.AuthUser', null=True, blank=True)

    class Meta:
        verbose_name = _("property")
        verbose_name_plural = _("properties")

    def __str__(self):
        if self.street_number:
            return u"%s at %s %s" % \
               (self.owner, self.street_number, self.street)
        else:
            return u"%s at %s" % \
               (self.owner, self.street)

    @property
    def short_address(self):
        if self.street_number and self.street and self.complement:
            return "%s %s, %s" % (self.street_number, self.street,
                                  self.complement)
        elif self.street and self.street_number:
            return "%s %s" % (self.street_number, self.street)
        elif self.street and self.complement:
            return "%s, %s" % (self.street, self.complement)
        else:
            return self.street

    def get_absolute_url(self):
        return reverse_lazy('harvest:property_detail', args=[self.id])

    def get_harvests(self):
        harvests_list = Harvest.objects.filter(
            property=self).order_by('-start_date')
        return harvests_list

    def get_last_succeeded_harvest(self):
        last_harvest = Harvest.objects.filter(property=self).filter(
            status="Succeeded").order_by('-start_date')
        if last_harvest:
            return last_harvest[0]

    @property
    def get_owner_name(self):
        return self.owner.__str__()
Пример #4
0
class Event(models.Model):
    """Model to represent Event objects"""

    initiative = models.ForeignKey(
        Initiative,
        verbose_name=_("Iniciativa que organiza la actividad"),
        blank=True,
        null=True,
        help_text=_('¿Qué iniciativa organiza el evento?'))
    title = models.CharField(
        _('Título del evento'),
        max_length=200,
        blank=False,
        null=True,
        help_text=_('¿Cuál es el título del evento que quieres organiza?'))
    featured = models.BooleanField(
        _('Destacado'),
        blank=True,
        default=False,
        help_text=_('Indica si es un evento destacado'))
    description = models.TextField(_('Describe el evento'),
                                   blank=False,
                                   null=True,
                                   help_text=_('Describe el evento.'))
    image = models.ImageField(
        _("Imagen"),
        blank=True,
        validators=[validate_image_size, validate_image_type],
        upload_to=events_images_path,
        help_text=
        _("Sube una imagen representativa del evento haciendo click en la imagen inferior. "
          "La imagen ha de tener ancho mínimo de 300 píxeles y máximo de 1920, y altura mínima "
          "de 300 píxeles y máxima de 1280. Formatos permitidos: PNG, JPG, JPEG."
          ))
    image_medium = ImageSpecField(
        source="image",
        processors=[processors.ResizeToFill(600, 300)],
        format='JPEG',
        options={'quality': 90})
    video = models.CharField(
        _('Video'),
        max_length=200,
        blank=True,
        null=True,
        help_text=_('Inserta la url de un video de Youtube o Vimeo'))
    website = models.URLField(
        _('Enlace'),
        blank=True,
        null=True,
        help_text=_(
            'Especifica opcionalmente un enlace para conocer mejor el evento.')
    )
    topic = models.CharField(_('Temática del evento'),
                             blank=False,
                             null=False,
                             default='DC',
                             max_length=2,
                             choices=categories.TOPICS,
                             help_text=_('El tema de la actividad'))
    category = models.CharField(
        _('Tipo de actividad'),
        blank=False,
        null=False,
        default='AU',
        max_length=2,
        choices=categories.ACTIVITIES,
        help_text=_('El tipo de actividad que quieres organizar'))
    agent = models.CharField(
        _('tipo de agente'),
        blank=False,
        null=False,
        default='IM',
        max_length=2,
        choices=categories.AGENTS,
        help_text=_('El tipo de agente involucrado en la actividad'))
    date = models.DateField(
        _('Fecha del evento'),
        help_text=_('Indica qué día se celebra o empieza el evento'))
    time = models.TimeField(_('Hora del evento'),
                            help_text=_('¿A qué hora se celebra el evento?'))
    periodicity = models.CharField(
        _('Periodicidad'),
        max_length=200,
        blank=True,
        null=True,
        help_text=
        _('Especifica, en ese caso, la periodicidad del evento. Puedes indicar la fecha de fin en el siguiente campo'
          ))
    expiration = models.DateField(
        _('Fecha de fin'),
        blank=True,
        null=True,
        help_text=
        _('Indica opcionalmente en eventos de varios dias la fecha en que acaba el evento.'
          ))
    city = models.ForeignKey(
        City,
        verbose_name=_('Ciudad'),
        blank=False,
        null=True,
        on_delete=models.SET_NULL,
        help_text=
        _('Ciudad donde se encuentra la iniciativa. Si no la encuentras en la lista puedes añadir una nueva.'
          ))
    address = models.CharField(
        _('Dirección'),
        max_length=200,
        blank=False,
        null=True,
        help_text=
        _('Dirección de la iniciativa. No es necesario que vuelvas a introducir la ciudad de la iniciativa.'
          ))
    position = PointField(
        _("Ubicación"),
        blank=False,
        null=True,
        help_text=
        _("Añade la ubicación de la actividad. Si lo dejas en blanco se usará la ubicación de la iniciativa asociada."
          ))
    facebook_id = models.CharField(max_length=128, blank=True, null=True)
    google_id = models.CharField(max_length=128, blank=True, null=True)
    slug = models.SlugField(editable=False, blank=True)
    creation_date = models.DateField(editable=False, default=timezone.now)

    class Meta:
        verbose_name = _('Actividad')
        verbose_name_plural = _('Actividades')

    def __str__(self):
        """String representation of this model objects."""
        return self.title or '---'

    def save(self, *args, **kwargs):
        """Populate automatically 'slug' field"""
        self.slug = slugify(self.title)
        # Notify by mail, only when creating new content
        if not self.id:
            send_mail(
                'Creado el evento \"' + self.title + "\"",
                'Creado el ' + self.creation_date.strftime("%d/%b/%Y") +
                ' por "' + self.initiative.name + '" (' +
                self.initiative.email + ')\n---\n' + self.title + ':\n' +
                self.description + '\n---\n' + 'Ciudad: ' + self.city.name,
                'civics.cc <*****@*****.**>',
                settings.NOTIFICATIONS_EMAILS,
                fail_silently=False,
            )
        super(Event, self).save(*args, **kwargs)

    def edit_permissions(self, user):
        """Returns users allowed to edit an instance of this model."""
        if user.is_staff or (self.initiative and self.initiative.user
                             and self.initiative.user == user):
            return True
        return False
Пример #5
0
class Tree(models.Model):
    EMERGENTE = 'Emergente'
    DOMINANTE = 'Dominante'
    CODOMINANTE = 'Codominante'
    INTERMEDIA = 'Intermedia'
    INFERIOR_SUPRIMIDO = 'Inferior suprimido'
    INFERIOR_SUMERGIDO = 'Inferior sumergido'
    SOCIOLOGICAL_CLASSIFICATION_CHOICES = [
        (EMERGENTE, 'Emergente'),
        (DOMINANTE, 'Dominante'),
        (CODOMINANTE, 'Codominante'),
        (INTERMEDIA, 'Intermedia'),
        (INFERIOR_SUPRIMIDO, 'Inferior Suprimido'),
        (INFERIOR_SUMERGIDO, 'Supeior Sumergido'),
    ]

    BUENO = 'Bueno'
    REGULAR = 'Regular'
    MALO = 'Malo'
    MUERTO = 'Muerto'
    PHYTOSANITARY_STATUS_CHOICES = [
        (BUENO, 'Bueno'),
        (REGULAR, 'Regular'),
        (MALO, 'Malo'),
        (MUERTO, 'Muerto')
    ]

    field = models.ForeignKey('FieldWork', on_delete=models.CASCADE)
    tree_id = models.IntegerField(verbose_name='ID Árbol') # todo ID Árbol: N colecta nombre subparcela (SY) o 2 numeros y cuatro letras o tres numeros y cuatro letras
    specie = models.CharField(verbose_name='Nombre especie', max_length=100)
    dap = models.FloatField(verbose_name='DAP', help_text='cm')
    dab = models.FloatField(verbose_name='DAB', help_text='cm')
    tree_height = models.FloatField(verbose_name='Altura del árbol', help_text='m', validators = [tree_height_validation])
    latitude = models.FloatField(verbose_name='latitud', validators=[validate_lat], help_text="informar en formato graus decimais WGS84")
    longitude = models.FloatField(verbose_name='longitud', validators=[validate_lon])
    picture = models.ForeignKey(Pictures, on_delete=models.CASCADE, blank=True, null = True)
    obs = models.TextField(verbose_name="Observaciones", blank=True)
    phytosanitary_status = models.CharField(max_length=100,
                                            choices=PHYTOSANITARY_STATUS_CHOICES,
                                            default=BUENO)
    sociological_classification = models.CharField(verbose_name='clasificación sociologica',
                                                   max_length=100,
                                                   choices=SOCIOLOGICAL_CLASSIFICATION_CHOICES,
                                                   default=EMERGENTE)
    geom = PointField(blank=True)

    class Meta:
        verbose_name = 'Árbol'
        verbose_name_plural = 'Árboles'

    def __str__(self):
        return f'{self.specie} {self.field.date}'

    def get_absolute_url(self):
        return reverse_lazy('imibio_tree_ecological_data:detail', kwargs={'pk': self.pk})

    @property
    def popup_content(self): # todo Me parece que lo importante es poner alguna foto
        popup = "<strong><span>Nombre científico: </span>{}</strong></p>".format(
            self.specie)
        popup += "<span>Condición fitosanitario: </span>{}<br>".format(
            self.phytosanitary_status)
        popup += "<span>Altura: </span>{}<br>".format(
            self.tree_height)
        popup += f"<span><a href={self.get_absolute_url()}>Detalles de la occurrencia</a></strong><br>"
        return popup
Пример #6
0
class LugarVotacion(models.Model):
    circuito = models.ForeignKey(Circuito,
                                 related_name='escuelas',
                                 on_delete=models.CASCADE)
    nombre = models.CharField(max_length=100)
    direccion = models.CharField(max_length=100)
    barrio = models.CharField(max_length=100, blank=True)
    ciudad = models.CharField(max_length=100, blank=True)
    calidad = models.CharField(max_length=20,
                               help_text='calidad de la geolocalizacion',
                               editable=False,
                               blank=True)
    electores = models.PositiveIntegerField(null=True, blank=True)
    geom = PointField(null=True)
    estado_geolocalizacion = models.PositiveIntegerField(
        default=0,
        help_text='Indicador (0-10) de que confianza hay en la geolozalización'
    )

    # denormalizacion para hacer queries más simples
    latitud = models.FloatField(null=True, editable=False)
    longitud = models.FloatField(null=True, editable=False)

    class Meta:
        verbose_name = 'Lugar de votación'
        verbose_name_plural = "Lugares de votación"

    def save(self, *args, **kwargs):

        if self.geom:
            self.longitud, self.latitud = self.geom['coordinates']
        else:
            self.longitud, self.latitud = None, None
        super().save(*args, **kwargs)

    @property
    def coordenadas(self):
        return f'{self.latitud},{self.longitud}'

    @property
    def direccion_completa(self):
        return f'{self.direccion} {self.barrio} {self.ciudad}'

    @property
    def mesas_desde_hasta(self):
        qs = self.mesas
        qs = qs.values_list('numero', flat=True).order_by('numero')
        inicio, fin = qs.first(), qs.last()
        if inicio == fin:
            return inicio
        return f'{inicio} - {fin}'

    def mesas(self, eleccion):
        return Mesa.objects.filter(lugar_votacion=self, eleccion=eleccion)

    @property
    def mesas_actuales(self):
        return self.mesas.filter(eleccion=Eleccion.actual())

    @property
    def color(self):
        if VotoMesaReportado.objects.filter(
                mesa__lugar_votacion=self).exists():
            return 'green'
        return 'orange'

    @property
    def seccion(self):
        return str(self.circuito.seccion)

    def __str__(self):
        return f"{self.nombre} - {self.circuito}"
Пример #7
0
class Barangay(models.Model):
    name = models.CharField(max_length=20)
    geom = PointField()

    def __str__(self):
        return self.name
Пример #8
0
class Event(models.Model):
    """Reference event model."""

    title = models.CharField(verbose_name=_("title"), max_length=400)

    description = models.TextField(verbose_name=_("description"))

    read_time = models.IntegerField(default=0, verbose_name=_("read time"))

    slug = models.SlugField(verbose_name=_("slug"), unique=True, blank=True)

    event_date = models.DateTimeField(verbose_name=_("event date"))

    total_guest = models.PositiveIntegerField(verbose_name=_("total of guest"),
                                              default=1)

    hosted_by = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        verbose_name=_("hosted by"),
        on_delete=models.CASCADE,
        related_name="events",
        db_index=True,
    )

    cover = models.ImageField(verbose_name=_("cover"),
                              blank=True,
                              null=True,
                              upload_to=event_upload_to)

    tags = models.ManyToManyField(to=Tag,
                                  verbose_name=_("tags"),
                                  related_name="events",
                                  blank=True)

    organizers = models.ManyToManyField(
        to=settings.AUTH_USER_MODEL,
        verbose_name=_("organizers"),
        related_name="events_organizers",
        blank=True,
    )

    created_at = models.DateTimeField(verbose_name=_("created at"),
                                      auto_now_add=True)

    updated_at = models.DateTimeField(verbose_name=_("updated at"),
                                      auto_now=True)

    geom = PointField(verbose_name=_("geo location"))

    class Meta:
        """Meta data."""

        verbose_name = _("event")

        verbose_name_plural = _("events")

    def __str__(self: "Event") -> str:
        """It return readable name for the model."""
        return f"{self.title}"

    def total_attendees(self: "Event") -> int:
        """Getting total of attendees for the event."""
        return self.attendees.count()

    def available_place(self: "Event") -> int:
        """Getting total of available place for the event."""
        return self.total_guest - self.attendees.count()

    def total_attended(self: "Event") -> int:
        """Getting total of people who actual attended for the event."""
        return self.attendees.filter(has_attended=True).count()

    def total_not_attended(self: "Event") -> int:
        """Getting total of people who didn't attended for the event."""
        return self.attendees.filter(has_attended=False).count()

    def total_sessions(self: "Event") -> int:
        """Getting total of sessions in event."""
        return self.sessions.count()

    def total_draft_sessions(self: "Event") -> int:
        """Getting total of draft sessions in event."""
        return self.sessions.filter(status="Draft").count()

    def total_accepted_sessions(self: "Event") -> int:
        """Getting total of accepted sessions in event."""
        return self.sessions.filter(status="Accepted").count()

    def total_denied_sessions(self: "Event") -> int:
        """Getting total of denied sessions in event."""
        return self.sessions.filter(status="Denied").count()

    def total_talk(self: "Event") -> int:
        """Getting total of talk in event."""
        return self.sessions.filter(session_type="Talk",
                                    status="Accepted").count()

    def total_lighting_talk(self: "Event") -> int:
        """Getting total of lighting talk in event."""
        return self.sessions.filter(session_type="Lighting Talk",
                                    status="Accepted").count()

    def total_workshop(self: "Event") -> int:
        """Getting total of workshop in event."""
        return self.sessions.filter(session_type="WorkShop",
                                    status="Accepted").count()

    total_sessions.short_description = _("Sessions")
    total_draft_sessions.short_description = _("Draft Sessions")
    total_accepted_sessions.short_description = _("Accepted Sessions")
    total_denied_sessions.short_description = _("Denied Sessions")
    total_talk.short_description = _("Talk")
    total_lighting_talk.short_description = _("Lighting Talk")
    total_workshop.short_description = _("Workshop")
    total_attendees.short_description = _("Attendees")
    total_attended.short_description = _("Has Attended")
    total_not_attended.short_description = _("Has Not Attended")
    available_place.short_description = _("Available Place")
Пример #9
0
class Agency(models.Model, RequestHelper):
    """An agency for a particular jurisdiction that has at least one agency type"""

    name = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255)
    jurisdiction = models.ForeignKey(Jurisdiction, related_name='agencies')
    types = models.ManyToManyField(AgencyType, blank=True)
    status = models.CharField(choices=(
        ('pending', 'Pending'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
        ), max_length=8, default='pending')
    user = models.ForeignKey(User, null=True, blank=True)
    appeal_agency = models.ForeignKey('self', null=True, blank=True)
    can_email_appeals = models.BooleanField(default=False)
    payable_to = models.ForeignKey('self', related_name='receivable', null=True, blank=True)
    image = ThumbnailerImageField(
        upload_to='agency_images',
        blank=True,
        null=True,
        resize_source={'size': (900, 600), 'crop': 'smart'}
    )
    image_attr_line = models.CharField(blank=True, max_length=255, help_text='May use html')
    public_notes = models.TextField(blank=True, help_text='May use html')
    stale = models.BooleanField(default=False)
    manual_stale = models.BooleanField(default=False,
        help_text='For marking an agency stale by hand.')
    address = models.TextField(blank=True)
    location = PointField(blank=True)
    email = models.EmailField(blank=True)
    other_emails = fields.EmailsListField(blank=True, max_length=255)
    contact_salutation = models.CharField(blank=True, max_length=30)
    contact_first_name = models.CharField(blank=True, max_length=100)
    contact_last_name = models.CharField(blank=True, max_length=100)
    contact_title = models.CharField(blank=True, max_length=255)
    url = models.URLField(blank=True, verbose_name='FOIA Web Page', help_text='Begin with http://')
    phone = models.CharField(blank=True, max_length=30)
    fax = models.CharField(blank=True, max_length=30)
    notes = models.TextField(blank=True)
    aliases = models.TextField(blank=True)
    parent = models.ForeignKey('self', null=True, blank=True, related_name='children')

    website = models.CharField(max_length=255, blank=True)
    twitter = models.CharField(max_length=255, blank=True)
    twitter_handles = models.TextField(blank=True)
    foia_logs = models.URLField(blank=True, verbose_name='FOIA Logs',
                                help_text='Begin with http://')
    foia_guide = models.URLField(blank=True, verbose_name='FOIA Processing Guide',
                                 help_text='Begin with http://')
    exempt = models.BooleanField(default=False)
    requires_proxy = models.BooleanField(default=False)

    objects = AgencyQuerySet.as_manager()

    def __unicode__(self):
        return self.name

    def get_absolute_url(self):
        """The url for this object"""
        return host_reverse(
                'agency-detail',
                host='default',
                kwargs={
                    'jurisdiction': self.jurisdiction.slug,
                    'jidx': self.jurisdiction.pk,
                    'slug': self.slug,
                    'idx': self.pk,
                    })

    def save(self, *args, **kwargs):
        """Save the agency"""
        self.email = self.email.strip()
        self.slug = slugify(self.slug)
        self.name = self.name.strip()
        super(Agency, self).save(*args, **kwargs)

    def normalize_fax(self):
        """Return a fax number suitable for use in a faxaway email address"""

        fax = ''.join(c for c in self.fax if c.isdigit())
        if len(fax) == 10:
            return '1' + fax
        if len(fax) == 11 and fax[0] == '1':
            return fax
        return None

    def get_email(self):
        """Returns an email address to send to"""

        if self.email:
            return self.email
        elif self.normalize_fax():
            return '*****@*****.**' % self.normalize_fax()
        else:
            return ''

    def get_other_emails(self):
        """Returns other emails as a list"""
        return fields.email_separator_re.split(self.other_emails)

    def link_display(self):
        """Returns link if approved"""
        if self.status == 'approved':
            return mark_safe('<a href="%s">%s</a>' % (self.get_absolute_url(), self.name))
        else:
            return self.name

    def is_stale(self):
        """Should this agency be marked as stale?

        If the latest response to any open request is greater than STALE_DURATION
        days ago, or if no responses to any open request, if the oldest open
        request was sent greater than STALE_DURATION days ago.  If no open requests,
        do not mark as stale."""
        # check if agency is manually marked as stale
        if self.manual_stale:
            return True
        # find any open requests, if none, not stale
        foias = self.foiarequest_set.get_open().order_by('date_submitted')
        if not foias:
            return False
        # find the latest response to an open request
        latest_responses = []
        for foia in foias:
            response = foia.latest_response()
            if response:
                latest_responses.append(response)
        if latest_responses:
            return min(latest_responses) >= STALE_DURATION
        # no response to open requests, use oldest open request submit date
        return (date.today() - foias[0].date_submitted).days >= STALE_DURATION

    def mark_stale(self, manual=False):
        """Mark this agency as stale and create a StaleAgencyTask if one doesn't already exist."""
        self.stale = True
        self.manual_stale = manual
        self.save()
        try:
            task, created = StaleAgencyTask.objects.get_or_create(resolved=False, agency=self)
            if created:
                logger.info('Created new StaleAgencyTask <%d> for Agency <%d>', task.pk, self.pk)
        except MultipleObjectsReturned as exception:
            # If there are multiple StaleAgencyTasks returned, just return the first one.
            # We only want this method to return a single task.
            # Also, log the exception as a warning.
            task = StaleAgencyTask.objects.filter(resolved=False, agency=self).first()
            logger.warning(exception)
        return task

    def unmark_stale(self):
        """Unmark this agency as stale and resolve all of its StaleAgencyTasks."""
        self.stale = False
        self.manual_stale = False
        self.save()

    def count_thanks(self):
        """Count how many thanks this agency has received"""
        return (self.foiarequest_set
                .filter(communications__thanks=True)
                .distinct()
                .count())

    def get_requests(self):
        """Just returns the foiareqest_set value. Used for compatability with RequestHeper mixin"""
        return self.foiarequest_set

    class Meta:
        # pylint: disable=too-few-public-methods
        verbose_name_plural = 'agencies'
Пример #10
0
class LugarVotacion(models.Model):
    """
    Define el lugar de votación (escuela) que pertenece a un circuito
    y contiene mesas.
    Tiene un representación geoespacial (point).

    Sección -> Circuito -> **Lugar de votación** -> Mesa
    """

    circuito = models.ForeignKey(Circuito,
                                 related_name='escuelas',
                                 on_delete=models.CASCADE)
    nombre = models.CharField(max_length=100)
    direccion = models.CharField(max_length=100)
    barrio = models.CharField(max_length=100, blank=True)
    ciudad = models.CharField(max_length=100, blank=True)

    # electores es una denormalización. debe coincidir con la sumatoria de
    # los electores de cada mesa de la escuela
    electores = models.PositiveIntegerField(null=True, blank=True)
    geom = PointField(null=True)

    # A veces, al importar datos, se realizan distintas iteraciones para geolocalizar
    # escuelas. Estos campos sirven para cuantificar la calidad y poder filtrar para
    # mejorar los valores de menor confianza
    estado_geolocalizacion = models.PositiveIntegerField(
        default=0,
        help_text='Indicador (0-10) de que confianza hay en la geolozalización'
    )
    calidad = models.CharField(max_length=20,
                               help_text='calidad de la geolocalizacion',
                               editable=False,
                               blank=True)
    # denormalizacion para hacer queries más simples
    # se sincronizan con ``geom`` en el método save()
    latitud = models.FloatField(null=True, editable=False)
    longitud = models.FloatField(null=True, editable=False)

    class Meta:
        verbose_name = 'Lugar de votación'
        verbose_name_plural = "Lugares de votación"

    def save(self, *args, **kwargs):

        if self.geom:
            self.longitud, self.latitud = self.geom['coordinates']
        else:
            self.longitud, self.latitud = None, None
        super().save(*args, **kwargs)

    @property
    def coordenadas(self):
        return f'{self.latitud},{self.longitud}'

    @property
    def direccion_completa(self):
        return f'{self.direccion} {self.barrio} {self.ciudad}'

    @property
    def mesas_desde_hasta(self):
        qs = self.mesas
        qs = qs.values_list('numero', flat=True).order_by('numero')
        inicio, fin = qs.first(), qs.last()
        if inicio == fin:
            return inicio
        return f'{inicio} - {fin}'

    def mesas(self, categoria):
        """
        Devuelve las mesas asociadas a este lugar de votación para una categoría dada
        """
        return Mesa.objects.filter(lugar_votacion=self, categoria=categoria)

    @property
    def mesas_actuales(self):
        return self.mesas.filter(categoria=Categoria.actual())

    @property
    def color(self):
        if VotoMesaReportado.objects.filter(
                mesa__lugar_votacion=self).exists():
            return 'green'
        return 'orange'

    @property
    def seccion(self):
        return str(self.circuito.seccion)

    def __str__(self):
        return f"{self.nombre} - {self.circuito}"
Пример #11
0
class ImibioOccurrence(models.Model):
    #author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    gbifID = models.BigIntegerField(blank=True, null=True)
    abstract = models.TextField(blank=True, null=True)
    accessRights = models.TextField(blank=True, null=True)
    accrualMethod = models.TextField(blank=True, null=True)
    accrualPeriodicity = models.TextField(blank=True, null=True)
    accrualPolicy = models.TextField(blank=True, null=True)
    alternative = models.TextField(blank=True, null=True)
    audience = models.TextField(blank=True, null=True)
    available = models.TextField(blank=True, null=True)
    bibliographicCitation = models.TextField(blank=True, null=True)
    conformsTo = models.TextField(blank=True, null=True)
    contributor = models.TextField(blank=True, null=True)
    coverage = models.TextField(blank=True, null=True)
    created = models.TextField(blank=True, null=True)
    creator = models.TextField(blank=True, null=True)
    date = models.TextField(blank=True, null=True)
    dateAccepted = models.TextField(blank=True, null=True)
    dateCopyrighted = models.TextField(blank=True, null=True)
    dateSubmitted = models.TextField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    educationLevel = models.TextField(blank=True, null=True)
    extent = models.TextField(blank=True, null=True)
    format = models.TextField(blank=True, null=True)
    hasFormat = models.TextField(blank=True, null=True)
    hasPart = models.TextField(blank=True, null=True)
    hasVersion = models.TextField(blank=True, null=True)
    identifier = models.TextField(blank=True, null=True)
    instructionalMethod = models.TextField(blank=True, null=True)
    isFormatOf = models.TextField(blank=True, null=True)
    isPartOf = models.TextField(blank=True, null=True)
    isReferencedBy = models.TextField(blank=True, null=True)
    isReplacedBy = models.TextField(blank=True, null=True)
    isRequiredBy = models.TextField(blank=True, null=True)
    isVersionOf = models.TextField(blank=True, null=True)
    issued = models.TextField(blank=True, null=True)
    language = models.TextField(blank=True, null=True)
    license = models.TextField(blank=True, null=True)
    mediator = models.TextField(blank=True, null=True)
    medium = models.TextField(blank=True, null=True)
    modified = models.TextField(blank=True, null=True)
    provenance = models.TextField(blank=True, null=True)
    publisher = models.TextField(blank=True, null=True)
    references = models.TextField(blank=True, null=True)
    relation = models.TextField(blank=True, null=True)
    replaces = models.TextField(blank=True, null=True)
    requires = models.TextField(blank=True, null=True)
    rights = models.TextField(blank=True, null=True)
    rightsHolder = models.TextField(blank=True, null=True)
    source = models.TextField(blank=True, null=True)
    spatial = models.TextField(blank=True, null=True)
    subject = models.TextField(blank=True, null=True)
    tableOfContents = models.TextField(blank=True, null=True)
    temporal = models.TextField(blank=True, null=True)
    title = models.TextField(blank=True, null=True)
    type = models.TextField(blank=True, null=True)
    valid = models.TextField(blank=True, null=True)
    institutionID = models.TextField(blank=True, null=True)
    collectionID = models.TextField(blank=True, null=True)
    datasetID = models.TextField(blank=True, null=True)
    institutionCode = models.TextField()
    collectionCode = models.TextField()
    datasetName = models.TextField(blank=True, null=True)
    ownerInstitutionCode = models.TextField(blank=True, null=True)
    basisOfRecord = models.TextField()
    informationWithheld = models.TextField(blank=True, null=True)
    dataGeneralizations = models.TextField(blank=True, null=True)
    dynamicProperties = models.TextField(blank=True, null=True)
    occurrenceID = models.TextField(blank=True, null=True)
    catalogNumber = models.TextField()
    recordNumber = models.TextField(blank=True, null=True)
    recordedBy = models.TextField(blank=True, null=True)
    individualCount = models.TextField(blank=True, null=True)
    organismQuantity = models.TextField(blank=True, null=True)
    organismQuantityType = models.TextField(blank=True, null=True)
    sex = models.TextField(blank=True, null=True)
    lifeStage = models.TextField(blank=True, null=True)
    reproductiveCondition = models.TextField(blank=True, null=True)
    behavior = models.TextField(blank=True, null=True)
    establishmentMeans = models.TextField(blank=True, null=True)
    occurrenceStatus = models.TextField(blank=True, null=True)
    preparations = models.TextField(blank=True, null=True)
    disposition = models.TextField(blank=True, null=True)
    associatedReferences = models.TextField(blank=True, null=True)
    associatedSequences = models.TextField(blank=True, null=True)
    associatedTaxa = models.TextField(blank=True, null=True)
    otherCatalogNumbers = models.TextField(blank=True, null=True)
    occurrenceRemarks = models.TextField(blank=True, null=True)
    organismID = models.TextField(blank=True, null=True)
    organismName = models.TextField(blank=True, null=True)
    organismScope = models.TextField(blank=True, null=True)
    associatedOccurrences = models.TextField(blank=True, null=True)
    associatedOrganisms = models.TextField(blank=True, null=True)
    previousIdentifications = models.TextField(blank=True, null=True)
    organismRemarks = models.TextField(blank=True, null=True)
    materialSampleID = models.TextField(blank=True, null=True)
    eventID = models.TextField(blank=True, null=True)
    parentEventID = models.TextField(blank=True, null=True)
    fieldNumber = models.TextField(blank=True, null=True)
    eventDate = models.TextField(blank=True, null=True)
    eventTime = models.TextField(blank=True, null=True)
    startDayOfYear = models.BigIntegerField(blank=True, null=True)
    endDayOfYear = models.BigIntegerField(blank=True, null=True)
    year = models.BigIntegerField(blank=True, null=True)
    month = models.BigIntegerField(blank=True, null=True)
    day = models.BigIntegerField(blank=True, null=True)
    verbatimEventDate = models.TextField(blank=True, null=True)
    habitat = models.TextField(blank=True, null=True)
    samplingProtocol = models.TextField(blank=True, null=True)
    samplingEffort = models.TextField(blank=True, null=True)
    sampleSizeValue = models.TextField(blank=True, null=True)
    sampleSizeUnit = models.TextField(blank=True, null=True)
    fieldNotes = models.TextField(blank=True, null=True)
    eventRemarks = models.TextField(blank=True, null=True)
    locationID = models.TextField(blank=True, null=True)
    higherGeographyID = models.TextField(blank=True, null=True)
    higherGeography = models.TextField(blank=True, null=True)
    continent = models.TextField(blank=True, null=True)
    waterBody = models.TextField(blank=True, null=True)
    islandGroup = models.TextField(blank=True, null=True)
    island = models.TextField(blank=True, null=True)
    countryCode = models.TextField(blank=True, null=True)
    stateProvince = models.TextField()
    county = models.TextField()
    municipality = models.TextField()
    locality = models.TextField()
    verbatimLocality = models.TextField(blank=True, null=True)
    verbatimElevation = models.TextField(blank=True, null=True)
    verbatimDepth = models.TextField(blank=True, null=True)
    minimumDistanceAboveSurfaceInMeters = models.TextField(blank=True,
                                                           null=True)
    maximumDistanceAboveSurfaceInMeters = models.TextField(blank=True,
                                                           null=True)
    locationAccordingTo = models.TextField(blank=True, null=True)
    locationRemarks = models.TextField(blank=True, null=True)
    decimalLatitude = models.FloatField("Latitud", blank=True, null=True)
    decimalLongitude = models.FloatField("Longitud", blank=True, null=True)
    coordinateUncertaintyInMeters = models.FloatField(blank=True, null=True)
    coordinatePrecision = models.TextField(blank=True, null=True)
    pointRadiusSpatialFit = models.TextField(blank=True, null=True)
    verbatimCoordinateSystem = models.TextField(blank=True, null=True)
    verbatimSRS = models.TextField(blank=True, null=True)
    footprintWKT = models.TextField(blank=True, null=True)
    footprintSRS = models.TextField(blank=True, null=True)
    footprintSpatialFit = models.TextField(blank=True, null=True)
    georeferencedBy = models.TextField(blank=True, null=True)
    georeferencedDate = models.TextField(blank=True, null=True)
    georeferenceProtocol = models.TextField(blank=True, null=True)
    georeferenceSources = models.TextField(blank=True, null=True)
    georeferenceVerificationStatus = models.TextField(blank=True, null=True)
    georeferenceRemarks = models.TextField(blank=True, null=True)
    geologicalContextID = models.TextField(blank=True, null=True)
    earliestEonOrLowestEonothem = models.TextField(blank=True, null=True)
    latestEonOrHighestEonothem = models.TextField(blank=True, null=True)
    earliestEraOrLowestErathem = models.TextField(blank=True, null=True)
    latestEraOrHighestErathem = models.TextField(blank=True, null=True)
    earliestPeriodOrLowestSystem = models.TextField(blank=True, null=True)
    latestPeriodOrHighestSystem = models.TextField(blank=True, null=True)
    earliestEpochOrLowestSeries = models.TextField(blank=True, null=True)
    latestEpochOrHighestSeries = models.TextField(blank=True, null=True)
    earliestAgeOrLowestStage = models.TextField(blank=True, null=True)
    latestAgeOrHighestStage = models.TextField(blank=True, null=True)
    lowestBiostratigraphicZone = models.TextField(blank=True, null=True)
    highestBiostratigraphicZone = models.TextField(blank=True, null=True)
    lithostratigraphicTerms = models.TextField(blank=True, null=True)
    group = models.TextField(blank=True, null=True)
    formation = models.TextField(blank=True, null=True)
    member = models.TextField(blank=True, null=True)
    bed = models.TextField(blank=True, null=True)
    identificationID = models.TextField(blank=True, null=True)
    identificationQualifier = models.TextField(blank=True, null=True)
    typeStatus = models.TextField(blank=True, null=True)
    identifiedBy = models.TextField(blank=True, null=True)
    dateIdentified = models.TextField(blank=True, null=True)
    identificationReferences = models.TextField(blank=True, null=True)
    identificationVerificationStatus = models.TextField(blank=True, null=True)
    identificationRemarks = models.TextField(blank=True, null=True)
    taxonID = models.TextField(blank=True, null=True)
    scientificNameID = models.TextField(blank=True, null=True)
    acceptedNameUsageID = models.TextField(blank=True, null=True)
    parentNameUsageID = models.TextField(blank=True, null=True)
    originalNameUsageID = models.TextField(blank=True, null=True)
    nameAccordingToID = models.TextField(blank=True, null=True)
    namePublishedInID = models.TextField(blank=True, null=True)
    taxonConceptID = models.TextField(blank=True, null=True)
    scientificName = models.TextField()
    acceptedNameUsage = models.TextField(blank=True, null=True)
    parentNameUsage = models.TextField(blank=True, null=True)
    originalNameUsage = models.TextField(blank=True, null=True)
    nameAccordingTo = models.TextField(blank=True, null=True)
    namePublishedIn = models.TextField(blank=True, null=True)
    namePublishedInYear = models.TextField(blank=True, null=True)
    higherClassification = models.TextField(blank=True, null=True)
    kingdom = models.TextField()
    phylum = models.TextField()
    clase = models.CharField("class", max_length=254)
    order = models.TextField()
    family = models.TextField()
    genus = models.TextField()
    subgenus = models.TextField(blank=True, null=True)
    specificEpithet = models.TextField(blank=True, null=True)
    infraspecificEpithet = models.TextField(blank=True, null=True)
    taxonRank = models.TextField(blank=True, null=True)
    verbatimTaxonRank = models.TextField(blank=True, null=True)
    vernacularName = models.TextField(blank=True, null=True)
    nomenclaturalCode = models.TextField(blank=True, null=True)
    taxonomicStatus = models.TextField(blank=True, null=True)
    nomenclaturalStatus = models.TextField(blank=True, null=True)
    taxonRemarks = models.TextField(blank=True, null=True)
    datasetKey = models.TextField(blank=True, null=True)
    publishingCountry = models.TextField(blank=True, null=True)
    lastInterpreted = models.TextField(blank=True, null=True)
    elevation = models.TextField(blank=True, null=True)
    elevationAccuracy = models.TextField(blank=True, null=True)
    depth = models.FloatField(blank=True, null=True)
    depthAccuracy = models.TextField(blank=True, null=True)
    distanceAboveSurface = models.TextField(blank=True, null=True)
    distanceAboveSurfaceAccuracy = models.TextField(blank=True, null=True)
    issue = models.TextField(blank=True, null=True)
    mediaType = models.TextField(blank=True, null=True)
    hasCoordinate = models.TextField(blank=True, null=True)
    hasGeospatialIssues = models.TextField(blank=True, null=True)
    taxonKey = models.BigIntegerField(blank=True, null=True)
    acceptedTaxonKey = models.BigIntegerField(blank=True, null=True)
    kingdomKey = models.BigIntegerField(blank=True, null=True)
    phylumKey = models.BigIntegerField(blank=True, null=True)
    classKey = models.BigIntegerField(blank=True, null=True)
    orderKey = models.BigIntegerField(blank=True, null=True)
    familyKey = models.BigIntegerField(blank=True, null=True)
    genusKey = models.BigIntegerField(blank=True, null=True)
    subgenusKey = models.TextField(blank=True, null=True)
    speciesKey = models.BigIntegerField(blank=True, null=True)
    species = models.TextField(blank=True, null=True)
    genericName = models.TextField(blank=True, null=True)
    acceptedScientificName = models.TextField(blank=True, null=True)
    verbatimScientificName = models.TextField(blank=True, null=True)
    typifiedName = models.TextField(blank=True, null=True)
    protocol = models.TextField(blank=True, null=True)
    lastParsed = models.TextField(blank=True, null=True)
    lastCrawled = models.TextField(blank=True, null=True)
    repatriated = models.TextField(blank=True, null=True)
    relativeOrganismQuantity = models.TextField(blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    geom = PointField()

    class Meta:
        verbose_name_plural = 'Ocorrencias'
        verbose_name = 'Ocurrencia'
        ordering = ('-created_at', )

    def __str__(self):
        return self.scientificName

    def save(self, *args, **kwargs):
        self.geom = {
            'type': 'Point',
            'coordinates': [self.decimalLongitude, self.decimalLatitude]
        }
        super(ImibioOccurrence, self).save(*args, **kwargs)