コード例 #1
0
class Country(models.Model):
    code = models.CharField(max_length=2, unique=True)
    alpha_3_code = models.CharField(max_length=3, blank=True, default="")
    name = models.CharField(max_length=75)
    region = models.ForeignKey(Region,
                               null=True,
                               blank=True,
                               related_name="countries")
    population = models.IntegerField(null=True, blank=True)
    primary_networks = models.ManyToManyField(
        Network, blank=True, db_table='uw_country_primary_networks')
    extra_data = JSONField(blank=True)

    tracker = FieldTracker()

    class Meta:
        db_table = 'uw_country'

    def gateway_language(self):
        if not hasattr(self, "_gateway_language"):
            data = self.extra_data
            if not isinstance(data, dict):
                data = {}
            self._gateway_language = next(
                iter(Language.objects.filter(
                    code=data.get("gateway_language"))), None)
        return self._gateway_language

    def gateway_languages(self, with_primary=True):
        gl = self.gateway_language()
        if gl:
            ogls = [gl]
        else:
            ogls = []
        for lang in self.language_set.all():
            if lang.gateway_flag and lang not in ogls:
                ogls.append(lang)
            elif lang.gateway_language and lang.gateway_language not in ogls:
                ogls.append(lang.gateway_language)
        if not with_primary and gl:
            ogls.remove(gl)
        return ogls

    @classmethod
    def regions(cls):
        qs = cls.objects.all().values_list("region", flat=True).distinct()
        qs = qs.order_by("region.name")
        return qs

    @classmethod
    def gateway_data(cls):
        with_gateways = cls.objects.filter(
            language__gateway_language__isnull=False).distinct()
        without_gateways = cls.objects.exclude(pk__in=with_gateways)
        data = {
            x.code: {
                "obj": x,
                "gateways": defaultdict(lambda: [])
            }
            for x in with_gateways
        }
        data.update({
            x.code: {
                "obj": x,
                "gateways": {
                    "n/a": list(x.language_set.all())
                }
            }
            for x in without_gateways
        })
        for country in with_gateways:
            for lang in country.language_set.all():
                if lang.gateway_language:
                    data[country.code]["gateways"][
                        lang.gateway_language.code].append(lang)
                else:
                    data[country.code]["gateways"]["n/a"].append(lang)
        return data

    def __str__(self):
        return self.name
コード例 #2
0
class Base(SoftDeletableModel, TimeStampedModel):

    tracker = FieldTracker()

    class Meta:
        abstract = True
コード例 #3
0
class People(index.Indexed, ClusterableModel, StatusModel, TimeStampedModel):
    """
    A Django model to store People objects.
    It uses the `@register_snippet` decorator to allow it to be accessible
    via the Snippets UI (e.g. /admin/snippets/base/people/)

    `People` uses the `ClusterableModel`, which allows the relationship with
    another model to be stored locally to the 'parent' model (e.g. a PageModel)
    until the parent is explicitly saved. This allows the editor to use the
    'Preview' button, to preview the content, without saving the relationships
    to the database.
    https://github.com/wagtail/django-modelcluster
    """

    first_name = models.CharField("First Name", max_length=254)
    last_name = models.CharField("Last Name", max_length=254)
    phone_number = PhoneNumberField("Phone Number")
    email_address = models.EmailField("Email Address")
    position = models.CharField("Position", max_length=254)
    bio = RichTextField(blank=True)
    facebook = models.URLField(
        "Facebook Link",
        max_length=254,
        blank=True,
        help_text=
        "(Optional) Enter Facebook Profile Link, for example: https://www.facebook.com/conrad.mbewe.1",
    )
    twitter = models.URLField(
        "Twitter Link",
        max_length=254,
        blank=True,
        help_text=
        "(Optional) Enter Twitter Profile Link, for example: https://twitter.com/voddiebaucham",
    )
    linked_in = models.URLField(
        "LinkedIn Link",
        max_length=254,
        blank=True,
        help_text=
        "(Optional) Enter LinkedIn Profile Link, for example: https://www.linkedin.com/in/justin-lupele-phd-31a35092",
    )

    STATUS = Choices("draft", "published")

    # https://django-model-utils.readthedocs.io/en/latest/utilities.html#field-tracker
    tracker = FieldTracker()

    image = models.ForeignKey(
        "wagtailimages.Image",
        null=True,
        # blank=True, # required
        on_delete=models.SET_NULL,
        related_name="+",
    )

    panels = [
        FieldPanel("status"),
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel("first_name", classname="col6"),
                    FieldPanel("last_name", classname="col6"),
                ])
            ],
            "Name",
        ),
        MultiFieldPanel(
            [
                FieldRowPanel([
                    FieldPanel("phone_number", classname="col6"),
                    FieldPanel("email_address", classname="col6"),
                ])
            ],
            "Contact Details",
        ),
        FieldPanel("position"),
        FieldPanel("bio", classname="full"),
        ImageChooserPanel("image"),
        MultiFieldPanel(
            [
                FieldPanel("facebook", classname="full"),
                FieldPanel("twitter", classname="full"),
                FieldPanel("linked_in", classname="full"),
            ],
            "Social Media Links",
        ),
    ]

    search_fields = [
        index.SearchField("first_name", partial_match=True),
        index.SearchField("last_name", partial_match=True),
    ]

    @property
    def thumb_image(self):
        # Returns an empty string if there is no profile pic or the rendition
        # file can't be found.
        try:
            return self.image.get_rendition("fill-50x50").img_tag()
        except:  # noqa: E:722
            return ""

    def __str__(self):
        return "{} {}".format(self.first_name, self.last_name)

    class Meta:
        verbose_name = "Person"
        verbose_name_plural = "People"
コード例 #4
0
class Order(models.Model):
    class OrderStatus(models.TextChoices):
        CALL = 'call', 'Call & Void'
        CANCELLED = 'cancelled', 'Cancelled'
        FRAUD = 'fraud', 'Fraud'
        NEW = 'new', 'New'
        UNVERIFIED = 'unverified', 'Unverified'
        VALID = 'valid', 'Valid'

    account = models.ForeignKey(settings.AUTH_USER_MODEL,
                                blank=False,
                                null=False,
                                on_delete=models.CASCADE,
                                related_name='order_account')

    billing_invoice = models.ForeignKey('BillingInvoice',
                                        blank=False,
                                        null=True,
                                        on_delete=models.CASCADE,
                                        related_name='order_billing_invoice')

    billing_invoice_transaction = models.ForeignKey(
        'BillingInvoiceTransaction',
        blank=False,
        null=True,
        on_delete=models.CASCADE,
        related_name='order_billing_invoice_transaction')

    billing_profile = models.ForeignKey('BillingProfile',
                                        blank=False,
                                        null=False,
                                        on_delete=models.CASCADE,
                                        related_name='order_billing_profile')

    company = models.ForeignKey('Company',
                                blank=False,
                                null=False,
                                on_delete=models.CASCADE,
                                related_name='order_company')

    product_profile = models.ForeignKey('ProductProfile',
                                        blank=False,
                                        null=False,
                                        on_delete=models.CASCADE,
                                        related_name='order_product_profile')

    date_from = models.DateTimeField(auto_now_add=True)

    status = models.CharField(blank=False,
                              choices=OrderStatus.choices,
                              max_length=10,
                              null=False)

    tracker = FieldTracker()

    class Meta:
        db_table = 'order'

        default_permissions = ()

        verbose_name = 'Order'
        verbose_name_plural = 'Orders'
コード例 #5
0
ファイル: models.py プロジェクト: rits1902/waldur-mastermind
class ExpertRequest(core_models.UuidMixin, core_models.NameMixin, PriceMixin,
                    common_mixins.ProductCodeMixin,
                    structure_models.StructureLoggableMixin,
                    structure_models.TimeStampedModel):
    class States(object):
        PENDING = 'pending'
        ACTIVE = 'active'
        CANCELLED = 'cancelled'
        COMPLETED = 'completed'

        CHOICES = ((PENDING, _('Pending')), (ACTIVE, _('Active')),
                   (CANCELLED, _('Cancelled')), (COMPLETED, _('Completed')))

    description = models.TextField(blank=True)
    user = models.ForeignKey(
        core_models.User,
        related_name='+',
        on_delete=models.CASCADE,
        help_text=_('The user which has created this request.'))
    project = models.ForeignKey(structure_models.Project,
                                related_name='+',
                                on_delete=models.SET_NULL,
                                null=True)
    # Project name, project UUID, customer should be stored separately
    # because they are not available after project removal
    project_name = models.CharField(max_length=150, blank=True)
    project_uuid = models.CharField(max_length=32, blank=True)
    customer = models.ForeignKey(structure_models.Customer,
                                 related_name='+',
                                 on_delete=models.CASCADE,
                                 null=True)

    state = models.CharField(default=States.PENDING,
                             max_length=30,
                             choices=States.CHOICES)
    type = models.CharField(max_length=255)
    extra = core_fields.JSONField(default={})
    issue = models.ForeignKey(support_models.Issue,
                              null=True,
                              on_delete=models.SET_NULL)
    recurring_billing = models.BooleanField(
        default=False,
        help_text=
        _('Defines whether expert request has to be billed every month or only once'
          ))
    objectives = models.TextField(blank=True)
    milestones = models.TextField(blank=True)
    contract_methodology = models.TextField(blank=True)
    out_of_scope = models.TextField(
        blank=True,
        help_text=_('Elements that are explicitly excluded from the contract'))
    common_tos = models.TextField(blank=True)

    tracker = FieldTracker()
    objects = managers.ExpertRequestManager()

    class Meta:
        ordering = ['-created']

    def get_log_fields(self):
        return super(ExpertRequest,
                     self).get_log_fields() + ('state', 'project', 'user')

    @classmethod
    def get_url_name(cls):
        return 'expert-request'

    @property
    def type_label(self):
        offerings = settings.WALDUR_SUPPORT.get('CONTRACT',
                                                {}).get('offerings', {})
        type_settings = offerings.get(self.type, {})
        return type_settings.get('label', None)

    @property
    def planned_budget(self):
        price = self.extra.get('price')
        if price:
            try:
                return float(price)
            except ValueError:
                return 0
        return 0

    def __str__(self):
        if self.project:
            return '%s (%s)' % (self.name, self.project)
        return self.name
コード例 #6
0
class _concept(baseAristotleObject):
    """
    This is the base concrete class that ``Status`` items attach to, and to
    which collection objects refer to. It is not marked abstract in the Django
    Meta class, and **must not be inherited from**. It has relatively few
    fields and is a convenience class to link with in relationships.
    """
    objects = ConceptManager()
    template = "aristotle_mdr/concepts/managedContent.html"
    workgroup = models.ForeignKey(Workgroup, related_name="items", null=True, blank=True)
    submitter = models.ForeignKey(
        User, related_name="created_items",
        null=True, blank=True,
        help_text=_('This is the person who first created an item. Users can always see items they made.'))
    # We will query on these, so want them cached with the items themselves
    # To be usable these must be updated when statuses are changed
    _is_public = models.BooleanField(default=False)
    _is_locked = models.BooleanField(default=False)

    tracker = FieldTracker()

    comparator = comparators.Comparator
    edit_page_excludes = None
    admin_page_excludes = None

    class Meta:
        # So the url_name works for items we can't determine.
        verbose_name = "item"

    @property
    def non_cached_fields_changed(self):
        changed = self.tracker.changed()
        public_changed = changed.pop('_is_public', False)
        locked_changed = changed.pop('_is_locked', False)
        return len(changed.keys()) > 0

    def can_edit(self, user):
        return _concept.objects.filter(pk=self.pk).editable(user).exists()

    def can_view(self, user):
        return _concept.objects.filter(pk=self.pk).visible(user).exists()

    @property
    def item(self):
        """
        Performs a lookup using ``model_utils.managers.InheritanceManager`` to
        find the subclassed item.
        """
        return _concept.objects.get_subclass(pk=self.pk)

    @property
    def concept(self):
        """
        Returns the parent _concept that an item is built on.
        If the item type is _concept, return itself.
        """
        return getattr(self, '_concept_ptr', self)

    @classmethod
    def get_autocomplete_name(self):
        return 'Autocomplete' + "".join(
            self._meta.verbose_name.title().split()
        )

    @staticmethod
    def autocomplete_search_fields(self):
        return ("name__icontains",)

    def get_absolute_url(self):
        return url_slugify_concept(self)

    @property
    def registry_cascade_items(self):
        """
        This returns the items that can be registered along with the this item.
        If a subclass of _concept defines this method, then when an instance
        of that class is registered using a cascading method then that
        instance, all instances returned by this method will all recieve the
        same registration status.

        Reimplementations of this MUST return iterables.
        """
        return []

    @property
    def is_registered(self):
        return self.statuses.count() > 0

    @property
    def is_superseded(self):
        return all(
            STATES.superseded == status.state for status in self.statuses.all()
        ) and self.superseded_by

    @property
    def is_retired(self):
        return all(
            STATES.retired == status.state for status in self.statuses.all()
        ) and self.statuses.count() > 0

    def check_is_public(self, when=timezone.now()):
        """
            A concept is public if any registration authority
            has advanced it to a public state in that RA.
        """
        statuses = self.statuses.all()
        statuses = self.current_statuses(qs=statuses, when=when)
        pub_state = True in [
            s.state >= s.registrationAuthority.public_state for s in statuses
        ]

        q = Q()
        extra = False
        extra_q = settings.ARISTOTLE_SETTINGS.get('EXTRA_CONCEPT_QUERYSETS', {}).get('public', None)
        if extra_q:
            for func in extra_q:
                q |= import_string(func)()
            extra = self.__class__.objects.filter(pk=self.pk).filter(q).exists()
        return pub_state or extra

    def is_public(self):
        return self._is_public
    is_public.boolean = True
    is_public.short_description = 'Public'

    def check_is_locked(self, when=timezone.now()):
        """
        A concept is locked if any registration authority
        has advanced it to a locked state in that RA.
        """
        statuses = self.statuses.all()
        statuses = self.current_statuses(qs=statuses, when=when)
        return True in [
            s.state >= s.registrationAuthority.locked_state for s in statuses
        ]

    def is_locked(self):
        return self._is_locked

    is_locked.boolean = True
    is_locked.short_description = 'Locked'

    def recache_states(self):
        self._is_public = self.check_is_public()
        self._is_locked = self.check_is_locked()
        self.save()
        concept_visibility_updated.send(sender=self.__class__, concept=self)

    def current_statuses(self, qs=None, when=timezone.now()):
        if qs is None:
            qs = self.statuses.all()
        if hasattr(when, 'date'):
            when = when.date()
        registered_before_now = Q(registrationDate__lte=when)
        registation_still_valid = (
            Q(until_date__gte=when) |
            Q(until_date__isnull=True)
        )

        states = qs.filter(
            registered_before_now & registation_still_valid
        ).order_by("registrationAuthority", "-registrationDate", "-created")

        from django.db import connection
        if connection.vendor == 'postgresql':
            states = states.distinct('registrationAuthority')
        else:
            current_ids = []
            seen_ras = []
            for s in states:
                ra = s.registrationAuthority
                if ra not in seen_ras:
                    current_ids.append(s.pk)
                    seen_ras.append(ra)
            # We hit again so we can return this as a queryset
            states = states.filter(pk__in=current_ids)
        return states

    def get_download_items(self):
        """
        When downloading a concept, extra items can be included for download by
        overriding the ``get_download_items`` method on your item. By default
        this returns an empty list, but can be modified to include any number of
        items that inherit from ``_concept``.

        When overriding, each entry in the list must be a two item tuple, with
        the first entry being the python class of the item or items being
        included, and the second being the queryset of items to include.
        """
        return []
