예제 #1
0
class Bid (models.Model):
    price = models.DecimalField(max_digits=10 ,decimal_places=2, default=0, validators=[MinValueValidator(0)])
    buyer = models.ForeignKey(User, on_delete=CASCADE, related_name="buyers")
    listing = models.ForeignKey(Listing, on_delete=CASCADE, related_name="bids")

    def __str__(self):
        return f"{self.buyer} Plaatst een bod op product: {self.listing.product} van {self.price} euro"
예제 #2
0
파일: models.py 프로젝트: neszt/freenas
class Advanced(Model):
    adv_consolemenu = models.BooleanField(
        verbose_name=_("Enable Console Menu"),
        default=False,
    )
    adv_serialconsole = models.BooleanField(
        verbose_name=_("Use Serial Console"),
        default=False,
    )
    adv_serialport = models.CharField(
        max_length=120,
        default="0x2f8",
        help_text=_(
            "Set this to match your serial port address (0x3f8, 0x2f8, etc.)"),
        verbose_name=_("Serial Port Address"),
        choices=choices.SERIAL_CHOICES(),
    )
    adv_serialspeed = models.CharField(
        max_length=120,
        choices=choices.SERIAL_SPEED,
        default="9600",
        help_text=_("Set this to match your serial port speed"),
        verbose_name=_("Serial Port Speed"))
    adv_consolescreensaver = models.BooleanField(
        verbose_name=_("Enable screen saver"),
        default=False,
    )
    adv_powerdaemon = models.BooleanField(
        verbose_name=_("Enable powerd (Power Saving Daemon)"),
        default=False,
    )
    adv_swapondrive = models.IntegerField(
        validators=[MinValueValidator(0)],
        verbose_name=_(
            "Swap size on each drive in GiB, affects new disks "
            "only. Setting this to 0 disables swap creation completely "
            "(STRONGLY DISCOURAGED)."),
        default=2,
    )
    adv_consolemsg = models.BooleanField(
        verbose_name=_("Show console messages in the footer"),
        default=True,
    )
    adv_traceback = models.BooleanField(
        verbose_name=_("Show tracebacks in case of fatal errors"),
        default=True,
    )
    adv_advancedmode = models.BooleanField(
        verbose_name=_("Show advanced fields by default"),
        default=False,
        help_text=_(
            "By default only essential fields are shown. Fields considered "
            "advanced can be displayed through the Advanced Mode button."),
    )
    adv_autotune = models.BooleanField(
        verbose_name=_("Enable autotune"),
        default=False,
        help_text=_(
            "Attempt to automatically tune the network and ZFS system control "
            "variables based on memory available."),
    )
    adv_debugkernel = models.BooleanField(
        verbose_name=_("Enable debug kernel"),
        default=False,
        help_text=_(
            "The kernel built with debug symbols will be booted instead."),
    )
    adv_uploadcrash = models.BooleanField(
        verbose_name=_(
            "Enable automatic upload of kernel crash dumps and daily telemetry"
        ),
        default=True,
    )
    adv_anonstats = models.BooleanField(
        verbose_name=_("Enable report anonymous statistics"),
        default=True,
        editable=False,
    )
    adv_anonstats_token = models.TextField(
        blank=True,
        editable=False,
    )
    adv_motd = models.TextField(
        max_length=1024,
        verbose_name=_("MOTD banner"),
        default='Welcome',
    )
    adv_boot_scrub = models.IntegerField(
        default=35,
        editable=False,
    )
    adv_periodic_notifyuser = UserField(
        default="root",
        verbose_name=_("Periodic Notification User"),
        help_text=
        _("If you wish periodic emails to be sent to a different email address than "
          "the alert emails are set to (root) set an email address for a user and "
          "select that user in the dropdown."))
    adv_graphite = models.CharField(
        max_length=120,
        default="",
        blank=True,
        verbose_name=_("Remote Graphite Server Hostname"),
        help_text=_(
            "A hostname or IP here will be used as the destination to send collectd "
            "data to using the graphite plugin to collectd."))

    class Meta:
        verbose_name = _("Advanced")

    class FreeAdmin:
        deletable = False
예제 #3
0
파일: models.py 프로젝트: neszt/freenas
class Settings(Model):
    stg_guiprotocol = models.CharField(max_length=120,
                                       choices=choices.PROTOCOL_CHOICES,
                                       default="http",
                                       verbose_name=_("Protocol"))
    stg_guicertificate = models.ForeignKey(
        "Certificate",
        verbose_name=_("Certificate"),
        limit_choices_to={'cert_CSR__isnull': True},
        on_delete=models.SET_NULL,
        blank=True,
        null=True)
    stg_guiaddress = models.CharField(max_length=120,
                                      blank=True,
                                      default='0.0.0.0',
                                      verbose_name=_("WebGUI IPv4 Address"))
    stg_guiv6address = models.CharField(max_length=120,
                                        blank=True,
                                        default='::',
                                        verbose_name=_("WebGUI IPv6 Address"))
    stg_guiport = models.IntegerField(
        verbose_name=_("WebGUI HTTP Port"),
        validators=[MinValueValidator(1),
                    MaxValueValidator(65535)],
        default=80,
    )
    stg_guihttpsport = models.IntegerField(
        verbose_name=_("WebGUI HTTPS Port"),
        validators=[MinValueValidator(1),
                    MaxValueValidator(65535)],
        default=443,
    )
    stg_guihttpsredirect = models.BooleanField(
        verbose_name=_('WebGUI HTTP -> HTTPS Redirect'),
        default=True,
        help_text=_(
            'Redirect HTTP (port 80) to HTTPS when only the HTTPS protocol is '
            'enabled'),
    )
    stg_language = models.CharField(max_length=120,
                                    choices=settings.LANGUAGES,
                                    default="en",
                                    verbose_name=_("Language"))
    stg_kbdmap = models.CharField(
        max_length=120,
        choices=choices.KBDMAP_CHOICES(),
        verbose_name=_("Console Keyboard Map"),
        blank=True,
    )
    stg_timezone = models.CharField(max_length=120,
                                    choices=choices.TimeZoneChoices(),
                                    default="America/Los_Angeles",
                                    verbose_name=_("Timezone"))
    stg_sysloglevel = models.CharField(
        max_length=120,
        choices=choices.SYS_LOG_LEVEL,
        default="f_info",
        verbose_name=_("Syslog level"),
        help_text=_("Specifies which messages will be logged by "
                    "server. INFO and VERBOSE log transactions that "
                    "server performs on behalf of the client. "
                    "f_is_debug specify higher levels of debugging output. "
                    "The default is f_info."),
    )
    stg_syslogserver = models.CharField(
        default='',
        blank=True,
        max_length=120,
        verbose_name=_("Syslog server"),
        help_text=_(
            "Specifies the server and port syslog messages "
            "will be sent to.  The accepted format is hostname:port "
            "or ip:port, if :port is not specified it will default to "
            "port 514 (this field currently only takes IPv4 addresses)"),
    )
    stg_wizardshown = models.BooleanField(
        editable=False,
        default=False,
    )
    stg_pwenc_check = models.CharField(
        max_length=100,
        editable=False,
    )

    class Meta:
        verbose_name = _("General")
예제 #4
0
class ConsultaMedica(models.Model):
    fk_consulta_expediente = models.ForeignKey(Expediente, null=False, blank=False)
    fecha = models.DateField('Fecha', auto_now_add=True)
    hora = models.TimeField('Hora de Consulta', blank=False, null=False)
    peso = models.DecimalField('Peso', max_digits=5, decimal_places=2, blank=False, null=False, validators=[MinValueValidator(0)])
    talla = models.DecimalField('Talla', max_digits=5, decimal_places=2, blank=False, null=False, validators=[MinValueValidator(0)])
    ta = models.CharField('Tensión arterial', max_length=6, blank=False, null=False, help_text='Tensión arterial ###/##')
    fc = models.DecimalField('Frecuencia cardíaca', max_digits=5, decimal_places=2, blank=False, null=False, help_text='Frecuencia cardíaca', validators=[MinValueValidator(0)])
    problema = models.CharField('Historia del problema', max_length=256, blank=False, null=False, help_text='Motivo de consulta')
    diagnostico = models.CharField('Diagnostico', max_length=256, blank=False, null=False)
    prox_control = models.DateTimeField(blank=True, null=True)
    precio_consulta = models.DecimalField('Precio de la Consulta', max_digits=5, decimal_places=2, blank=False, null=False, validators=[MinValueValidator(0)])

    def __str__(self):
        return '{}: {}'.format('Consulta del expediente', self.fk_consulta_expediente)

    def get_edad(self):
        diff = (self.fecha - self.fk_consulta_expediente.paciente.fecha_nacimiento).days
        edad = str(int(diff / 365))
        cantidad_tiempo = 'años'
        if edad == '0':
            edad = str(int(diff / 12))
            cantidad_tiempo = 'meses'
        return '{} {}'.format(self.edad, self.cantidad_tiempo)

    class Meta:
        ordering = ["fecha", "hora"]
        verbose_name = 'Cita Médica'
        verbose_name_plural = 'Citas Médicas'
예제 #5
0
class Application(models.Model):
    # META
    uuid = models.UUIDField(default=uuid.uuid4, editable=False)
    user = models.OneToOneField(User, primary_key=True)
    invited_by = models.ForeignKey(User, related_name='invited_applications', blank=True, null=True)

    # When was the application submitted
    submission_date = models.DateTimeField(default=timezone.now)
    # When was the last status update
    status_update_date = models.DateTimeField(blank=True, null=True)
    # Application status
    status = models.CharField(choices=STATUS, default=APP_PENDING,
                              max_length=2)

    # ABOUT YOU
    # Population analysis, optional
    gender = models.CharField(max_length=20, choices=GENDERS, default=NO_ANSWER)
    # Personal data (asking here because we don't want to ask birthday)
    under_age = models.BooleanField()

    phone_number = models.CharField(blank=True, null=True, max_length=16,
                                    validators=[RegexValidator(regex=r'^\+?1?\d{9,15}$',
                                                               message="Phone number must be entered in the format: \
                                                                  '+#########'. Up to 15 digits allowed.")])

    # Where is this person coming from?
    origin = models.CharField(max_length=300)

    # Is this your first hackathon?
    first_timer = models.BooleanField()
    # Why do you want to come to X?
    description = models.TextField(max_length=500)
    # Explain a little bit what projects have you done lately
    projects = models.TextField(max_length=500, blank=True, null=True)

    # Reimbursement
    reimb = models.BooleanField(default=False)
    reimb_amount = models.FloatField(blank=True, null=True, validators=[
        MinValueValidator(0, "Negative? Really? Please put a positive value")])

    # Random lenny face
    lennyface = models.CharField(max_length=300, default='-.-')

    # Giv me a resume here!
    resume = models.FileField(upload_to='resumes', null=True, blank=True)

    # University
    graduation_year = models.IntegerField(choices=YEARS, default=DEFAULT_YEAR)
    university = models.CharField(max_length=300)
    degree = models.CharField(max_length=300)

    # URLs
    github = models.URLField(blank=True, null=True)
    devpost = models.URLField(blank=True, null=True)
    linkedin = models.URLField(blank=True, null=True)
    site = models.URLField(blank=True, null=True)

    # Info for swag and food
    diet = models.CharField(max_length=300, choices=DIETS, default=D_NONE)
    other_diet = models.CharField(max_length=600, blank=True, null=True)
    tshirt_size = models.CharField(max_length=3, default=DEFAULT_TSHIRT_SIZE, choices=TSHIRT_SIZES)

    @classmethod
    def annotate_vote(cls, qs):
        return qs.annotate(vote_avg=Avg('vote__calculated_vote'))

    @property
    def uuid_str(self):
        return str(self.uuid)

    def get_soft_status_display(self):
        text = self.get_status_display()
        if "Not" in text or 'Rejected' in text:
            return "Pending"
        return text

    def __str__(self):
        return self.user.email

    def save(self, **kwargs):
        self.status_update_date = timezone.now()
        super(Application, self).save(**kwargs)

    def invite(self, user):
        # We can re-invite someone invited
        if self.status in [APP_CONFIRMED, APP_ATTENDED]:
            raise ValidationError('Application has already answered invite. '
                                  'Current status: %s' % self.status)
        self.status = APP_INVITED
        if not self.invited_by:
            self.invited_by = user
        self.last_invite = timezone.now()
        self.last_reminder = None
        self.status_update_date = timezone.now()
        self.save()

    def last_reminder(self):
        if self.status != APP_INVITED:
            raise ValidationError('Reminder can\'t be sent to non-pending '
                                  'applications')
        self.status_update_date = timezone.now()
        self.status = APP_LAST_REMIDER
        self.save()

    def expire(self):
        self.status_update_date = timezone.now()
        self.status = APP_EXPIRED
        self.save()

    def reject(self, request):
        if self.status == APP_ATTENDED:
            raise ValidationError('Application has already attended. '
                                  'Current status: %s' % self.status)
        self.status = APP_REJECTED
        self.status_update_date = timezone.now()
        self.save()

    def confirm(self):
        if self.status == APP_CANCELLED:
            raise ValidationError('This invite has been cancelled.')
        elif self.status == APP_EXPIRED:
            raise ValidationError('Unfortunately your invite has expired.')
        elif self.status in [APP_INVITED, APP_LAST_REMIDER]:
            self.status = APP_CONFIRMED
            self.status_update_date = timezone.now()
            self.save()
        elif self.status in [APP_CONFIRMED, APP_ATTENDED]:
            return None
        else:
            raise ValidationError('Unfortunately his application hasn\'t been '
                                  'invited [yet]')

    def cancel(self):
        if not self.can_be_cancelled():
            raise ValidationError('Application can\'t be cancelled. Current '
                                  'status: %s' % self.status)
        if self.status != APP_CANCELLED:
            self.status = APP_CANCELLED
            self.status_update_date = timezone.now()
            self.save()
            reimb = getattr(self.user, 'reimbursement', None)
            if reimb:
                reimb.delete()

    def check_in(self):
        self.status = APP_ATTENDED
        self.status_update_date = timezone.now()
        self.save()

    def is_confirmed(self):
        return self.status == APP_CONFIRMED

    def is_cancelled(self):
        return self.status == APP_CANCELLED

    def answered_invite(self):
        return self.status in [APP_CONFIRMED, APP_CANCELLED, APP_ATTENDED]

    def needs_action(self):
        return self.status == APP_INVITED

    def is_pending(self):
        return self.status == APP_PENDING

    def can_be_edit(self):
        return self.status == APP_PENDING and not self.vote_set.exists() and not utils.is_app_closed()

    def is_invited(self):
        return self.status == APP_INVITED

    def is_expired(self):
        return self.status == APP_EXPIRED

    def is_rejected(self):
        return self.status == APP_REJECTED

    def is_attended(self):
        return self.status == APP_ATTENDED

    def is_last_reminder(self):
        return self.status == APP_LAST_REMIDER

    def can_be_cancelled(self):
        return self.status == APP_CONFIRMED or self.status == APP_INVITED or self.status == APP_LAST_REMIDER

    def can_confirm(self):
        return self.status in [APP_INVITED, APP_LAST_REMIDER]
