Example #1
0
class Experiment(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    external_id = models.CharField(max_length=100, db_index=True, null=True)
    modification_date = models.DateTimeField(auto_now=True)
    creation_date = models.DateTimeField(default=timezone.now)
    airtable_json = JSONField(null=True, blank=True)

    farmer = models.ForeignKey(Farmer,
                               related_name='experiments',
                               on_delete=models.CASCADE,
                               null=True)
    approved = models.BooleanField(default=False, db_index=True)
    tags = ChoiceArrayField(models.CharField(max_length=255, choices=TAGS),
                            default=list,
                            blank=True,
                            null=True)
    name = models.TextField()
    objectives = models.TextField(null=True, blank=True)
    equipment = models.TextField(null=True, blank=True)
    control_presence = models.BooleanField(null=True, blank=True)
    ongoing = models.BooleanField(null=True, blank=True)
    results = models.TextField(null=True, blank=True, choices=RESULTS)
    results_details = models.TextField(null=True, blank=True)
    links = ArrayField(models.TextField(), default=list, blank=True, null=True)
    description = models.TextField(null=True, blank=True)
    investment = models.TextField(null=True, blank=True)
    xp_type = models.TextField(null=True, blank=True, choices=XP_TYPE)

    surface = models.TextField(null=True, blank=True)
    surface_type = ChoiceArrayField(models.TextField(choices=SURFACE_TYPE),
                                    default=list,
                                    blank=True,
                                    null=True)

    def __str__(self):
        return self.name
Example #2
0
class Farmer(models.Model):

    class Meta:
        ordering = ['name']

    # These two are unique values. UUIDs were chosen initially as IDs as they
    # allow client ID generation, less issues when working with multiple DBs, etc.
    # However, they are cumbersome to use on some situations (e.g., URLs), so we
    # also benefit from a short sequential ID that uses a Postgres sequence.
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    sequence_number = models.IntegerField(default=get_next_increment, editable=False, unique=True)
    #############################################################################

    external_id = models.CharField(max_length=100, db_index=True, null=True)

    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, null=True)

    approved = models.BooleanField(default=False, db_index=True)

    modification_date = models.DateTimeField(auto_now=True)
    creation_date = models.DateTimeField(default=timezone.now)
    airtable_json = JSONField(null=True, blank=True)
    airtable_url = models.TextField(null=True)

    cgu_approved = models.BooleanField(default=False)

    name = models.TextField(null=True, blank=True)
    farm_name = models.TextField(null=True, blank=True)
    email = models.EmailField(db_index=True, null=True, blank=True)
    phone_number = models.CharField(max_length=50, null=True, blank=True)

    installation_date = models.DateField(null=True, blank=True)
    description = models.TextField(null=True, blank=True)

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

    lat = models.DecimalField(null=True, blank=True, max_digits=9, decimal_places=6)
    lon = models.DecimalField(null=True, blank=True, max_digits=9, decimal_places=6)

    production = ChoiceArrayField(models.CharField(max_length=100, choices=PRODUCTIONS), default=list, null=True, blank=True)
    groups = ChoiceArrayField(models.CharField(max_length=200, choices=GROUPS), default=list, null=True, blank=True)
    agriculture_types = ChoiceArrayField(models.TextField(choices=TYPE_AGRICULTURE), default=list, null=True, blank=True)

    profile_image = models.ImageField(null=True, blank=True)
    postal_code = models.CharField(max_length=20, null=True, blank=True)
    personnel = models.TextField(null=True, blank=True)

    livestock_types = ChoiceArrayField(models.TextField(choices=TYPE_LIVESTOCK), default=list, null=True, blank=True)

    livestock_number = models.TextField(null=True, blank=True)
    soil_type = models.TextField(null=True, blank=True)
    specificities = models.TextField(null=True, blank=True)
    contact_possible = models.BooleanField(default=False)

    email_for_messages_allowed = models.BooleanField(default=True)

    links = ArrayField(models.TextField(), default=list, blank=True, null=True)

    surface = models.TextField(null=True, blank=True)
    surface_cultures = models.TextField(null=True, blank=True)
    surface_meadows = models.TextField(null=True, blank=True)

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

    onboarding_shown = models.BooleanField(default=False)

    @property
    def approved_experiments(self):
        return self.experiments.filter(approved=True)

    @property
    def pending_experiments(self):
        return self.experiments.filter(approved=False)

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if self.profile_image:
            self.profile_image = optimize_image(self.profile_image, self.profile_image.name)
        if self.email:
            self.email = get_user_model().objects.normalize_email(self.email)
        super(Farmer, self).save(force_insert, force_update, using, update_fields)

    @property
    def url_slug(self):
        url_name = quote(self.farm_name or self.name)
        return f'{url_name}--{self.sequence_number or ""}'

    @property
    def url_path(self):
        url_name = quote(self.farm_name or self.name)
        return f'/exploitation/{self.url_slug}'

    @property
    def html_link(self):
        """
        This is used in the admin panel to link to the farmer's page
        """
        if self.sequence_number and self.approved:
            unescaped_url = f'/exploitation/{self.farm_name or self.name}--{self.sequence_number}'
            return mark_safe(f'<a href="{self.url_path}" target="_blank">{unescaped_url}</a>')
        else:
            return 'Pas encore live'

    def __str__(self):
        return self.name