コード例 #7
0
ファイル: models.py プロジェクト: tcmaker/tcmaker-membership
class Person(BaseEntity):
    # Basic Information
    given_name = models.CharField('Given Name', max_length=100)
    family_name = models.CharField('Family Name', max_length=100)
    email = models.EmailField('Email Address')
    member_since = models.DateField('Date Joined', blank=True, null=True)

    household = models.ForeignKey('Household',
                                  on_delete=models.SET_NULL,
                                  blank=True,
                                  null=True)
    student_team = models.ForeignKey('StudentTeam',
                                     on_delete=models.SET_NULL,
                                     blank=True,
                                     null=True)

    # Address
    address_street1 = models.CharField('Street Address', max_length=100)
    address_street2 = models.CharField('Street Address 2',
                                       max_length=100,
                                       blank=True,
                                       null=True)
    address_city = models.CharField('City', max_length=100)
    address_state = USStateField('State')
    address_zip = USZipCodeField('Zip Code')

    # Phone Info
    phone_number = PhoneNumberField()
    phone_can_receive_sms = models.BooleanField(null=False, default=False)

    # Emergency Contact Information
    emergency_contact_name = models.CharField(max_length=100,
                                              blank=True,
                                              null=True)
    emergency_contact_phone = PhoneNumberField(blank=True, null=True)

    # Temporary, until CiviCRM import is complete
    civicrm_contact_id = models.CharField('CiviCRM Contact ID',
                                          max_length=5,
                                          null=True,
                                          blank=True)

    # Managers
    objects = managers.MemberManager()

    # This tells us which fields have been modified so custom save methods
    # and signal handlers can do less work.
    tracker = FieldTracker()

    def __str__(self):
        return ", ".join([self.family_name, self.given_name])

    def address_lines(self):
        ret = [self.address_street1]

        if self.address_street2:
            ret.append(self.address_street2)

        ret.append("%s %s, %s" %
                   (self.address_city, self.address_state, self.address_zip))

        return ret

    def membership_status(self):
        if self.household:
            return self.household.status
        if self.student_team:
            return self.student_team.status
        return 'none'

    def household_or_student_team(self):
        if self.household:
            return self.household.name
        if self.student_team:
            return self.student_team.name
        return None

    #### custom validation of member fields ####
    def __household_has_vacancies(self):
        if self.household == None:
            return True

        if self.household.has_vacancy_for(self):
            return True

        return False

    def clean(self):
        if not self.__household_has_vacancies():
            raise ValidationError(
                {'household': 'The household is already full.'})

        if self.household and self.student_team:
            raise ValidationError({
                'household':
                'One cannot join both a household and a student team',
                'student_team':
                'One cannot join both a household and a student team',
            })

        super().clean()

    def save(self, *args, **kwargs):
        if not self.tracker.has_changed('household_id'):
            return super().save(*args, **kwargs)

        if not self.__household_has_vacancies():
            raise DataError('Household is already full')

        if self.household_id and self.student_team_id:
            raise DataError(
                'One cannot join both a household and a student team')

        # we're in the clear
        super().save(*args, **kwargs)
コード例 #8
0
ファイル: models.py プロジェクト: yashodhank/ve-waldur-v2
class Issue(core_models.UuidMixin, structure_models.StructureLoggableMixin,
            core_models.BackendModelMixin, TimeStampedModel,
            core_models.StateMixin):
    class Meta:
        ordering = ['-created']

    class Permissions(object):
        customer_path = 'customer'
        project_path = 'project'

    backend_id = models.CharField(max_length=255,
                                  blank=True,
                                  null=True,
                                  unique=True)
    key = models.CharField(max_length=255, blank=True)
    type = models.CharField(max_length=255)
    link = models.URLField(max_length=255,
                           help_text=_('Link to issue in support system.'),
                           blank=True)

    summary = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    deadline = models.DateTimeField(blank=True, null=True)
    impact = models.CharField(max_length=255, blank=True)

    status = models.CharField(max_length=255)
    resolution = models.CharField(max_length=255, blank=True)
    priority = models.CharField(max_length=255, blank=True)

    caller = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        related_name='created_issues',
        help_text=_('Waldur user who has reported the issue.'),
        on_delete=models.PROTECT)
    reporter = models.ForeignKey(
        'SupportUser',
        related_name='reported_issues',
        blank=True,
        null=True,
        help_text=
        _('Help desk user who have created the issue that is reported by caller.'
          ),
        on_delete=models.PROTECT)
    assignee = models.ForeignKey(
        'SupportUser',
        related_name='issues',
        blank=True,
        null=True,
        help_text=_('Help desk user who will implement the issue'),
        on_delete=models.PROTECT)

    customer = models.ForeignKey(structure_models.Customer,
                                 verbose_name=_('organization'),
                                 related_name='issues',
                                 blank=True,
                                 null=True,
                                 on_delete=models.CASCADE)
    project = models.ForeignKey(structure_models.Project,
                                related_name='issues',
                                blank=True,
                                null=True,
                                on_delete=models.CASCADE)

    resource_content_type = models.ForeignKey(ContentType, null=True)
    resource_object_id = models.PositiveIntegerField(null=True)
    resource = GenericForeignKey('resource_content_type', 'resource_object_id')

    first_response_sla = models.DateTimeField(blank=True, null=True)

    tracker = FieldTracker()

    def get_description(self):
        return self.description

    @classmethod
    def get_url_name(cls):
        return 'support-issue'

    @classmethod
    def get_backend_fields(cls):
        return super(Issue, cls).get_backend_fields() + (
            'backend_id', 'key', 'type', 'link', 'summary', 'description',
            'deadline', 'impact', 'status', 'resolution', 'priority', 'caller',
            'reporter', 'assignee', 'customer', 'project', 'resource',
            'first_response_sla')

    def get_log_fields(self):
        return ('uuid', 'type', 'key', 'status', 'link', 'summary', 'reporter',
                'caller', 'customer', 'project', 'resource')

    def __str__(self):
        return '{}: {}'.format(self.key or '???', self.summary)
コード例 #9
0
class Thermostat(NameBaseModel):
    """
    Store thermostat data.
    """
    house = models.ForeignKey(House,
                              related_name='thermostats',
                              on_delete=models.CASCADE,
                              help_text='Related house.')

    mode = models.CharField(choices=MODES,
                            default=MODES.off,
                            max_length=5,
                            help_text='Current mode of the thermostat.')
    current_temperature = models.DecimalField(
        decimal_places=2,
        max_digits=5,
        help_text='Current temperature at the thermostat.')
    temperature_set_point = models.DecimalField(
        decimal_places=2, max_digits=5, help_text='Temperature set point.')
    tracker = FieldTracker()
    track_records = GenericRelation(
        TrackRecord,
        object_id_field='target_object_id',
        content_type_field='target_content_type',
        related_query_name="Thermostat track records")

    def __str__(self):
        return self.name

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

        if self.pk is None:
            return super(Thermostat, self).save(*args, **kwargs)

        # If its an update to the record and mode or temperature is changed,
        # Keep a track record for each change in temperature or mode
        if self.tracker.has_changed("current_temperature"):
            TrackRecord.objects.create(
                name=self.name,
                state_type="Temperature",
                target_content_type=ContentType.objects.get_for_model(
                    Thermostat),
                target_object_id=self.pk,
                from_state=self.tracker.previous("current_temperature"),
                to_state=self.current_temperature,
            )
        if self.tracker.has_changed("temperature_set_point"):
            TrackRecord.objects.create(
                name=self.name,
                state_type="Temperature set point",
                target_content_type=ContentType.objects.get_for_model(
                    Thermostat),
                target_object_id=self.pk,
                from_state=self.tracker.previous("temperature_set_point"),
                to_state=self.temperature_set_point,
            )

        if self.tracker.has_changed("mode"):
            TrackRecord.objects.create(
                name=self.name,
                state_type="Mode",
                target_content_type=ContentType.objects.get_for_model(
                    Thermostat),
                target_object_id=self.pk,
                from_state=self.tracker.previous("mode"),
                to_state=self.mode,
            )

        return super(Thermostat, self).save(*args, **kwargs)