예제 #6
0
파일: models.py 프로젝트: niveKKumar/wger
class MealItem(models.Model):
    '''
    An item (component) of a meal
    '''

    meal = models.ForeignKey(Meal,
                             verbose_name=_('Nutrition plan'),
                             editable=False,
                             on_delete=models.CASCADE)
    ingredient = models.ForeignKey(Ingredient,
                                   verbose_name=_('Ingredient'),
                                   on_delete=models.CASCADE)
    weight_unit = models.ForeignKey(IngredientWeightUnit,
                                    verbose_name=_('Weight unit'),
                                    null=True,
                                    blank=True,
                                    on_delete=models.CASCADE)

    order = models.IntegerField(verbose_name=_('Order'),
                                blank=True,
                                editable=False)
    amount = models.DecimalField(decimal_places=2,
                                 max_digits=6,
                                 verbose_name=_('Amount'),
                                 validators=[MinValueValidator(1),
                                             MaxValueValidator(1000)])

    def __str__(self):
        '''
        Return a more human-readable representation
        '''
        return u"{0}g ingredient {1}".format(self.amount, self.ingredient_id)

    def get_owner_object(self):
        '''
        Returns the object that has owner information
        '''
        return self.meal.plan

    def get_unit_type(self):
        '''
        Returns the type of unit used:
        - a value in grams
        - a 'human' unit like 'a cup' or 'a slice'
        '''

        if self.weight_unit:
            return MEALITEM_WEIGHT_UNIT
        else:
            return MEALITEM_WEIGHT_GRAM

    def get_nutritional_values(self, use_metric=True):
        '''
        Sums the nutrional info for the ingredient in the MealItem

        :param use_metric Flag that controls the units used
        '''
        nutritional_info = {'energy': 0,
                            'protein': 0,
                            'carbohydrates': 0,
                            'carbohydrates_sugar': 0,
                            'fat': 0,
                            'fat_saturated': 0,
                            'fibres': 0,
                            'sodium': 0}
        # Calculate the base weight of the item
        if self.get_unit_type() == MEALITEM_WEIGHT_GRAM:
            item_weight = self.amount
        else:
            item_weight = (self.amount *
                           self.weight_unit.amount *
                           self.weight_unit.gram)

        nutritional_info['energy'] += self.ingredient.energy * item_weight / 100
        nutritional_info['protein'] += self.ingredient.protein * item_weight / 100
        nutritional_info['carbohydrates'] += self.ingredient.carbohydrates * item_weight / 100

        if self.ingredient.carbohydrates_sugar:
            nutritional_info['carbohydrates_sugar'] += self.ingredient.carbohydrates_sugar \
                * item_weight / 100

        nutritional_info['fat'] += self.ingredient.fat * item_weight / 100

        if self.ingredient.fat_saturated:
            nutritional_info['fat_saturated'] += self.ingredient.fat_saturated * item_weight / 100

        if self.ingredient.fibres:
            nutritional_info['fibres'] += self.ingredient.fibres * item_weight / 100

        if self.ingredient.sodium:
            nutritional_info['sodium'] += self.ingredient.sodium * item_weight / 100

        # If necessary, convert weight units
        if not use_metric:
            for key, value in nutritional_info.items():

                # Energy is not a weight!
                if key == 'energy':
                    continue

                # Everything else, to ounces
                nutritional_info[key] = AbstractWeight(value, 'g').oz

        # Only 2 decimal places, anything else doesn't make sense
        for i in nutritional_info:
            nutritional_info[i] = Decimal(nutritional_info[i]).quantize(TWOPLACES)

        return nutritional_info
class InfantBirthData(InfantCrfModel):
    """ A model completed by the user on the infant's birth exam. """

    infant_gender = models.CharField(
        max_length=6,
        choices=GENDER,
        verbose_name="What is the gender of the infant?",
        help_text="")

    weight_kg = models.DecimalField(
        max_digits=3,
        decimal_places=2,
        verbose_name="What was the infant's birth weight? ",
        help_text="Measured in Kilograms (kg)")

    infant_length = models.DecimalField(
        max_digits=4,
        decimal_places=2,
        validators=[MinValueValidator(0),
                    MaxValueValidator(90)],
        verbose_name="What was the infant's length at birth? ",
        help_text="Measured in centimeters, (cm)")

    head_circumference = models.DecimalField(
        max_digits=4,
        decimal_places=2,
        validators=[MinValueValidator(0),
                    MaxValueValidator(41)],
        verbose_name="What was the head circumference in centimeters? ",
        help_text="Measured in centimeters, (cm)")

    apgar_score = models.CharField(
        max_length=3,
        choices=YES_NO,
        verbose_name="Was Apgar Score performed? ",
        help_text="If 'No' go to question 10. Otherwise continue")

    apgar_score_min_1 = models.IntegerField(
        verbose_name="At 1 minute: ",
        help_text="",
        blank=True,
        null=True,
        validators=[MaxValueValidator(10),
                    MinValueValidator(0)])

    apgar_score_min_5 = models.IntegerField(
        verbose_name="At 5 minutes: ",
        help_text="",
        blank=True,
        null=True,
        validators=[MaxValueValidator(10),
                    MinValueValidator(0)])

    apgar_score_min_10 = models.IntegerField(
        verbose_name="At 10 minutes: ",
        help_text="",
        blank=True,
        null=True,
        validators=[MaxValueValidator(10),
                    MinValueValidator(0)])

    congenital_anomalities = models.CharField(
        max_length=3,
        choices=YES_NO,
        verbose_name="Were any congenital anomalies identified? ",
        help_text="If 'Yes' please complete the Congenital Anomalies Form",
    )

    other_birth_info = models.TextField(
        max_length=250,
        verbose_name="Other birth information ",
        blank=True,
        null=True)

    class Meta:
        app_label = 'td_infant'
        verbose_name = "Infant Birth: Data"
        verbose_name_plural = "Infant Birth: Data"
예제 #8
0
파일: models.py 프로젝트: nknganda/saleor
class OrderedItem(models.Model, ItemLine):
    delivery_group = models.ForeignKey(DeliveryGroup,
                                       related_name='items',
                                       editable=False,
                                       verbose_name=pgettext_lazy(
                                           'Ordered item field',
                                           'delivery group'))
    product = models.ForeignKey(Product,
                                blank=True,
                                null=True,
                                related_name='+',
                                on_delete=models.SET_NULL,
                                verbose_name=pgettext_lazy(
                                    'Ordered item field', 'product'))
    product_name = models.CharField(pgettext_lazy('Ordered item field',
                                                  'product name'),
                                    max_length=128)
    product_sku = models.CharField(pgettext_lazy('Ordered item field', 'sku'),
                                   max_length=32)
    stock_location = models.CharField(pgettext_lazy('OrderedItem field',
                                                    'stock location'),
                                      max_length=100,
                                      default='')
    stock = models.ForeignKey('product.Stock',
                              on_delete=models.SET_NULL,
                              null=True,
                              verbose_name=pgettext_lazy(
                                  'Ordered item field', 'stock'))
    quantity = models.IntegerField(
        pgettext_lazy('Ordered item field', 'quantity'),
        validators=[MinValueValidator(0),
                    MaxValueValidator(999)])
    unit_price_net = models.DecimalField(pgettext_lazy('Ordered item field',
                                                       'unit price (net)'),
                                         max_digits=12,
                                         decimal_places=4)
    unit_price_gross = models.DecimalField(pgettext_lazy(
        'Ordered item field', 'unit price (gross)'),
                                           max_digits=12,
                                           decimal_places=4)

    objects = OrderedItemManager()

    class Meta:
        verbose_name = pgettext_lazy('Ordered item model', 'Ordered item')
        verbose_name_plural = pgettext_lazy('Ordered item model',
                                            'Ordered items')

    def __str__(self):
        return self.product_name

    def get_price_per_item(self, **kwargs):
        return Price(net=self.unit_price_net,
                     gross=self.unit_price_gross,
                     currency=settings.DEFAULT_CURRENCY)

    def get_quantity(self):
        return self.quantity

    def change_quantity(self, new_quantity):
        order = self.delivery_group.order
        self.quantity = new_quantity
        self.save()
        if not self.delivery_group.get_total_quantity():
            self.delivery_group.delete()
        if not order.get_items():
            order.change_status('cancelled')
예제 #9
0
    'apptemplates.Loader',
    'django.template.loaders.eggs.Loader',
)

#Engrade
# http://ww7.engrade.com/api/key.php
ENGRADE_APIKEY = ''
ENGRADE_LOGIN = ''
ENGRADE_PASSWORD = ''
# School UID (admin must be connected to school)
ENGRADE_SCHOOLID = ''

# Global date validators, to help prevent data entry errors
import datetime
from django.core.validators import MinValueValidator  # Could use MaxValueValidator too
DATE_VALIDATORS = [MinValueValidator(datetime.date(1970, 1, 1))]  # Unix epoch!

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.contrib.auth.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.static",
    "django.contrib.messages.context_processors.messages",
    "django.core.context_processors.request",
    'noticeapp.context_processors.processor',
)
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
예제 #10
0
class URLInputForm(forms.Form, BaseFormFieldPluginForm):
    """Form for ``URLPlugin``."""

    plugin_data_fields = [
        ("label", ""),
        ("name", ""),
        ("help_text", ""),
        ("initial", ""),
        ("max_length", str(DEFAULT_MAX_LENGTH)),
        ("required", False),
        ("placeholder", ""),
    ]

    label = forms.CharField(
        label=_("Question text"),
        required=True,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}
        )
    )
    name = forms.CharField(
        label=_("Name"),
        required=True,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}
        )
    )
    help_text = forms.CharField(
        label=_("Help text"),
        required=False,
        widget=forms.widgets.Textarea(
            attrs={'class': theme.form_element_html_class}
        )
    )
    initial = forms.URLField(
        label=_("Initial"),
        required=False,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}
        )
    )
    max_length = forms.IntegerField(
        label=_("Max length"),
        required=True,
        widget=NumberInput(attrs={'class': theme.form_element_html_class,
                                  'min': str(DEFAULT_MIN_LENGTH)}),
        initial=DEFAULT_MAX_LENGTH,
        validators=[MinValueValidator(DEFAULT_MIN_LENGTH)]
    )
    required = forms.BooleanField(
        label=_("Required"),
        required=False,
        widget=forms.widgets.CheckboxInput(
            attrs={'class': theme.form_element_checkbox_html_class}
        )
    )
    placeholder = forms.CharField(
        label=_("Placeholder"),
        required=False,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}
        )
    )

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

        max_length = self.cleaned_data.get('max_length', DEFAULT_MAX_LENGTH)

        if self.cleaned_data['initial']:
            len_initial = len(self.cleaned_data['initial'])
            if len_initial > max_length:
                self.add_error(
                    'initial',
                    _("Ensure this value has at most {0} characters "
                      "(it has {1}).".format(max_length, len_initial))
                )
