Example #1
0
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)

        # Summarize all the booth sales
        booth_sales = Booth.objects.annotate(Sum('purchase__amount')).order_by(
            'category', 'name')
        booths = {}
        for b in booth_sales:
            amount = b.purchase__amount__sum
            booths[b.name] = D(amount)

        # Donations without a recorded booth need to be accounted for too
        donations = Purchase.objects.filter(booth__isnull=True).aggregate(
            Sum('amount'))['amount__sum']
        booths['Generic Donations'] = D(donations)

        # Fees
        fees = D(Fee.objects.all().aggregate(Sum('amount'))['amount__sum'])
        booths['Fees'] = fees

        total = D(Purchase.objects.all().aggregate(
            Sum('amount'))['amount__sum']) + fees
        context['total_sum'] = D(total)
        context['booth_sums'] = booths

        return context
Example #2
0
    def create_auction_item_purchase(cls, patron, amount, auction_item, quantity):
        desc = 'Auction Item "{}"'.format(auction_item.name)
        desc = desc + ': Quantity: {}'.format( quantity) if quantity else desc
        p = Purchase.objects.create(patron=patron, amount=D(amount), auction_item=auction_item, description=desc,
                                    booth=auction_item.booth, fair_market_value=auction_item.fair_market_value,
                                    quantity=quantity)
        auction_item.sale_time = p.transaction_time
        auction_item.save()

        return p
Example #3
0
class Purchase(TrackedModel, models.Model):
    patron = models.ForeignKey(Patron, related_name='purchases', on_delete=models.CASCADE)
    amount = models.DecimalField(max_digits=15, decimal_places=2)
    transaction_time = models.DateTimeField(auto_now_add=True, blank=True, null=True)
    booth = models.ForeignKey('Booth', blank=True, null=True, on_delete=models.SET_NULL)
    quantity = models.CharField(max_length=50, blank=True, verbose_name="Quantity",
                                help_text="2 dozen, 3 gallons, etc.")
    is_donation = models.BooleanField(default=False,
                                      help_text="True only when the full amount was a donation "
                                                "with nothing received by the Patron")
    description = models.TextField(blank=True, verbose_name="Description",
                                   help_text="A description of the purchase")
    auction_item = models.ForeignKey('AuctionItem', null=True, blank=True, on_delete=models.CASCADE)
    fair_market_value = models.DecimalField(max_digits=15, decimal_places=2, help_text="Fair Market Value",
                                            default=D(0))

    def __str__(self):
        return "{amount} purchase by {patron}".format(amount=USD(self.amount), patron=self.patron.name)

    def get_absolute_url(self):
        return reverse('purchase_detail', kwargs={'pk': self.pk})

    @property
    def donation_amount(self):
        if self.is_donation:
            return D(self.amount)
        return D(0)

    @classmethod
    def create_donation(cls, patron, amount, booth, note=None):
        desc = 'Donation' + ': {}'.format(note) if note else ''
        p = Purchase.objects.create(patron=patron, amount=D(amount), description=desc, booth=booth, is_donation=True,
                                    fair_market_value=D(0))
        return p

    @classmethod
    def create_priced_purchase(cls, patron, amount, booth):
        desc = 'Priced Item(s)'
        p = Purchase.objects.create(patron=patron, amount=D(amount), description=desc, booth=booth,
                                    fair_market_value=D(amount))
        return p

    @classmethod
    def create_auction_item_purchase(cls, patron, amount, auction_item, quantity):
        desc = 'Auction Item "{}"'.format(auction_item.name)
        desc = desc + ': Quantity: {}'.format( quantity) if quantity else desc
        p = Purchase.objects.create(patron=patron, amount=D(amount), auction_item=auction_item, description=desc,
                                    booth=auction_item.booth, fair_market_value=auction_item.fair_market_value,
                                    quantity=quantity)
        auction_item.sale_time = p.transaction_time
        auction_item.save()

        return p
Example #4
0
    def form_valid(self, form):
        purchase_total = D(self.request.session['purchase_total'])

        # Save the purchase for the patron
        p = Purchase.create_priced_purchase(patron=self.patron,
                                            amount=purchase_total,
                                            booth=self.booth)

        # Clear the session state
        del (self.request.session['purchase_total'])
        del (self.request.session['purchase_forms'])

        msg = "Completed Purchase of {amount} by {name} ({number})".format(
            amount=USD(purchase_total),
            name=self.patron.name,
            number=self.patron.buyer_num)
        messages.add_message(self.request, messages.INFO, msg, 'alert-success')

        return redirect('checkout_patron', booth_slug=self.booth.slug)