コード例 #10
0
ファイル: models.py プロジェクト: bristolapproach/to-fro
class Action(models.Model):

    STATUSES_WITHOUT_ASSIGNED_VOLUNTEER = (
        ActionStatus.INTEREST, ActionStatus.PENDING)

    external_action_id = models.CharField(
        max_length=50, null=True, blank=True, help_text="The ID of the action in an external system")
    added_by = models.ForeignKey(user_models.Coordinator, related_name='added_by',
                                 on_delete=models.PROTECT, help_text="What's your name?")
    coordinator = models.ForeignKey(user_models.Coordinator, related_name='coordinator',
                                    on_delete=models.PROTECT, help_text="Who will mediate this action?")
    call_datetime = models.DateTimeField(
        null=True, help_text="What time did you receive the call about this action?")
    call_duration = models.DurationField(
        null=True, blank=True, help_text="How long was the call?")
    resident = models.ForeignKey(
        user_models.Resident, on_delete=models.PROTECT, null=True, help_text="Who made the request?")
    requested_datetime = models.DateTimeField(
        null=True, verbose_name="Due", help_text="When should the action be completed by?")

    interested_volunteers = models.ManyToManyField(user_models.Volunteer, blank=True, related_name="actions_interested_in",
                                                   help_text="Volunteers who have expressed interest in completing the action..")
    assigned_volunteer = models.ForeignKey(user_models.Volunteer, on_delete=models.PROTECT,
                                           null=True, blank=True, help_text="The volunteer who will complete the action.")

    action_status = models.CharField(max_length=1, choices=ActionStatus.STATUSES,
                                     default=ActionStatus.PENDING, help_text="What's the status of this action?")
    action_priority = models.CharField(max_length=1, choices=ActionPriority.PRIORITIES,
                                       default=ActionPriority.MEDIUM, help_text="What priority should this action be given?")
    public_description = models.TextField(max_length=500, null=True, blank=True,
                                          help_text="Text that gets displayed to volunteers who are browsing actions.")
    private_description = models.TextField(
        null=True, blank=True, help_text="Text that only gets displayed to a volunteer when they're assigned to the action.")
    help_type = models.ForeignKey(HelpType, on_delete=models.PROTECT, null=True,
                                  verbose_name="Action type", help_text="Which kind of help is needed")
    requirements = models.ManyToManyField(Requirement, blank=True, related_name="actions",
                                          help_text="Only volunteers matching these requirements will see the action.")
    volunteer_made_contact_on = models.DateTimeField(null=True, blank=True)
    assigned_date = models.DateTimeField(
        null=True, blank=True, verbose_name="Assigned on")
    completed_date = models.DateTimeField(
        null=True, blank=True, verbose_name="Completed on")

    action_uuid = models.UUIDField(default=uuid.uuid4, unique=True, db_index=True)

    time_taken = models.DurationField(null=True, blank=True)

    # Track changes to the model so we can access the previous status
    # when it changes, and update the volunteer accordingly if it swapped
    # to a status that doesn't have a volunteer assigned
    tracker = FieldTracker()

    def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
        # Ensure that the volunteer gets cleared when we move from a status
        # that has an assigned volunteer to one that doesn't.
        if (self.tracker.has_changed('action_status')
            and self.action_status in self.STATUSES_WITHOUT_ASSIGNED_VOLUNTEER
                and self.tracker.previous('action_status') not in self.STATUSES_WITHOUT_ASSIGNED_VOLUNTEER
                and self.tracker.previous('action_status') is not None):
            self.assigned_volunteer = None

        # Ensures that the status gets to assigned if we set a volunteer
        # and the status was one that doesn't need a volunteer
        # This needs to happen after the clearing of the volunteer
        # when switching to a status without volunteer so there is no
        # volunteer and we don't update the status
        if (self.assigned_volunteer and self.action_status in self.STATUSES_WITHOUT_ASSIGNED_VOLUNTEER):
            self.action_status = ActionStatus.ASSIGNED

        # Track the contact date when setting the status
        # to one implying that contact would have happened
        if (self.action_status in (ActionStatus.ONGOING, ActionStatus.COMPLETED, ActionStatus.COULDNT_COMPLETE) and not self.volunteer_made_contact_on):
            self.volunteer_made_contact_on = timezone.now()

        # Track other interesting dates
        if (self.action_status not in self.STATUSES_WITHOUT_ASSIGNED_VOLUNTEER and not self.assigned_date):
            self.assigned_date = timezone.now()
        # if (self.action_status in self.STATUSES_WITHOUT_ASSIGNED_VOLUNTEER and self.assigned_date):
        #     self.assigned_date = None

        if (self.action_status == ActionStatus.COMPLETED and not self.completed_date):
            self.completed_date = timezone.now()
        # if (self.action_status != ActionStatus.COMPLETED and self.completed_date):
        #     self.completed_date = None

        # Only for updates as it runs on a related field
        if self.pk is not None:
            # Update the status according to whether there are interested_volunteers or not
            if (self.action_status == ActionStatus.PENDING and self.interested_volunteers.count() > 0):
                self.action_status = ActionStatus.INTEREST
            if (self.action_status == ActionStatus.INTEREST and self.interested_volunteers.count() == 0):
                self.action_status = ActionStatus.PENDING

        super().save(force_insert=force_insert, force_update=force_update,
                     using=using, update_fields=update_fields)

        # Needs to happen after the save so the M2M relation can be saved properly
        # when creating an action
        # Without waiting for the end of the transaction, the volunteer
        # doesn't actually gets saved
        transaction.on_commit(self.save_assigned_volunteer, using=using)

    def save_assigned_volunteer(self):
        """
        Ensures the assigned_volunteer is within the list of interested volunteers
        """
        if (self.assigned_volunteer and not self.assigned_volunteer in self.interested_volunteers.all()):
            self.interested_volunteers.add(self.assigned_volunteer)

    def register_interest_from(self, volunteer):
        if volunteer not in self.interested_volunteers.all():
            self.interested_volunteers.add(volunteer)
            self.save()

    def withdraw_interest_from(self, volunteer):
        if volunteer in self.interested_volunteers.all():
            self.interested_volunteers.remove(volunteer)
            self.save()

    @property
    def ward(self):
        return self.resident.ward

    @property
    def description(self):
        return f"Help with {self.help_type} around {self.ward}"

    @property
    def description_with_date(self):
        return f"{self.description} by {self.requested_datetime.strftime('%d %b')}"

    @property
    def is_pending(self):
        return self.action_status == ActionStatus.PENDING

    @property
    def is_ongoing(self):
        return self.action_status == ActionStatus.ONGOING

    @property
    def has_interest(self):
        return self.action_status == ActionStatus.INTEREST

    @property
    def is_assigned(self):
        return self.assigned_volunteer is not None

    @property
    def is_completed(self):
        return self.action_status == ActionStatus.COMPLETED

    @property
    def is_failed(self):
        return self.action_status == ActionStatus.COULDNT_COMPLETE

    @property
    def can_reveal_private_information(self):
        return not (
            self.action_status == ActionStatus.INTEREST or self.action_status == ActionStatus.PENDING)

    @property
    def can_give_feedback(self):
        return self.action_status == ActionStatus.ASSIGNED or self.action_status == ActionStatus.ONGOING

    @property
    def potential_volunteers(self):
        return user_models.Volunteer.objects \
            .filter(wards__id=self.ward.id) \
            .filter(help_types__id=self.help_type.id) \
            .all()

    def get_absolute_url(self):
        from django.urls import reverse
        return reverse('actions:detail', kwargs={'action_uuid': self.action_uuid})

    def __str__(self):
        return f"Action {self.id} - {self.resident.full_name}"
コード例 #11
0
ファイル: models.py プロジェクト: yashodhank/ve-waldur-v2
class Offering(core_models.UuidMixin, core_models.NameMixin,
               common_mixins.ProductCodeMixin, common_mixins.UnitPriceMixin,
               structure_models.StructureLoggableMixin, TimeStampedModel):
    class Meta:
        ordering = ['-created']
        verbose_name = _('Request')
        verbose_name_plural = _('Requests')

    class Permissions(object):
        customer_path = 'project__customer'
        project_path = 'project'

    class States(object):
        REQUESTED = 'requested'
        OK = 'ok'
        TERMINATED = 'terminated'

        CHOICES = ((REQUESTED, _('Requested')), (OK, _('OK')),
                   (TERMINATED, _('Terminated')))

    template = models.ForeignKey('OfferingTemplate', on_delete=models.PROTECT)
    issue = models.ForeignKey(Issue, null=True, on_delete=models.PROTECT)
    project = models.ForeignKey(structure_models.Project,
                                null=True,
                                on_delete=models.PROTECT)
    state = models.CharField(default=States.REQUESTED,
                             max_length=30,
                             choices=States.CHOICES)
    report = core_fields.JSONField(blank=True)
    terminated_at = models.DateTimeField(editable=False, blank=True, null=True)

    tracker = FieldTracker()

    def get_backend(self):
        backend.get_active_backend()

    def get_log_fields(self):
        return super(Offering, self).get_log_fields() + ('state', )

    @property
    def type(self):
        return self.template.name

    @property
    def type_label(self):
        return self.template.config.get('label', None)

    @classmethod
    def get_url_name(cls):
        return 'support-offering'

    def __str__(self):
        return '{}: {}'.format(self.type_label or self.name, self.state)

    @classmethod
    def get_scope_type(cls):
        return 'Support.Offering'

    def _get_log_context(self, entity_name):
        context = super(Offering, self)._get_log_context(entity_name)
        context['resource_type'] = self.get_scope_type()
        context['resource_uuid'] = self.uuid.hex
        return context

    @property
    def config(self):
        return self.template.config if self.template else {}
コード例 #12
0
class ActivitySubmission(AuditModel):
    """
    Activity information on a Well submitted by a user.
    """
    filing_number = models.AutoField(primary_key=True)
    activity_submission_guid = models.UUIDField(primary_key=False, default=uuid.uuid4, editable=False)
    well_tag_number = models.ForeignKey(Well, db_column='well_tag_number', on_delete=models.CASCADE, blank=True, null=True)
    well_activity_type = models.ForeignKey(WellActivityCode, db_column='well_activity_code', on_delete=models.CASCADE, verbose_name='Type of Work')
    well_class = models.ForeignKey(WellClassCode, null=True, db_column='well_class_code', on_delete=models.CASCADE, verbose_name='Well Class')
    well_subclass = models.ForeignKey(WellSubclassCode, db_column='well_subclass_guid', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Well Subclass')
    intended_water_use = models.ForeignKey(IntendedWaterUseCode, db_column='intended_water_use_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Intended Water Use')
    driller_responsible = models.ForeignKey(Driller, db_column='driller_responsible_guid', on_delete=models.CASCADE, verbose_name='Person Responsible for Drilling')
    driller_name = models.CharField(max_length=200, blank=True, verbose_name='Name of Person Who Did the Work')
    consultant_name = models.CharField(max_length=200, blank=True, verbose_name='Consultant Name')
    consultant_company = models.CharField(max_length=200, blank=True, verbose_name='Consultant Company')
    work_start_date = models.DateField(verbose_name='Work Start Date')
    work_end_date = models.DateField(verbose_name='Work End Date')

    owner_full_name = models.CharField(max_length=200, verbose_name='Owner Name')
    owner_mailing_address = models.CharField(max_length=100, verbose_name='Mailing Address')
    owner_city = models.CharField(max_length=100, verbose_name='Town/City')
    owner_province_state = models.ForeignKey(ProvinceStateCode, db_column='province_state_code', on_delete=models.CASCADE, verbose_name='Province')
    owner_postal_code = models.CharField(max_length=10, blank=True, verbose_name='Postal Code')

    street_address = models.CharField(max_length=100, blank=True, verbose_name='Street Address')
    city = models.CharField(max_length=50, blank=True, verbose_name='Town/City')
    legal_lot = models.CharField(max_length=10, blank=True, verbose_name='Lot')
    legal_plan = models.CharField(max_length=20, blank=True, verbose_name='Plan')
    legal_district_lot = models.CharField(max_length=20, blank=True, verbose_name='District Lot')
    legal_block = models.CharField(max_length=10, blank=True, verbose_name='Block')
    legal_section = models.CharField(max_length=10, blank=True, verbose_name='Section')
    legal_township = models.CharField(max_length=20, blank=True, verbose_name='Township')
    legal_range = models.CharField(max_length=10, blank=True, verbose_name='Range')
    land_district = models.ForeignKey(LandDistrictCode, db_column='land_district_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Land District')
    legal_pid = models.PositiveIntegerField(blank=True, null=True, verbose_name='PID')
    well_location_description = models.CharField(max_length=500, blank=True, verbose_name='Well Location Description')

    identification_plate_number = models.PositiveIntegerField(blank=True, null=True, verbose_name='Identification Plate Number')
    well_plate_attached = models.CharField(max_length=500, blank=True, verbose_name='Well Identification Plate Is Attached')

    latitude = models.DecimalField(max_digits=8, decimal_places=6, blank=True, null=True)
    longitude = models.DecimalField(max_digits=9, decimal_places=6, blank=True, null=True)
    ground_elevation = models.DecimalField(max_digits=10, decimal_places=2, blank=True, null=True, verbose_name='Ground Elevation')
    ground_elevation_method = models.ForeignKey(GroundElevationMethodCode, db_column='ground_elevation_method_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Elevation Determined By')
    drilling_method = models.ForeignKey(DrillingMethodCode, db_column='drilling_method_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Drilling Method')
    other_drilling_method = models.CharField(max_length=50, blank=True, verbose_name='Specify Other Drilling Method')
    well_orientation = models.BooleanField(default=True, verbose_name='Orientation of Well', choices=((True, 'vertical'), (False, 'horizontal')))
    water_supply_system_name = models.CharField(max_length=50, blank=True, verbose_name='Water Supply System Name')
    water_supply_system_well_name = models.CharField(max_length=50, blank=True, verbose_name='Water Supply System Well Name')

    surface_seal_material = models.ForeignKey(SurfaceSealMaterialCode, db_column='surface_seal_material_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Surface Seal Material')
    surface_seal_depth = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, verbose_name='Surface Seal Depth')
    surface_seal_thickness = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Surface Seal Thickness', validators=[MinValueValidator(Decimal('1.00'))])
    surface_seal_method = models.ForeignKey(SurfaceSealMethodCode, db_column='surface_seal_method_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Surface Seal Installation Method')
    backfill_above_surface_seal = models.CharField(max_length=250, blank=True, verbose_name='Backfill Material Above Surface Seal')
    backfill_above_surface_seal_depth = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Backfill Depth')

    liner_material = models.ForeignKey(LinerMaterialCode, db_column='liner_material_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Liner Material')
    liner_diameter = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Liner Diameter', validators=[MinValueValidator(Decimal('0.00'))])
    liner_thickness = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True, verbose_name='Liner Thickness', validators=[MinValueValidator(Decimal('0.00'))])
    liner_from = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Liner From', validators=[MinValueValidator(Decimal('0.00'))])
    liner_to = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Liner To', validators=[MinValueValidator(Decimal('0.01'))])

    screen_intake_method = models.ForeignKey(ScreenIntakeMethodCode, db_column='screen_intake_method_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Intake')
    screen_type = models.ForeignKey(ScreenTypeCode, db_column='screen_type_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Type')
    screen_material = models.ForeignKey(ScreenMaterialCode, db_column='screen_material_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Material')
    other_screen_material = models.CharField(max_length=50, blank=True, verbose_name='Specify Other Screen Material')
    screen_opening = models.ForeignKey(ScreenOpeningCode, db_column='screen_opening_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Opening')
    screen_bottom = models.ForeignKey(ScreenBottomCode, db_column='screen_bottom_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Bottom')
    other_screen_bottom = models.CharField(max_length=50, blank=True, verbose_name='Specify Other Screen Bottom')

    filter_pack_from = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Filter Pack From', validators=[MinValueValidator(Decimal('0.00'))])
    filter_pack_to = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Filter Pack To', validators=[MinValueValidator(Decimal('0.01'))])
    filter_pack_thickness = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True, verbose_name='Filter Pack Thickness', validators=[MinValueValidator(Decimal('0.00'))])
    filter_pack_material = models.ForeignKey(FilterPackMaterialCode, db_column='filter_pack_material_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Filter Pack Material')
    filter_pack_material_size = models.ForeignKey(FilterPackMaterialSizeCode, db_column='filter_pack_material_size_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Filter Pack Material Size')

    development_method = models.ForeignKey(DevelopmentMethodCode, db_column='development_method_code', on_delete=models.CASCADE, blank=True, null=True, verbose_name='Development Method')
    development_hours = models.DecimalField(max_digits=9, decimal_places=2, blank=True, null=True, verbose_name='Development Total Duration', validators=[MinValueValidator(Decimal('0.00'))])
    development_notes = models.CharField(max_length=255, blank=True, verbose_name='Development Notes')

    water_quality_characteristics = models.ManyToManyField(WaterQualityCharacteristic, db_table='activity_submission_water_quality', blank=True, verbose_name='Obvious Water Quality Characteristics')
    water_quality_colour = models.CharField(max_length=60, blank=True, verbose_name='Water Quality Colour')
    water_quality_odour = models.CharField(max_length=60, blank=True, verbose_name='Water Quality Odour')

    total_depth_drilled = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Total Depth Drilled')
    finished_well_depth = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Finished Well Depth')
    final_casing_stick_up = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True, verbose_name='Final Casing Stick Up')
    bedrock_depth = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Depth to Bedrock')
    static_water_level = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Static Water Level (BTOC)')
    well_yield = models.DecimalField(max_digits=8, decimal_places=3, blank=True, null=True, verbose_name='Estimated Well Yield')
    artesian_flow = models.DecimalField(max_digits=7, decimal_places=2, blank=True, null=True, verbose_name='Artesian Flow')
    artesian_pressure = models.DecimalField(max_digits=5, decimal_places=2, blank=True, null=True, verbose_name='Artesian Pressure')
    well_cap_type = models.CharField(max_length=40, blank=True, verbose_name='Well Cap Type')
    well_disinfected = models.BooleanField(default=False, verbose_name='Well Disinfected?', choices=((False, 'No'), (True, 'Yes')))

    comments = models.CharField(max_length=3000, blank=True)
    alternative_specs_submitted = models.BooleanField(default=False, verbose_name='Alternative specs submitted (if required)')

    well_yield_unit = models.ForeignKey(WellYieldUnitCode, db_column='well_yield_unit_code', on_delete=models.CASCADE, blank=True, null=True)
    diameter = models.CharField(max_length=9, blank=True)  #want to be integer in future

    tracker = FieldTracker()

    def create_well(self):
        w = Well(well_class = self.well_class)
        w.well_subclass = self.well_subclass
        w.intended_water_use = self.intended_water_use
        w.owner_full_name = self.owner_full_name
        w.owner_mailing_address = self.owner_mailing_address
        w.owner_city = self.owner_city
        w.owner_province_state = self.owner_province_state
        w.owner_postal_code = self.owner_postal_code

        w.street_address = self.street_address
        w.city = self.city
        w.legal_lot = self.legal_lot
        w.legal_plan = self.legal_plan
        w.legal_district_lot = self.legal_district_lot
        w.legal_block = self.legal_block
        w.legal_section = self.legal_section
        w.legal_township = self.legal_township
        w.legal_range = self.legal_range
        w.land_district = self.land_district
        w.legal_pid = self.legal_pid
        w.well_location_description = self.well_location_description

        w.identification_plate_number = self.identification_plate_number
        w.latitude = self.latitude
        w.longitude = self.longitude
        w.ground_elevation = self.ground_elevation
        w.ground_elevation_method = self.ground_elevation_method
        w.drilling_method = self.drilling_method
        w.other_drilling_method = self.other_drilling_method
        w.well_orientation = self.well_orientation

        w.surface_seal_material = self.surface_seal_material
        w.surface_seal_depth = self.surface_seal_depth
        w.surface_seal_thickness = self.surface_seal_thickness
        w.surface_seal_method = self.surface_seal_method
        w.backfill_above_surface_seal = self.backfill_above_surface_seal
        w.backfill_above_surface_seal_depth = self.backfill_above_surface_seal_depth

        w.liner_material = self.liner_material
        w.liner_diameter = self.liner_diameter
        w.liner_thickness = self.liner_thickness
        w.liner_from = self.liner_from
        w.liner_to = self.liner_to

        w.screen_intake = self.screen_intake
        w.screen_type = self.screen_type
        w.screen_material = self.screen_material
        w.other_screen_material = self.other_screen_material
        w.screen_opening = self.screen_opening
        w.screen_bottom = self.screen_bottom
        w.other_screen_bottom = self.other_screen_bottom

        w.filter_pack_from = self.filter_pack_from
        w.filter_pack_to = self.filter_pack_to
        w.filter_pack_thickness = self.filter_pack_thickness
        w.filter_pack_material = self.filter_pack_material
        w.filter_pack_material_size = self.filter_pack_material_size

        w.development_method = self.development_method
        w.development_hours = self.development_hours
        w.development_notes = self.development_notes

        w.water_quality_colour = self.water_quality_colour
        w.water_quality_odour = self.water_quality_odour

        w.total_depth_drilled = self.total_depth_drilled
        w.finished_well_depth = self.finished_well_depth
        w.final_casing_stick_up = self.final_casing_stick_up
        w.bedrock_depth = self.bedrock_depth
        w._water_level = self.static_water_level
        w.well_yield = self.well_yield
        w.artestian_flow = self.artestian_flow
        w.artestian_pressure = self.artestian_pressure
        w.well_cap_type = self.well_cap_type
        w.well_disinfected = self.well_disinfected

        w.comments = self.comments
        w.alternative_specs_submitted = self.alternative_specs_submitted
        #TODO

        return w;

    class Meta:
        db_table = 'activity_submission'

    def __str__(self):
        if self.filing_number:
            return '%s %d %s %s' % (self.activity_submission_guid, self.filing_number, self.well_activity_type.well_activity_code, self.street_address)
        else:
            return '%s %s' % (self.activity_submission_guid, self.street_address)