예제 #11
0
class RegexInputForm(forms.Form, BaseFormFieldPluginForm):
    """Form for ``RegexInputPlugin``."""

    plugin_data_fields = [
        ("label", ""),
        ("name", ""),
        ("help_text", ""),
        ("initial", ""),
        ("regex", ""),
        ("max_length", str(DEFAULT_MAX_LENGTH)),
        ("required", False),
        ("placeholder", ""),
    ]

    label = forms.CharField(
        label=_("Label"),
        required=True,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}))
    name = forms.CharField(label=_("Name"),
                           required=True,
                           widget=forms.widgets.TextInput(
                               attrs={'class': theme.form_element_html_class}))
    help_text = forms.CharField(
        label=_("Help text"),
        required=False,
        widget=forms.widgets.Textarea(
            attrs={'class': theme.form_element_html_class}))
    regex = forms.RegexField(
        label=_("Regex"),
        required=True,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}),
        regex="",
        help_text=_("Enter a valid regular expression. A couple of common "
                    "examples are listed below.<br/>"
                    "- Allow a single digit from 1 to 9 (example value 6): "
                    "<code>^[1-9]$</code><br/>"
                    "- Allow any combination of characters from a to z, "
                    "including capitals (example value abcXYZ):"
                    "<code>^([a-zA-Z])+$</code><br/>"
                    "- Allow a hex value (example value #a5c125:"
                    "<code>^#?([a-f0-9]{6}|[a-f0-9]{3})$</code><br/>"))
    initial = forms.CharField(
        label=_("Initial"),
        required=False,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}))
    max_length = forms.IntegerField(
        label=_("Max length"),
        required=True,
        widget=NumberInput(attrs={
            'class': theme.form_element_html_class,
            'min': str(DEFAULT_MIN_LENGTH)
        }),
        initial=DEFAULT_MAX_LENGTH,
        validators=[MinValueValidator(DEFAULT_MIN_LENGTH)])
    required = forms.BooleanField(
        label=_("Required"),
        required=False,
        widget=forms.widgets.CheckboxInput(
            attrs={'class': theme.form_element_checkbox_html_class}))
    placeholder = forms.CharField(
        label=_("Placeholder"),
        required=False,
        widget=forms.widgets.TextInput(
            attrs={'class': theme.form_element_html_class}))

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

        max_length = self.cleaned_data.get('max_length', DEFAULT_MAX_LENGTH)

        if self.cleaned_data['initial']:
            len_initial = len(self.cleaned_data['initial'])
            if len_initial > max_length:
                self.add_error(
                    'initial',
                    _("Ensure this value has at most {0} characters "
                      "(it has {1}).".format(max_length, len_initial)))
예제 #12
0
파일: models.py 프로젝트: reshma-t/care
class User(AbstractUser):
    TYPE_VALUE_MAP = {
        "Doctor": 5,
        "Staff": 10,
        "Patient": 15,
        "Volunteer": 20,
        "DistrictLabAdmin": 25,
        "DistrictAdmin": 30,
        "StateLabAdmin": 35,
    }

    TYPE_CHOICES = [(value, name) for name, value in TYPE_VALUE_MAP.items()]

    user_type = models.IntegerField(choices=TYPE_CHOICES, blank=False)

    local_body = models.ForeignKey(LocalBody, on_delete=models.PROTECT, null=True, blank=True)
    district = models.ForeignKey(District, on_delete=models.PROTECT, null=True, blank=True)
    state = models.ForeignKey(State, on_delete=models.PROTECT, null=True, blank=True)

    phone_number = models.CharField(max_length=14, validators=[phone_number_regex])
    gender = models.IntegerField(choices=GENDER_CHOICES, blank=False)
    age = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(100)])
    skill = models.ForeignKey("Skill", on_delete=models.SET_NULL, null=True, blank=True)
    verified = models.BooleanField(default=False)
    deleted = models.BooleanField(default=False)

    REQUIRED_FIELDS = [
        "user_type",
        "email",
        "phone_number",
        "age",
        "gender",
        "district",
    ]

    objects = CustomUserManager()

    @staticmethod
    def has_read_permission(request):
        return True

    def has_object_read_permission(self, request):
        return request.user.is_superuser or self == request.user

    @staticmethod
    def has_write_permission(request):
        try:
            return request.data["user_type"] <= User.TYPE_VALUE_MAP["Volunteer"]
        except TypeError:
            return User.TYPE_VALUE_MAP[request.data["user_type"]] <= User.TYPE_VALUE_MAP["Volunteer"]
        except KeyError:
            # No user_type passed, the view shall raise a 400
            return True

    def has_object_write_permission(self, request):
        return request.user.is_superuser

    def has_object_update_permission(self, request):
        if request.user.is_superuser:
            return True
        if not self == request.user:
            return False
        if (request.data.get("district") or request.data.get("state")) and self.user_type >= User.TYPE_VALUE_MAP[
            "DistrictLabAdmin"
        ]:
            # District/state admins shouldn't be able to edit their district/state, that'll practically give them
            # access to everything
            return False
        return True

    def delete(self, *args, **kwargs):
        self.deleted = True
        self.save()

    def get_absolute_url(self):
        return reverse("users:detail", kwargs={"username": self.username})

    def save(self, *args, **kwargs) -> None:
        """
        While saving, if the local body is not null, then district will be local body's district
        Overriding save will help in a collision where the local body's district and district fields are different.
        """
        if self.local_body is not None:
            self.district = self.local_body.district
        if self.district is not None:
            self.state = self.district.state
        super().save(*args, **kwargs)
예제 #13
0
파일: models.py 프로젝트: vaibhavmule/hypha
class Project(BaseStreamForm, AccessFormData, models.Model):
    lead = models.ForeignKey(settings.AUTH_USER_MODEL,
                             null=True,
                             on_delete=models.SET_NULL,
                             related_name='lead_projects')
    submission = models.OneToOneField("funds.ApplicationSubmission",
                                      on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
                             on_delete=models.SET_NULL,
                             null=True,
                             related_name='owned_projects')

    title = models.TextField()

    contact_legal_name = models.TextField(_('Person or Organisation name'),
                                          default='')
    contact_email = models.TextField(_('Email'), default='')
    contact_address = models.TextField(_('Address'), default='')
    contact_phone = models.TextField(_('Phone'), default='')
    value = models.DecimalField(
        default=0,
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(decimal.Decimal('0.01'))],
    )
    proposed_start = models.DateTimeField(_('Proposed Start Date'), null=True)
    proposed_end = models.DateTimeField(_('Proposed End Date'), null=True)

    status = models.TextField(choices=PROJECT_STATUS_CHOICES,
                              default=COMMITTED)

    form_data = JSONField(encoder=StreamFieldDataEncoder, default=dict)
    form_fields = StreamField(FormFieldsBlock(), null=True)

    # tracks read/write state of the Project
    is_locked = models.BooleanField(default=False)

    # tracks updates to the Projects fields via the Project Application Form.
    user_has_updated_details = models.BooleanField(default=False)

    activities = GenericRelation(
        'activity.Activity',
        content_type_field='source_content_type',
        object_id_field='source_object_id',
        related_query_name='project',
    )
    created_at = models.DateTimeField(auto_now_add=True)

    sent_to_compliance_at = models.DateTimeField(null=True)

    objects = ProjectQuerySet.as_manager()

    def __str__(self):
        return self.title

    @property
    def status_display(self):
        return self.get_status_display()

    def get_address_display(self):
        try:
            address = json.loads(self.contact_address)
        except json.JSONDecodeError:
            return ''
        else:
            return ', '.join(
                address.get(field) for field in ADDRESS_FIELDS_ORDER
                if address.get(field))

    @classmethod
    def create_from_submission(cls, submission):
        """
        Create a Project from the given submission.

        Returns a new Project or the given ApplicationSubmissions existing
        Project.
        """
        if not settings.PROJECTS_ENABLED:
            logging.error(
                f'Tried to create a Project for Submission ID={submission.id} while projects are disabled'
            )
            return None

        # OneToOne relations on the targetted model cannot be accessed without
        # an exception when the relation doesn't exist (is None).  Since we
        # want to fail fast here, we can use hasattr instead.
        if hasattr(submission, 'project'):
            return submission.project

        return Project.objects.create(
            submission=submission,
            title=submission.title,
            user=submission.user,
            contact_email=submission.user.email,
            contact_legal_name=submission.user.full_name,
            contact_address=submission.form_data.get('address', ''),
            value=submission.form_data.get('value', 0),
        )

    @property
    def start_date(self):
        # Assume project starts when OTF are happy with the first signed contract
        first_approved_contract = self.contracts.approved().order_by(
            'approved_at').first()
        if not first_approved_contract:
            return None

        return first_approved_contract.approved_at.date()

    @property
    def end_date(self):
        # Aiming for the proposed end date as the last day of the project
        # If still ongoing assume today is the end
        return max(
            self.proposed_end.date(),
            timezone.now().date(),
        )

    def paid_value(self):
        return self.payment_requests.paid_value()

    def unpaid_value(self):
        return self.payment_requests.unpaid_value()

    def clean(self):
        if self.proposed_start is None:
            return

        if self.proposed_end is None:
            return

        if self.proposed_start > self.proposed_end:
            raise ValidationError(
                _('Proposed End Date must be after Proposed Start Date'))

    def save(self, *args, **kwargs):
        creating = not self.pk

        if creating:
            files = self.extract_files()
        else:
            self.process_file_data(self.form_data)

        super().save(*args, **kwargs)

        if creating:
            self.process_file_data(files)

    def editable_by(self, user):
        if self.editable:
            return True

        # Approver can edit it when they are approving
        return user.is_approver and self.can_make_approval

    @property
    def editable(self):
        if self.status not in (CONTRACTING, COMMITTED):
            return True

        # Someone has approved the project - consider it locked while with contracting
        if self.approvals.exists():
            return False

        # Someone must lead the project to make changes
        return self.lead and not self.is_locked

    def get_absolute_url(self):
        if settings.PROJECTS_ENABLED:
            return reverse('apply:projects:detail', args=[self.id])
        return '#'

    @property
    def can_make_approval(self):
        return self.is_locked and self.status == COMMITTED

    def can_request_funding(self):
        """
        Should we show this Project's funding block?
        """
        return self.status in (CLOSING, IN_PROGRESS)

    @property
    def can_send_for_approval(self):
        """
        Wrapper to expose the pending approval state

        We don't want to expose a "Sent for Approval" state to the end User so
        we infer it from the current status being "Comitted" and the Project
        being locked.
        """
        correct_state = self.status == COMMITTED and not self.is_locked
        return correct_state and self.user_has_updated_details

    @property
    def requires_approval(self):
        return not self.approvals.exists()

    def get_missing_document_categories(self):
        """
        Get the number of documents required to meet each DocumentCategorys minimum
        """
        # Count the number of documents in each category currently
        existing_categories = DocumentCategory.objects.filter(
            packet_files__project=self)
        counter = collections.Counter(existing_categories)

        # Find the difference between the current count and recommended count
        for category in DocumentCategory.objects.all():
            current_count = counter[category]
            difference = category.recommended_minimum - current_count
            if difference > 0:
                yield {
                    'category': category,
                    'difference': difference,
                }

    @property
    def is_in_progress(self):
        return self.status == IN_PROGRESS

    def send_to_compliance(self, request):
        """Notify Compliance about this Project."""

        messenger(
            MESSAGES.SENT_TO_COMPLIANCE,
            request=request,
            user=request.user,
            source=self,
        )

        self.sent_to_compliance_at = timezone.now()
        self.save(update_fields=['sent_to_compliance_at'])
예제 #14
0
파일: models.py 프로젝트: vaibhavmule/hypha
class PaymentRequest(models.Model):
    project = models.ForeignKey("Project",
                                on_delete=models.CASCADE,
                                related_name="payment_requests")
    by = models.ForeignKey(settings.AUTH_USER_MODEL,
                           on_delete=models.CASCADE,
                           related_name="payment_requests")

    requested_value = models.DecimalField(
        default=0,
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(decimal.Decimal('0.01'))],
    )
    paid_value = models.DecimalField(
        max_digits=10,
        decimal_places=2,
        validators=[MinValueValidator(decimal.Decimal('0.01'))],
        null=True)

    invoice = models.FileField(upload_to=invoice_path,
                               storage=PrivateStorage())
    requested_at = models.DateTimeField(auto_now_add=True)
    date_from = models.DateTimeField()
    date_to = models.DateTimeField()
    comment = models.TextField(blank=True)
    status = models.TextField(choices=REQUEST_STATUS_CHOICES,
                              default=SUBMITTED)

    objects = PaymentRequestQueryset.as_manager()

    def __str__(self):
        return f'Payment requested for {self.project}'

    @property
    def has_changes_requested(self):
        return self.status == CHANGES_REQUESTED

    @property
    def status_display(self):
        return self.get_status_display()

    def can_user_delete(self, user):
        if user.is_applicant:
            if self.status in (SUBMITTED, CHANGES_REQUESTED):
                return True

        if user.is_apply_staff:
            if self.status in {SUBMITTED}:
                return True

        return False

    def can_user_edit(self, user):
        if user.is_applicant:
            if self.status in {SUBMITTED, CHANGES_REQUESTED}:
                return True

        if user.is_apply_staff:
            if self.status in {SUBMITTED}:
                return True

        return False

    def can_user_change_status(self, user):
        if not user.is_apply_staff:
            return False  # Users can't change status

        if self.status in {PAID, DECLINED}:
            return False

        return True

    @property
    def value(self):
        return self.paid_value or self.requested_value

    def get_absolute_url(self):
        return reverse('apply:projects:payments:detail', args=[self.pk])
예제 #15
0
from django.db import models
from django.core.exceptions import ObjectDoesNotExist
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db.models.signals import post_save, post_delete

from .signals import (
    post_reporting_signal, new_post_like_signal, inactive_post_like_signal
)

min_max_range = [
    MinValueValidator(0),
    MaxValueValidator(20)
]


def uploads_path(instance, filename):
    '''
    Function to organize the upload directory
    this way, every file is organized by username and management
    is a lot faster
    '''
    return '/'.join(['uploads', 'posts', filename])


class UserLikesPost(models.Model):
    user = models.ForeignKey('users.User', related_name='user_likes')
    post = models.ForeignKey('posts.Post', related_name='user_likes')

    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
