good day, need help in my django template, I’ve been struggling to figure out how can I put the subtotal below each Item Category.
here is my template:
{% load crispy_forms_tags %}
{% load static %}
{% load romanize %}
{% load humanize %}
{% csrf_token %}
<table class="table table-bordered" id="boqs">
<thead>
<tr>
<th class="text-center py-1">Item</th>
<th class="text-center py-1">Description</th>
<th class="text-center py-1">Qty</th>
<th class="text-center py-1">Unit</th>
<th class="text-center py-1">Unit Cost</th>
<th class="text-center py-1">Material Cost</th>
<th class="text-center py-1">Unit Cost</th>
<th class="text-center py-1">Labor Cost</th>
<th class="text-center py-1">Line Total</th>
<th class="text-center py-1">Actions</th>
</tr>
</thead>
<tbody>
{% for boq in boqs %}
{% ifchanged boq.item %}
<tr class="bg-light">
<td style="text-align: center; font-weight: bold" type="I">{{ boq.item|romanize }}.</td>
<td style="text-align: left; font-weight: bold" colspan="9">{{ boq.get_item_display }}</td>
</tr>
{% endifchanged %}
<tr>
<td class="text-start"></td>
<td class="text-start">{{ boq.description }}</td>
<td class="text-center">{{ boq.quantity }}</td>
<td class="text-center">{{ boq.unit }}</td>
<td class="text-center">{{ boq.rate_material|intcomma }}</td>
<td class="text-center">{{ boq.material_costs|intcomma }}</td>
<td class="text-center">{{ boq.rate_labor|intcomma }}</td>
<td class="text-center">{{ boq.labor_costs|intcomma }}</td>
<td class="text-center">{{ boq.costs|intcomma }}</td>
<td class="px-2 py-1 text-center">
<button type="button" class="boq-edit btn btn-warning" data-form-url="{% url 'boq-update' boq.pk %}">
<span class="fa fa-pen"></span>
</button>
<a href="{% url 'boq-delete' boq.pk %}" class="btn btn-danger">
<span class="fa fa-trash"></span>
</a>
</td>
</tr>
{% if forloop.counter0 %}
<tr class="bg-light">
<td colspan="2" class="text-bold text-end">SubTotal</td>
<td></td>
<td></td>
<td></td>
<td class="text-center">{{ subtotal_material_cost|intcomma }}</td>
<td></td>
<td class="text-center">subTotal Labor Cost</td>
<td class="text-center">SubTotal Line Total</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
this is the output:
this is the output that I’m trying to figure
this is my views.py
@method_decorator(admin_required, name='dispatch')
class BOQList(LoginRequiredMixin, ListView):
model = BOQ
template_name = 'pms/boq/boq-list-copy.html'
context_object_name = 'boqs'
def get_queryset(self): # new
project_id = self.kwargs['project_id']
return BOQ.objects.filter(project_id=project_id).order_by_item()
this is my models.py
class ItemQuerySet(models.QuerySet): # WORKING
def order_by_item(self):
return self.alias(item_order=Case(
When(item=BOQ.ItemDesciption.GENERAL_REQUIREMENTS, then=Value(1)),
When(item=BOQ.ItemDesciption.SITE_WORK, then=Value(2)),
When(item=BOQ.ItemDesciption.FORMS_SCAFFOLDS, then=Value(3)),
When(item=BOQ.ItemDesciption.STRUCTURAL_CONCRETE, then=Value(4)),
When(item=BOQ.ItemDesciption.STRUCTURAL_STEEL, then=Value(5)),
When(item=BOQ.ItemDesciption.ROOFING, then=Value(6)),
When(item=BOQ.ItemDesciption.WATERPROOFING, then=Value(7)),
When(item=BOQ.ItemDesciption.MASONRY, then=Value(8)),
When(item=BOQ.ItemDesciption.WALL_PLASTERING, then=Value(9)),
When(item=BOQ.ItemDesciption.PAINTING_WORKS, then=Value(10)),
When(item=BOQ.ItemDesciption.WALL_FINISHES, then=Value(11)),
When(item=BOQ.ItemDesciption.FLOOR_FINISHES, then=Value(12)),
When(item=BOQ.ItemDesciption.CEILING_WORKS, then=Value(13)),
When(item=BOQ.ItemDesciption.DOORS, then=Value(14)),
When(item=BOQ.ItemDesciption.WINDOWS, then=Value(15)),
When(item=BOQ.ItemDesciption.ELECTRICAL_WORKS, then=Value(16)),
When(item=BOQ.ItemDesciption.PLUMBING_WORKS, then=Value(17)),
When(item=BOQ.ItemDesciption.MILLWORKS, then=Value(18)),
)).order_by("item_order", "description")
class BOQ(models.Model): # WORKING
class ItemDesciption(models.IntegerChoices):
GENERAL_REQUIREMENTS = 1, _("GENERAL REQUIREMENTS")
SITE_WORK = 2, _("SITE WORK")
FORMS_SCAFFOLDS = 3, _("FORMS & SCAFFOLDS")
STRUCTURAL_CONCRETE = 4, _("STRUCTURAL CONCRETE")
STRUCTURAL_STEEL = 5, _("STRUCTURAL STEEL")
ROOFING = 6, _("ROOFING")
WATERPROOFING = 7, _("WATERPROOFING")
MASONRY = 8, _("MASONRY")
WALL_PLASTERING = 9, _("WALL PLASTERING")
PAINTING_WORKS = 10, _("PAINTING WORKS")
WALL_FINISHES = 11, _("WALL FINISHES")
FLOOR_FINISHES = 12, _("FLOOR FINISHES")
CEILING_WORKS = 13, _("CEILING WORKS")
DOORS = 14, _("DOORS")
WINDOWS = 15, _("WINDOWS")
ELECTRICAL_WORKS = 16, _("ELECTRICAL WORKS")
PLUMBING_WORKS = 17, _("PLUMBING WORKS")
MILLWORKS = 18, _("MILLWORKS")
class Units(models.TextChoices):
LOT = "lot", "lot"
CUM = "cum", "cum"
SQM = "sqm", "sqm"
BFT = "bft", "bft"
KGS = "kgs", "kgs"
LM = "lm", "lm"
PCS = "pcs", "pcs"
SETS = "sets", "sets"
PAIRS = "pairs", "pairs"
METERS = "meters", "meters"
CBM = "cbm", "cbm"
project = models.ForeignKey(Project, on_delete=models.SET_NULL, null=True, blank=True)
item = models.PositiveSmallIntegerField(choices=ItemDesciption.choices, default=ItemDesciption.GENERAL_REQUIREMENTS, db_index=True)
description = models.CharField(max_length=250, null=True, blank=True)
quantity = models.DecimalField(max_digits=10, decimal_places=2, default=1)
unit = models.CharField(max_length=10, choices=Units.choices, default=Units.LOT)
rate_material = models.DecimalField(_("Unit Cost for Material"), max_digits=10, decimal_places=2, default=0)
material_cost = models.DecimalField(_("Material Cost"), max_digits=10, decimal_places=2, default=0)
rate_labor = models.DecimalField(_("Unit Cost for Labor"), max_digits=10, decimal_places=2, default=0)
labor_cost = models.DecimalField(_("Labor Cost"), max_digits=10, decimal_places=2, default=0)
line_total = models.DecimalField(_("Line Total"), max_digits=10, decimal_places=2, default=0)
# SUBTOTAL
subTotal_material_cost = models.DecimalField(_("Subtotal Material Cost"), max_digits=10, decimal_places=2, default=0)
subTotal_labor_cost = models.DecimalField(_("Subtotal Material Cost"), max_digits=10, decimal_places=2, default=0)
subTotal_line_total = models.DecimalField(_("Subtotal Material Cost"), max_digits=10, decimal_places=2, default=0)
# GRANDTOTAL
grandTotal_material_cost = models.DecimalField(_("Grand Total Material Cost"), max_digits=10, decimal_places=2, default=0)
grandTotal_labor_cost = models.DecimalField(_("Grand Total Material Cost"), max_digits=10, decimal_places=2, default=0)
grandTotal_line_total = models.DecimalField(_("Grand Total Material Cost"), max_digits=10, decimal_places=2, default=0)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
objects = ItemQuerySet.as_manager()
class Meta:
verbose_name = "Bill Of Quantities"
verbose_name_plural = "Bill Of Quantities"
ordering = ['item', 'description']
def __str__(self):
return self.description
@property
def material_costs(self):
self.material_cost = self.rate_material * self.quantity
return self.material_cost.quantize(Decimal('0.00'))
@property
def labor_costs(self):
self.labor_cost = self.rate_labor * self.quantity
return self.labor_cost.quantize(Decimal('0.00'))
@property
def costs(self):
self.line_total = self.material_costs + self.labor_costs
return self.line_total.quantize(Decimal('0.00'))
@property
def get_subtotal_material_cost(self):
subtotal = BOQ.objects.filter(item=self.item).aggregate(Sum('material_cost'))
self.subTotal_material_cost = subtotal
return self.subTotal_material_cost.quantize(Decimal('0.00'))