コード例 #13
0
class SiteSettings(models.Model):
    """customized settings for this instance"""

    name = models.CharField(default="BookWyrm", max_length=100)
    instance_tagline = models.CharField(
        max_length=150, default="Social Reading and Reviewing"
    )
    instance_description = models.TextField(default="This instance has no description.")
    instance_short_description = models.CharField(max_length=255, blank=True, null=True)

    # about page
    registration_closed_text = models.TextField(
        default="We aren't taking new users at this time. You can find an open "
        'instance at <a href="https://joinbookwyrm.com/instances">'
        "joinbookwyrm.com/instances</a>."
    )
    invite_request_text = models.TextField(
        default="If your request is approved, you will receive an email with a "
        "registration link."
    )
    code_of_conduct = models.TextField(default="Add a code of conduct here.")
    privacy_policy = models.TextField(default="Add a privacy policy here.")

    # registration
    allow_registration = models.BooleanField(default=True)
    allow_invite_requests = models.BooleanField(default=True)
    require_confirm_email = models.BooleanField(default=True)

    # images
    logo = models.ImageField(upload_to="logos/", null=True, blank=True)
    logo_small = models.ImageField(upload_to="logos/", null=True, blank=True)
    favicon = models.ImageField(upload_to="logos/", null=True, blank=True)
    preview_image = models.ImageField(
        upload_to="previews/logos/", null=True, blank=True
    )

    # footer
    support_link = models.CharField(max_length=255, null=True, blank=True)
    support_title = models.CharField(max_length=100, null=True, blank=True)
    admin_email = models.EmailField(max_length=255, null=True, blank=True)
    footer_item = models.TextField(null=True, blank=True)

    field_tracker = FieldTracker(fields=["name", "instance_tagline", "logo"])

    @classmethod
    def get(cls):
        """gets the site settings db entry or defaults"""
        try:
            return cls.objects.get(id=1)
        except cls.DoesNotExist:
            default_settings = SiteSettings(id=1)
            default_settings.save()
            return default_settings

    @property
    def logo_url(self):
        """helper to build the logo url"""
        return self.get_url("logo", "images/logo.png")

    @property
    def logo_small_url(self):
        """helper to build the logo url"""
        return self.get_url("logo_small", "images/logo-small.png")

    @property
    def favicon_url(self):
        """helper to build the logo url"""
        return self.get_url("favicon", "images/favicon.png")

    def get_url(self, field, default_path):
        """get a media url or a default static path"""
        uploaded = getattr(self, field, None)
        if uploaded:
            return get_absolute_url(uploaded)
        return urljoin(STATIC_FULL_URL, default_path)
コード例 #14
0
class Comment(
    core_models.UuidMixin,
    core_models.BackendModelMixin,
    TimeStampedModel,
    core_models.StateMixin,
):
    class Meta:
        ordering = ['-created']
        unique_together = ('backend_id', 'issue')

    class Permissions:
        customer_path = 'issue__customer'
        project_path = 'issue__project'

    issue = models.ForeignKey(
        on_delete=models.CASCADE, to=Issue, related_name='comments'
    )
    author = models.ForeignKey(
        on_delete=models.CASCADE, to=SupportUser, related_name='comments'
    )
    description = models.TextField()
    is_public = models.BooleanField(default=True)
    backend_id = models.CharField(max_length=255, blank=True, null=True)
    tracker = FieldTracker()

    def clean_message(self, message):
        """
        Extracts comment message from JIRA comment which contains user's info in its body.
        """
        match = re.search(r'^(\[.*?\]\:\s)', message)
        return message.replace(match.group(0), '') if match else message

    def prepare_message(self):
        """
        Prepends user info to the comment description to display comment author in JIRA.
        User info format - '[user.full_name user.civil_number]: '.
        """
        prefix = self.author.name
        # User is optional
        user = self.author.user
        if user:
            prefix = user.full_name or user.username
            if user.civil_number:
                prefix += ' ' + user.civil_number
        return '[%s]: %s' % (prefix, self.description)

    def update_message(self, message):
        self.description = self.clean_message(message)

    @classmethod
    def get_url_name(cls):
        return 'support-comment'

    @classmethod
    def get_backend_fields(cls):
        return super(Comment, cls).get_backend_fields() + (
            'issue',
            'author',
            'description',
            'is_public',
            'backend_id',
        )

    def __str__(self):
        return self.description[:50]
コード例 #15
0
class RegistrationAuthority(registryGroup):
    """
    A registration authority is a proxy group that describes a governance
    process for "standardising" metadata.
    """
    template = "aristotle_mdr/registrationAuthority.html"
    locked_state = models.IntegerField(
        choices=STATES,
        default=STATES.candidate
    )
    public_state = models.IntegerField(
        choices=STATES,
        default=STATES.recorded
    )

    registrars = models.ManyToManyField(
        User,
        blank=True,
        related_name='registrar_in',
        verbose_name=_('Registrars')
    )

    # The below text fields allow for brief descriptions of the context of each
    # state for a particular Registration Authority
    # For example:
    # For a particular Registration Authority standard may mean"
    #   "Approved by a simple majority of the standing council of metadata
    #    standardisation"
    # While "Preferred Standard" may mean:
    #   "Approved by a two-thirds majority of the standing council of metadata
    #    standardisation"

    notprogressed = models.TextField(blank=True)
    incomplete = models.TextField(blank=True)
    candidate = models.TextField(blank=True)
    recorded = models.TextField(blank=True)
    qualified = models.TextField(blank=True)
    standard = models.TextField(blank=True)
    preferred = models.TextField(blank=True)
    superseded = models.TextField(blank=True)
    retired = models.TextField(blank=True)

    tracker = FieldTracker()

    class Meta:
        verbose_name_plural = _("Registration Authorities")

    def get_absolute_url(self):
        return url_slugify_registration_authoritity(self)

    def can_view(self, user):
        return True

    @property
    def unlocked_states(self):
        return range(STATES.notprogressed, self.locked_state)

    @property
    def locked_states(self):
        return range(self.locked_state, self.public_state)

    @property
    def public_states(self):
        return range(self.public_state, STATES.retired + 1)

    def statusDescriptions(self):
        descriptions = [
            self.notprogressed,
            self.incomplete,
            self.candidate,
            self.recorded,
            self.qualified,
            self.standard,
            self.preferred,
            self.superseded,
            self.retired
        ]

        unlocked = [
            (i, STATES[i], descriptions[i]) for i in self.unlocked_states
        ]
        locked = [
            (i, STATES[i], descriptions[i]) for i in self.locked_states
        ]
        public = [
            (i, STATES[i], descriptions[i]) for i in self.public_states
        ]

        return (
            ('unlocked', unlocked),
            ('locked', locked),
            ('public', public)
        )

    def cascaded_register(self, item, state, user, *args, **kwargs):
        if not perms.user_can_change_status(user, item):
            # Return a failure as this item isn't allowed
            return {'success': [], 'failed': [item] + item.registry_cascade_items}

        revision_message = _(
            "Cascade registration of item '%(name)s' (id:%(iid)s)\n"
        ) % {
            'name': item.name,
            'iid': item.id
        }
        revision_message = revision_message + kwargs.get('changeDetails', "")
        seen_items = {'success': [], 'failed': []}

        with transaction.atomic(), reversion.revisions.create_revision():
            reversion.revisions.set_user(user)
            reversion.revisions.set_comment(revision_message)

            for child_item in [item] + item.registry_cascade_items:
                self._register(
                    child_item, state, user, *args, **kwargs
                )
                seen_items['success'] = seen_items['success'] + [child_item]
        return seen_items

    def register(self, item, state, user, *args, **kwargs):
        if not perms.user_can_change_status(user, item):
            # Return a failure as this item isn't allowed
            return {'success': [], 'failed': [item]}

        revision_message = kwargs.get('changeDetails', "")
        with transaction.atomic(), reversion.revisions.create_revision():
            reversion.revisions.set_user(user)
            reversion.revisions.set_comment(revision_message)
            self._register(item, state, user, *args, **kwargs)

        return {'success': [item], 'failed': []}

    def _register(self, item, state, user, *args, **kwargs):
        changeDetails = kwargs.get('changeDetails', "")
        # If registrationDate is None (like from a form), override it with
        # todays date.
        registrationDate = kwargs.get('registrationDate', None) \
            or timezone.now().date()
        until_date = kwargs.get('until_date', None)

        Status.objects.create(
            concept=item,
            registrationAuthority=self,
            registrationDate=registrationDate,
            state=state,
            changeDetails=changeDetails,
            until_date=until_date
        )

    def giveRoleToUser(self, role, user):
        if role == 'registrar':
            self.registrars.add(user)
        if role == "manager":
            self.managers.add(user)

    def removeRoleFromUser(self, role, user):
        if role == 'registrar':
            self.registrars.remove(user)
        if role == "manager":
            self.managers.remove(user)