예제 #16
0
파일: models.py 프로젝트: zspencer/calc
class SubmittedPriceList(models.Model):
    CONTRACTOR_SITE_CHOICES = [
        ('Customer', 'Customer/Offsite'),
        ('Contractor', 'Contractor/Onsite'),
        ('Both', 'Both'),
    ]

    STATUS_UNREVIEWED = 0
    STATUS_APPROVED = 1
    STATUS_RETIRED = 2
    STATUS_REJECTED = 3

    STATUS_CHOICES = (
        (STATUS_UNREVIEWED, 'unreviewed'),
        (STATUS_APPROVED, 'approved'),
        (STATUS_RETIRED, 'retired'),
        (STATUS_REJECTED, 'rejected'),
    )

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    # This is the equivalent of Contract.idv_piid.
    contract_number = models.CharField(
        max_length=128,
        help_text='This should be the full contract number, e.g. GS-XXX-XXXX.',
        validators=[
            RegexValidator(
                regex=r'^[a-zA-Z0-9-_]+$',
                message='Please use only letters, numbers, and dashes (-).')
        ],
    )
    vendor_name = models.CharField(max_length=128)
    schedule = models.CharField(max_length=128)
    is_small_business = models.BooleanField()
    contractor_site = models.CharField(verbose_name='Worksite',
                                       choices=CONTRACTOR_SITE_CHOICES,
                                       max_length=128)
    contract_start = models.DateField(
        null=True,
        blank=True,
    )
    contract_end = models.DateField(
        null=True,
        blank=True,
    )
    escalation_rate = models.FloatField(
        verbose_name='escalation rate (%)',
        validators=[
            MinValueValidator(MIN_ESCALATION_RATE),
            MaxValueValidator(MAX_ESCALATION_RATE)
        ])

    submitter = models.ForeignKey(User)

    status = models.IntegerField(choices=STATUS_CHOICES,
                                 default=STATUS_UNREVIEWED)
    status_changed_by = models.ForeignKey(User, related_name='+')
    status_changed_at = models.DateTimeField()

    uploaded_filename = models.CharField(
        max_length=128,
        help_text=('Name of the file that was uploaded, as it was called on '
                   'the uploader\'s system. For display purposes only.'))
    serialized_gleaned_data = models.TextField(
        help_text=('The JSON-serialized data from the upload, including '
                   'information about any rows that failed validation.'))

    def add_row(self, **kwargs):
        row = SubmittedPriceListRow(**kwargs)
        row.price_list = self
        row.save()
        return row

    def get_schedule_title(self):
        # We're importing here to avoid a circular import. Kinda icky.
        from .schedules.registry import get_class

        return get_class(self.schedule).title

    def get_business_size_string(self):
        # 'S' means 'Small Business' and 'O' means 'Other'
        if self.is_small_business:
            return 'S'
        return 'O'

    def _change_status(self, status, user):
        self.status = status
        self.status_changed_at = timezone.now()
        self.status_changed_by = user

        status_name = self.STATUS_CHOICES[status][1]
        logger.info(f'Price list with id {self.id} has been set to '
                    f'{status_name} by user id {user.id} ({user.email})')

    def approve(self, user):
        '''
        Approve this SubmittedPriceList. This causes its rows of pricing data
        to be converted to Contract models, which are then accessible via
        CALC's API and in the Data Explorer.
        '''
        self._change_status(self.STATUS_APPROVED, user)

        for row in self.rows.filter(is_muted=False):
            if row.contract_model is not None:
                raise AssertionError()

            contract = Contract(
                idv_piid=self.contract_number,
                contract_start=self.contract_start,
                contract_end=self.contract_end,
                vendor_name=self.vendor_name,
                labor_category=row.labor_category,
                education_level=row.education_level,
                min_years_experience=row.min_years_experience,
                contractor_site=self.contractor_site,
                schedule=self.get_schedule_title(),
                business_size=self.get_business_size_string(),
                sin=row.sin,
            )

            contract.adjust_contract_year()

            # Assuming the rate in the price list is the 'base rate'
            # Escalate the hourly_rate_yearX fields
            contract.escalate_hourly_rate_fields(row.base_year_rate,
                                                 self.escalation_rate)

            # Update current/next/second year price fields
            contract.update_price_fields()

            contract.full_clean(exclude=['piid'])
            contract.save()
            row.contract_model = contract
            row.save()

        self.save()

    def unreview(self, user):
        '''
        Mark this SubmittedPriceList as "unreviewed" and delete all associated
        Contract models. An "unreviewed" price list is one that has been
        either newly submitted or that has had modifications made to it and
        requires review (to approve or reject it) by an administrator.
        '''
        self._change_status(self.STATUS_UNREVIEWED, user)
        self._delete_associated_contracts()
        self.save()

    def retire(self, user):
        '''
        Mark this SubmittedPriceList as "retired" and delete all associated
        Contract models. Retiring a price list is for removing a once approved
        price list that is now either out-of-date or now otherwise invalid.
        '''
        self._change_status(self.STATUS_RETIRED, user)
        self._delete_associated_contracts()
        self.save()

    def reject(self, user):
        '''
        Reject this SubmittedPriceList. This method should be called on
        "unreviewed" price lists. It is the opposite of approving a price list.
        '''
        if self.status is not self.STATUS_UNREVIEWED:
            raise AssertionError()
        self._change_status(self.STATUS_REJECTED, user)
        self.save()

    def _delete_associated_contracts(self):
        for row in self.rows.all():
            if row.contract_model:
                row.contract_model.delete()
        self.save()

    def __str__(self):
        return "Price List for {}".format(self.contract_number)

    @classmethod
    def get_latest_by_contract_number(cls, contract_number):
        return cls.objects.filter(contract_number__iexact=contract_number
                                  ).latest('status_changed_at')
예제 #17
0
파일: models.py 프로젝트: niveKKumar/wger
class Ingredient(AbstractSubmissionModel, AbstractLicenseModel, models.Model):
    '''
    An ingredient, with some approximate nutrition values
    '''

    ENERGY_APPROXIMATION = 15
    '''
    How much the calculated energy from protein, etc. can deviate from the
    energy amount given (in percent).
    '''

    # Metaclass to set some other properties
    class Meta:
        ordering = ["name", ]

    language = models.ForeignKey(Language,
                                 verbose_name=_('Language'),
                                 editable=False,
                                 on_delete=models.CASCADE)

    creation_date = models.DateField(_('Date'), auto_now_add=True)
    update_date = models.DateField(_('Date'),
                                   auto_now=True,
                                   blank=True,
                                   editable=False)

    name = models.CharField(max_length=200,
                            verbose_name=_('Name'),)

    energy = models.IntegerField(verbose_name=_('Energy'),
                                 help_text=_('In kcal per 100g'))

    protein = models.DecimalField(decimal_places=3,
                                  max_digits=6,
                                  verbose_name=_('Protein'),
                                  help_text=_('In g per 100g of product'),
                                  validators=[MinValueValidator(0),
                                              MaxValueValidator(100)])

    carbohydrates = models.DecimalField(decimal_places=3,
                                        max_digits=6,
                                        verbose_name=_('Carbohydrates'),
                                        help_text=_('In g per 100g of product'),
                                        validators=[MinValueValidator(0),
                                                    MaxValueValidator(100)])

    carbohydrates_sugar = models.DecimalField(decimal_places=3,
                                              max_digits=6,
                                              blank=True,
                                              null=True,
                                              verbose_name=_('Sugar content in carbohydrates'),
                                              help_text=_('In g per 100g of product'),
                                              validators=[MinValueValidator(0),
                                                          MaxValueValidator(100)])

    fat = models.DecimalField(decimal_places=3,
                              max_digits=6,
                              verbose_name=_('Fat'),
                              help_text=_('In g per 100g of product'),
                              validators=[MinValueValidator(0),
                                          MaxValueValidator(100)])

    fat_saturated = models.DecimalField(decimal_places=3,
                                        max_digits=6,
                                        blank=True,
                                        null=True,
                                        verbose_name=_('Saturated fat content in fats'),
                                        help_text=_('In g per 100g of product'),
                                        validators=[MinValueValidator(0),
                                                    MaxValueValidator(100)])

    fibres = models.DecimalField(decimal_places=3,
                                 max_digits=6,
                                 blank=True,
                                 null=True,
                                 verbose_name=_('Fibres'),
                                 help_text=_('In g per 100g of product'),
                                 validators=[MinValueValidator(0),
                                             MaxValueValidator(100)])

    sodium = models.DecimalField(decimal_places=3,
                                 max_digits=6,
                                 blank=True,
                                 null=True,
                                 verbose_name=_('Sodium'),
                                 help_text=_('In g per 100g of product'),
                                 validators=[MinValueValidator(0),
                                             MaxValueValidator(100)])

    #
    # Django methods
    #

    def get_absolute_url(self):
        '''
        Returns the canonical URL to view this object
        '''
        return reverse('nutrition:ingredient:view',
                       kwargs={'id': self.id, 'slug': slugify(self.name)})

    def clean(self):
        '''
        Do a very broad sanity check on the nutritional values according to
        the following rules:
        - 1g of protein: 4kcal
        - 1g of carbohydrates: 4kcal
        - 1g of fat: 9kcal

        The sum is then compared to the given total energy, with ENERGY_APPROXIMATION
        percent tolerance.
        '''

        # Note: calculations in 100 grams, to save us the '/100' everywhere
        energy_protein = 0
        if self.protein:
            energy_protein = self.protein * ENERGY_FACTOR['protein']['kg']

        energy_carbohydrates = 0
        if self.carbohydrates:
            energy_carbohydrates = self.carbohydrates * ENERGY_FACTOR['carbohydrates']['kg']

        energy_fat = 0
        if self.fat:
            # TODO: for some reason, during the tests the fat value is not
            #       converted to decimal (django 1.9)
            energy_fat = Decimal(self.fat * ENERGY_FACTOR['fat']['kg'])

        energy_calculated = energy_protein + energy_carbohydrates + energy_fat

        # Compare the values, but be generous
        if self.energy:
            energy_upper = self.energy * (1 + (self.ENERGY_APPROXIMATION / Decimal(100.0)))
            energy_lower = self.energy * (1 - (self.ENERGY_APPROXIMATION / Decimal(100.0)))

            if not ((energy_upper > energy_calculated) and (energy_calculated > energy_lower)):
                raise ValidationError(_('Total energy is not the approximate sum of the energy '
                                        'provided by protein, carbohydrates and fat.'))

    def save(self, *args, **kwargs):
        '''
        Reset the cache
        '''

        super(Ingredient, self).save(*args, **kwargs)
        cache.delete(cache_mapper.get_ingredient_key(self.id))

    def __str__(self):
        '''
        Return a more human-readable representation
        '''
        return self.name

    def __eq__(self, other):
        '''
        Compare ingredients based on their values, not like django on their PKs
        '''

        logger.debug('Overwritten behaviour: comparing ingredients on values, not PK.')
        equal = True
        if isinstance(other, self.__class__):
            for i in self._meta.fields:
                if (hasattr(self, i.name) and hasattr(other, i.name) and
                   (getattr(self, i.name, None) != getattr(other, i.name, None))):
                        equal = False
        else:
            equal = False
        return equal

    def __hash__(self):
        """
        Define a hash function

        This is rather unnecessary, but it seems that newer versions of django
        have a problem when the __eq__ function is implemented, but not the
        __hash__ one. Returning hash(pk) is also django's default.

        :return: hash(pk)
        """
        return hash(self.pk)

    #
    # Own methods
    #
    def compare_with_database(self):
        '''
        Compares the current ingredient with the version saved in the database.

        If the current object has no PK, returns false
        '''
        if not self.pk:
            return False

        ingredient = Ingredient.objects.get(pk=self.pk)
        if self != ingredient:
            return False
        else:
            return True

    def send_email(self, request):
        '''
        Sends an email after being successfully added to the database (for user
        submitted ingredients only)
        '''
        try:
            user = User.objects.get(username=self.license_author)
        except User.DoesNotExist:
            return

        if self.license_author and user.email:
            translation.activate(user.userprofile.notification_language.short_name)
            url = request.build_absolute_uri(self.get_absolute_url())
            subject = _('Ingredient was successfully added to the general database')
            context = {
                'ingredient': self.name,
                'url': url,
                'site': Site.objects.get_current().domain
            }
            message = render_to_string('ingredient/email_new.tpl', context)
            mail.send_mail(subject,
                           message,
                           settings.WGER_SETTINGS['EMAIL_FROM'],
                           [user.email],
                           fail_silently=True)

    def set_author(self, request):
        if request.user.has_perm('nutrition.add_ingredient'):
            self.status = Ingredient.STATUS_ACCEPTED
            if not self.license_author:
                self.license_author = request.get_host().split(':')[0]
        else:
            if not self.license_author:
                self.license_author = request.user.username

            # Send email to administrator
            subject = _('New user submitted ingredient')
            message = _(u'''The user {0} submitted a new ingredient "{1}".'''.format(
                request.user.username, self.name))
            mail.mail_admins(subject,
                             message,
                             fail_silently=True)

    def get_owner_object(self):
        '''
        Ingredient has no owner information
        '''
        return False