Example #3
0
class Farmer(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    external_id = models.CharField(max_length=100, db_index=True, null=True)

    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, null=True)

    approved = models.BooleanField(default=False, db_index=True)

    modification_date = models.DateTimeField(auto_now=True)
    creation_date = models.DateTimeField(default=timezone.now)
    airtable_json = JSONField(null=True, blank=True)
    airtable_url = models.TextField(null=True)

    name = models.TextField(null=True, blank=True)
    email = models.EmailField(db_index=True, null=True, blank=True)
    phone_number = models.CharField(max_length=50, null=True, blank=True)

    installation_date = models.DateField(null=True, blank=True)
    description = models.TextField(null=True, blank=True)

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

    lat = models.DecimalField(max_digits=9, decimal_places=6)
    lon = models.DecimalField(max_digits=9, decimal_places=6)

    production = ChoiceArrayField(models.CharField(max_length=100, choices=PRODUCTIONS), default=list, null=True, blank=True)
    groups = ChoiceArrayField(models.CharField(max_length=200, choices=GROUPS), default=list, null=True, blank=True)
    agriculture_types = ChoiceArrayField(models.TextField(choices=TYPE_AGRICULTURE), default=list, null=True, blank=True)

    profile_image = models.ImageField(null=True, blank=True)
    postal_code = models.CharField(max_length=20, null=True, blank=True)
    personnel = models.TextField(null=True, blank=True)

    livestock_types = ChoiceArrayField(models.TextField(choices=TYPE_LIVESTOCK), default=list, null=True, blank=True)

    livestock_number = models.TextField(null=True, blank=True)
    soil_type = models.TextField(null=True, blank=True)
    specificities = models.TextField(null=True, blank=True)
    contact_possible = models.BooleanField(default=False)

    links = ArrayField(models.TextField(), default=list, blank=True, null=True)

    surface = models.TextField(null=True, blank=True)
    surface_cultures = models.TextField(null=True, blank=True)
    surface_meadows = models.TextField(null=True, blank=True)

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

    @property
    def approved_experiments(self):
        return self.experiments.filter(approved=True)

    @property
    def pending_experiments(self):
        return self.experiments.filter(approved=False)

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        if self.profile_image:
            self.profile_image = optimize_image(self.profile_image, self.profile_image.name)
        super(Farmer, self).save(force_insert, force_update, using, update_fields)

    def __str__(self):
        return self.name