コード例 #16
0
class ActionPoint(TimeStampedModel):
    MODULE_CHOICES = Choices(
        ('t2f', _('Trip Management')),
        ('tpm', 'Third Party Monitoring'),
        ('audit', _('Auditor Portal')),
    )

    STATUSES = Choices(
        ('open', _('Open')),
        ('completed', _('Completed')),
    )

    STATUSES_DATES = {
        STATUSES.open: 'created',
        STATUSES.completed: 'date_of_completion'
    }

    KEY_EVENTS = Choices(
        ('status_update', _('Status Update')),
        ('reassign', _('Reassign')),
    )

    author = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='created_action_points',
                               verbose_name=_('Author'),
                               on_delete=models.CASCADE,
                               )
    assigned_by = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='+', verbose_name=_('Assigned By'),
                                    on_delete=models.CASCADE,
                                    )
    assigned_to = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='assigned_action_points',
                                    verbose_name=_('Assigned To'),
                                    on_delete=models.CASCADE,
                                    )

    status = FSMField(verbose_name=_('Status'), max_length=10, choices=STATUSES, default=STATUSES.open, protected=True)

    description = models.TextField(verbose_name=_('Description'))
    due_date = models.DateField(verbose_name=_('Due Date'), blank=True, null=True)
    high_priority = models.BooleanField(default=False, verbose_name=_('High Priority'))

    section = models.ForeignKey('reports.Sector', verbose_name=_('Section'), blank=True, null=True,
                                on_delete=models.CASCADE,
                                )
    office = models.ForeignKey('users.Office', verbose_name=_('Office'), blank=True, null=True,
                               on_delete=models.CASCADE,
                               )

    location = models.ForeignKey('locations.Location', verbose_name=_('Location'), blank=True, null=True,
                                 on_delete=models.CASCADE,
                                 )
    partner = models.ForeignKey('partners.PartnerOrganization', verbose_name=_('Partner'), blank=True, null=True,
                                on_delete=models.CASCADE,
                                )
    cp_output = models.ForeignKey('reports.Result', verbose_name=_('CP Output'), blank=True, null=True,
                                  on_delete=models.CASCADE,
                                  )
    intervention = models.ForeignKey('partners.Intervention', verbose_name=_('PD/SSFA'), blank=True, null=True,
                                     on_delete=models.CASCADE,
                                     )
    engagement = models.ForeignKey('audit.Engagement', verbose_name=_('Engagement'), blank=True, null=True,
                                   related_name='action_points', on_delete=models.CASCADE,
                                   )
    tpm_activity = models.ForeignKey('tpm.TPMActivity', verbose_name=_('TPM Activity'), blank=True, null=True,
                                     related_name='action_points', on_delete=models.CASCADE,
                                     )
    travel = models.ForeignKey('t2f.Travel', verbose_name=_('Travel'), blank=True, null=True,
                               on_delete=models.CASCADE,
                               )

    date_of_completion = MonitorField(verbose_name=_('Date Action Point Completed'), null=True, blank=True,
                                      default=None, monitor='status', when=[STATUSES.completed])

    comments = GenericRelation('django_comments.Comment', object_id_field='object_pk')

    history = GenericRelation('snapshot.Activity', object_id_field='target_object_id',
                              content_type_field='target_content_type')

    tracker = FieldTracker(fields=['assigned_to'])

    class Meta:
        ordering = ('id', )
        verbose_name = _('Action Point')
        verbose_name_plural = _('Action Points')

    @property
    def engagement_subclass(self):
        return self.engagement.get_subclass() if self.engagement else None

    @property
    def related_object(self):
        return self.engagement_subclass or self.tpm_activity or self.travel

    @property
    def related_module(self):
        if self.engagement:
            return self.MODULE_CHOICES.audit
        if self.tpm_activity:
            return self.MODULE_CHOICES.tpm
        if self.travel:
            return self.MODULE_CHOICES.t2f
        return None

    @property
    def reference_number(self):
        return '{}/{}/{}/APD'.format(
            connection.tenant.country_short_code or '',
            self.created.year,
            self.id,
        )

    def get_object_url(self, **kwargs):
        return build_frontend_url('apd', 'action-points', 'detail', self.id, **kwargs)

    @property
    def status_date(self):
        return getattr(self, self.STATUSES_DATES[self.status])

    def __str__(self):
        return self.reference_number

    def get_meaningful_history(self):
        return self.history.filter(
            models.Q(action=Activity.CREATE) |
            models.Q(models.Q(action=Activity.UPDATE), ~models.Q(change={}))
        )

    def snapshot_additional_data(self, diff):
        key_events = []
        if 'status' in diff:
            key_events.append(self.KEY_EVENTS.status_update)
        if 'assigned_to' in diff:
            key_events.append(self.KEY_EVENTS.reassign)

        return {'key_events': key_events}

    @classmethod
    def get_snapshot_action_display(cls, activity):
        key_events = activity.data.get('key_events')
        if key_events:
            if cls.KEY_EVENTS.status_update in key_events:
                return _('Changed status to {}').format(cls.STATUSES[activity.change['status']['after']])
            elif cls.KEY_EVENTS.reassign in key_events:
                return _('Reassigned to {}').format(
                    get_user_model().objects.get(pk=activity.change['assigned_to']['after']).get_full_name()
                )

        return activity.get_action_display()

    def get_mail_context(self, user=None, include_token=False):
        return {
            'person_responsible': self.assigned_to.get_full_name(),
            'assigned_by': self.assigned_by.get_full_name(),
            'reference_number': self.reference_number,
            'partner': self.partner.name if self.partner else '',
            'description': self.description,
            'due_date': self.due_date.strftime('%d %b %Y') if self.due_date else '',
            'object_url': self.get_object_url(user=user, include_token=include_token),
        }

    def send_email(self, recipient, template_name, additional_context=None):
        context = {
            'environment': get_environment(),
            'action_point': self.get_mail_context(user=recipient),
            'recipient': recipient.get_full_name(),
        }
        context.update(additional_context or {})

        notification = Notification.objects.create(
            sender=self,
            recipients=[recipient.email], template_name=template_name,
            template_data=context
        )
        notification.send_notification()

    def _do_complete(self):
        self.send_email(self.assigned_by, 'action_points/action_point/completed')

    @transition(status, source=STATUSES.open, target=STATUSES.completed,
                permission=has_action_permission(action='complete'),
                conditions=[
                    ActionPointCompleteActionsTakenCheck.as_condition()
                ])
    def complete(self):
        self._do_complete()
コード例 #17
0
class Workgroup(registryGroup):
    """
    A workgroup is a collection of associated users given control to work on a
    specific piece of work. Usually this work will be the creation of a
    specific collection of objects, such as data elements, for a specific
    topic.

    Workgroup owners may choose to 'archive' a workgroup. All content remains
    visible, but the workgroup is hidden in lists and new items cannot be
    created in that workgroup.
    """
    template = "aristotle_mdr/workgroup.html"
    archived = models.BooleanField(
        default=False,
        help_text=_("Archived workgroups can no longer have new items or "
                    "discussions created within them."),
        verbose_name=_('Archived'),
    )

    viewers = models.ManyToManyField(
        User,
        blank=True,
        related_name='viewer_in',
        verbose_name=_('Viewers')
    )
    submitters = models.ManyToManyField(
        User,
        blank=True,
        related_name='submitter_in',
        verbose_name=_('Submitters')
    )
    stewards = models.ManyToManyField(
        User,
        blank=True,
        related_name='steward_in',
        verbose_name=_('Stewards')
    )

    roles = {
        'submitter': _("Submitter"),
        'viewer': _("Viewer"),
        'steward': _("Steward"),
        'manager': _("Manager")
    }

    tracker = FieldTracker()

    def get_absolute_url(self):
        return url_slugify_workgroup(self)

    @property
    def members(self):
        return self.viewers.all() \
            | self.submitters.all() \
            | self.stewards.all() \
            | self.managers.all()

    def can_view(self, user):
        return self.members.filter(pk=user.pk).exists()

    @property
    def classedItems(self):
        # Convenience class as we can't call functions in templates
        return self.items.select_subclasses()

    def giveRoleToUser(self, role, user):
        if role == "manager":
            self.managers.add(user)
        if role == "viewer":
            self.viewers.add(user)
        if role == "submitter":
            self.submitters.add(user)
        if role == "steward":
            self.stewards.add(user)
        self.save()

    def removeRoleFromUser(self, role, user):
        if role == "manager":
            self.managers.remove(user)
        if role == "viewer":
            self.viewers.remove(user)
        if role == "submitter":
            self.submitters.remove(user)
        if role == "steward":
            self.stewards.remove(user)
        self.save()

    def removeUser(self, user):
        self.viewers.remove(user)
        self.submitters.remove(user)
        self.stewards.remove(user)
        self.managers.remove(user)
コード例 #18
0
ファイル: models.py プロジェクト: p-p-m/nodeconductor
class Project(core_models.DescribableMixin, core_models.UuidMixin,
              core_models.NameMixin, core_models.DescendantMixin,
              quotas_models.QuotaModelMixin, LoggableMixin, TimeStampedModel,
              StructureModel):
    class Permissions(object):
        customer_path = 'customer'
        project_path = 'self'
        project_group_path = 'project_groups'

    QUOTAS_NAMES = ['nc_resource_count', 'nc_service_project_link_count']
    GLOBAL_COUNT_QUOTA_NAME = 'nc_global_project_count'

    customer = models.ForeignKey(Customer,
                                 related_name='projects',
                                 on_delete=models.PROTECT)
    tracker = FieldTracker()

    # XXX: Hack for gcloud and logging
    @property
    def project_group(self):
        return self.project_groups.first()

    @property
    def full_name(self):
        project_group = self.project_group
        name = (project_group.name +
                ' / ' if project_group else '') + self.name
        return name

    def add_user(self, user, role_type):
        UserGroup = get_user_model().groups.through

        with transaction.atomic():

            role = self.roles.get(role_type=role_type)

            membership, created = UserGroup.objects.get_or_create(
                user=user,
                group=role.permission_group,
            )

            if created:
                structure_role_granted.send(
                    sender=Project,
                    structure=self,
                    user=user,
                    role=role_type,
                )

            return membership, created

    def remove_user(self, user, role_type=None):
        UserGroup = get_user_model().groups.through

        with transaction.atomic():
            memberships = UserGroup.objects.filter(
                group__projectrole__project=self,
                user=user,
            )

            if role_type is not None:
                memberships = memberships.filter(
                    group__projectrole__role_type=role_type)

            self.remove_memberships(memberships)

    def remove_all_users(self):
        UserGroup = get_user_model().groups.through

        with transaction.atomic():
            memberships = UserGroup.objects.filter(
                group__projectrole__project=self)
            self.remove_memberships(memberships)

    def remove_memberships(self, memberships):
        for membership in memberships.iterator():
            role = membership.group.projectrole
            structure_role_revoked.send(
                sender=Project,
                structure=self,
                user=membership.user,
                role=role.role_type,
            )

            membership.delete()

    def has_user(self, user, role_type=None):
        queryset = self.roles.filter(permission_group__user=user)

        if role_type is not None:
            queryset = queryset.filter(role_type=role_type)

        return queryset.exists()

    def get_users(self):
        return get_user_model().objects.filter(
            groups__projectrole__project=self)

    def __str__(self):
        return '%(name)s | %(customer)s' % {
            'name': self.name,
            'customer': self.customer.name
        }

    def can_user_update_quotas(self, user):
        return user.is_staff

    def get_log_fields(self):
        return ('uuid', 'customer', 'name', 'project_group')

    @classmethod
    def get_permitted_objects_uuids(cls, user):
        return {
            'project_uuid':
            filter_queryset_for_user(cls.objects.all(),
                                     user).values_list('uuid', flat=True)
        }

    def get_parents(self):
        return [self.customer]

    def get_links(self):
        """
        Get all service project links connected to current project
        """
        return [
            link for model in SupportedServices.get_service_models().values()
            for link in model['service_project_link'].objects.filter(
                project=self)
        ]