예제 #18
0
class Device(PrimaryModel, ConfigContextModel, StatusModel):
    """
    A Device represents a piece of physical hardware mounted within a Rack. Each Device is assigned a DeviceType,
    DeviceRole, and (optionally) a Platform. Device names are not required, however if one is set it must be unique.

    Each Device must be assigned to a site, and optionally to a rack within that site. Associating a device with a
    particular rack face or unit is optional (for example, vertically mounted PDUs do not consume rack units).

    When a new Device is created, console/power/interface/device bay components are created along with it as dictated
    by the component templates assigned to its DeviceType. Components can also be added, modified, or deleted after the
    creation of a Device.
    """

    device_type = models.ForeignKey(to="dcim.DeviceType",
                                    on_delete=models.PROTECT,
                                    related_name="instances")
    device_role = models.ForeignKey(to="dcim.DeviceRole",
                                    on_delete=models.PROTECT,
                                    related_name="devices")
    tenant = models.ForeignKey(
        to="tenancy.Tenant",
        on_delete=models.PROTECT,
        related_name="devices",
        blank=True,
        null=True,
    )
    platform = models.ForeignKey(
        to="dcim.Platform",
        on_delete=models.SET_NULL,
        related_name="devices",
        blank=True,
        null=True,
    )
    name = models.CharField(max_length=64,
                            blank=True,
                            null=True,
                            db_index=True)
    _name = NaturalOrderingField(target_field="name",
                                 max_length=100,
                                 blank=True,
                                 null=True,
                                 db_index=True)
    serial = models.CharField(max_length=255,
                              blank=True,
                              verbose_name="Serial number",
                              db_index=True)
    asset_tag = models.CharField(
        max_length=50,
        blank=True,
        null=True,
        unique=True,
        verbose_name="Asset tag",
        help_text="A unique tag used to identify this device",
    )
    site = models.ForeignKey(to="dcim.Site",
                             on_delete=models.PROTECT,
                             related_name="devices")
    rack = models.ForeignKey(
        to="dcim.Rack",
        on_delete=models.PROTECT,
        related_name="devices",
        blank=True,
        null=True,
    )
    position = models.PositiveSmallIntegerField(
        blank=True,
        null=True,
        validators=[MinValueValidator(1)],
        verbose_name="Position (U)",
        help_text="The lowest-numbered unit occupied by the device",
    )
    face = models.CharField(max_length=50,
                            blank=True,
                            choices=DeviceFaceChoices,
                            verbose_name="Rack face")
    primary_ip4 = models.OneToOneField(
        to="ipam.IPAddress",
        on_delete=models.SET_NULL,
        related_name="primary_ip4_for",
        blank=True,
        null=True,
        verbose_name="Primary IPv4",
    )
    primary_ip6 = models.OneToOneField(
        to="ipam.IPAddress",
        on_delete=models.SET_NULL,
        related_name="primary_ip6_for",
        blank=True,
        null=True,
        verbose_name="Primary IPv6",
    )
    cluster = models.ForeignKey(
        to="virtualization.Cluster",
        on_delete=models.SET_NULL,
        related_name="devices",
        blank=True,
        null=True,
    )
    virtual_chassis = models.ForeignKey(
        to="VirtualChassis",
        on_delete=models.SET_NULL,
        related_name="members",
        blank=True,
        null=True,
    )
    vc_position = models.PositiveSmallIntegerField(
        blank=True, null=True, validators=[MaxValueValidator(255)])
    vc_priority = models.PositiveSmallIntegerField(
        blank=True, null=True, validators=[MaxValueValidator(255)])
    comments = models.TextField(blank=True)
    images = GenericRelation(to="extras.ImageAttachment")

    secrets_group = models.ForeignKey(
        to="extras.SecretsGroup",
        on_delete=models.SET_NULL,
        default=None,
        blank=True,
        null=True,
    )

    objects = ConfigContextModelQuerySet.as_manager()

    csv_headers = [
        "name",
        "device_role",
        "tenant",
        "manufacturer",
        "device_type",
        "platform",
        "serial",
        "asset_tag",
        "status",
        "site",
        "rack_group",
        "rack_name",
        "position",
        "face",
        "secrets_group",
        "primary_ip",
        "comments",
    ]
    clone_fields = [
        "device_type",
        "device_role",
        "tenant",
        "platform",
        "site",
        "rack",
        "status",
        "cluster",
        "secrets_group",
    ]

    class Meta:
        ordering = ("_name", )  # Name may be null
        unique_together = (
            ("site", "tenant", "name"),  # See validate_unique below
            ("rack", "position", "face"),
            ("virtual_chassis", "vc_position"),
        )

    def __str__(self):
        return self.display or super().__str__()

    def get_absolute_url(self):
        return reverse("dcim:device", args=[self.pk])

    def validate_unique(self, exclude=None):

        # Check for a duplicate name on a device assigned to the same Site and no Tenant. This is necessary
        # because Django does not consider two NULL fields to be equal, and thus will not trigger a violation
        # of the uniqueness constraint without manual intervention.
        if self.name and hasattr(self, "site") and self.tenant is None:
            if Device.objects.exclude(pk=self.pk).filter(name=self.name,
                                                         site=self.site,
                                                         tenant__isnull=True):
                raise ValidationError(
                    {"name": "A device with this name already exists."})

        super().validate_unique(exclude)

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

        # Validate site/rack combination
        if self.rack and self.site != self.rack.site:
            raise ValidationError({
                "rack":
                f"Rack {self.rack} does not belong to site {self.site}.",
            })

        if self.rack is None:
            if self.face:
                raise ValidationError({
                    "face":
                    "Cannot select a rack face without assigning a rack.",
                })
            if self.position:
                raise ValidationError({
                    "position":
                    "Cannot select a rack position without assigning a rack.",
                })

        # Validate position/face combination
        if self.position and not self.face:
            raise ValidationError({
                "face":
                "Must specify rack face when defining rack position.",
            })

        # Prevent 0U devices from being assigned to a specific position
        if self.position and self.device_type.u_height == 0:
            raise ValidationError({
                "position":
                f"A U0 device type ({self.device_type}) cannot be assigned to a rack position."
            })

        if self.rack:

            try:
                # Child devices cannot be assigned to a rack face/unit
                if self.device_type.is_child_device and self.face:
                    raise ValidationError({
                        "face":
                        "Child device types cannot be assigned to a rack face. This is an attribute of the "
                        "parent device."
                    })
                if self.device_type.is_child_device and self.position:
                    raise ValidationError({
                        "position":
                        "Child device types cannot be assigned to a rack position. This is an attribute of "
                        "the parent device."
                    })

                # Validate rack space
                rack_face = self.face if not self.device_type.is_full_depth else None
                exclude_list = [self.pk] if self.present_in_database else []
                available_units = self.rack.get_available_units(
                    u_height=self.device_type.u_height,
                    rack_face=rack_face,
                    exclude=exclude_list,
                )
                if self.position and self.position not in available_units:
                    raise ValidationError({
                        "position":
                        f"U{self.position} is already occupied or does not have sufficient space to "
                        f"accommodate this device type: {self.device_type} ({self.device_type.u_height}U)"
                    })

            except DeviceType.DoesNotExist:
                pass

        # Validate primary IP addresses
        vc_interfaces = self.vc_interfaces.all()
        if self.primary_ip4:
            if self.primary_ip4.family != 4:
                raise ValidationError({
                    "primary_ip4":
                    f"{self.primary_ip4} is not an IPv4 address."
                })
            if self.primary_ip4.assigned_object in vc_interfaces:
                pass
            elif (self.primary_ip4.nat_inside is not None
                  and self.primary_ip4.nat_inside.assigned_object
                  in vc_interfaces):
                pass
            else:
                raise ValidationError({
                    "primary_ip4":
                    f"The specified IP address ({self.primary_ip4}) is not assigned to this device."
                })
        if self.primary_ip6:
            if self.primary_ip6.family != 6:
                raise ValidationError({
                    "primary_ip6":
                    f"{self.primary_ip6} is not an IPv6 address."
                })
            if self.primary_ip6.assigned_object in vc_interfaces:
                pass
            elif (self.primary_ip6.nat_inside is not None
                  and self.primary_ip6.nat_inside.assigned_object
                  in vc_interfaces):
                pass
            else:
                raise ValidationError({
                    "primary_ip6":
                    f"The specified IP address ({self.primary_ip6}) is not assigned to this device."
                })

        # Validate manufacturer/platform
        if hasattr(self, "device_type") and self.platform:
            if self.platform.manufacturer and self.platform.manufacturer != self.device_type.manufacturer:
                raise ValidationError({
                    "platform":
                    "The assigned platform is limited to {} device types, but this device's type belongs "
                    "to {}.".format(self.platform.manufacturer,
                                    self.device_type.manufacturer)
                })

        # A Device can only be assigned to a Cluster in the same Site (or no Site)
        if self.cluster and self.cluster.site is not None and self.cluster.site != self.site:
            raise ValidationError({
                "cluster":
                "The assigned cluster belongs to a different site ({})".format(
                    self.cluster.site)
            })

        # Validate virtual chassis assignment
        if self.virtual_chassis and self.vc_position is None:
            raise ValidationError({
                "vc_position":
                "A device assigned to a virtual chassis must have its position defined."
            })

        # Validate device isn't being removed from a virtual chassis when it is the master
        if not self.virtual_chassis and self.present_in_database:
            existing_virtual_chassis = Device.objects.get(
                id=self.id).virtual_chassis
            if existing_virtual_chassis and existing_virtual_chassis.master == self:
                raise ValidationError({
                    "virtual_chassis":
                    "The master device for the virtual chassis ({}) may not be removed"
                    .format(existing_virtual_chassis)
                })

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

        is_new = not self.present_in_database

        super().save(*args, **kwargs)

        # If this is a new Device, instantiate all of the related components per the DeviceType definition
        if is_new:
            ConsolePort.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.consoleporttemplates.all()
            ])
            ConsoleServerPort.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.consoleserverporttemplates.all()
            ])
            PowerPort.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.powerporttemplates.all()
            ])
            PowerOutlet.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.poweroutlettemplates.all()
            ])
            Interface.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.interfacetemplates.all()
            ])
            RearPort.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.rearporttemplates.all()
            ])
            FrontPort.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.frontporttemplates.all()
            ])
            DeviceBay.objects.bulk_create([
                x.instantiate(self)
                for x in self.device_type.devicebaytemplates.all()
            ])

        # Update Site and Rack assignment for any child Devices
        devices = Device.objects.filter(parent_bay__device=self)
        for device in devices:
            device.site = self.site
            device.rack = self.rack
            device.save()

    def to_csv(self):
        return (
            self.name or "",
            self.device_role.name,
            self.tenant.name if self.tenant else None,
            self.device_type.manufacturer.name,
            self.device_type.model,
            self.platform.name if self.platform else None,
            self.serial,
            self.asset_tag,
            self.get_status_display(),
            self.site.name,
            self.rack.group.name if self.rack and self.rack.group else None,
            self.rack.name if self.rack else None,
            self.position,
            self.get_face_display(),
            self.secrets_group.name if self.secrets_group else None,
            self.primary_ip if self.primary_ip else None,
            self.comments,
        )

    @property
    def display(self):
        if self.name:
            return self.name
        elif self.virtual_chassis:
            return f"{self.virtual_chassis.name}:{self.vc_position} ({self.pk})"
        elif self.device_type:
            return f"{self.device_type.manufacturer} {self.device_type.model} ({self.pk})"
        else:
            return ""  # Device has not yet been created

    @property
    def identifier(self):
        """
        Return the device name if set; otherwise return the Device's primary key as {pk}
        """
        if self.name is not None:
            return self.name
        return "{{{}}}".format(self.pk)

    @property
    def primary_ip(self):
        if get_settings_or_config("PREFER_IPV4") and self.primary_ip4:
            return self.primary_ip4
        elif self.primary_ip6:
            return self.primary_ip6
        elif self.primary_ip4:
            return self.primary_ip4
        else:
            return None

    def get_vc_master(self):
        """
        If this Device is a VirtualChassis member, return the VC master. Otherwise, return None.
        """
        return self.virtual_chassis.master if self.virtual_chassis else None

    @property
    def vc_interfaces(self):
        """
        Return a QuerySet matching all Interfaces assigned to this Device or, if this Device is a VC master, to another
        Device belonging to the same VirtualChassis.
        """
        filter = Q(device=self)
        if self.virtual_chassis and self.virtual_chassis.master == self:
            filter |= Q(device__virtual_chassis=self.virtual_chassis,
                        mgmt_only=False)
        return Interface.objects.filter(filter)

    def get_cables(self, pk_list=False):
        """
        Return a QuerySet or PK list matching all Cables connected to a component of this Device.
        """
        from .cables import Cable

        cable_pks = []
        for component_model in [
                ConsolePort,
                ConsoleServerPort,
                PowerPort,
                PowerOutlet,
                Interface,
                FrontPort,
                RearPort,
        ]:
            cable_pks += component_model.objects.filter(
                device=self, cable__isnull=False).values_list("cable",
                                                              flat=True)
        if pk_list:
            return cable_pks
        return Cable.objects.filter(pk__in=cable_pks)

    def get_children(self):
        """
        Return the set of child Devices installed in DeviceBays within this Device.
        """
        return Device.objects.filter(parent_bay__device=self.pk)