Example #4
0
class Experiment(models.Model):
    # These two are unique values. UUIDs were chosen initially as IDs as they
    # allow client ID generation, less issues when working with multiple DBs, etc.
    # However, they are cumbersome to use on some situations (e.g., URLs), so we
    # also benefit from a short sequential ID that uses a Postgres sequence.
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    sequence_number = models.IntegerField(default=get_next_increment,
                                          editable=False,
                                          unique=True)
    #############################################################################

    external_id = models.CharField(max_length=100, db_index=True, null=True)
    modification_date = models.DateTimeField(auto_now=True)
    creation_date = models.DateTimeField(default=timezone.now)
    airtable_json = JSONField(null=True, blank=True)

    farmer = models.ForeignKey(Farmer,
                               related_name='experiments',
                               on_delete=models.CASCADE,
                               null=True)
    state = models.TextField(choices=STATES,
                             default="Brouillon",
                             db_index=True)
    tags = ChoiceArrayField(models.CharField(max_length=255, choices=TAGS),
                            default=list,
                            blank=True,
                            null=True)
    name = models.TextField(max_length=70)
    short_name = models.TextField(
        max_length=30,
        null=True,
        blank=True,
        help_text='Si ce champ est présent, il sera utilisé pour l\'URL')
    objectives = models.TextField(null=True, blank=True)
    equipment = models.TextField(null=True, blank=True)
    control_presence = models.BooleanField(null=True, blank=True)
    ongoing = models.BooleanField(null=True, blank=True)
    results = models.TextField(null=True, blank=True, choices=RESULTS)
    results_details = models.TextField(null=True, blank=True)
    links = ArrayField(models.TextField(), default=list, blank=True, null=True)
    description = models.TextField(null=True, blank=True)
    investment = models.TextField(null=True, blank=True)
    xp_type = models.TextField(null=True, blank=True, choices=XP_TYPE)

    surface = models.TextField(null=True, blank=True)
    surface_type = ChoiceArrayField(models.TextField(choices=SURFACE_TYPE),
                                    default=list,
                                    blank=True,
                                    null=True)

    cultures = ArrayField(models.TextField(),
                          default=list,
                          blank=True,
                          null=True)

    def __str__(self):
        return self.name

    @property
    def url_path(self):
        if not self.farmer:
            return ''
        url_name = quote(self.short_name or self.name)
        return f'{self.farmer.url_path}/{quote("expérience")}/{url_name}--{self.sequence_number or ""}'

    @property
    def html_link(self):
        if self.sequence_number and self.approved:
            unescaped_url = f'/exploitation/{self.farmer.farm_name or self.farmer.name}--{self.farmer.sequence_number}/expérience/{self.short_name or self.name}--{self.sequence_number}'
            return mark_safe(
                f'<a href="{self.url_path}" target="_blank">{unescaped_url}</a>'
            )
        else:
            return 'Pas encore live'

    @property
    def approved(self):
        return self.state == 'Validé'

    @property
    def admin_link(self):
        return reverse('admin:data_experiment_change', args=(self.id, ))

    def save(self,
             force_insert=False,
             force_update=False,
             using=None,
             update_fields=None):
        """
        We need to check if the experiment has been put as awaiting for validation to
        send an Asana task
        """
        try:
            send_task = False
            if self.state == 'En attente de validation' and self.pk is not None:
                if self._state.adding or Experiment.objects.get(
                        pk=self.pk).state != 'En attente de validation':
                    task_name = "Retour d'experience '{0}' est en attente de validation".format(
                        self.name)
                    body = "Expérience créée par {0}. Lien pour admin : https://www.peps.beta.gouv.fr{1}".format(
                        self.farmer.name, self.admin_link)
                    AsanaUtils.send_task(settings.ASANA_PROJECT, task_name,
                                         body, None)
        except Exception as _:
            print(
                'Error creating task in Asana for experiment awaiting validation'
            )
        finally:
            super(Experiment, self).save(force_insert, force_update, using,
                                         update_fields)
Example #5
0
class Experiment(models.Model):
    # These two are unique values. UUIDs were chosen initially as IDs as they
    # allow client ID generation, less issues when working with multiple DBs, etc.
    # However, they are cumbersome to use on some situations (e.g., URLs), so we
    # also benefit from a short sequential ID that uses a Postgres sequence.
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    sequence_number = models.IntegerField(default=get_next_increment,
                                          editable=False,
                                          unique=True)
    #############################################################################

    external_id = models.CharField(max_length=100, db_index=True, null=True)
    modification_date = models.DateTimeField(auto_now=True)
    creation_date = models.DateTimeField(default=timezone.now)
    airtable_json = JSONField(null=True, blank=True)

    farmer = models.ForeignKey(Farmer,
                               related_name='experiments',
                               on_delete=models.CASCADE,
                               null=True)
    approved = models.BooleanField(default=False, db_index=True)
    tags = ChoiceArrayField(models.CharField(max_length=255, choices=TAGS),
                            default=list,
                            blank=True,
                            null=True)
    name = models.TextField(max_length=70)
    short_name = models.TextField(
        max_length=30,
        null=True,
        blank=True,
        help_text='Si ce champ est présent, il sera utilisé pour l\'URL')
    objectives = models.TextField(null=True, blank=True)
    equipment = models.TextField(null=True, blank=True)
    control_presence = models.BooleanField(null=True, blank=True)
    ongoing = models.BooleanField(null=True, blank=True)
    results = models.TextField(null=True, blank=True, choices=RESULTS)
    results_details = models.TextField(null=True, blank=True)
    links = ArrayField(models.TextField(), default=list, blank=True, null=True)
    description = models.TextField(null=True, blank=True)
    investment = models.TextField(null=True, blank=True)
    xp_type = models.TextField(null=True, blank=True, choices=XP_TYPE)

    surface = models.TextField(null=True, blank=True)
    surface_type = ChoiceArrayField(models.TextField(choices=SURFACE_TYPE),
                                    default=list,
                                    blank=True,
                                    null=True)

    cultures = ArrayField(models.TextField(),
                          default=list,
                          blank=True,
                          null=True)

    def __str__(self):
        return self.name

    @property
    def url_path(self):
        if not self.farmer:
            return ''
        url_name = quote(self.short_name or self.name)
        return f'{self.farmer.url_path}/{quote("expérience")}/{url_name}--{self.sequence_number or ""}'

    @property
    def html_link(self):
        if self.sequence_number and self.approved:
            unescaped_url = f'/exploitation/{self.farmer.farm_name or self.farmer.name}--{self.farmer.sequence_number}/expérience/{self.short_name or self.name}--{self.sequence_number}'
            return mark_safe(
                f'<a href="{self.url_path}" target="_blank">{unescaped_url}</a>'
            )
        else:
            return 'Pas encore live'