Hi!
I am stuck and can not figure out how availability in a rental system:
Background:
To learn django, I am trying to scratch an itch and create a rental system. It has 3 models:
- Products, contains data about a product such as name and price
- Projects, an event where the products are rented out. It contains a start/end date and some general info
- Transactions, this is where a store all the “line items”. Each has a foreign key to product and project, and a quantity.
What I want to do, is when I created a new project, show a table of products and show the number of available of each item.
For each product, filter out the transactions that overlap the current project, and calculate the available quantity for each product.
class Product(models.Model):
name = models.CharField(max_length=200)
objects = ProductManager()
class Project(models.Model):
name = models.CharField(max_length=200)
description = models.CharField(max_length=400, blank=True)
start_date = models.DateField(editable=True, blank=True, null=True)
end_date = models.DateField(editable=True, blank=True, null=True)
class Transaction(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='transactions')
product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='transactions')
quantity = models.IntegerField()
@property
def available(self):
bought = self.transactions.filter(type='ADD').aggregate(
Sum('quantity'))['quantity__sum']
out = self.transactions.filter(type='REN').aggregate(
Sum('quantity'))['quantity__sum']
if bought is None:
bought = 0
if out is None:
out = 0
return bought-out
I have tried to in the view do things like:
products = Product.objects.event_filter(project.start_date, project.end_date).all()
where the event filter is
def event_filter(self, start_date, end_date):
lookup = ((Q(transactions__type='REN') & Q(transactions__project__start_date__lt=end_date) & Q(transactions__project__end_date__gt=start_date)) |
(~Q(transactions__type='REN') & (Q(transactions__project__start_date__lte=start_date) | Q(transactions__project__end_date__lt=start_date))) |
(Q(transactions__id=None))
)
return self.get_queryset().filter(lookup).distinct()
and in the template use, but the event filter added in the view gets “ignored”.:
<table class="product-table">
<tr>
<th>Product</th>
<th>Available</th>
</tr>
<tr>
<td>{{product.name}}</td>
<td>{{product.available}}</td>
</tr>
{% endfor %}
</table>
I can not figure out how to handle that the start/end date moves. Annotation feels like it should be on the right track, but I can not figure out how do it with the dynamic dates instead of the fixed ratings for books in the tutorials and documentation.
I feel like I am missing something. Any tips?