コード例 #19
0
class Instance(TenantQuotaMixin, structure_models.VirtualMachine):
    class RuntimeStates(object):
        # All possible OpenStack Instance states on backend.
        # See https://docs.openstack.org/developer/nova/vmstates.html
        ACTIVE = 'ACTIVE'
        BUILDING = 'BUILDING'
        DELETED = 'DELETED'
        SOFT_DELETED = 'SOFT_DELETED'
        ERROR = 'ERROR'
        UNKNOWN = 'UNKNOWN'
        HARD_REBOOT = 'HARD_REBOOT'
        REBOOT = 'REBOOT'
        REBUILD = 'REBUILD'
        PASSWORD = '******'
        PAUSED = 'PAUSED'
        RESCUED = 'RESCUED'
        RESIZED = 'RESIZED'
        REVERT_RESIZE = 'REVERT_RESIZE'
        SHUTOFF = 'SHUTOFF'
        STOPPED = 'STOPPED'
        SUSPENDED = 'SUSPENDED'
        VERIFY_RESIZE = 'VERIFY_RESIZE'

    # backend_id is nullable on purpose, otherwise
    # it wouldn't be possible to put a unique constraint on it
    backend_id = models.CharField(max_length=255, blank=True, null=True)
    service_project_link = models.ForeignKey(OpenStackTenantServiceProjectLink,
                                             related_name='instances',
                                             on_delete=models.PROTECT)

    flavor_name = models.CharField(max_length=255, blank=True)
    flavor_disk = models.PositiveIntegerField(
        default=0, help_text=_('Flavor disk size in MiB'))
    security_groups = models.ManyToManyField(SecurityGroup,
                                             related_name='instances')
    # TODO: Move this fields to resource model.
    action = models.CharField(max_length=50, blank=True)
    action_details = JSONField(default=dict)
    subnets = models.ManyToManyField('SubNet', through='InternalIP')

    tracker = FieldTracker()

    class Meta(object):
        unique_together = ('service_project_link', 'backend_id')

    @property
    def external_ips(self):
        return list(self.floating_ips.values_list('address', flat=True))

    @property
    def internal_ips(self):
        return list(self.internal_ips_set.values_list('ip4_address',
                                                      flat=True))

    @property
    def size(self):
        return self.volumes.aggregate(models.Sum('size'))['size__sum']

    @classmethod
    def get_url_name(cls):
        return 'openstacktenant-instance'

    def get_log_fields(self):
        return (
            'uuid',
            'name',
            'type',
            'service_project_link',
            'ram',
            'cores',
        )

    def detect_coordinates(self):
        settings = self.service_project_link.service.settings
        options = settings.options or {}
        if 'latitude' in options and 'longitude' in options:
            return structure_utils.Coordinates(latitude=settings['latitude'],
                                               longitude=settings['longitude'])
        else:
            hostname = urlparse(settings.backend_url).hostname
            if hostname:
                return structure_utils.get_coordinates_by_ip(hostname)

    def get_quota_deltas(self):
        return {
            TenantQuotas.instances: 1,
            TenantQuotas.ram: self.ram,
            TenantQuotas.vcpu: self.cores,
        }

    @property
    def floating_ips(self):
        return FloatingIP.objects.filter(internal_ip__instance=self)

    @classmethod
    def get_backend_fields(cls):
        return super(Instance, cls).get_backend_fields() + (
            'flavor_name', 'flavor_disk', 'ram', 'cores', 'disk',
            'runtime_state')

    @classmethod
    def get_online_state(cls):
        return Instance.RuntimeStates.ACTIVE

    @classmethod
    def get_offline_state(cls):
        return Instance.RuntimeStates.SHUTOFF
コード例 #20
0
ファイル: models.py プロジェクト: p-p-m/nodeconductor
class ProjectGroup(core_models.UuidMixin, core_models.DescribableMixin,
                   core_models.NameMixin, core_models.DescendantMixin,
                   quotas_models.QuotaModelMixin, LoggableMixin,
                   TimeStampedModel):
    """
    Project groups are means to organize customer's projects into arbitrary sets.
    """
    class Permissions(object):
        customer_path = 'customer'
        project_path = 'projects'
        project_group_path = 'self'

    customer = models.ForeignKey(Customer,
                                 related_name='project_groups',
                                 on_delete=models.PROTECT)
    projects = models.ManyToManyField(Project, related_name='project_groups')

    tracker = FieldTracker()

    GLOBAL_COUNT_QUOTA_NAME = 'nc_global_project_group_count'

    def __str__(self):
        return self.name

    def add_user(self, user, role_type):
        UserGroup = get_user_model().groups.through

        with transaction.atomic():
            role = self.roles.get(role_type=role_type)

            membership, created = UserGroup.objects.get_or_create(
                user=user,
                group=role.permission_group,
            )

            if created:
                structure_role_granted.send(
                    sender=ProjectGroup,
                    structure=self,
                    user=user,
                    role=role_type,
                )

            return membership, created

    def remove_user(self, user, role_type=None):
        UserGroup = get_user_model().groups.through

        with transaction.atomic():
            memberships = UserGroup.objects.filter(
                group__projectgrouprole__project_group=self,
                user=user,
            )

            if role_type is not None:
                memberships = memberships.filter(
                    group__projectgrouprole__role_type=role_type)

            for membership in memberships.iterator():
                role = membership.group.projectgrouprole
                structure_role_revoked.send(
                    sender=ProjectGroup,
                    structure=self,
                    user=membership.user,
                    role=role.role_type,
                )

                membership.delete()

    def has_user(self, user, role_type=None):
        queryset = self.roles.filter(permission_group__user=user)

        if role_type is not None:
            queryset = queryset.filter(role_type=role_type)

        return queryset.exists()

    def get_log_fields(self):
        return ('uuid', 'customer', 'name')

    def get_parents(self):
        return [self.customer]

    @classmethod
    def get_permitted_objects_uuids(cls, user):
        return {
            'project_group_uuid':
            filter_queryset_for_user(cls.objects.all(),
                                     user).values_list('uuid', flat=True)
        }