예제 #19
0
class RefuelingStop(models.Model):

    equipment = models.ForeignKey(Equipment,
                                  verbose_name=_("equipment"),
                                  on_delete=models.CASCADE)
    datetime = models.DateTimeField(default=timezone.now, db_index=True)
    mileage = models.DecimalField(
        _("mileage"),
        max_digits=9,
        decimal_places=2,
        validators=[MinValueValidator(Decimal("0.01"))],
    )
    distance = models.DecimalField(
        _("distance"),
        max_digits=9,
        decimal_places=2,
        blank=True,
        null=True,
        validators=[MinValueValidator(Decimal("0.01"))],
    )
    liters = models.DecimalField(
        _("refueled liters"),
        max_digits=5,
        decimal_places=2,
        default=Decimal(0),
        validators=[MinValueValidator(Decimal("0.01"))],
    )
    price_per_liter = models.DecimalField(
        _("price per liter"),
        max_digits=6,
        decimal_places=3,
        validators=[MinValueValidator(Decimal("0.001"))],
    )
    average_consumption = models.DecimalField(_("average consumption"),
                                              max_digits=6,
                                              decimal_places=2,
                                              null=True,
                                              blank=True)

    def __str__(self):
        return "{}: {} {} {} {} {}".format(
            self.id,
            date_filter(self.datetime),
            self.liters,
            _("l"),
            self.mileage,
            _("km"),
        )

    @cached_property
    def older_refueling_stop(self):
        older_refueling_stop = (RefuelingStop.objects.filter(
            equipment_id=self.equipment.id, mileage__lt=self.mileage).exclude(
                id=self.id).order_by("-mileage").first())
        return older_refueling_stop

    @cached_property
    def younger_refueling_stop(self):
        younger_refueling_stop = (RefuelingStop.objects.filter(
            equipment_id=self.equipment.id, mileage__gt=self.mileage).exclude(
                id=self.id).order_by("mileage").first())
        return younger_refueling_stop

    def save(self, *args, **kwargs):
        # Save average consumption
        if self.equipment:
            self.calc_average_consumption()
            # Update last_refueling_stop in equipment object/table
            if (not self.equipment.last_refueling_stop
                    or not self.younger_refueling_stop):
                self.equipment.last_refueling_stop = self.datetime
                self.equipment.save()
        super(RefuelingStop, self).save(*args, **kwargs)

    def calc_average_consumption(self):
        if self.older_refueling_stop is None:
            last_mileage = Decimal(0)
        else:
            last_mileage = self.older_refueling_stop.mileage
        self.distance = self.mileage - last_mileage
        self.average_consumption = round(self.liters / self.distance * 100, 2)
