Beispiel #1
0
class InheritorModel(AbstractModel):
    second_field = MoneyField(max_digits=10,
                              decimal_places=2,
                              default_currency='USD')
Beispiel #2
0
class ProviderProduct(models.Model):
    TERNARY_YES_NO_CHOICES = (
        ('Unknown', 'Unknown'),
        ('Yes', 'Yes'),
        ('No', 'No'),
    )

    # product = models.ForeignKey(Product, on_delete=models.CASCADE)
    name = models.CharField(max_length=255, verbose_name="Product Name")
    dateInfoAdded = models.DateTimeField(auto_now_add=True,
                                         verbose_name='Record created date')
    dateInfoUpdated = models.DateTimeField(
        auto_now=True,
        verbose_name='Date information updated',
        help_text="This is automatic.")
    category = models.ForeignKey(ProductCategory,
                                 on_delete=models.PROTECT,
                                 verbose_name="Product Category")
    image = models.ImageField(null=True,
                              blank=True,
                              default=None,
                              upload_to='product_images')
    provider = models.ForeignKey(Provider, on_delete=models.CASCADE)
    capacityValue = models.IntegerField(null=True,
                                        blank=True,
                                        default=None,
                                        verbose_name="Capacity (value)")
    capacityMeasurement = models.ForeignKey(
        CapacityMeasurement,
        null=True,
        blank=True,
        default=None,
        on_delete=models.SET_NULL,
        verbose_name="Capacity (Measurement)")
    description = models.TextField(
        null=True,
        blank=True,
        default=None,
        help_text="Discription shown in search view",
        verbose_name="Product Description")
    notes = models.TextField(null=True,
                             blank=True,
                             default=None,
                             verbose_name="Additional Notes")
    packSize = models.TextField(
        null=True,
        blank=True,
        default=None,
        help_text="Unit size of orders and other details",
        verbose_name="Packaging Info")

    #######################################################################
    #   The following may need to be "Provider Specific"
    #######################################################################

    productLiabilityInsurance = models.CharField(
        max_length=20,
        choices=TERNARY_YES_NO_CHOICES,
        default='Unknown',
        verbose_name='Has insurance')
    productLiabilityInsuranceAmount = MoneyField(
        max_digits=10,
        decimal_places=0,
        default_currency='USD',
        null=True,
        blank=True,
        default=None,
        verbose_name="Product liability Insurance amount")
    deliveryMethods = models.ManyToManyField(
        DeliveryMethod,
        blank=True,
        verbose_name="Delivery Methods for this product")
    regionalAvailability = models.ManyToManyField(
        PoliticalSubregion,
        blank=True,
        verbose_name="Regions where this product is available")
    orderMinimum = MoneyField(max_digits=8,
                              decimal_places=2,
                              default_currency='USD',
                              null=True,
                              blank=True,
                              default=None,
                              verbose_name="Order Minimum")
    deliveryMinimum = MoneyField(max_digits=8,
                                 decimal_places=2,
                                 default_currency='USD',
                                 null=True,
                                 blank=True,
                                 default=None,
                                 verbose_name="Delivery Minimum")
    distributors = models.ManyToManyField(Distributor, blank=True)
    productionPractices = models.ManyToManyField(
        ProductionPractice, blank=True, verbose_name="Production Practices")

    def __str__(self):
        return "%s: %s - %s" % (self.name, str(
            self.category), str(self.provider))

    def to_dict(self):
        out_dict = self.to_json()
        out_dict['category'] = self.category
        out_dict['provider'] = self.provider
        out_dict[
            'productLiabilityInsuranceAmount'] = self.productLiabilityInsuranceAmount
        out_dict['deliveryMethods'] = self.deliveryMethods
        out_dict['regionalAvailability'] = self.regionalAvailability
        out_dict['orderMinimum'] = self.orderMinimum
        out_dict['deliveryMinimum'] = self.deliveryMinimum
        out_dict['distributors'] = self.distributors
        out_dict['productionPractices'] = self.productionPractices
        out_dict['capacityMeasurement'] = self.capacityMeasurement
        out_dict['dateInfoUpdated'] = self.dateInfoUpdated
        return out_dict

    @property
    def image_string(self):
        if not self.image:
            if not self.category:
                image = settings.DEFAULT_CATEGORY_IMAGE
            else:
                image = self.category.to_json()['image']
        else:
            image = '/media/%s' % str(self.image)
        return image

    def to_json(self):
        return {
            'id':
            self.pk,
            'pk':
            self.pk,
            'name':
            self.name,
            'category':
            self.category.to_json() if self.category else None,
            'image':
            self.image_string,
            'provider': {
                'name': self.provider.name,
                'id': self.provider.id,
                'pk': self.provider.pk
            } if self.provider else {
                'name': None,
                'id': None
            },
            'description':
            self.description,
            'notes':
            self.notes,
            'productLiabilityInsurance':
            self.productLiabilityInsurance,
            'productLiabilityInsuranceAmount':
            str(self.productLiabilityInsuranceAmount),
            'deliveryMethods': [{
                'id': x.id,
                'name': x.name
            } for x in self.deliveryMethods.all()],
            'regionalAvailability': [{
                'id': x.id,
                'name': x.name
            } for x in self.regionalAvailability.all()],
            'orderMinimum':
            str(self.orderMinimum),
            'deliveryMinimum':
            str(self.deliveryMinimum),
            'distributors': [{
                'id': x.id,
                'name': x.name
            } for x in self.distributors.all()],
            'productionPractices': [{
                'id': x.id,
                'name': x.name
            } for x in self.productionPractices.all()],
            'capacityValue':
            self.capacityValue,
            'capacityMeasurement':
            self.capacityMeasurement.to_dict()
            if self.capacityMeasurement else None,
            'dateInfoUpdated':
            self.dateInfoUpdated.strftime('%D'),
        }

    class Meta:
        verbose_name = 'supplier product'
        verbose_name_plural = 'supplier products'
        ordering = ('category', 'provider')
class Transaction(TimeStampedModel):
    """
    Transaction model
    """
    class STATE:
        INITIAL = 'initial'
        PENDING = 'pending'
        SETTLING = 'settling'
        SETTLED = 'settled'
        FAILED = 'failed'
        CANCELED = 'canceled'
        REFUNDED = 'refunded'

        @classmethod
        def as_list(cls):
            return [
                getattr(cls, state) for state in vars(cls).keys()
                if state[0].isupper()
            ]

        @classmethod
        def as_choices(cls):
            return ((state, state.capitalize()) for state in cls.as_list())

    uuid = models.UUIDField(default=uuid.uuid4)
    amount = MoneyField(max_digits=14,
                        decimal_places=2,
                        default_currency='USD')
    state = FSMField(choices=STATE.as_choices(), default=STATE.INITIAL)
    payment_method = models.ForeignKey('flexible_payments.PaymentMethod',
                                       on_delete=models.DO_NOTHING)
    external_reference = models.CharField(max_length=256,
                                          null=True,
                                          blank=True)
    data = JSONField(default=dict, null=True, blank=True)

    @property
    def payment_processor(self):
        return self.payment_method.payment_processor

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

    ####################################
    # Finite State Machine Transitions #
    ####################################

    @transition(field=state, source=STATE.INITIAL, target=STATE.PENDING)
    def process(self):
        transaction_process.send(sender=self.__class__, transaction=self)
        pass

    @transition(field=state,
                source=[STATE.INITIAL, STATE.PENDING],
                target=STATE.SETTLED)
    def settle(self):
        transaction_settled.send(sender=self.__class__, transaction=self)
        pass

    @transition(field=state,
                source=[STATE.INITIAL, STATE.PENDING],
                target=STATE.CANCELED)
    def cancel(self,
               cancel_code='default',
               cancel_reason='Unknown cancel reason'):
        self.cancel_code = cancel_code
        logger.error(str(cancel_reason))

    @transition(field=state,
                source=[STATE.INITIAL, STATE.PENDING],
                target=STATE.FAILED)
    def fail(self, fail_code='default', fail_reason='Unknown fail reason'):
        self.fail_code = fail_code
        logger.error(str(fail_reason))

    @transition(field=state, source=STATE.SETTLED, target=STATE.REFUNDED)
    def refund(self,
               refund_code='default',
               refund_reason='Unknown refund reason'):
        self.refund_code = refund_code
        logger.error(str(refund_reason))

    @transaction.atomic()
    def save(self, *args, **kwargs):
        # TODO: emit signal? builtin signals for saving models should trigger automatically
        super(Transaction, self).save(*args, **kwargs)