Example #5
0
class AuctionItem(TrackedModel):
    class Meta:
        pass

    name = models.CharField(max_length=100, blank=False, help_text="Short but descriptive name of item.")
    long_desc = models.TextField(blank=True, verbose_name="Long Description",
                                 help_text="Enter a description, donor information, etc.")
    fair_market_value = models.DecimalField(max_digits=15, decimal_places=2, default=D(0),
                                            verbose_name="Fair Market Value (FMV)", help_text="Dollars, e.g. 10.00")
    quantity = models.CharField(max_length=50, blank=True, null=True, verbose_name="Quantity",
                                     help_text="2 dozen, 3 gallons, etc.")
    item_number = models.PositiveIntegerField(unique=True, db_index=True, default=item_number_generator,
                                              help_text="Leave blank to auto-generate.")
    scheduled_sale_time = models.DateTimeField(blank=True, null=True, verbose_name="Scheduled Sale Time",
                                               help_text="The time when the item is scheduled during the auction.")
    sale_time = models.DateTimeField(blank=True, null=True, verbose_name="Sale Time",
                                     help_text="When the item sold. Leave blank when creating")
    donor_display = models.CharField(max_length=50, blank=True, null=True, verbose_name="Displayed Donor Name",
                                     help_text="How the item's donor would be displayed to the public")
    donor = models.ForeignKey('Patron', null=True, blank=True, help_text="The patron/donor for tax receipt purposes.",
                              related_name="donations", on_delete=models.SET_NULL)
    booth = models.ForeignKey('Booth', blank=True, null=True, on_delete=models.SET_NULL)

    @property
    def is_purchased(self):
        if self.purchase_set.count() > 0:
            return True
        return False

    def purchase_sum(self):
        amount = self.purchase_set.aggregate(Sum('amount'))['amount__sum']
        return amount if amount else 0

    def purchaser_count(self):
        return self.purchase_set.count()

    def get_absolute_url(self):
        return reverse('item_detail', kwargs={'item_number': self.item_number})
Example #6
0
 def test_fee_rounding_down(self):
     assert D('0.09') == calc_cc_fee_amount(D('3.12'))
Example #7
0
 def get_context_data(self, **kwargs):
     context = super(CheckoutConfirm, self).get_context_data(**kwargs)
     context['patron'] = self.patron
     context['booth'] = self.booth
     context['purchase_total'] = D(self.request.session['purchase_total'])
     return context
Example #8
0
 def int_to_dec(self, i):
     return D(i) / D(100)
Example #9
0
 def purchases_total(self):
     purchases = self.purchases.all().aggregate(models.Sum('amount'))['amount__sum']
     return D(purchases)
Example #10
0
 def payments_total(self):
     payments = self.payments.all().aggregate(models.Sum('amount'))['amount__sum']
     return D(payments)
Example #11
0
 def create_donation(cls, patron, amount, booth, note=None):
     desc = 'Donation' + ': {}'.format(note) if note else ''
     p = Purchase.objects.create(patron=patron, amount=D(amount), description=desc, booth=booth, is_donation=True,
                                 fair_market_value=D(0))
     return p
Example #12
0
 def create_priced_purchase(cls, patron, amount, booth):
     desc = 'Priced Item(s)'
     p = Purchase.objects.create(patron=patron, amount=D(amount), description=desc, booth=booth,
                                 fair_market_value=D(amount))
     return p
Example #13
0
 def test_fee_rounding_up(self):
     assert D('0.10') == calc_cc_fee_amount(D('3.17'))
Example #14
0
 def donation_amount(self):
     if self.is_donation:
         return D(self.amount)
     return D(0)
Example #15
0
 def in_kind_donations_sales_total(self):
     return D(sum([i.purchase_sum() for i in self.donations.all()]))
Example #16
0
 def in_kind_donations_total(self):
     return D(sum([i.fair_market_value for i in self.donations.all()]))
Example #17
0
 def account_is_settled(self):
     return self.outstanding_balance == D(0)
Example #18
0
 def purchase_donations_total(self):
     donations = self.purchases.filter(is_donation=True).aggregate(models.Sum('amount'))['amount__sum']
     return D(donations)
Example #19
0
 def fees_total(self):
     fees = self.fees.all().aggregate(models.Sum('amount'))['amount__sum']
     return D(fees)