예제 #20
0
class OrderLine(models.Model):
    order = models.ForeignKey(Order,
                              related_name="lines",
                              editable=False,
                              on_delete=models.CASCADE)
    variant = models.ForeignKey(
        "product.ProductVariant",
        related_name="order_lines",
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    # max_length is as produced by ProductVariant's display_product method
    product_name = models.CharField(max_length=386)
    variant_name = models.CharField(max_length=255, default="", blank=True)
    translated_product_name = models.CharField(max_length=386,
                                               default="",
                                               blank=True)
    translated_variant_name = models.CharField(max_length=255,
                                               default="",
                                               blank=True)
    product_sku = models.CharField(max_length=255)
    is_shipping_required = models.BooleanField()
    quantity = models.IntegerField(validators=[MinValueValidator(1)])
    quantity_fulfilled = models.IntegerField(validators=[MinValueValidator(0)],
                                             default=0)

    currency = models.CharField(
        max_length=settings.DEFAULT_CURRENCY_CODE_LENGTH,
        default=settings.DEFAULT_CURRENCY,
    )

    unit_price_net_amount = models.DecimalField(
        max_digits=settings.DEFAULT_MAX_DIGITS,
        decimal_places=settings.DEFAULT_DECIMAL_PLACES,
    )
    unit_price_net = MoneyField(amount_field="unit_price_net_amount",
                                currency_field="currency")

    unit_price_gross_amount = models.DecimalField(
        max_digits=settings.DEFAULT_MAX_DIGITS,
        decimal_places=settings.DEFAULT_DECIMAL_PLACES,
    )
    unit_price_gross = MoneyField(amount_field="unit_price_gross_amount",
                                  currency_field="currency")

    unit_price = TaxedMoneyField(
        net_amount_field="unit_price_net_amount",
        gross_amount_field="unit_price_gross_amount",
        currency="currency",
    )

    tax_rate = models.DecimalField(max_digits=5,
                                   decimal_places=2,
                                   default=Decimal("0.0"))

    objects = OrderLineQueryset.as_manager()

    class Meta:
        ordering = ("pk", )

    def __str__(self):
        return (f"{self.product_name} ({self.variant_name})"
                if self.variant_name else self.product_name)

    def get_total(self):
        return self.unit_price * self.quantity

    @property
    def quantity_unfulfilled(self):
        return self.quantity - self.quantity_fulfilled

    @property
    def is_digital(self) -> Optional[bool]:
        """Check if a variant is digital and contains digital content."""
        if not self.variant:
            return None
        is_digital = self.variant.is_digital()
        has_digital = hasattr(self.variant, "digital_content")
        return is_digital and has_digital
예제 #21
0
class Hint(models.Model):
    """ A class to represent an hint """
    class Meta:
        verbose_name_plural = "Hints"

    puzzle = models.ForeignKey(
        Puzzle,
        on_delete=models.CASCADE,
        help_text="The puzzle that this automated response is related to")
    text = models.CharField(max_length=400, help_text="The text to display")
    time = models.DurationField(
        verbose_name='Delay',
        help_text=('Time after anyone on the team first loads the puzzle'),
        validators=(MinValueValidator(timedelta(seconds=0)), ),
    )
    number_eurekas = models.IntegerField(
        verbose_name='Number required',
        help_text=(
            'How many Eurekas are reguired to trigger the shorter time'),
        default=1,
    )
    eurekas = models.ManyToManyField(
        'Eureka',
        verbose_name='Eureka conditions',
        blank=True,
        help_text="Eurekas that are a prerequisite for shorter time")
    short_time = models.DurationField(
        verbose_name='Shorter Delay',
        help_text=('Time after all the associated Eurekas were found'),
        validators=(MinValueValidator(timedelta(seconds=0)), ),
    )

    def __str__(self):
        return str(self.time) + " => " + self.text

    @property
    def compact_id(self):
        return self.id

    def delay_for_team(self, team):
        """Returns how long until the hint unlocks for the given team.

        Parameters as for `unlocked_by`.
        """
        if team is None:
            return self.time
        else:
            if self.eurekas.all().count() > 0:
                teams_eurekas = team.teameurekalink_set.all()
                start_time = self.starting_time_for_team(team)
                eureka_times = []
                for eureka in self.eurekas.all():
                    for team_eureka in teams_eurekas:
                        if eureka == team_eureka.eureka:
                            eureka_times.append(team_eureka.time - start_time)
                if len(eureka_times) >= self.number_eurekas:
                    return min(self.time, max(eureka_times) + self.short_time)
                else:
                    return self.time
            else:
                return self.time

    def starting_time_for_team(self, team):
        return self.puzzle.starting_time_for_team(team)
예제 #22
0
class FilterBookForm(Form):
    
    author = ModelChoiceField(queryset=Author.objects.all())
    notation = IntegerField(validators=[MaxValueValidator(5), MinValueValidator(0)])
예제 #23
0
class Repository(BaseModel):
    class Meta:
        unique_together = [
            ('provider_namespace', 'name'),
            ('provider_namespace', 'original_name'),
        ]
        ordering = ('provider_namespace', 'name')

    # Foreign keys
    owners = models.ManyToManyField(
        settings.AUTH_USER_MODEL,
        related_name='repositories'
    )
    provider_namespace = models.ForeignKey(
        ProviderNamespace,
        related_name='repositories',
        on_delete=models.CASCADE,
    )
    readme = models.ForeignKey(
        'Readme',
        null=True,
        on_delete=models.SET_NULL,
        related_name='+',
    )

    # Fields
    name = models.CharField(max_length=256)
    original_name = models.CharField(max_length=256, null=False)
    format = models.CharField(max_length=16, null=True,
                              choices=constants.RepositoryFormat.choices())
    description = fields.TruncatingCharField(
        max_length=255, blank=True, default='')
    import_branch = models.CharField(max_length=256, null=True)
    is_enabled = models.BooleanField(default=False)

    # Repository attributes
    commit = models.CharField(max_length=256, blank=True, default='')
    commit_message = fields.TruncatingCharField(
        max_length=256, blank=True, default='')
    commit_url = models.CharField(max_length=256, blank=True, default='')
    commit_created = models.DateTimeField(
        null=True, verbose_name="Last Commit DateTime")
    stargazers_count = models.IntegerField(default=0)
    watchers_count = models.IntegerField(default=0)
    forks_count = models.IntegerField(default=0)
    open_issues_count = models.IntegerField(default=0)
    travis_status_url = models.CharField(
        max_length=256,
        blank=True,
        default='',
        verbose_name="Travis Build Status"
    )
    travis_build_url = models.CharField(
        max_length=256,
        blank=True,
        default='',
        verbose_name="Travis Build URL"
    )
    issue_tracker_url = models.CharField(
        max_length=256,
        blank=True,
        null=True,
        verbose_name="Issue Tracker URL",
    )
    download_count = models.IntegerField(
        default=0
    )
    deprecated = models.BooleanField(
        default=False,
    )
    community_score = models.FloatField(
        null=True
    )
    community_survey_count = models.IntegerField(
        default=0
    )

    quality_score = models.FloatField(
        null=True,
        validators=[MinValueValidator(0.0), MaxValueValidator(5.0)],
    )
    quality_score_date = models.DateTimeField(
        null=True,
        verbose_name="DateTime last scored",
    )

    is_new = models.BooleanField(
        default=False,
    )

    @property
    def clone_url(self):
        return "https://github.com/{user}/{repo}.git".format(
            user=self.provider_namespace.name,
            repo=self.original_name
        )

    @property
    def github_user(self):
        return self.provider_namespace.name

    @property
    def github_repo(self):
        return self.original_name

    @property
    def content_counts(self):
        return Content.objects \
            .filter(repository=self.pk) \
            .values('content_type__name') \
            .annotate(count=models.Count('content_type__name')) \
            .order_by('content_type__name')

    def get_absolute_url(self):
        return reverse('api:repository_detail', args=(self.pk,))

    def get_download_url(self, ref=None):
        download_url = self.provider_namespace.provider.download_url

        if ref is None:
            last_version = self.last_version()
            if last_version:
                ref = last_version.tag
            else:
                ref = self.import_branch

        return download_url.format(
            username=self.provider_namespace.name,
            repository=self.original_name,
            ref=ref,
        )

    def all_versions(self):
        return sorted(self.versions.filter(version__isnull=False).all(),
                      key=operator.attrgetter('version'),
                      reverse=True)

    def last_version(self):
        versions = self.all_versions()
        if versions:
            return versions[0]
        return None
예제 #24
0
class Store(models.Model, CachedTreeItem, base.TranslationStore):
    """A model representing a translation store (i.e. a PO or XLIFF file)."""

    UnitClass = Unit
    Name = "Model Store"
    is_dir = False

    file = TranslationStoreField(max_length=255,
                                 storage=fs,
                                 db_index=True,
                                 null=False,
                                 editable=False)

    parent = models.ForeignKey('pootle_app.Directory',
                               related_name='child_stores',
                               db_index=True,
                               editable=False)

    translation_project_fk = 'pootle_translationproject.TranslationProject'
    translation_project = models.ForeignKey(translation_project_fk,
                                            related_name='stores',
                                            db_index=True,
                                            editable=False)

    filetype = models.ForeignKey(Format,
                                 related_name='stores',
                                 null=True,
                                 blank=True,
                                 db_index=True)
    is_template = models.BooleanField(default=False)

    # any changes to the `pootle_path` field may require updating the schema
    # see migration 0007_case_sensitive_schema.py
    pootle_path = models.CharField(max_length=255,
                                   null=False,
                                   unique=True,
                                   db_index=True,
                                   verbose_name=_("Path"))
    # any changes to the `name` field may require updating the schema
    # see migration 0007_case_sensitive_schema.py
    name = models.CharField(max_length=128,
                            null=False,
                            editable=False,
                            validators=[validate_no_slashes])

    file_mtime = models.DateTimeField(default=datetime_min)
    state = models.IntegerField(null=False,
                                default=NEW,
                                editable=False,
                                db_index=True)
    creation_time = models.DateTimeField(auto_now_add=True,
                                         db_index=True,
                                         editable=False,
                                         null=True)
    last_sync_revision = models.IntegerField(db_index=True,
                                             null=True,
                                             blank=True)
    obsolete = models.BooleanField(default=False)

    # this is calculated from virtualfolders if installed and linked
    priority = models.FloatField(db_index=True,
                                 default=1,
                                 validators=[MinValueValidator(0)])

    objects = StoreManager()
    simple_objects = models.Manager()

    class Meta(object):
        ordering = ['pootle_path']
        unique_together = ('parent', 'name')

    # # # # # # # # # # # # # #  Properties # # # # # # # # # # # # # # # # # #

    @property
    def code(self):
        return self.name.replace('.', '-')

    @property
    def real_path(self):
        return self.file.name

    @property
    def has_terminology(self):
        """is this a project specific terminology store?"""
        # TODO: Consider if this should check if the store belongs to a
        # terminology project. Probably not, in case this might be called over
        # several files in a project.
        return self.name.startswith('pootle-terminology')

    @property
    def units(self):
        return self.unit_set.filter(state__gt=OBSOLETE).order_by('index')

    @units.setter
    def units(self, value):
        """Null setter to avoid tracebacks if :meth:`TranslationStore.__init__`
        is called.
        """
        pass

    # # # # # # # # # # # # # #  Methods # # # # # # # # # # # # # # # # # # #

    @cached_property
    def path(self):
        """Returns just the path part omitting language and project codes.

        If the `pootle_path` of a :cls:`Store` object `store` is
        `/af/project/dir1/dir2/file.po`, `store.path` will return
        `dir1/dir2/file.po`.
        """
        return to_tp_relative_path(self.pootle_path)

    def __init__(self, *args, **kwargs):
        super(Store, self).__init__(*args, **kwargs)

    def __unicode__(self):
        return unicode(self.pootle_path)

    def __str__(self):
        return str(self.syncer.convert())

    def save(self, *args, **kwargs):
        created = not self.id
        self.pootle_path = self.parent.pootle_path + self.name

        # Force validation of fields.
        self.full_clean()

        super(Store, self).save(*args, **kwargs)
        if created:
            store_log(user='******',
                      action=STORE_ADDED,
                      path=self.pootle_path,
                      store=self.id)

    def delete(self, *args, **kwargs):
        store_log(user='******',
                  action=STORE_DELETED,
                  path=self.pootle_path,
                  store=self.id)

        lang = self.translation_project.language.code
        for unit in self.unit_set.iterator():
            action_log(user='******',
                       action=UNIT_DELETED,
                       lang=lang,
                       unit=unit.id,
                       translation='',
                       path=self.pootle_path)

        super(Store, self).delete(*args, **kwargs)

    def calculate_priority(self):
        if not vfolders_installed():
            return DEFAULT_PRIORITY

        from virtualfolder.models import VirtualFolder

        vfolders = VirtualFolder.objects
        priority = (vfolders.filter(stores=self).aggregate(
            priority=models.Max("priority"))["priority"])
        if priority is None:
            return DEFAULT_PRIORITY
        return priority

    def set_priority(self, priority=None):
        priority = (self.calculate_priority()
                    if priority is None else priority)

        if priority != self.priority:
            Store.objects.filter(pk=self.pk).update(priority=priority)

    def makeobsolete(self):
        """Make this store and all its units obsolete."""
        store_log(user='******',
                  action=STORE_OBSOLETE,
                  path=self.pootle_path,
                  store=self.id)

        lang = self.translation_project.language.code
        unit_query = self.unit_set.filter(state__gt=OBSOLETE)
        unit_ids = unit_query.values_list('id', flat=True)
        for unit_id in unit_ids:
            action_log(user='******',
                       action=UNIT_OBSOLETE,
                       lang=lang,
                       unit=unit_id,
                       translation='',
                       path=self.pootle_path)
        unit_query.update(state=OBSOLETE, index=0)
        self.obsolete = True
        self.save()

    def get_absolute_url(self):
        return reverse('pootle-tp-store-browse',
                       args=split_pootle_path(self.pootle_path))

    def get_translate_url(self, **kwargs):
        return u''.join([
            reverse("pootle-tp-store-translate",
                    args=split_pootle_path(self.pootle_path)),
            get_editor_filter(**kwargs)
        ])

    def findid_bulk(self, ids, unit_set=None):
        chunks = 200
        for i in xrange(0, len(ids), chunks):
            units = (unit_set
                     or self.unit_set).filter(id__in=ids[i:i + chunks])
            for unit in units.iterator():
                yield unit

    def get_file_mtime(self):
        disk_mtime = datetime.datetime.fromtimestamp(self.file.getpomtime()[0])
        # set microsecond to 0 for comparing with a time value without
        # microseconds
        disk_mtime = make_aware(disk_mtime.replace(microsecond=0))

        return disk_mtime

    def update_index(self, start, delta):
        with update_data_after(self):
            Unit.objects.filter(
                store_id=self.id,
                index__gte=start).update(index=operator.add(F('index'), delta))

    def mark_units_obsolete(self, uids_to_obsolete, update_revision=None):
        """Marks a bulk of units as obsolete.

        :param uids_to_obsolete: UIDs of the units to be marked as obsolete.
        :return: The number of units marked as obsolete.
        """
        obsoleted = 0
        for unit in self.findid_bulk(uids_to_obsolete):
            # Use the same (parent) object since units will
            # accumulate the list of cache attributes to clear
            # in the parent Store object
            unit.store = self
            if not unit.isobsolete():
                unit.makeobsolete()
                unit.save(revision=update_revision)
                obsoleted += 1

        return obsoleted

    @cached_property
    def data_tool(self):
        return data_tool.get(self.__class__)(self)

    @cached_property
    def updater(self):
        updaters = format_updaters.gather()
        updater_class = (updaters.get(self.filetype.name)
                         or updaters.get("default"))
        return updater_class(self)

    @cached_property
    def syncer(self):
        syncers = format_syncers.gather()
        syncer_class = (syncers.get(self.filetype.name)
                        or syncers.get("default"))
        return syncer_class(self)

    def record_submissions(self,
                           unit,
                           old_target,
                           old_state,
                           current_time,
                           user,
                           submission_type=None,
                           **kwargs):
        """Records all applicable submissions for `unit`.

        EXTREME HAZARD: this relies on implicit `._<field>_updated` members
        being available in `unit`. Let's look into replacing such members with
        something saner (#3895).
        """
        state_updated = kwargs.get("state_updated") or unit._state_updated
        target_updated = kwargs.get("target_updated") or unit._target_updated
        comment_updated = kwargs.get(
            "comment_updated") or unit._comment_updated

        create_subs = OrderedDict()

        if state_updated:
            create_subs[SubmissionFields.STATE] = [old_state, unit.state]

        if target_updated:
            create_subs[SubmissionFields.TARGET] = [old_target, unit.target_f]

        if comment_updated:
            create_subs[SubmissionFields.COMMENT] = [
                '', unit.translator_comment or ''
            ]

        if submission_type is None:
            submission_type = SubmissionTypes.SYSTEM

        subs_created = []
        for field in create_subs:
            subs_created.append(
                Submission(creation_time=current_time,
                           translation_project_id=self.translation_project_id,
                           submitter=user,
                           unit=unit,
                           store_id=self.id,
                           field=field,
                           type=submission_type,
                           old_value=create_subs[field][0],
                           new_value=create_subs[field][1]))
        if subs_created:
            unit.submission_set.add(*subs_created, bulk=False)

    def update(self,
               store,
               user=None,
               store_revision=None,
               submission_type=None,
               resolve_conflict=POOTLE_WINS,
               allow_add_and_obsolete=True):
        """Update DB with units from a ttk Store.

        :param store: a source `Store` instance from TTK.
        :param store_revision: revision at which the source `Store` was last
            synced.
        :param user: User to attribute updates to.
        :param submission_type: Submission type of saved updates.
        :param allow_add_and_obsolete: allow to add new units
            and make obsolete existing units
        """
        self.updater.update(store,
                            user=user,
                            store_revision=store_revision,
                            submission_type=submission_type,
                            resolve_conflict=resolve_conflict,
                            allow_add_and_obsolete=allow_add_and_obsolete)

    def deserialize(self, data):
        return StoreDeserialization(self).deserialize(data)

    def serialize(self):
        return StoreSerialization(self).serialize()

    def sync(self,
             update_structure=False,
             conservative=True,
             user=None,
             skip_missing=False,
             only_newer=True):
        """Sync file with translations from DB."""
        if skip_missing and not self.file.exists():
            return

        self.syncer.sync(update_structure=update_structure,
                         conservative=conservative,
                         user=user,
                         only_newer=only_newer)

# # # # # # # # # # # #  TranslationStore # # # # # # # # # # # # #

    suggestions_in_format = True

    def max_index(self):
        """Largest unit index"""
        return max_column(self.unit_set.all(), 'index', -1)

    def addunit(self, unit, index=None, user=None, update_revision=None):
        if index is None:
            index = self.max_index() + 1

        newunit = self.UnitClass(store=self, index=index)
        newunit.update(unit, user=user)

        if self.id:
            newunit.save(revision=update_revision, user=user)
        return newunit

    def findunits(self, source, obsolete=False):
        if not obsolete and hasattr(self, "sourceindex"):
            return super(Store, self).findunits(source)

        # find using hash instead of index
        source_hash = md5(source.encode("utf-8")).hexdigest()
        units = self.unit_set.filter(source_hash=source_hash)
        if obsolete:
            units = units.filter(state=OBSOLETE)
        else:
            units = units.filter(state__gt=OBSOLETE)
        if units.count():
            return units

    def findunit(self, source, obsolete=False):
        units = self.findunits(source, obsolete)
        if units:
            return units[0]

    def findid(self, id):
        if hasattr(self, "id_index"):
            return self.id_index.get(id, None)

        unitid_hash = md5(id.encode("utf-8")).hexdigest()
        try:
            return self.unit_set.get(unitid_hash=unitid_hash)
        except Unit.DoesNotExist:
            return None

    def header(self):
        # FIXME: we should store some metadata in db
        if self.file and hasattr(self.file.store, 'header'):
            return self.file.store.header()

    def get_max_unit_revision(self):
        return max_column(self.unit_set.all(), 'revision', 0)

    # # # TreeItem
    def get_parents(self):
        if self.parent.is_translationproject():
            return [self.translation_project]
        return [self.parent]
예제 #25
0
파일: models.py 프로젝트: neszt/freenas
class NTPServer(Model):
    ntp_address = models.CharField(
        verbose_name=_("Address"),
        max_length=120,
    )
    ntp_burst = models.BooleanField(
        verbose_name=_("Burst"),
        default=False,
        help_text=_(
            "When the server is reachable, send a burst of eight "
            "packets instead of the usual one. This is designed to improve"
            " timekeeping quality with the server command and s addresses."),
    )
    ntp_iburst = models.BooleanField(
        verbose_name=_("IBurst"),
        default=True,
        help_text=_(
            "When the server is unreachable, send a burst of eight"
            " packets instead of the usual one. This is designed to speed "
            "the initial synchronization acquisition with the server "
            "command and s addresses."),
    )
    ntp_prefer = models.BooleanField(
        verbose_name=_("Prefer"),
        default=False,
        help_text=_(
            "Marks the server as preferred. All other things being"
            " equal, this host will be chosen for synchronization among a "
            "set of correctly operating hosts."),
    )
    ntp_minpoll = models.IntegerField(
        verbose_name=_("Min. Poll"),
        default=6,
        validators=[MinValueValidator(4)],
        help_text=_("The minimum poll interval for NTP messages, as a "
                    "power of 2 in seconds. Defaults to 6 (64 s), but can be "
                    "decreased to a lower limit of 4 (16 s)"),
    )
    ntp_maxpoll = models.IntegerField(
        verbose_name=_("Max. Poll"),
        default=10,
        validators=[MaxValueValidator(17)],
        help_text=_(
            "The maximum poll interval for NTP messages, as a "
            "power of 2 in seconds. Defaults to 10 (1,024 s), but can be "
            "increased to an upper limit of 17 (36.4 h)"),
    )

    def __unicode__(self):
        return self.ntp_address

    def delete(self):
        super(NTPServer, self).delete()
        notifier().start("ix-ntpd")
        notifier().restart("ntpd")

    class Meta:
        verbose_name = _("NTP Server")
        verbose_name_plural = _("NTP Servers")
        ordering = ["ntp_address"]

    class FreeAdmin:
        icon_model = u"NTPServerIcon"
        icon_object = u"NTPServerIcon"
        icon_view = u"ViewNTPServerIcon"
        icon_add = u"AddNTPServerIcon"
예제 #26
0
class Student(models.Model):
    """
        Represents a student with personal information such as student ID, email, ect. 
        and class information, i.e courses currently enrolled in, ect.
    """
    name = models.CharField(max_length=25)
    idnumber = models.IntegerField(
        primary_key=True,
        validators=[MaxValueValidator(40000000),
                    MinValueValidator(30000000)])
    phonenumber = models.CharField(max_length=100)
    address = models.CharField(max_length=60)
    gender = models.CharField(max_length=25)

    pronouns = models.CharField(max_length=25)
    emergency = models.CharField(max_length=25)

    relationships = models.ManyToManyField('self',
                                           through='Relationship',
                                           symmetrical=False,
                                           related_name='related_to+')

    coursestaken = models.ManyToManyField('CourseInstance')
    coursesnow = models.ManyToManyField("CourseInstance",
                                        related_name='coursesnow')
    shoppingcart = models.ManyToManyField('CourseInstance',
                                          related_name='shoppingcart')

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

    def __str__(self):
        return self.name

    def get_shoppingcart(self):
        return ", ".join(shoppingcart.name
                         for shoppingcart in self.shoppingcart.all())

    get_shoppingcart.short_description = "Shopping Cart"

    def get_coursestaken(self):
        return ", ".join(coursestaken.name
                         for coursestaken in self.coursestaken.all())

    get_coursestaken.short_description = "Courses Taken"

    def add_relationship(self, person, status):
        relationship, created = Relationship.objects.get_or_create(
            from_student=self, to_student=student)
        if symm:
            student.add_relationship(self, status, False)
        return relationship

    def remove_relationship(self, person, status):
        Relationship.objects.filter(from_student=self,
                                    to_student=student,
                                    status=status).delete()
        if symm:
            student.remove_relationship(self, status, False)
        return

    def get_relationships(self, status):
        return self.relationships.filter(to_students__status=status,
                                         to_students__from_student=self)

    class Meta:
        permissions = (("can_view_student_list",
                        "Can view the list of student view"), )
예제 #27
0
파일: models.py 프로젝트: neszt/freenas
class Email(Model):
    em_fromemail = models.CharField(
        max_length=120,
        verbose_name=_("From email"),
        help_text=_(
            "An email address that the system will use for the "
            "sending address for mail it sends, eg: [email protected]"),
        default='',
    )
    em_outgoingserver = models.CharField(
        max_length=120,
        verbose_name=_("Outgoing mail server"),
        help_text=_("A hostname or ip that will accept our mail, for "
                    "instance mail.example.org, or 192.168.1.1"),
        blank=True,
    )
    em_port = models.IntegerField(
        default=25,
        validators=[MinValueValidator(1),
                    MaxValueValidator(65535)],
        help_text=_("An integer from 1 - 65535, generally will be 25, "
                    "465, or 587"),
        verbose_name=_("Port to connect to"),
    )
    em_security = models.CharField(max_length=120,
                                   choices=choices.SMTPAUTH_CHOICES,
                                   default="plain",
                                   help_text=_("encryption of the connection"),
                                   verbose_name=_("TLS/SSL"))
    em_smtp = models.BooleanField(verbose_name=_("Use SMTP Authentication"),
                                  default=False)
    em_user = models.CharField(
        blank=True,
        null=True,
        max_length=120,
        verbose_name=_("Username"),
        help_text=_("A username to authenticate to the remote server"),
    )
    em_pass = models.CharField(
        blank=True,
        null=True,
        max_length=120,
        verbose_name=_("Password"),
        help_text=_("A password to authenticate to the remote server"),
    )

    class Meta:
        verbose_name = _("Email")

    class FreeAdmin:
        deletable = False

    def __init__(self, *args, **kwargs):
        super(Email, self).__init__(*args, **kwargs)
        if self.em_pass:
            try:
                self.em_pass = notifier().pwenc_decrypt(self.em_pass)
            except:
                log.debug('Failed to decrypt email password', exc_info=True)
                self.em_pass = ''
        self._em_pass_encrypted = False

    def save(self, *args, **kwargs):
        if self.em_pass and not self._em_pass_encrypted:
            self.em_pass = notifier().pwenc_encrypt(self.em_pass)
            self._em_pass_encrypted = True
        return super(Email, self).save(*args, **kwargs)
예제 #28
0
class Tileset(models.Model):
    # base
    name = models.CharField(max_length=255)
    created_by = models.CharField(max_length=256)
    created_at = models.DateTimeField(auto_now_add=True)
    source_type = models.CharField(max_length=10, choices=SOURCE_TYPES)

    # server
    server_url = models.URLField(blank=True, null=True)
    server_username = models.CharField(blank=True, null=True, max_length=30)
    server_password = models.CharField(blank=True, null=True, max_length=30)

    # layer
    layer_name = models.CharField(blank=True, null=True, max_length=200)
    layer_zoom_start = models.IntegerField(default=0)
    layer_zoom_stop = models.IntegerField(default=12)

    # area
    bbox_x0 = models.DecimalField(
        max_digits=19,
        decimal_places=15,
        default=-180,
        validators=[MinValueValidator(-180),
                    MaxValueValidator(180)])
    bbox_x1 = models.DecimalField(
        max_digits=19,
        decimal_places=15,
        default=180,
        validators=[MinValueValidator(-180),
                    MaxValueValidator(180)])
    bbox_y0 = models.DecimalField(
        max_digits=19,
        decimal_places=15,
        default=-89.9,
        validators=[MinValueValidator(-89.9),
                    MaxValueValidator(89.9)])
    bbox_y1 = models.DecimalField(
        max_digits=19,
        decimal_places=15,
        default=89.9,
        validators=[MinValueValidator(-89.9),
                    MaxValueValidator(89.9)])

    # cache
    cache_type = models.CharField(max_length=10, choices=CACHE_TYPES)
    # file cache params
    directory_layout = models.CharField(max_length=20,
                                        choices=DIR_LAYOUTS,
                                        blank=True,
                                        null=True)
    directory = models.CharField(max_length=256,
                                 default=TILESET_CACHE_DIRECTORY,
                                 blank=True,
                                 null=True)
    # gpkg cache params
    filename = models.CharField(max_length=256, blank=True, null=True)
    table_name = models.CharField(max_length=128, blank=True, null=True)

    # mapnik params
    mapfile = models.FileField(blank=True, null=True, upload_to='mapfiles')

    # geonode params
    layer_uuid = models.CharField(max_length=36, null=True, blank=True)

    # size
    size = models.CharField('Size (MB)', default='0', max_length=128)

    def __unicode__(self):
        return self.name

    # terminate the seeding of this tileset!
    def stop(self):
        log.debug('tileset.stop')
        res = {'status': 'not in progress'}
        pid_str = helpers.get_pid_from_lock_file(self)
        process = helpers.get_process_from_pid(pid_str)
        if process:
            log.debug('tileset.stop, will stop, pid: {}').format(pid_str)
            res = {'status': 'stopped'}
            children = process.children()
            for c in children:
                c.terminate()
            process.terminate()
        else:
            if pid_str == 'preparing_to_start':
                res = {'status': 'debug, prevent start!'}
                # TODO: prevent it from starting!
                log.debug('process not running but may be started shortly')
            elif helpers.is_int_str(pid_str):
                log.debug(
                    'tileset.stop, process not running but cleaned lock file')

        helpers.remove_lock_file(self.id)
        return res

    def seed(self):

        lock_file = helpers.get_lock_file(self)
        if lock_file:
            log.debug('generating tileset')
            try:
                pid = helpers.seed_process_spawn(self)
                lock_file.write("{}\n".format(pid))
                res = {'status': 'started'}
            except (SeedConfigurationError, ConfigurationError) as e:
                log.error(
                    'Something went wrong when generating.. removing lock file'
                )
                res = {'status': 'unable to start', 'error': e.message}
            finally:
                lock_file.flush()
                lock_file.close()
                helpers.remove_lock_file(self)
        else:
            log.debug(
                'tileset.generate, will NOT generate. already running, pid: {}'
                .format(helpers.get_pid_from_lock_file(self)))
            res = {'status': 'already started'}

        return res

    def bbox_3857(self):
        inProj = Proj(init='epsg:4326')
        outProj = Proj(init='epsg:3857')

        sw = transform(inProj, outProj, self.bbox_x0, self.bbox_y0)
        ne = transform(inProj, outProj, self.bbox_x1, self.bbox_y1)

        return [sw[0], sw[1], ne[0], ne[1]]

    def bbox(self):
        return [self.bbox_x0, self.bbox_y0, self.bbox_x1, self.bbox_y1]

    def add_read_perm(self, user_or_group):
        return assign_perm('view_tileset', user_or_group, self)

    def set_up_permissions(self, user_or_group=None):
        # TODO(mvv): handle default anonymous permissions

        if user_or_group:
            self.add_read_perm(user_or_group)

    class Meta:
        permissions = (('view_tileset', 'View Tileset'), )
예제 #29
0
class Agrifield(models.Model, AgrifieldSWBMixin, AgrifieldSWBResultsMixin):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=255, default="i.e. MyField1")
    is_virtual = models.NullBooleanField(choices=YES_OR_NO_OR_NULL,
                                         null=True,
                                         default=None)
    location = models.PointField()
    crop_type = models.ForeignKey(CropType, on_delete=models.CASCADE)
    irrigation_type = models.ForeignKey(IrrigationType,
                                        on_delete=models.CASCADE)
    area = models.FloatField()
    use_custom_parameters = models.BooleanField(default=False)
    custom_kc = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(1.50),
                    MinValueValidator(0.10)],
    )
    custom_root_depth_max = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(4.00),
                    MinValueValidator(0.20)],
    )
    custom_root_depth_min = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(2.00),
                    MinValueValidator(0.1)],
    )
    custom_max_allowed_depletion = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(0.99),
                    MinValueValidator(0.00)],
    )
    custom_efficiency = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(1.00),
                    MinValueValidator(0.05)],
    )
    custom_irrigation_optimizer = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(1.00),
                    MinValueValidator(0.10)],
    )
    custom_field_capacity = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(0.45),
                    MinValueValidator(0.10)],
    )
    custom_thetaS = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(0.55),
                    MinValueValidator(0.30)],
    )
    custom_wilting_point = models.FloatField(
        null=True,
        blank=True,
        validators=[MaxValueValidator(0.22),
                    MinValueValidator(0.00)],
    )
    soil_analysis = models.FileField(blank=True,
                                     storage=SoilAnalysisStorage(),
                                     upload_to="soil_analyses")

    @property
    def wilting_point(self):
        if self.use_custom_parameters and self.custom_wilting_point:
            return self.custom_wilting_point
        else:
            return self.default_wilting_point

    @property
    def default_wilting_point(self):
        if not self.in_covered_area:
            return None
        else:
            return extract_point_from_raster(
                self.location,
                gdal.Open(os.path.join(settings.AIRA_DATA_SOIL, "pwp.tif")),
            )

    @property
    def theta_s(self):
        if self.use_custom_parameters and self.custom_thetaS:
            return self.custom_thetaS
        else:
            return self.default_theta_s

    @property
    def default_theta_s(self):
        if not self.in_covered_area:
            return None
        else:
            return extract_point_from_raster(
                self.location,
                gdal.Open(os.path.join(settings.AIRA_DATA_SOIL,
                                       "theta_s.tif")),
            )

    @property
    def field_capacity(self):
        if self.use_custom_parameters and self.custom_field_capacity:
            return self.custom_field_capacity
        else:
            return self.default_field_capacity

    @property
    def default_field_capacity(self):
        if not self.in_covered_area:
            return None
        else:
            return extract_point_from_raster(
                self.location,
                gdal.Open(os.path.join(settings.AIRA_DATA_SOIL, "fc.tif")),
            )

    @property
    def irrigation_efficiency(self):
        if self.use_custom_parameters and self.custom_efficiency:
            return self.custom_efficiency
        else:
            return self.irrigation_type.efficiency

    @property
    def p(self):
        if self.use_custom_parameters and self.custom_max_allowed_depletion:
            return self.custom_max_allowed_depletion
        else:
            return self.crop_type.max_allowed_depletion

    @property
    def root_depth_max(self):
        if self.use_custom_parameters and self.custom_root_depth_max:
            return self.custom_root_depth_max
        else:
            return self.crop_type.root_depth_max

    @property
    def root_depth_min(self):
        if self.use_custom_parameters and self.custom_root_depth_min:
            return self.custom_root_depth_min
        else:
            return self.crop_type.root_depth_min

    @property
    def root_depth(self):
        return (self.root_depth_max + self.root_depth_min) / 2.0

    @property
    def irrigation_optimizer(self):
        if self.use_custom_parameters and self.custom_irrigation_optimizer:
            return self.custom_irrigation_optimizer
        else:
            return 0.5

    @property
    def last_irrigation(self):
        try:
            result = self.irrigationlog_set.latest()
        except IrrigationLog.DoesNotExist:
            return None
        if result.applied_water is None:
            result.applied_water = (
                float(self.p) * (self.field_capacity - self.wilting_point) *
                self.root_depth * self.area)
            result.message = _(
                "Irrigation water is estimated using system's default parameters."
            )
        return result

    def can_edit(self, user):
        if (user == self.owner) or (user == self.owner.profile.supervisor):
            return True
        raise Http404

    class Meta:
        ordering = ("name", "area")
        verbose_name_plural = "Agrifields"

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        super(Agrifield, self).save(*args, **kwargs)
        self._queue_for_calculation()
        self._delete_cached_point_timeseries()

    def _queue_for_calculation(self):
        from aira import tasks

        cache_key = "agrifield_{}_status".format(self.id)

        # If the agrifield is already in the Celery queue for calculation,
        # return without doing anything.
        if cache.get(cache_key) == "queued":
            return

        tasks.calculate_agrifield.delay(self)
        cache.set(cache_key, "queued", None)

    @property
    def status(self):
        return cache.get("agrifield_{}_status".format(self.id))

    @property
    def in_covered_area(self):
        mask = os.path.join(settings.AIRA_DATA_SOIL, "fc.tif")
        try:
            tmp_check = extract_point_from_raster(self.location,
                                                  gdal.Open(mask))
        except (RuntimeError, ValueError):
            tmp_check = float("nan")
        return not math.isnan(tmp_check)

    def get_point_timeseries(self, variable):
        prefix = os.path.join(settings.AIRA_DATA_HISTORICAL,
                              "daily_" + variable)
        dest = os.path.join(
            settings.AIRA_TIMESERIES_CACHE_DIR,
            "agrifield{}-{}.hts".format(self.id, variable),
        )
        PointTimeseries(point=self.location,
                        prefix=prefix,
                        default_time=dt.time(23, 59)).get_cached(dest,
                                                                 version=2)
        return dest

    def _delete_cached_point_timeseries(self):
        filenamesglob = os.path.join(settings.AIRA_TIMESERIES_CACHE_DIR,
                                     "agrifield{}-*".format(self.id))
        for filename in iglob(filenamesglob):
            os.remove(filename)
예제 #30
0
class Listing(models.Model):
    seller = models.ForeignKey(User, on_delete=CASCADE, related_name="sellers")
    product = models.CharField(max_length=64)
    description = models.CharField(max_length=256)
    price = models.DecimalField(max_digits=10 ,decimal_places=2, default=0, validators=[MinValueValidator(0)])
    image = models.URLField(default="https://www.thermaxglobal.com/wp-content/uploads/2020/05/image-not-found.jpg")
    category = models.CharField(max_length=20)
    active = models.BooleanField(default=True)
    newOwner = models.ForeignKey(User, on_delete=CASCADE, related_name="newowner")
    watchlist = models.ManyToManyField(User)

    def __str__(self):
        return f"{self.seller} is selling {self.product} for a minimum price of {self.price} euro."