コード例 #21
0
class CourseTeam(models.Model):
    """
    This model represents team related info.

    .. no_pii:
    """
    class Meta(object):
        app_label = "teams"

    team_id = models.CharField(max_length=255, unique=True)
    discussion_topic_id = models.CharField(max_length=255, unique=True)
    name = models.CharField(max_length=255, db_index=True)
    course_id = CourseKeyField(max_length=255, db_index=True)
    topic_id = models.CharField(max_length=255, db_index=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    description = models.CharField(max_length=300)
    country = CountryField(blank=True)
    language = LanguageField(
        blank=True,
        help_text=ugettext_lazy(
            "Optional language the team uses as ISO 639-1 code."),
    )
    last_activity_at = models.DateTimeField(
        db_index=True)  # indexed for ordering
    users = models.ManyToManyField(User,
                                   db_index=True,
                                   related_name='teams',
                                   through='CourseTeamMembership')
    team_size = models.IntegerField(default=0,
                                    db_index=True)  # indexed for ordering

    field_tracker = FieldTracker()

    # Don't emit changed events when these fields change.
    FIELD_BLACKLIST = ['last_activity_at', 'team_size']

    @classmethod
    def create(cls,
               name,
               course_id,
               description,
               topic_id=None,
               country=None,
               language=None):
        """Create a complete CourseTeam object.

        Args:
            name (str): The name of the team to be created.
            course_id (str): The ID string of the course associated
              with this team.
            description (str): A description of the team.
            topic_id (str): An optional identifier for the topic the
              team formed around.
            country (str, optional): An optional country where the team
              is based, as ISO 3166-1 code.
            language (str, optional): An optional language which the
              team uses, as ISO 639-1 code.

        """
        unique_id = uuid4().hex
        team_id = slugify(name)[0:20] + '-' + unique_id
        discussion_topic_id = unique_id

        course_team = cls(
            team_id=team_id,
            discussion_topic_id=discussion_topic_id,
            name=name,
            course_id=course_id,
            topic_id=topic_id if topic_id else '',
            description=description,
            country=country if country else '',
            language=language if language else '',
            last_activity_at=datetime.utcnow().replace(tzinfo=pytz.utc))

        return course_team

    def __repr__(self):
        return "<CourseTeam team_id={0.team_id}>".format(self)

    def add_user(self, user):
        """Adds the given user to the CourseTeam."""
        if not CourseEnrollment.is_enrolled(user, self.course_id):
            raise NotEnrolledInCourseForTeam
        if CourseTeamMembership.user_in_team_for_course(user, self.course_id):
            raise AlreadyOnTeamInCourse
        return CourseTeamMembership.objects.create(user=user, team=self)

    def reset_team_size(self):
        """Reset team_size to reflect the current membership count."""
        self.team_size = CourseTeamMembership.objects.filter(team=self).count()
        self.save()
コード例 #22
0
ファイル: models.py プロジェクト: ZechyW/cs-toolkit
class Derivation(NotifyModel):
    """
    A Django model representing a grammatical derivation.

    Each Derivation can host multiple DerivationStep chains, since multiple
    operation types can result in multiple branching paths at each
    individual DerivationStep.

    Each DerivationStep chain should either converge or crash, as determined
    by the last step in the chain.
    """

    id = models.UUIDField(primary_key=True, default=uuid.uuid4)

    # Derivations are complete if all their possible chains have been
    # processed to a crash/convergence
    complete = models.BooleanField(default=False)

    @property
    def converged_count(self):
        return self.converged_steps.count()

    @property
    def crashed_count(self):
        return self.crashed_steps.count()

    @property
    def converged_chains(self):
        """
        Returns all the DerivationStep chains associated with this
        Derivation which converged.
        :return:
        """
        return Derivation.get_chains_from_steps(self.converged_steps.all())

    @property
    def crashed_chains(self):
        """
        Returns all the DerivationStep chains associated with this
        Derivation which converged.
        :return:
        """
        return Derivation.get_chains_from_steps(self.crashed_steps.all())

    @staticmethod
    def get_chains_from_steps(end_steps):
        """
        From a given iterable of end DerivationSteps, retrieve all the
        corresponding full chains.
        :param end_steps:
        :return:
        """
        chains = []
        for end_step in end_steps:
            this_chain = [end_step]
            this_step = end_step

            # Each DerivationStep may have multiple `next_steps`, but only one
            # `previous_step`.  If we follow the chain backward, we will get
            # back to the `first_step`.
            while this_step.previous_step:
                this_chain.append(this_step.previous_step)
                this_step = this_step.previous_step

            # We now have a chain from last step to first -- Reverse it and
            # append it to the list of all chains for this Derivation.
            this_chain.reverse()
            chains.append(this_chain)

        return chains

    #: Used for change notifications. Subscribers will only be alerted when a
    #: substantive change is made to a model instance.
    tracker = FieldTracker()

    #: Used for change notifications. Subscribers will receive the latest model
    #: data processed via this serializer.
    serializer_class = "grammar.serializers.DerivationSerializer"

    def __str__(self):
        if hasattr(self, "first_step"):
            return str(self.first_step)
        else:
            return "<Invalid Derivation>"
コード例 #23
0
class CourseTeam(models.Model):
    """
    This model represents team related info.

    .. no_pii:
    """
    def __str__(self):
        return "{} in {}".format(self.name, self.course_id)

    def __repr__(self):
        return (
            "<CourseTeam"
            " id={0.id}"
            " team_id={0.team_id}"
            " team_size={0.team_size}"
            " topic_id={0.topic_id}"
            " course_id={0.course_id}"
            ">"
        ).format(self)

    class Meta(object):
        app_label = "teams"

    team_id = models.SlugField(max_length=255, unique=True)
    discussion_topic_id = models.SlugField(max_length=255, unique=True)
    name = models.CharField(max_length=255, db_index=True)
    course_id = CourseKeyField(max_length=255, db_index=True)
    topic_id = models.CharField(max_length=255, db_index=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True)
    description = models.CharField(max_length=300)
    country = CountryField(blank=True)
    language = LanguageField(
        blank=True,
        help_text=ugettext_lazy("Optional language the team uses as ISO 639-1 code."),
    )
    last_activity_at = models.DateTimeField(db_index=True)  # indexed for ordering
    users = models.ManyToManyField(User, db_index=True, related_name='teams', through='CourseTeamMembership')
    team_size = models.IntegerField(default=0, db_index=True)  # indexed for ordering

    field_tracker = FieldTracker()

    # This field would divide the teams into two mutually exclusive groups
    # If the team is org protected, the members in a team is enrolled into a degree bearing institution
    # If the team is not org protected, the members in a team is part of the general edX learning community
    # We need this exclusion for learner privacy protection
    organization_protected = models.BooleanField(default=False)

    # Don't emit changed events when these fields change.
    FIELD_BLACKLIST = ['last_activity_at', 'team_size']

    @classmethod
    def create(
        cls,
        name,
        course_id,
        description,
        topic_id=None,
        country=None,
        language=None,
        organization_protected=False
    ):
        """Create a complete CourseTeam object.

        Args:
            name (str): The name of the team to be created.
            course_id (str): The ID string of the course associated
              with this team.
            description (str): A description of the team.
            topic_id (str): An optional identifier for the topic the
              team formed around.
            country (str, optional): An optional country where the team
              is based, as ISO 3166-1 code.
            language (str, optional): An optional language which the
              team uses, as ISO 639-1 code.
            organization_protected (bool, optional): specifies whether the team should only
              contain members who are in a organization context, or not

        """
        unique_id = uuid4().hex
        team_id = slugify(name)[0:20] + '-' + unique_id
        discussion_topic_id = unique_id

        course_team = cls(
            team_id=team_id,
            discussion_topic_id=discussion_topic_id,
            name=name,
            course_id=course_id,
            topic_id=topic_id if topic_id else '',
            description=description,
            country=country if country else '',
            language=language if language else '',
            last_activity_at=datetime.utcnow().replace(tzinfo=pytz.utc),
            organization_protected=organization_protected
        )

        return course_team

    def add_user(self, user):
        """Adds the given user to the CourseTeam."""
        if not CourseEnrollment.is_enrolled(user, self.course_id):
            raise NotEnrolledInCourseForTeam
        if CourseTeamMembership.user_in_team_for_course(user, self.course_id):
            raise AlreadyOnTeamInCourse
        return CourseTeamMembership.objects.create(
            user=user,
            team=self
        )

    def reset_team_size(self):
        """Reset team_size to reflect the current membership count."""
        self.team_size = CourseTeamMembership.objects.filter(team=self).count()
        self.save()
コード例 #24
0
class Account(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    username = models.CharField(max_length=255)
    foreign_id = models.CharField(
        max_length=255, null=True, unique=True,
        help_text='The foreign identifier from the datastore.')
    default_project = models.ForeignKey(
        'karaage.Project', null=True, blank=True,
        on_delete=models.SET_NULL)
    date_created = models.DateField()
    date_deleted = models.DateField(null=True, blank=True)
    disk_quota = models.IntegerField(null=True, blank=True, help_text="In GB")
    shell = models.CharField(max_length=50)
    login_enabled = models.BooleanField(default=True)
    extra_data = JSONField(
        default={},
        help_text='Datastore specific values should be stored in this field.')

    _tracker = FieldTracker()

    def __init__(self, *args, **kwargs):
        super(Account, self).__init__(*args, **kwargs)
        self._password = None

    class Meta:
        ordering = ['person', ]
        db_table = 'account'
        app_label = 'karaage'

    def __str__(self):
        return '%s' % self.username

    def get_absolute_url(self):
        return reverse('kg_account_detail', args=[self.pk])

    @classmethod
    def create(cls, person, default_project):
        """Creates a Account (if needed) and activates person.
        """
        ua = Account.objects.create(
            person=person, username=person.username,
            shell=settings.DEFAULT_SHELL,
            default_project=default_project,
            date_created=datetime.datetime.today())

        if default_project is not None:
            person.add_group(default_project.group)

        return ua

    def project_list(self):
        return self.person.projects.all()

    def save(self, *args, **kwargs):
        created = self.pk is None

        # save the object
        super(Account, self).save(*args, **kwargs)

        if created:
            log.add(
                self.person,
                'Account %s: Created' % self)
        for field in self._tracker.changed():
            if field != "password":
                log.change(
                    self.person,
                    'Account %s: Changed %s to %s'
                    % (self, field, getattr(self, field)))

        # check if it was renamed
        if self._tracker.has_changed('username'):
            old_username = self._tracker.previous('username')
            if old_username is not None:
                new_username = self.username
                if self.date_deleted is None:
                    from karaage.datastores import set_account_username
                    set_account_username(self, old_username, new_username)
                log.change(
                    self.person,
                    'Account %s: Changed username from %s to %s' %
                    (self, old_username, new_username))

        # check if deleted status changed
        if self._tracker.has_changed('date_deleted'):
            if self.date_deleted is not None:
                # account is deactivated
                from karaage.datastores import delete_account
                delete_account(self)
                log.delete(
                    self.person,
                    'Account %s: Deactivated account' % self)
                # deleted
            else:
                # account is reactivated
                log.add(
                    self.person,
                    'Account %s: Activated' % self)

        # makes sense to lock non-existant account
        if self.date_deleted is not None:
            self.login_enabled = False

        # update the datastore
        if self.date_deleted is None:
            from karaage.datastores import save_account
            save_account(self)

            if self._password is not None:
                from karaage.datastores import set_account_password
                set_account_password(self, self._password)
                log.change(
                    self.person,
                    'Account %s: Changed Password' % self)
                self._password = None
    save.alters_data = True

    def can_view(self, request):
        # if user not authenticated, no access
        if not request.user.is_authenticated:
            return False

        # ensure person making request isn't deleted.
        if not request.user.is_active:
            return False

        # ensure person making request isn't locked.
        if request.user.is_locked():
            return False

        # if user is admin, full access
        if is_admin(request):
            return True

        # ensure this account is not locked
        if self.is_locked():
            return False

        # ensure this account is not deleted
        if self.date_deleted is not None:
            return False

        # ensure person owning account isn't locked.
        if self.person.is_locked():
            return False

        # ensure person owning account isn't deleted.
        if not self.person.is_active:
            return False

        return True

    def can_edit(self, request):
        # if we can't view this account, we can't edit it either
        if not self.can_view(request):
            return False

        if not is_admin(request):
            # if not admin, ensure we are the person being altered
            if self.person != request.user:
                return False

        return True

    def delete(self, **kwargs):
        # delete the object
        log.delete(self.person, 'Account %s: Deleted' % self)
        super(Account, self).delete(**kwargs)
        if self.date_deleted is None:
            # delete the datastore
            from karaage.datastores import delete_account
            delete_account(self)
    delete.alters_data = True

    def deactivate(self):
        if self.date_deleted is not None:
            raise RuntimeError("Account is deactivated")
        # save the object
        self.date_deleted = datetime.datetime.now()
        self.login_enabled = False
        self.save()
        # self.save() will delete the datastore for us.
    deactivate.alters_data = True

    def change_shell(self, shell):
        self.shell = shell
        self.save()
        # self.save() will update the datastore for us.
    change_shell.alters_data = True

    def set_password(self, password):
        if self.date_deleted is not None:
            raise RuntimeError("Account is deactivated")
        self._password = password
    set_password.alters_data = True

    def get_disk_quota(self):
        # FIXME: should this become deprecated?
        return self.disk_quota

    def login_shell(self):
        return self.shell

    def lock(self):
        if self.date_deleted is not None:
            raise RuntimeError("Account is deactivated")
        self.login_enabled = False
        self.save()
    lock.alters_data = True

    def unlock(self):
        if self.date_deleted is not None:
            raise RuntimeError("Account is deactivated")
        self.login_enabled = True
        self.save()
    unlock.alters_data = True

    def is_locked(self):
        return not self.login_enabled
コード例 #25
0
class VirtualMachine(VirtualMachineMixin, core_models.RuntimeStateMixin,
                     structure_models.BaseResource):
    class RuntimeStates:
        POWERED_OFF = 'POWERED_OFF'
        POWERED_ON = 'POWERED_ON'
        SUSPENDED = 'SUSPENDED'

        CHOICES = (
            (POWERED_OFF, 'Powered off'),
            (POWERED_ON, 'Powered on'),
            (SUSPENDED, 'Suspended'),
        )

    class GuestPowerStates:
        RUNNING = 'RUNNING'
        SHUTTING_DOWN = 'SHUTTING_DOWN'
        RESETTING = 'RESETTING'
        STANDBY = 'STANDBY'
        NOT_RUNNING = 'NOT_RUNNING'
        UNAVAILABLE = 'UNAVAILABLE'

        CHOICES = (
            (RUNNING, 'Running'),
            (SHUTTING_DOWN, 'Shutting down'),
            (RESETTING, 'Resetting'),
            (STANDBY, 'Standby'),
            (NOT_RUNNING, 'Not running'),
            (UNAVAILABLE, 'Unavailable'),
        )

    class ToolsStates:
        STARTING = 'STARTING'
        RUNNING = 'RUNNING'
        NOT_RUNNING = 'NOT_RUNNING'

        CHOICES = (
            (STARTING, 'Starting'),
            (RUNNING, 'Running'),
            (NOT_RUNNING, 'Not running'),
        )

    template = models.ForeignKey('Template',
                                 null=True,
                                 on_delete=models.SET_NULL)
    cluster = models.ForeignKey('Cluster',
                                null=True,
                                on_delete=models.SET_NULL)
    datastore = models.ForeignKey('Datastore',
                                  null=True,
                                  on_delete=models.SET_NULL)
    folder = models.ForeignKey('Folder', null=True, on_delete=models.SET_NULL)
    networks = models.ManyToManyField('Network', blank=True)
    guest_power_enabled = models.BooleanField(
        default=False,
        help_text=
        'Flag indicating if the virtual machine is ready to process soft power operations.',
    )
    guest_power_state = models.CharField(
        'The power state of the guest operating system.',
        max_length=150,
        blank=True,
        choices=GuestPowerStates.CHOICES,
    )
    tools_installed = models.BooleanField(default=False)
    tools_state = models.CharField(
        'Current running status of VMware Tools running in the guest operating system.',
        max_length=50,
        blank=True,
        choices=ToolsStates.CHOICES,
    )
    tracker = FieldTracker()

    @classmethod
    def get_backend_fields(cls):
        return super(VirtualMachine, cls).get_backend_fields() + (
            'runtime_state',
            'cores',
            'cores_per_socket',
            'ram',
            'disk',
            'tools_installed',
            'tools_state',
        )

    @classmethod
    def get_url_name(cls):
        return 'vmware-virtual-machine'

    @property
    def total_disk(self):
        return self.disks.aggregate(models.Sum('size'))['size__sum'] or 0

    def __str__(self):
        return self.name
コード例 #26
0
class MysqlUser(models.Model):
    account = models.ForeignKey(settings.AUTH_USER_MODEL,
                                blank=False,
                                null=False,
                                on_delete=models.CASCADE,
                                related_name='mysql_user_account')

    mysql_database = models.ForeignKey(
        'MysqlDatabase',
        blank=False,
        null=False,
        on_delete=models.CASCADE,
        related_name='mysql_user_mysql_database')

    product_profile = models.ForeignKey(
        'ProductProfile',
        blank=False,
        null=False,
        on_delete=models.CASCADE,
        related_name='mysql_user_product_profile')

    date_from = models.DateTimeField(auto_now_add=True)

    in_queue = models.BooleanField(default=False)

    is_active = models.BooleanField(default=False)

    password = models.TextField(blank=False, null=False)

    permission_alter = models.BooleanField(default=False)

    permission_create = models.BooleanField(default=False)

    permission_create_view = models.BooleanField(default=False)

    permission_delete = models.BooleanField(default=False)

    permission_drop = models.BooleanField(default=False)

    permission_index = models.BooleanField(default=False)

    permission_insert = models.BooleanField(default=False, )

    permission_select = models.BooleanField(default=False)

    permission_show_view = models.BooleanField(default=False)

    permission_update = models.BooleanField(default=False)

    username = models.CharField(
        blank=False,
        max_length=32,
        null=False,
        validators=[
            validators.MinLengthValidator(2),
            validators.RegexValidator('^[a-z][a-z0-9_]+$')
        ])

    tracker = FieldTracker()

    class Meta:
        db_table = 'mysql_user'

        default_permissions = ()

        verbose_name = 'MySQL User'
        verbose_name_plural = 'MySQL Users'
コード例 #27
0
class Application(models.Model):
    """ Generic application for anything. """
    WAITING_FOR_ADMIN = 'K'
    COMPLETED = 'C'
    ARCHIVED = 'A'
    DECLINED = 'R'

    secret_token = models.CharField(max_length=64,
                                    default=new_random_token,
                                    editable=False,
                                    unique=True)
    expires = models.DateTimeField(editable=False)
    created_by = models.ForeignKey(Person,
                                   editable=False,
                                   null=True,
                                   blank=True)
    created_date = models.DateTimeField(auto_now_add=True, editable=False)
    submitted_date = models.DateTimeField(null=True, blank=True)
    state = models.CharField(max_length=5)
    complete_date = models.DateTimeField(null=True, blank=True, editable=False)
    content_type = models.ForeignKey(
        ContentType,
        limit_choices_to={'model__in': ['person', 'applicant']},
        null=True,
        blank=True)
    object_id = models.PositiveIntegerField(null=True, blank=True)
    applicant = GenericForeignKey()
    header_message = models.TextField(
        'Message',
        null=True,
        blank=True,
        help_text=six.u("Message displayed at top of application form "
                        "for the invitee and also in invitation email"))
    _class = models.CharField(max_length=100, editable=False)

    objects = ApplicationManager()

    _tracker = FieldTracker()

    class Meta:
        db_table = "applications_application"

    def __str__(self):
        return "Application #%s" % self.id

    def info(self):
        return six.text_type(self)

    def get_type(self):
        return self._class

    @models.permalink
    def get_absolute_url(self):
        return 'kg_application_detail', [self.id]

    def save(self, *args, **kwargs):
        created = self.pk is None
        if not self.expires:
            self.expires = datetime.datetime.now() + datetime.timedelta(days=7)
        if not self.pk:
            self.created_by = get_current_person()

            # Find the accessor from Application to type(self) class
            if hasattr(Application._meta, 'get_fields'):
                # Django >= 1.8
                fields = [
                    f for f in Application._meta.get_fields()
                    if isinstance(f, OneToOneRel) and f.field.primary_key
                    and f.auto_created
                ]

            else:
                # Django <= 1.8
                fields = [
                    f for f in Application._meta.get_all_related_objects()
                    if isinstance(f, OneToOneRel) and f.field.primary_key
                ]

            for rel in fields:
                # Works with Django < 1.8 and => 1.8
                related_model = getattr(rel, 'related_model', rel.model)

                # if we find it, save the name
                if related_model == type(self):
                    self._class = rel.get_accessor_name()
                    break

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

        if created:
            log.add(self, 'Created')
        for field in self._tracker.changed():
            log.change(self,
                       'Changed %s to %s' % (field, getattr(self, field)))

    save.alters_data = True

    def delete(self, *args, **kwargs):
        log.delete(self, 'Deleted')
        super(Application, self).delete(*args, **kwargs)

    def get_object(self):
        if self._class:
            return getattr(self, self._class)
        return self

    def reopen(self):
        self.submitted_date = None
        self.complete_date = None
        self.expires = datetime.datetime.now() + datetime.timedelta(days=7)
        self.save()

    def extend(self):
        self.expires = datetime.datetime.now() + datetime.timedelta(days=7)
        self.save()

    def submit(self):
        self.submitted_date = datetime.datetime.now()
        self.save()

    def approve(self, approved_by):
        assert self.applicant is not None
        if self.content_type.model == 'applicant':
            person = self.applicant.approve(approved_by)
            created_person = True
        elif self.content_type.model == 'person':
            person = self.applicant
            created_person = False
        else:
            assert False
        self.applicant = person
        self.complete_date = datetime.datetime.now()
        self.save()
        return created_person, False

    approve.alters_data = True

    def decline(self):
        self.complete_date = datetime.datetime.now()
        self.save()

    decline.alters_data = True

    def check_valid(self):
        errors = []

        if self.applicant is None:
            errors.append("Applicant not set.")
        elif self.content_type.model == 'applicant':
            errors.extend(self.applicant.check_valid())

        return errors

    def get_roles_for_person(self, person):
        roles = set()

        if person == self.applicant:
            roles.add('is_applicant')
            roles.add('is_authorised')

        return roles
コード例 #28
0
ファイル: models.py プロジェクト: bernallium/roadstartire
class Cart(TimeStampMixin):
    class Status(models.IntegerChoices):
        CURRENT = 1
        ABANDONED = -1
        IN_PROGRESS = 2
        CANCELLED = -2
        FULFILLED = 3

    status_help_text = """
    <br/>
    A Cart can be in 1 of 5 states:<br/>
    🛒 <strong>Current</strong> - The currently open cart (each user can only have 1 cart in this state)<br/>
    ⏳ <strong>In progress</strong> - Cart has been submitted but not yet fulfilled or cancelled<br/>
    ✅ <strong>Fulfilled</strong> - Items have been delivered to client and payment has been received<br/>
    ❌ <strong>Cancelled</strong> - Cart can no longer be fulfilled<br/>
    🚧 <strong>Abandoned</strong> - The last item in the cart was removed (this will occur automatically)<br/>
  
  """

    discount_percent_applied_help_text = """
    Defaults to using the User's discount percent<br/>
  """

    tax_percent_help_text = """
    Defaults to using the User's tax percent<br/>
  """

    closed_at_help_text = """
    Date when the cart was last marked as <strong>Fulfilled</strong>, <strong>Cancelled</strong>, or <strong>Abandoned</strong>
  """

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE)  # 1:M, a user can have many carts
    status = models.IntegerField(choices=Status.choices,
                                 help_text=status_help_text)
    discount_percent_applied = models.DecimalField(
        max_digits=5,
        decimal_places=2,
        blank=True,
        validators=[
            MinValueValidator(0),
            MaxValueValidator(100),
        ],
        verbose_name='Discount (%)',
        help_text=discount_percent_applied_help_text)
    tax_percent_applied = models.DecimalField(max_digits=5,
                                              decimal_places=2,
                                              blank=True,
                                              validators=[
                                                  MinValueValidator(0),
                                                  MaxValueValidator(100),
                                              ],
                                              verbose_name='Tax (%)',
                                              help_text=tax_percent_help_text)
    ordered_at = models.DateTimeField(null=True,
                                      blank=True,
                                      verbose_name='Date Ordered')
    closed_at = models.DateTimeField(null=True,
                                     blank=True,
                                     verbose_name='Date Closed',
                                     help_text=closed_at_help_text)

    def __str__(self):
        return f'Cart #{self.id}'

    # @property
    # def get_total(self):
    #   return self.cartDetail_set.all().count()

    # discount_percent_applied and tax_percent_applied default values are pulled from the User when one is not explicitly entered
    def save(self, *args, **kwargs):
        if not self.discount_percent_applied:
            self.discount_percent_applied = self.user.discount_percent
        if not self.tax_percent_applied:
            self.tax_percent_applied = self.user.tax_percent
        super(Cart, self).save(*args, **kwargs)

# @receiver(pre_save, sender=Cart)
# def get_user_discount_ratio(sender, instance, *args, **kwargs):
#     instance.discount_ratio = instance.user.discount_ratio

    def get_subtotal(self):
        cart = Cart.objects.get(pk=self.pk)
        subtotal = Decimal(
            '0.00')  # Need to use Decimal type so that 0 is displayed as 0.00
        for cartDetail in self.cartdetail_set.all():
            subtotal += cartDetail.quantity * cartDetail.tire.price
        return subtotal

    get_subtotal.short_description = 'Subtotal ($)'

    def get_discount_amount(self):
        return round(self.get_subtotal() * self.discount_percent_applied / 100,
                     2)

    get_discount_amount.short_description = 'Discount amount ($)'

    def get_tax_amount(self):
        return round(self.get_subtotal() * self.tax_percent_applied / 100, 2)

    get_tax_amount.short_description = 'Tax amount ($)'

    def get_total(self):
        return self.get_subtotal() - self.get_discount_amount(
        ) + self.get_tax_amount()

    get_total.short_description = 'Total ($)'

    def get_owner(self):
        return self.user.full_name

    get_owner.short_description = 'Full name'

    # def get_item_count(self):
    #   cart = Cart.objects.get(id=self.id)
    #   count = 0
    #   for cartDetail in cart.cartdetail_set.all():
    #     count += cartDetail.quantity
    #   return count
    # get_item_count.short_description = 'Number of items'

    def get_item_count(self):
        return self.cartdetail_set.all().count()

    get_item_count.short_description = 'Number of items'

    status_tracker = FieldTracker(fields=['status'])

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['user', 'status'],
                                    condition=Q(status=1),
                                    name='unique_current_cart')
        ]

    @staticmethod
    def does_state_require_shipping_info(status):
        if (status == Cart.Status.IN_PROGRESS
                or status == Cart.Status.FULFILLED
                or status == Cart.Status.CANCELLED):
            return True

    def get_order_number(self):
        order_number = self.ordershipping.pk
        return order_number

    get_order_number.short_description = 'Order #'