Beispiel #4
0
class WorkOrder(models.Model):
    class Meta:
        app_label = 'tenant_foundation'
        db_table = 'workery_work_orders'
        verbose_name = _('Work Order')
        verbose_name_plural = _('Work Orders')
        default_permissions = ()
        permissions = (
            ("can_get_orders", "Can get work orders"),
            ("can_get_order", "Can get work order"),
            ("can_post_order", "Can create work order"),
            ("can_put_order", "Can update work order"),
            ("can_delete_order", "Can delete work order"),
        )

    objects = WorkOrderManager()
    id = models.BigAutoField(
       primary_key=True,
       default = increment_order_id_number,
       editable=False,
       db_index=True
    )

    #
    #  FIELDS
    #

    customer = models.ForeignKey(
        "Customer",
        help_text=_('The customer of our order.'),
        related_name="work_orders",
        on_delete=models.CASCADE
    )
    associate = models.ForeignKey(
        "Associate",
        help_text=_('The associate of our order.'),
        related_name="work_orders",
        on_delete=models.CASCADE,
        blank=True,
        null=True
    )
    description = models.TextField(
        _("Description"),
        help_text=_('A description of this job.'),
        blank=True,
        null=True,
        default='',
    )
    assignment_date = models.DateField(
        _('Assignment Date'),
        help_text=_('The date that an associate was assigned to the customer.'),
        blank=True,
        null=True
    )
    tags = models.ManyToManyField(
        "Tag",
        help_text=_('The category tags that this order belongs to.'),
        blank=True,
        related_name="%(app_label)s_%(class)s_tags_related",
    )
    is_ongoing = models.BooleanField(
        _("Is ongoing"),
        help_text=_('Track whether this order is ongoing job or one-time job.'),
        default=False,
        blank=True
    )
    is_home_support_service = models.BooleanField(
        _("Is Home Support Service"),
        help_text=_('Track whether this order is a home support service request.'),
        default=False,
        blank=True
    )
    start_date = models.DateField(
        _('Start Date'),
        help_text=_('The date that this order will begin.'),
        blank=True,
        default=get_todays_date
    )
    completion_date = models.DateField(
        _('Completion Date'),
        help_text=_('The date that this order was completed.'),
        blank=True,
        null=True
    )
    hours = models.DecimalField(
        _("Hours"),
        help_text=_('The total amount of hours worked on for this order by the associate.'),
        default=0,
        max_digits=7,
        decimal_places=1,
        blank=True,
        null=True
    )
    skill_sets = models.ManyToManyField(
        "SkillSet",
        help_text=_('The skill sets that belong to this order.'),
        blank=True,
        related_name="%(app_label)s_%(class)s_skill_sets_related",
    )
    type_of = models.PositiveSmallIntegerField(
        _("Type Of"),
        help_text=_('The type of job this is.'),
        default=UNASSIGNED_JOB_TYPE_OF_ID,
        choices=JOB_TYPE_OF_CHOICES,
        blank=True,
    )
    indexed_text = models.CharField(
        _("Indexed Text"),
        max_length=1024,
        help_text=_('The searchable content text used by the keyword searcher function.'),
        blank=True,
        null=True,
        db_index=True,
        unique=True
    )
    comments = models.ManyToManyField(
        "Comment",
        help_text=_('The comments belonging to this order made by other people.'),
        blank=True,
        through='WorkOrderComment',
        related_name="%(app_label)s_%(class)s_order_comments_related"
    )
    closing_reason = models.PositiveSmallIntegerField(
        _("Closing Reason"),
        help_text=_('The reason for this job order closing.'),
        blank=True,
        null=True,
        default=0,
    )
    closing_reason_other = models.CharField(
        _("Closing Reason other"),
        help_text=_('A specific reason this job order was closed.'),
        max_length=1024,
        blank=True,
        null=True,
        default='',
    )
    latest_pending_task = models.ForeignKey(
        "TaskItem",
        help_text=_('The latest pending task of our job order.'),
        related_name="work_orders",
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    activity_sheet = models.ManyToManyField(
        "Associate",
        help_text=_('The activity sheet items related to the associates who accepted or rejected this order.'),
        blank=True,
        through='ActivitySheetItem',
        related_name="%(app_label)s_%(class)s_activity_sheet_items_related"
    )

    #
    # State
    #

    state = FSMField(
        _('State'),
        help_text=_('The state of this job order.'),
        default=WORK_ORDER_STATE.NEW,
        blank=True,
        db_index=True,
    )

    #
    #  Satisfaction Survey & Score Fields
    #

    was_survey_conducted = models.BooleanField(
        _("Was Survey Conducted"),
        help_text=_('Track whether survey was conducted post completion (if completed).'),
        default=False,
        blank=True
    )
    was_job_satisfactory = models.BooleanField(
        _("Was job satisfactory?"),
        help_text=_('Customer Survey Q1: Was the quality of the work satisfactory?'),
        default=True,
        blank=True
    )
    was_job_finished_on_time_and_on_budget = models.BooleanField(
        _("Was job finished on time and on budget?"),
        help_text=_('Customer Survey Q2: Was the work completed on time and on budget?'),
        default=True,
        blank=True
    )
    was_associate_punctual = models.BooleanField(
        _("Was associate punctual?"),
        help_text=_('Customer Survey Q3: Was the Associate Member punctual?'),
        default=True,
        blank=True
    )
    was_associate_professional = models.BooleanField(
        _("Was associate professional?"),
        help_text=_('Customer Survey Q4: Was the Associate Member professional?'),
        default=True,
        blank=True
    )
    would_customer_refer_our_organization = models.BooleanField(
        _("Would customer refer our organization?"),
        help_text=_('Customer Survey Q5: Would you refer Over55 to a friend of family member?'),
        default=True,
        blank=True
    )
    score = models.PositiveSmallIntegerField(
        _("Score"),
        help_text=_('The score number earned at the completion of this date.'),
        default=0,
        blank=True,
    )

    #
    #  Financial Fields
    #

    was_there_financials_inputted = models.BooleanField(
        _("Was there financials inputted?"),
        help_text=_('Track whether financials where inputted.'),
        default=True,
        blank=True
    )
    invoice_date = models.DateField(
        _('Invoice Date'),
        help_text=_('The date that this order was completed.'),
        blank=True,
        null=True
    )
    invoice_ids = models.CharField(
        _("Invoice ID(s)"),
        help_text=_('A list of invoice ID values associated with this order.'),
        max_length=127,
        blank=True,
        null=True,
        default='',
    )
    invoice_quote_amount = MoneyField(
        _("Invoice Original Quote Amount"),
        help_text=_('The original quote made by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_labour_amount = MoneyField(
        _("Invoice Labour Costs Amount"),
        help_text=_('The amount charged for labour by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_material_amount = MoneyField(
        _("Invoice Material Costs Amount"),
        help_text=_('The amount charged for material costs by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_quoted_material_amount = MoneyField(
        _("Invoice Quoted Material Costs Amount"),
        help_text=_('The quoted amount to charge for material costs by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_quoted_labour_amount = MoneyField(
        _("Invoice Quoted Labour Costs Amount"),
        help_text=_('The quoted amount to charge for labour by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_total_quote_amount = MoneyField(
        _("Invoice Total Quoted Amount"),
        help_text=_('The quoted amount to charge for material costs by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_tax_amount = MoneyField(
        _("Invoice Tax Amount"),
        help_text=_('The amount charged for taxes by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_total_amount = MoneyField(
        _("Invoice Total Amount"),
        help_text=_('The total amount charged by the associate for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_service_fee_amount = MoneyField(
        _("Invoice Service Fee Amount"),
        help_text=_('The invoice service fee amount that associate needs to pay.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_actual_service_fee_amount_paid = MoneyField(
        _("Invoice Actual Service Fee Amount Paid"),
        help_text=_('The actual amount paid by the associate for service fee for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    invoice_service_fee = models.ForeignKey(
        "WorkOrderServiceFee",
        help_text=_('The service fee applied by the franchise on the total cost of this job order which will be paid by the associate member.'),
        related_name="work_orders",
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    invoice_service_fee_payment_date = models.DateField(
        _('Invoice Service Fee Payment Date'),
        help_text=_('The date when the service fee was paid by the associate.'),
        blank=True,
        null=True,
        db_index=True
    )
    invoice_balance_owing_amount = MoneyField(
        _("Invoice Balance Owing Amount"),
        help_text=_('The amount remaining to be paid by the associate for service fee for this job.'),
        max_digits=10,
        decimal_places=2,
        default_currency=WORKERY_APP_DEFAULT_MONEY_CURRENCY,
        default=Money(0,WORKERY_APP_DEFAULT_MONEY_CURRENCY),
        blank=True,
    )
    visits = models.PositiveSmallIntegerField(
        _("Visits"),
        help_text=_('The the number of visits that were made between the customer and associate for this particular work order.'),
        default=1,
        blank=True,
        validators=[
            MinValueValidator(1),
            MaxValueValidator(100)
        ],
    )

    #
    #  ONGOING WORK ORDER
    #

    ongoing_work_order = models.ForeignKey(
        "OngoingWorkOrder",
        help_text=_('The ongoing work order that this work order is a part of.'),
        related_name="work_orders",
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )

    #
    #  SYSTEM
    #

    created = models.DateTimeField(auto_now_add=True, db_index=True)
    created_by = models.ForeignKey(
        SharedUser,
        help_text=_('The user whom created this order.'),
        related_name="created_work_orders",
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    created_from = models.GenericIPAddressField(
        _("Created from"),
        help_text=_('The IP address of the creator.'),
        blank=True,
        null=True
    )
    created_from_is_public = models.BooleanField(
        _("Is the IP "),
        help_text=_('Is creator a public IP and is routable.'),
        default=False,
        blank=True
    )
    last_modified = models.DateTimeField(auto_now=True)
    last_modified_by = models.ForeignKey(
        SharedUser,
        help_text=_('The user whom last modified this order.'),
        related_name="last_modified_work_orders",
        on_delete=models.SET_NULL,
        blank=True,
        null=True
    )
    last_modified_from = models.GenericIPAddressField(
        _("Last modified from"),
        help_text=_('The IP address of the modifier.'),
        blank=True,
        null=True
    )
    last_modified_from_is_public = models.BooleanField(
        _("Is the IP "),
        help_text=_('Is modifier a public IP and is routable.'),
        default=False,
        blank=True
    )

    #
    #  FUNCTIONS
    #

    def __str__(self):
        return str(self.pk)

    def get_skill_sets_string(self):
        # Attach all the skill sets that are associated with each job.
        skill_set_count = self.skill_sets.count() - 1
        skill_set_string = ""
        for i, skill_set in enumerate(self.skill_sets.all()):

            skill_set_string += skill_set.sub_category

            if i != skill_set_count:
                skill_set_string += "|"
            else:
                pass # Skip last
        return skill_set_string

    # def get_pretty_state(self):
    #     return dict(self.WORK_ORDER_STATE).get(self.state)

    def get_pretty_status(self):
        """
        Function returns the job status in a more user-friendly format.
        """
        if self.state == WORK_ORDER_STATE.PENDING:
            return 'Pending'
        elif self.state == WORK_ORDER_STATE.CANCELLED:
            if self.closing_reason == 2:
                return "Cancelled - Quote was too high"
            elif self.closing_reason == 3:
                return "Cancelled - Job completed by someone else"
            elif self.closing_reason == 5:
                return "Cancelled - Work no longer needed"
            elif self.closing_reason == 6:
                return "Cancelled - Client not satisfied with Associate"
            elif self.closing_reason == 7:
                return "Cancelled - Client did work themselves"
            elif self.closing_reason == 8:
                return "Cancelled - No Associate available"
            elif self.closing_reason == 9:
                return "Cancelled - Work environment unsuitable"
            elif self.closing_reason == 10:
                return "Cancelled - Client did not return call"
            elif self.closing_reason == 11:
                return "Cancelled - Associate did not have necessary equipment"
            elif self.closing_reason == 12:
                return "Cancelled - Repair not possible"
            elif self.closing_reason == 13:
                return "Cancelled - Could not meet deadline"
            elif self.closing_reason == 14:
                return "Cancelled - Associate did not call client"
            elif self.closing_reason == 15:
                return "Cancelled - Member issue"
            elif self.closing_reason == 16:
                return "Cancelled - Client billing issue"
            else:
                return "Cancelled - Other: "+str(self.closing_reason_other)
        elif self.state == WORK_ORDER_STATE.ONGOING:
            return 'Ongoing'
        elif self.state == WORK_ORDER_STATE.IN_PROGRESS:
            return 'In Progress'
        elif self.state == WORK_ORDER_STATE.COMPLETED_BUT_UNPAID:
            return 'Completed but unpaid'
        elif self.state == WORK_ORDER_STATE.COMPLETED_AND_PAID:
            return 'Completed and paid'
        elif self.state == WORK_ORDER_STATE.ARCHIVED:
            return 'Archived'
        elif self.state == WORK_ORDER_STATE.DECLINED:
            return 'Declined'
        elif self.state == WORK_ORDER_STATE.NEW:
            return 'New'
        else:
            return self.state

        return None

    def pretty_closing_reason(self):
        if self.closing_reason == 2:
            return "Quote was too high"
        elif self.closing_reason == 3:
            return "Job completed by someone else"
        elif self.closing_reason == 5:
            return "Work no longer needed"
        elif self.closing_reason == 6:
            return "Client not satisfied with Associate"
        elif self.closing_reason == 7:
            return "Client did work themselves"
        elif self.closing_reason == 8:
            return "No Associate available"
        elif self.closing_reason == 9:
            return "Work environment unsuitable"
        elif self.closing_reason == 10:
            return "Client did not return call"
        elif self.closing_reason == 11:
            return "Associate did not have necessary equipment"
        elif self.closing_reason == 12:
            return "Repair not possible"
        elif self.closing_reason == 13:
            return "Could not meet deadline"
        elif self.closing_reason == 14:
            return "Associate did not call client"
        elif self.closing_reason == 15:
            return "Member issue"
        elif self.closing_reason == 16:
            return "Client billing issue"
        else:
            return "Other: "+str(self.closing_reason_other)

    """
    Override the `save` function to support save cached searchable terms.
    """
    def save(self, *args, **kwargs):
        '''
        The following code will populate our indexed_custom search text with
        the latest model data before we save.
        '''
        search_text = str(self.id)

        if self.description:
            search_text += " " + self.description

        if self.customer:
            if self.customer.organization:
                search_text += " " + self.customer.organization.name
            if self.customer.given_name:
                search_text += " " + self.customer.given_name
            if self.customer.middle_name:
                search_text += " " + self.customer.middle_name
            if self.customer.last_name:
                search_text += " " + self.customer.last_name
            if self.customer.email:
                search_text += " " + self.customer.email
            if self.customer.telephone:
                search_text += " " + phonenumbers.format_number(self.customer.telephone, phonenumbers.PhoneNumberFormat.NATIONAL)
                search_text += " " + phonenumbers.format_number(self.customer.telephone, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
                search_text += " " + phonenumbers.format_number(self.customer.telephone, phonenumbers.PhoneNumberFormat.E164)
            if self.customer.other_telephone:
                search_text += " " + phonenumbers.format_number(self.customer.other_telephone, phonenumbers.PhoneNumberFormat.NATIONAL)
                search_text += " " + phonenumbers.format_number(self.customer.other_telephone, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
                search_text += " " + phonenumbers.format_number(self.customer.other_telephone, phonenumbers.PhoneNumberFormat.E164)
            if self.description:
                search_text += " " + self.description

        if self.associate:
            if self.associate.given_name:
                search_text += " " + self.associate.given_name
            if self.associate.middle_name:
                search_text += " " + self.associate.middle_name
            if self.associate.last_name:
                search_text += " " + self.associate.last_name
            if self.associate.email:
                search_text += " " + self.associate.email
            if self.associate.telephone:
                search_text += " " + phonenumbers.format_number(self.associate.telephone, phonenumbers.PhoneNumberFormat.NATIONAL)
                search_text += " " + phonenumbers.format_number(self.associate.telephone, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
                search_text += " " + phonenumbers.format_number(self.associate.telephone, phonenumbers.PhoneNumberFormat.E164)
            if self.associate.other_telephone:
                search_text += " " + phonenumbers.format_number(self.associate.other_telephone, phonenumbers.PhoneNumberFormat.NATIONAL)
                search_text += " " + phonenumbers.format_number(self.associate.other_telephone, phonenumbers.PhoneNumberFormat.INTERNATIONAL)
                search_text += " " + phonenumbers.format_number(self.associate.other_telephone, phonenumbers.PhoneNumberFormat.E164)
            if self.description:
                search_text += " " + self.description

        if self.invoice_ids:
            search_text += " " + str(self.invoice_ids)

        self.indexed_text = Truncator(search_text).chars(1024)

        '''
        Run our `save` function.
        '''
        super(WorkOrder, self).save(*args, **kwargs)
Beispiel #5
0
class SkipTheDishesOrder(models.Model):
    account = models.ForeignKey('Account', on_delete=models.CASCADE)
    order_number = models.PositiveIntegerField(unique=True)
    status = models.CharField(max_length=32)
    type = models.CharField(max_length=32)
    time_placed = models.DateTimeField()
    time_collected = models.DateField(null=True)
    payment_method = models.CharField(max_length=64)
    food_subtotal = MoneyField(max_digits=19,
                               decimal_places=4,
                               default_currency='CAD')
    food_hst = MoneyField(max_digits=19,
                          decimal_places=4,
                          default_currency='CAD')
    skip_vouchers = MoneyField(max_digits=19,
                               decimal_places=4,
                               default_currency='CAD')
    gross_earnings = MoneyField(max_digits=19,
                                decimal_places=4,
                                default_currency='CAD')
    restaurant_subsidy = MoneyField(max_digits=19,
                                    decimal_places=4,
                                    default_currency='CAD')
    skip_subsidy = MoneyField(max_digits=19,
                              decimal_places=4,
                              default_currency='CAD')
    adjustment_details = models.TextField(blank=True)
    adjustments = MoneyField(max_digits=19,
                             decimal_places=4,
                             default_currency='CAD')
    courier_delay = models.DurationField()
    courier_delay_contribution = MoneyField(max_digits=19,
                                            decimal_places=4,
                                            default_currency='CAD')
    courier_tip = MoneyField(max_digits=19,
                             decimal_places=4,
                             default_currency='CAD')
    delivery_fee = MoneyField(max_digits=19,
                              decimal_places=4,
                              default_currency='CAD')
    delivery_hst = MoneyField(max_digits=19,
                              decimal_places=4,
                              default_currency='CAD')

    def __str__(self):
        return f"[{self.time_placed}] {self.order_number} ({self.type})"
Beispiel #6
0
class ModelWithChoicesMoneyField(models.Model):
    money = MoneyField(
        max_digits=10,
        decimal_places=2,
        currency_choices=[('USD', 'US Dollars'), ('ZWN', 'Zimbabwian')],
    )
Beispiel #7
0
class courses(models.Model):
    def courseName(self):
        return "Course " + self.name

    # Returns a random subject, level, and alternate classroom in the form:
    # 	'Algebra-4001-B'
    # @Param void
    # @Return str
    def randomCourseName():
        subjects = [
            'Algebra', 'Accounting', 'Archaeology', 'Biodiversity', 'Business',
            'Algorithms', 'LinearAlgebra', 'Calculus', 'Chemistry',
            'DataStructures', 'PolySci', 'Cardiovascular', 'Celtic',
            'Hungarian', 'ComputerScience', 'Economics', 'Education',
            'History', 'English', 'Wellbeing', 'Engineering', 'Film', 'Law',
            'Psychology', 'Physics', 'Philisophy', 'Music', 'Mathematics',
            'Astronomy', 'Statistics', 'Theater', 'Translation', 'Sociology',
            'Theology', 'VeterinaryMedicine'
        ]
        alternates = ['A', 'B', 'C', 'D', 'E', 'F']
        levels = ['0', '1', '2', '3', '4']

        return choice(subjects) + '-' + ''.join(
            [choice(levels) for _ in range(4)]) + '-' + choice(alternates)

    # Returns a random professor first and last name using the following list, i.e.:
    #	'Angela Lizard'
    # @Param void
    # @Return str
    def randomProfName():
        names = [
            "Tommy", "Bill", "Janet", "Bill", "Stacy", "Spider", "Moth",
            "Butterfly", "Lizard", "Rabbit", "Mouse", "Gorilla", "Giraffe",
            'Abigail', 'Alexandra', 'Alison', 'Amanda', 'Amelia', 'Amy',
            'Andrea', 'Angela', 'Anna', 'Anne', 'Audrey', 'Ava', 'Bella',
            'Bernadette', 'Carol', 'Caroline', 'Carolyn', 'Chloe', 'Claire',
            'Deirdre', 'Diana', 'Diane', 'Donna', 'Dorothy', 'Elizabeth',
            'Ella', 'Emily', 'Emma', 'Adam', 'Adrian', 'Alan', 'Alexander',
            'Andrew', 'Anthony', 'Austin', 'Benjamin', 'Blake', 'Boris',
            'Brandon', 'Brian', 'Cameron', 'Carl', 'Charles', 'Christian',
            'Christopher', 'Colin', 'Connor', 'Dan', 'David', 'Dominic',
            'Dylan', 'Edward', 'Eric', 'Evan', 'Frank', 'Gavin', 'Gordon',
            'Harry', 'Ian', 'Isaac'
        ]
        return choice(names) + ' ' + choice(names)

    # @TODO Should change to only randomize hour then M/W/F vs. T/H/S
    # This function will return a random datetime between two datetime objects.
    # @Param 	datetime, datetime 	(date range start, end)
    # @Return 	datetime 	(random date in the range)
    def randomDatetime(start, end):
        delta = end - start
        int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
        random_second = randrange(int_delta)
        return str(start + timedelta(seconds=random_second))

    # Python fiddle, called sing_sen_maker() by them
    # Makes a random senctence from the different parts of speech. Uses a SINGULAR subject
    # Used to build course descriptions
    # @Param	void
    # @Return 	string
    def randSentenceGen():
        s_nouns = [
            "A dude", "My mom", "The king", "Some guy", "A cat with rabies",
            "A sloth", "Your homie", "This cool guy my gardener met yesterday",
            "Superman"
        ]
        p_nouns = [
            "These dudes", "Both of my moms", "All the kings of the world",
            "Some guys", "All of a cattery's cats",
            "The multitude of sloths living under your bed", "Your homies",
            "Like, these, like, all these people", "Supermen"
        ]
        s_verbs = [
            "eats", "kicks", "gives", "treats", "meets with", "creates",
            "hacks", "configures", "spies on", "encourages", "meows on",
            "flees from", "tries to automate", "explodes"
        ]
        p_verbs = [
            "eat", "kick", "give", "treat", "meet with", "create", "hack",
            "configure", "spy on", "encourages", "meow on", "flee from",
            "try to automate", "explode"
        ]
        infinitives = [
            "to make a pie.", "for no apparent reason.",
            "because the sky is green.", "for a disease.",
            "to be able to make toast explode.",
            "to know more about archeology."
        ]
        string = ""
        for i in range(5):
            # Map could be fun here
            # Explicit for readability
            string += choice(s_nouns) + " "
            string += choice(s_verbs) + " "
            string += choice(s_nouns).lower() + " " or choice(
                p_nouns).lower() + " "
            string += choice(infinitives) + "  "
        return string

    # '2017-05-01 2017 18:55:35'
    semester_start = datetime(2017, 5, 1, 18, 55, 35)
    # Oct 1, 2017 18:55:35
    semester_end = datetime(2017, 10, 1, 18, 55, 35)

    # FIELDS
    name = models.CharField(default=randomCourseName(),
                            unique=True,
                            max_length=120)
    # Why use datetime?  Should standardize semester length, randomize hour then M/W/F vs. T/H/S
    # These are only one-time courses
    datetimes = models.DateTimeField(
        default=randomDatetime(semester_start, semester_end))
    # datetimes = models.DateTimeField(default = randomDateTime())
    professors = models.CharField(default=randomProfName(), max_length=120)
    cost = MoneyField(max_digits=4,
                      decimal_places=0,
                      default=randint(50, 9000),
                      default_currency='USD')
    description = models.TextField(default=randSentenceGen())

    # NOT USED
    # Replaced by django-money
    # @property
    # def cost(self):
    # 	return '$%s' %self.cost

    # unique key
    def __unicode__(self):
        return self.name
Beispiel #8
0
class DateTimeModel(models.Model):
    field = MoneyField(max_digits=10, decimal_places=2)
    created = models.DateTimeField(null=True, blank=True)
Beispiel #9
0
class ModelIssue300(models.Model):
    money = models.ForeignKey(DateTimeModel, on_delete=models.CASCADE)
    price = MoneyField(max_digits=10,
                       decimal_places=2,
                       default_currency='EUR',
                       default=Decimal('0.0'))
Beispiel #10
0
class NullMoneyFieldModel(models.Model):
    field = MoneyField(max_digits=10,
                       decimal_places=2,
                       null=True,
                       default_currency='USD',
                       blank=True)
Beispiel #11
0
class ModelWithCustomManager(models.Model):
    field = MoneyField(max_digits=10, decimal_places=2)

    manager = money_manager(MoneyManager())
Beispiel #12
0
class SimpleModel(models.Model):
    money = MoneyField(max_digits=10, decimal_places=2, default_currency='USD')
Beispiel #13
0
class InheritedModel(BaseModel):
    second_field = MoneyField(max_digits=10,
                              decimal_places=2,
                              default_currency='USD')
Beispiel #14
0
class RevisionedModel(models.Model):
    amount = MoneyField(max_digits=10,
                        decimal_places=2,
                        default_currency='USD')
Beispiel #15
0
class ModelWithDefaultAsOldMoney(models.Model):
    money = MoneyField(default=OldMoney('0.01', 'RUB'),
                       max_digits=10,
                       decimal_places=2)
Beispiel #16
0
class ModelWithValidation(models.Model):
    balance = MoneyField(max_digits=10,
                         decimal_places=2,
                         validators=[MinValueValidator(Money(100, 'GBP'))])
Beispiel #17
0
class ModelWithTwoMoneyFields(models.Model):
    amount1 = MoneyField(max_digits=10, decimal_places=2)
    amount2 = MoneyField(max_digits=10, decimal_places=3)
Beispiel #18
0
class ModelWithVanillaMoneyField(models.Model):
    money = MoneyField(max_digits=10, decimal_places=2)
    second_money = MoneyField(max_digits=10,
                              decimal_places=2,
                              default_currency='EUR')
    integer = models.IntegerField(default=0)
Beispiel #19
0
class Contratado(Pessoa):
    #  basicas
    con_matricula = models.CharField(db_column='con_matricula',
                                     primary_key=True,
                                     max_length=30)
    estabelecimento = models.ForeignKey('empregador.Estabelecimento',
                                        on_delete=models.CASCADE)
    lotacao = models.ForeignKey('empregador.Lotacao', on_delete=models.CASCADE)
    funcao = models.ForeignKey('empregador.Funcao', on_delete=models.CASCADE)
    sindicato = models.ForeignKey('empregador.Sindicato',
                                  on_delete=models.CASCADE)

    #  trabalhistas
    con_tipo_reg_trabalhista = models.CharField(
        max_length=3,
        choices=TIPO_REGIME_TRABALHISTA,
        db_column='con_tipo_reg_trabalhista')
    con_tipo_reg_previdenciario = models.CharField(
        max_length=4,
        choices=TIPO_REGIME_PREVIDENCIARIO,
        db_column='con_tipo_reg_previdenciario')
    con_regime_jornada = models.CharField(max_length=1,
                                          choices=REGIME_DE_JORNADA,
                                          db_column='con_regime_jornada')
    con_natureza_atividade = models.CharField(
        max_length=1,
        choices=NATUREZA_DA_ATIVIDADE,
        db_column='con_natureza_atividade')
    con_categoria = models.CharField(max_length=1,
                                     choices=CATEGORIA,
                                     db_column='con_categoria')

    #  info_contrato
    con_data_admissao = models.DateField(db_column='con_data_admissao',
                                         null=True,
                                         blank=True)
    con_tipo_contrato = models.CharField(db_column='con_tipo_contrato',
                                         max_length=1,
                                         blank=True,
                                         null=True,
                                         choices=TIPO_CONTRATO_TRABALHO)
    con_tipo_admissao = models.CharField(db_column='con_tipo_admissao',
                                         max_length=1,
                                         blank=True,
                                         null=True,
                                         choices=TIPO_ADMISSAO,
                                         default='A')
    con_unidade_salario = models.CharField(db_column='con_unidade_salario',
                                           max_length=1,
                                           choices=UNIDADE_SALARIO,
                                           default='M')
    con_indicativo_admissao = models.CharField(
        db_column='con_indicativo_admissao',
        max_length=1,
        choices=INDICATIVO_ADMISSAO,
        default='N')
    con_salario_mensal = MoneyField(db_column='con_salario_mensal',
                                    max_digits=10,
                                    decimal_places=2,
                                    default_currency='BRL',
                                    null=True,
                                    blank=True)
    con_calcular_dsr = models.BooleanField(db_column='con_calcular_dsr',
                                           default=True)
    con_receber_fgts = models.BooleanField(db_column='con_receber_fgts',
                                           default=True)

    #  outra empresa
    con_vinculo_outra_empresa = models.CharField(
        max_length=1,
        db_column='con_vinculo_outra_empresa',
        null=True,
        blank=True,
        choices=VINCULO_COM_OUTRA_EMPRESA)
    con_cnpj_outra_empresa = models.CharField(
        max_length=14,
        db_column='con_cnjp_outra_empresa',
        null=True,
        blank=True)
    con_remuneracao_outra_empresa = MoneyField(
        db_column='con_remuneracao_outra_empresa',
        max_digits=10,
        decimal_places=2,
        default_currency='BRL',
        null=True,
        blank=True)

    class Meta:
        ordering = ['-con_matricula']
        db_table = 'CONTRATADOS'
        verbose_name = 'Contratado'
        verbose_name_plural = 'Contratados'

    def __str__(self):
        return self.pes_nome
Beispiel #20
0
class ModelWithDefaultAsInt(models.Model):
    money = MoneyField(default=123,
                       max_digits=10,
                       decimal_places=2,
                       default_currency='GHS')
Beispiel #21
0
class Property(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    address = map_fields.AddressField(max_length=200, unique=True)
    geolocation = map_fields.GeoLocationField(max_length=100)
    property_type = models.CharField(choices=PROPERTY_CHOICES, max_length=2)
    bought_for = MoneyField(
        max_digits=20,
        decimal_places=2,
        default_currency='USD',
        null=True,
        blank=True,
        help_text="Total value of the property at the moment of purchse")

    image_url = models.URLField(null=True)
    owned_since = models.DateField()
    property_taxes = MoneyField(max_digits=20,
                                decimal_places=2,
                                default_currency='USD',
                                null=True,
                                blank=True,
                                help_text="per month")
    insurance = MoneyField(max_digits=20,
                           decimal_places=2,
                           default_currency='USD',
                           null=True,
                           blank=True,
                           help_text="per month")
    # Zillow fields
    zpid = models.IntegerField(null=True, blank=True)
    zillow_url = models.URLField(null=True, blank=True)
    rental_estimated_value = MoneyField(max_digits=20,
                                        decimal_places=2,
                                        default_currency='USD',
                                        null=True,
                                        blank=True)
    estimated_value = MoneyField(
        max_digits=20,
        decimal_places=2,
        default_currency='USD',
        null=True,
        blank=True,
        help_text=
        "Value generated automatically by zillow, but you can edit freely")

    def save(self, *args, **kwargs):
        if not self.estimated_value:
            self.estimated_value = get_estimated_value(self)
        self.image_url = get_property_image(self)
        return super().save(*args, **kwargs)

    def get_net_cashflow(self):
        return self.tenant.rent_payment - (
            self.loan.monthly_payment + self.insurance + self.property_taxes)

    def get_total_expenses(self):
        return self.loan.monthly_payment + self.insurance + self.property_taxes

    def get_absolute_url(self):
        return reverse("property_edit", kwargs={"pk": self.pk})

    def __str__(self):
        return str(self.address)

    class Meta:
        verbose_name_plural = 'properties'
        ordering = ['id']
Beispiel #22
0
class ModelWithDefaultAsStringWithCurrency(models.Model):
    money = MoneyField(default='123 USD', max_digits=10, decimal_places=2)

    class Meta:
        verbose_name = 'model_default_string_currency'
Beispiel #23
0
class Charge(models.Model):
    service = models.CharField(max_length=8)
    charge = MoneyField(max_digits=10,
                        decimal_places=2,
                        default_currency='TZS')
Beispiel #24
0
class ModelWithDefaultAsString(models.Model):
    money = MoneyField(default='123',
                       max_digits=10,
                       decimal_places=2,
                       default_currency='PLN')
        class Model(models.Model):
            field = MoneyField(**field_kwargs)

            class Meta:
                app_label = 'test'
Beispiel #26
0
class ModelWithDefaultAsFloat(models.Model):
    money = MoneyField(default=12.05,
                       max_digits=10,
                       decimal_places=2,
                       default_currency='PLN')
Beispiel #27
0
class Provider(models.Model):
    TERNARY_YES_NO_CHOICES = (
        ('Unknown', 'Unknown'),
        ('Yes', 'Yes'),
        ('No', 'No'),
    )

    name = models.CharField(max_length=255, verbose_name="Supplier Name")
    outreachConductor = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name='Outreach conducted by',
        help_text="The name of the teammate who reached out to this supplier")
    dateInfoAdded = models.DateTimeField(auto_now_add=True,
                                         verbose_name='Record created date')
    dateInfoUpdated = models.DateTimeField(
        auto_now=True,
        verbose_name='Date information updated',
        help_text="This is automatic.")
    soldToSchoolsBefore = models.CharField(
        max_length=20,
        choices=TERNARY_YES_NO_CHOICES,
        default='Unknown',
        verbose_name='This supplier has sold to schools before')
    schoolsSoldTo = models.ManyToManyField(
        School,
        blank=True,
        verbose_name='Schools this supplier has done business with before')
    description = models.TextField(blank=True,
                                   null=True,
                                   default=None,
                                   verbose_name="Brief Description",
                                   help_text="2-3 Sentences")
    primaryContactFirstName = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        default=None,
        verbose_name="Primary contact's first name")
    primaryContactLastName = models.CharField(
        max_length=100,
        blank=True,
        null=True,
        default=None,
        verbose_name="Primary contact's last name")
    businessAddressLine1 = models.CharField(
        max_length=255,
        verbose_name="Business Address Line 1",
        blank=True,
        null=True,
        default=None)
    businessAddressLine2 = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name="Business Address Line 2")
    businessAddressCity = models.CharField(
        max_length=255, verbose_name="Business Address City")
    businessAddressState = models.ForeignKey(
        PoliticalRegion,
        on_delete=models.PROTECT,
        verbose_name="Business Address State",
        related_name="providerBusinessAddresses")
    businessAddressZipCode = models.CharField(
        max_length=25,
        verbose_name="Business Address Zip Code",
        blank=True,
        null=True,
        default=None)
    businessCounty = models.ForeignKey(
        PoliticalSubregion,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        default=None,
        verbose_name="Business County Location",
        related_name="providerBusinessCountyLocation")

    physicalAddressIsSame = models.BooleanField(
        default=False,
        verbose_name="Physical address is the same as business address")

    physicalAddressLine1 = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical Address Line 1")
    physicalAddressLine2 = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical Address Line 2")
    physicalAddressCity = models.CharField(
        max_length=255,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical Address City")
    physicalAddressState = models.ForeignKey(
        PoliticalRegion,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical Address State",
        related_name="providerPhysicalAddresses")
    physicalAddressZipCode = models.CharField(
        max_length=25,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical Address Zip Code")
    physicalCounty = models.ForeignKey(
        PoliticalSubregion,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        default=None,
        verbose_name="Physical County Location",
        related_name="providerPhysicalCountyLocation")

    officePhone = PhoneNumberField(verbose_name="Office Phone",
                                   blank=True,
                                   null=True,
                                   default=None)
    cellPhone = PhoneNumberField(blank=True,
                                 null=True,
                                 default=None,
                                 verbose_name="Cell Phone")
    email = models.EmailField(max_length=255,
                              null=True,
                              blank=True,
                              default=None)
    websiteAddress = models.URLField(
        max_length=255,
        null=True,
        blank=True,
        default=None,
        verbose_name="Website Address",
        help_text=
        "Try to include either http:// (good) or https:// (better if available)"
    )

    preferredLanguage = models.ManyToManyField(
        Language, blank=True, verbose_name='Preferred contact language')
    preferredContactMethod = models.ManyToManyField(
        ContactMethod, blank=True, verbose_name='Preferred contact method')

    identities = models.ManyToManyField(Identity, blank=True)

    notes = models.TextField(null=True,
                             blank=True,
                             default=None,
                             verbose_name="Additional Notes")

    #######################################################################
    #   The following may need to be "Provider-Product Specific"
    #######################################################################

    productLiabilityInsurance = models.CharField(
        max_length=20,
        choices=TERNARY_YES_NO_CHOICES,
        default='Unknown',
        verbose_name='This supplier has product liability insurance')
    productLiabilityInsuranceAmount = MoneyField(
        max_digits=10,
        decimal_places=0,
        default_currency='USD',
        null=True,
        blank=True,
        default=None,
        verbose_name="Product Liability Insurance Amount")
    deliveryMethods = models.ManyToManyField(DeliveryMethod,
                                             blank=True,
                                             verbose_name='Delivery Methods')
    regionalAvailability = models.ManyToManyField(
        PoliticalSubregion,
        blank=True,
        verbose_name='Regions where product is available')
    orderMinimum = MoneyField(max_digits=8,
                              decimal_places=2,
                              default_currency='USD',
                              null=True,
                              blank=True,
                              default=None,
                              verbose_name='Order Minimum')
    deliveryMinimum = MoneyField(max_digits=8,
                                 decimal_places=2,
                                 default_currency='USD',
                                 null=True,
                                 blank=True,
                                 default=None,
                                 verbose_name='Delivery Minimum')
    distributors = models.ManyToManyField(Distributor, blank=True)
    productionPractices = models.ManyToManyField(
        ProductionPractice, blank=True, verbose_name='Production Practices')

    class Meta:
        verbose_name = "supplier"
        verbose_name_plural = "suppliers"
        ordering = (
            'name',
            'dateInfoUpdated',
        )

    @property
    def components_offered(self):
        component_ids = []
        for product in self.providerproduct_set.all():
            for component in product.category.usdaComponentCategories.all():
                if component.id not in component_ids:
                    component_ids.append(component.id)
        return ComponentCategory.objects.filter(id__in=component_ids)

    @property
    def product_categories(self):
        product_categories = {}
        for product in self.providerproduct_set.all().order_by('name'):
            product_ancestor_category = product.category.get_prime_ancestor()
            if not product_ancestor_category.name in product_categories.keys():
                product_categories[product_ancestor_category.name] = {
                    'object': product_ancestor_category,
                    'products': [],
                    'descriptions_present': False,
                    'pack_size_present': False,
                    'notes_present': False
                }
            if product.description:
                product_categories[product_ancestor_category.
                                   name]['descriptions_present'] = True
            if product.packSize:
                product_categories[
                    product_ancestor_category.name]['pack_size_present'] = True
            if product.notes:
                product_categories[
                    product_ancestor_category.name]['notes_present'] = True

            product_name = product.name
            if ',' in product_name and product_name.split(
                    ',')[0].lower() == product_ancestor_category.name.lower():
                product_name = ','.join(product_name.split(',')[1:])
            product_categories[
                product_ancestor_category.name]['products'].append({
                    'variety':
                    product_name,
                    'form':
                    product.category.name,
                    'description':
                    product.description,
                    'pack_size':
                    product.packSize,
                    'notes':
                    product.notes,
                    'usda_meal_components':
                    ', '.join([
                        x.name
                        for x in product.category.componentCategories.all()
                    ]),
                })
        ordered_categories = []
        category_keys = [x for x in product_categories.keys()]
        category_keys.sort()
        for category_key in category_keys:
            ordered_categories.append(product_categories[category_key])
        return ordered_categories

    @property
    def dateUpdated(self):
        monthNames = [
            'None',
            'Jan.',
            'Feb.',
            'Mar.',
            'Apr.',
            'May',
            'June',
            'July',
            'Aug.',
            'Sep.',
            'Oct.',
            'Nov.',
            'Dec.',
        ]
        updateString = '{month} {day}, {year}'.format(
            month=monthNames[self.dateInfoUpdated.month],
            day=self.dateInfoUpdated.day,
            year=self.dateInfoUpdated.year)
        return updateString

    def get_address_string(self, locationType=None, fullAddress=True):
        if locationType == 'Business':
            fields = [
                self.businessAddressLine1,
                self.businessAddressLine2 if fullAddress else None,
                self.businessAddressCity,
                self.businessAddressState.to_dict()['initialism']
                if self.businessAddressState else None,
                self.businessAddressZipCode,
            ]
        elif locationType == 'Physical':
            if self.physicalAddressIsSame:
                address = self.get_address_string('Business',
                                                  fullAddress=fullAddress)
                if not address == None:
                    return address
            fields = [
                self.physicalAddressLine1,
                self.physicalAddressLine2 if fullAddress else None,
                self.physicalAddressCity,
                self.physicalAddressState.to_dict()['initialism']
                if self.physicalAddressState else None,
                self.physicalAddressZipCode,
            ]
        else:
            return self.get_address_string('Business')

        return ', '.join([x for x in fields if not x == None])

    def geocode(self, locationType='Physical'):
        address_string = self.get_address_string(locationType=locationType)
        if len(address_string) > 1:
            try:
                results = geocoder.mapbox(address_string,
                                          key=settings.MAPBOX_TOKEN)
            except Exception as e:
                print(e)
                results = None
            if not results or len(results) < 1 or results.error:
                address_string = self.get_address_string(
                    locationType=locationType, fullAddress=False)
                results = geocoder.mapbox(address_string,
                                          key=settings.MAPBOX_TOKEN)
            return results

        else:
            return []

    def get_county(self, locationType='Physical'):
        if locationType == 'Business':
            county_field = self.businessCounty
        else:
            county_field = self.physicalCounty
        if not county_field:
            county_record = None
            for geocode_hit in self.geocode(locationType=locationType):
                geocode = geocode_hit.json
                try:
                    if 'raw' in geocode.keys() and 'district' in geocode[
                            'raw'].keys() and 'state' in geocode.keys():
                        district = geocode['raw']['district']
                        state = geocode['state']
                        if district and state and '' not in [
                                district, state
                        ] and 'County' in district:
                            county_name = ' '.join(district.split(' ')[0:-1])
                            county_record = PoliticalSubregion.objects.get(
                                name=county_name, region__name=state)
                            break

                except Exception as e:
                    pass
            if county_record:
                if locationType == 'Business':
                    self.businessCounty = county_record
                else:
                    self.physicalCounty = county_record
                self.save()
                county_field = county_record

        return county_field

    def to_json(self):
        products = [x.to_json() for x in self.providerproduct_set.all()]
        product_categories = []
        for product in self.providerproduct_set.all():
            product_ancestor_category = product.category.get_prime_ancestor(
            ).to_json()
            is_dupe = False
            for category in product_categories:
                if product_ancestor_category == category:
                    is_dupe = True
            if not is_dupe:
                product_categories.append(product_ancestor_category)

        physicalCounty = self.physicalCounty
        if not physicalCounty == None:
            physicalCounty = physicalCounty.to_dict()
        businessCounty = self.businessCounty
        if not businessCounty == None:
            businessCounty = businessCounty.to_dict()
        return {
            'id':
            self.id,
            'pk':
            self.pk,
            'name':
            self.name,
            'outreachConductor':
            self.outreachConductor,
            'dateInfoAdded':
            self.dateInfoAdded.strftime('%D'),
            'dateInfoUpdated':
            self.dateInfoUpdated.strftime('%D'),
            'soldToSchoolsBefore':
            self.soldToSchoolsBefore,
            'description':
            self.description,
            'primaryContactFirstName':
            self.primaryContactFirstName,
            'primaryContactLastName':
            self.primaryContactLastName,
            'businessAddressLine1':
            self.businessAddressLine1,
            'businessAddressLine2':
            self.businessAddressLine2,
            'businessAddressCity':
            self.businessAddressCity,
            'businessAddressState':
            self.businessAddressState.to_dict()
            if self.businessAddressState else None,
            'businessAddressZipCode':
            self.businessAddressZipCode,
            'businessCounty':
            businessCounty,
            'physicalAddressIsSame':
            self.physicalAddressIsSame,
            'physicalAddressLine1':
            self.physicalAddressLine1,
            'physicalAddressLine2':
            self.physicalAddressLine2,
            'physicalAddressCity':
            self.physicalAddressCity,
            'physicalAddressState':
            self.physicalAddressState.to_dict()
            if self.physicalAddressState else None,
            'physicalAddressZipCode':
            self.physicalAddressZipCode,
            'physicalCounty':
            physicalCounty,
            'officePhone':
            self.officePhone.as_national if self.officePhone else None,
            'cellPhone':
            self.cellPhone.as_national if self.cellPhone else None,
            'email':
            self.email,
            'websiteAddress':
            self.websiteAddress,
            'identities': [x.to_dict() for x in self.identities.all()],
            'notes':
            self.notes,
            #######################################################################
            #   The following may need to be "Provider-Product Specific"
            #######################################################################
            'productLiabilityInsurance':
            self.productLiabilityInsurance,
            'productLiabilityInsuranceAmount':
            str(self.productLiabilityInsuranceAmount) if
            (self.productLiabilityInsuranceAmount
             and not self.productLiabilityInsuranceAmount == None) else None,
            'deliveryMethods': [{
                'id': x.id,
                'name': x.name
            } for x in self.deliveryMethods.all()],
            'regionalAvailability': [{
                'id': x.id,
                'name': x.name
            } for x in self.regionalAvailability.all()],
            'orderMinimum':
            str(self.orderMinimum),
            'deliveryMinimum':
            str(self.deliveryMinimum),
            'distributors': [{
                'id': x.id,
                'name': x.name
            } for x in self.distributors.all()],
            'productionPractices': [{
                'id': x.id,
                'name': x.name
            } for x in self.productionPractices.all()],
            'products':
            products,
            'product_categories':
            product_categories,
        }

    def to_dict(self):
        product_categories = []
        for product in self.providerproduct_set.all():
            product_ancestor_category = product.category.get_prime_ancestor()
            if not product_ancestor_category in product_categories:
                product_categories.append(product_ancestor_category)

        out_dict = self.to_json()
        out_dict['dateInfoAdded'] = self.dateInfoAdded
        out_dict['dateInfoUpdated'] = self.dateInfoUpdated
        out_dict['businessAddressState'] = self.businessAddressState
        out_dict['physicalAddressState'] = self.physicalAddressState
        out_dict['identities'] = self.identities
        out_dict[
            'productLiabilityInsuranceAmount'] = self.productLiabilityInsuranceAmount
        out_dict['deliveryMethods'] = self.deliveryMethods
        out_dict['regionalAvailability'] = self.regionalAvailability
        out_dict['orderMinimum'] = self.orderMinimum
        out_dict['deliveryMinimum'] = self.deliveryMinimum
        out_dict['distributors'] = self.distributors
        out_dict['productionPractices'] = self.productionPractices
        out_dict['products'] = self.providerproduct_set.all()
        out_dict['product_categories'] = product_categories
        return out_dict

    def __str__(self):
        return self.name
Beispiel #28
0
class ModelWithDefaultAsDecimal(models.Model):
    money = MoneyField(default=Decimal('0.01'),
                       max_digits=10,
                       decimal_places=2,
                       default_currency='CHF')
class Listing(models.Model):
    title = models.CharField(max_length=100, verbose_name=_('Title'))
    slug = models.SlugField(max_length=100, unique=True, blank=False, verbose_name=_('Slug'))
    description = models.TextField(verbose_name=_('Description'), null=True, blank=True)
    price = MoneyField(default=Money(0, NGN), max_digits=12, decimal_places=2, verbose_name=_('Price'))
    location = models.ForeignKey(Location, null=True, blank=True)
    type = models.CharField(_('Listing Type'), max_length=30, choices=TYPES)
    offer = models.CharField(max_length=10, choices=OFFERS, verbose_name=_('Offer'))
    active = models.BooleanField(_('Active'), default=False)
    featured = models.BooleanField(default=False, verbose_name=_('Featured'))
    baths = models.PositiveIntegerField(_('Bathrooms'), default=0, null=True, blank=True)
    beds = models.PositiveIntegerField(_('Bedrooms'), default=0, null=True, blank=True)
    size = models.PositiveIntegerField(_('Size(m2)'), default=0, null=True, blank=True)
    coords = models.CharField(max_length=255, default='19.000000,-70.400000', verbose_name=_('Coords'), null=True,
                              blank=True)
    agent = models.ForeignKey(Agent, null=True, blank=True, verbose_name=_('Agent'))
    contact = models.ForeignKey(Contact, null=True, blank=True)
    notes = models.TextField(max_length=500, verbose_name=_('Private Notes'), null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name=_('Created'))
    last_modified = models.DateTimeField(auto_now=True, verbose_name=_('Last Modified'))

    objects = ListingManager()

    @property
    def main_image(self):
        im = self.images.all()
        if im.count():
            return im[0]
        return None

    @property
    def image_list(self):
        return [{'title': image.name, 'url': image.absolute_url, 'order': image.order} for image in self.images.all()]

    @property
    def address(self):
        return self.get_address()

    def get_address(self):
        if self.location is None:
            return _('No location provided')
        return self.location

    def __str__(self):
        return self.title

    class Meta:
        verbose_name = _('Listing')
        verbose_name_plural = _('Listings')
        ordering = ['-pk', ]

    def save(self, **kwargs):
        self._generate_valid_slug()
        super(Listing, self).save(**kwargs)

    def _generate_valid_slug(self):
        if not self.is_valid_slug():
            slug = slugify(self.title)
            while Listing.objects.filter(slug=slug).exclude(id=self.id).exists():
                slug_parts = slug.split('-')
                if slug_parts[-1].isdigit():
                    slug_parts[-1] = '%s' % (int(slug_parts[-1]) + 1)
                else:
                    slug_parts.append('2')
                slug = '-'.join(slug_parts)
            self.slug = slug

    def is_valid_slug(self):
        if self.slug is None or len(self.slug) < 10:
            return False
        match = re.match('[^\w\s-]', self.slug)
        if not match:
            return False
        return self.slug == slugify(self.slug)

    @property
    def absolute_url(self):
        return self.get_absolute_url()

    def get_absolute_url(self):
        return reverse('feather:property_details', args=[self.slug])

    def get_features(self):
        attributes = []
        for attribute in self.attributelisting_set.all():
            attribute_name = _(attribute.attribute.name)
            if attribute.attribute.validation == 'feather.utils.validation_simple':
                attributes.append('{0}: {1}'.format(attribute_name, attribute.value))
            elif attribute.attribute.validation == 'feather.utils.validation_yesno':
                attributes.append(attribute_name)
            else:
                if attribute.attribute.validation == 'feather.utils.validation_integer':
                    attributes.append('{0} {1}'.format(attribute.value, attribute_name))
                else:
                    attributes.append('{0:.2f} {1}'.format(Decimal(attribute.value), attribute_name))

        return attributes

    @property
    def nearby(self):
        return Listing.objects.active(location=self.location).exclude(id=self.id).order_by('?')

    @property
    def has_baths_or_beds(self):
        return self.should_have_beds or self.should_have_baths

    @property
    def suggested(self):
        qs = Listing.objects.active(type=self.type)

        price = self.price
        lh = price * .90
        rh = price * 1.10

        if self.has_baths_or_beds:
            if self.should_have_baths:
                qs = qs.filter(baths=self.baths)
            if self.should_have_beds:
                qs = qs.filter(beds=self.beds)

            if qs.count() == 0:
                qs = Listing.objects.active(type=self.type, price__range=(lh, rh))
        else:
            qs = qs.filter(price__range=(lh, rh))

        return qs.exclude(id=self.id).order_by('?')

    @property
    def should_have_beds(self):
        return self.type in ('house', 'penthouse', 'apartment', 'villa',)

    @property
    def should_have_baths(self):
        return 'land' not in self.type

    @property
    def on_sale(self):
        return Deal.objects.on_sale(listing__in=(self,)).exists()

    @property
    def code(self):
        if self.agent is not None:
            agent = self.agent
            prefix = '{0}{1}'.format(agent.first_name[0], agent.last_name[0])
            return '{0}{1:04}'.format(prefix, self.id).upper()

        rent_or_sale = 'v' if self.offer in ('buy-rent', 'buy') else 'r'
        return '{0}{1:04x}'.format(rent_or_sale, self.id).upper()
Beispiel #30
0
class AbstractModel(models.Model):
    money = MoneyField(max_digits=10, decimal_places=2, default_currency='USD')
    m2m_field = models.ManyToManyField(ModelWithDefaultAsInt)

    class Meta:
        abstract = True