コード例 #29
0
class Resource(
        ResourceDetailsMixin,
        core_models.UuidMixin,
        core_models.BackendMixin,
        TimeStampedModel,
        core_mixins.ScopeMixin,
        structure_models.StructureLoggableMixin,
):
    """
    Core resource is abstract model, marketplace resource is not abstract,
    therefore we don't need to compromise database query efficiency when
    we are getting a list of all resources.

    While migration from ad-hoc resources to marketplace as single entry point is pending,
    the core resource model may continue to be used in plugins and referenced via
    generic foreign key, and marketplace resource is going to be used as consolidated
    model for synchronization with external plugins.

    Eventually it is expected that core resource model is going to be superseded by
    marketplace resource model as a primary mean.
    """
    class States:
        CREATING = 1
        OK = 2
        ERRED = 3
        UPDATING = 4
        TERMINATING = 5
        TERMINATED = 6

        CHOICES = (
            (CREATING, 'Creating'),
            (OK, 'OK'),
            (ERRED, 'Erred'),
            (UPDATING, 'Updating'),
            (TERMINATING, 'Terminating'),
            (TERMINATED, 'Terminated'),
        )

    class Permissions:
        customer_path = 'project__customer'
        project_path = 'project'

    state = FSMIntegerField(default=States.CREATING, choices=States.CHOICES)
    project = models.ForeignKey(structure_models.Project,
                                on_delete=models.CASCADE)
    backend_metadata = BetterJSONField(blank=True, default=dict)
    report = BetterJSONField(blank=True, null=True)
    current_usages = BetterJSONField(blank=True, default=dict)
    tracker = FieldTracker()
    objects = managers.MixinManager('scope')

    @property
    def customer(self):
        return self.project.customer

    @transition(
        field=state,
        source=[States.ERRED, States.CREATING, States.UPDATING],
        target=States.OK,
    )
    def set_state_ok(self):
        pass

    @transition(field=state, source='*', target=States.ERRED)
    def set_state_erred(self):
        pass

    @transition(field=state, source='*', target=States.UPDATING)
    def set_state_updating(self):
        pass

    @transition(field=state, source='*', target=States.TERMINATING)
    def set_state_terminating(self):
        pass

    @transition(field=state, source='*', target=States.TERMINATED)
    def set_state_terminated(self):
        pass

    @property
    def backend_uuid(self):
        if self.scope:
            return self.scope.uuid

    @property
    def backend_type(self):
        if self.scope:
            scope_type = self.scope.get_scope_type()
            return scope_type if scope_type else 'Marketplace.Resource'

    def init_quotas(self):
        if self.limits:
            components_map = self.offering.get_limit_components()
            for key, value in self.limits.items():
                component = components_map.get(key)
                if component:
                    ComponentQuota.objects.create(resource=self,
                                                  component=component,
                                                  limit=value)

    def get_log_fields(self):
        return (
            'uuid',
            'name',
            'project',
            'offering',
            'created',
            'modified',
            'attributes',
            'cost',
            'plan',
            'limits',
            'get_state_display',
            'backend_metadata',
            'backend_uuid',
            'backend_type',
        )

    @property
    def invoice_registrator_key(self):
        return self.offering.type

    @classmethod
    def get_scope_type(cls):
        return 'Marketplace.Resource'

    @classmethod
    def get_url_name(cls):
        return 'marketplace-resource'

    @property
    def is_expired(self):
        return self.end_date and self.end_date <= timezone.datetime.today(
        ).date()

    def __str__(self):
        if self.name:
            return f'{self.name} ({self.offering.name})'
        if self.scope:
            return f'{self.name} ({self.content_type} / {self.object_id})'

        return f'{self.uuid} ({self.offering.name})'
コード例 #30
0
class Language(models.Model):
    DIRECTION_CHOICES = (("l", "ltr"), ("r", "rtl"))
    code = models.CharField(max_length=100, unique=True)
    name = models.CharField(max_length=100, blank=True)
    anglicized_name = models.CharField(max_length=100, blank=True)
    country = models.ForeignKey(Country, null=True, blank=True)
    gateway_language = models.ForeignKey("self",
                                         related_name="gateway_to",
                                         null=True,
                                         blank=True)
    native_speakers = models.IntegerField(null=True, blank=True)
    networks_translating = models.ManyToManyField(
        Network, blank=True, db_table='uw_language_networks_translating')
    gateway_flag = models.BooleanField(default=False,
                                       blank=True,
                                       db_index=True)
    direction = models.CharField(max_length=1,
                                 choices=DIRECTION_CHOICES,
                                 default="l")
    iso_639_3 = models.CharField(max_length=3,
                                 default="",
                                 db_index=True,
                                 blank=True,
                                 verbose_name="ISO-639-3")
    extra_data = JSONField(blank=True)

    tracker = FieldTracker()

    class Meta:
        db_table = 'uw_language'

    def __str__(self):
        return self.name

    @property
    def cc(self):
        if self.country:
            return self.country.code.encode("utf-8")
        return ""

    @property
    def cc_all(self):
        pks = [
            int(pk) for pk in self.attributes.filter(
                attribute="country_id").values_list("value", flat=True)
        ]
        countries = Country.objects.filter(pk__in=pks)
        return [c.code.encode("utf-8") for c in countries]

    @property
    def lr(self):
        if self.country and self.country.region:
            return self.country.region.name.encode("utf-8")
        return ""

    @property
    def lc(self):
        return self.code

    @property
    def ln(self):
        return self.name.encode("utf-8")

    @property
    def ang(self):
        return self.anglicized_name

    @classmethod
    def codes_text(cls):
        return " ".join([x.code for x in cls.objects.all().order_by("code")])

    @classmethod
    def names_text(cls):
        return "\n".join([
            "{}\t{}".format(x.code, x.name.encode("utf-8"))
            for x in cls.objects.all().order_by("code")
        ])

    @classmethod
    def names_data(cls):
        return [
            dict(pk=x.pk,
                 lc=x.lc,
                 ln=x.ln,
                 ang=x.ang,
                 cc=x.cc_all,
                 lr=x.lr,
                 gw=x.gateway_flag,
                 ld=x.get_direction_display())
            for x in cls.objects.all().order_by("code")
        ]