Skip to content

Commit c891a99

Browse files
Copilotnijel
andcommitted
Add CRM income tracking view with yearly/monthly aggregation
Co-authored-by: nijel <212189+nijel@users.noreply.github.com>
1 parent 9951597 commit c891a99

File tree

2 files changed

+35
-35
lines changed

2 files changed

+35
-35
lines changed

weblate_web/crm/tests.py

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -267,13 +267,13 @@ def test_income_yearly_view(self):
267267

268268
# Create test invoices
269269
self.create_test_invoice(
270-
current_year, 1, InvoiceCategory.HOSTING, Decimal("1000")
270+
current_year, 1, InvoiceCategory.HOSTING, Decimal(1000)
271271
)
272272
self.create_test_invoice(
273-
current_year, 2, InvoiceCategory.SUPPORT, Decimal("2000")
273+
current_year, 2, InvoiceCategory.SUPPORT, Decimal(2000)
274274
)
275275
self.create_test_invoice(
276-
current_year, 3, InvoiceCategory.HOSTING, Decimal("1500")
276+
current_year, 3, InvoiceCategory.HOSTING, Decimal(1500)
277277
)
278278

279279
response = self.client.get(reverse("crm:income"))
@@ -292,14 +292,12 @@ def test_income_monthly_view(self):
292292

293293
# Create test invoices for different categories
294294
self.create_test_invoice(
295-
current_year, 3, InvoiceCategory.HOSTING, Decimal("1000")
295+
current_year, 3, InvoiceCategory.HOSTING, Decimal(1000)
296296
)
297297
self.create_test_invoice(
298-
current_year, 3, InvoiceCategory.SUPPORT, Decimal("2000")
299-
)
300-
self.create_test_invoice(
301-
current_year, 3, InvoiceCategory.DEVEL, Decimal("3000")
298+
current_year, 3, InvoiceCategory.SUPPORT, Decimal(2000)
302299
)
300+
self.create_test_invoice(current_year, 3, InvoiceCategory.DEVEL, Decimal(3000))
303301

304302
response = self.client.get(
305303
reverse("crm:income-month", kwargs={"year": current_year, "month": 3})
@@ -328,7 +326,7 @@ def test_income_filters_only_invoices(self):
328326
currency=0,
329327
)
330328
invoice.invoiceitem_set.create(
331-
description="Invoice item", quantity=1, unit_price=Decimal("1000")
329+
description="Invoice item", quantity=1, unit_price=Decimal(1000)
332330
)
333331

334332
# Create quote (should not be counted)
@@ -340,10 +338,12 @@ def test_income_filters_only_invoices(self):
340338
currency=0,
341339
)
342340
quote.invoiceitem_set.create(
343-
description="Quote item", quantity=1, unit_price=Decimal("5000")
341+
description="Quote item", quantity=1, unit_price=Decimal(5000)
344342
)
345343

346-
response = self.client.get(reverse("crm:income-year", kwargs={"year": current_year}))
344+
response = self.client.get(
345+
reverse("crm:income-year", kwargs={"year": current_year})
346+
)
347347
self.assertEqual(response.status_code, 200)
348348

349349
# Check that total income only includes the invoice, not the quote
@@ -355,7 +355,9 @@ def test_income_year_navigation(self):
355355
"""Test year navigation."""
356356
current_year = timezone.now().year
357357

358-
response = self.client.get(reverse("crm:income-year", kwargs={"year": current_year}))
358+
response = self.client.get(
359+
reverse("crm:income-year", kwargs={"year": current_year})
360+
)
359361
self.assertEqual(response.status_code, 200)
360362

361363
# Check for year links
@@ -373,10 +375,12 @@ def test_income_svg_chart_generation(self):
373375
self.mock_exchange_rates_for_date(f"{current_year}-01-15")
374376

375377
self.create_test_invoice(
376-
current_year, 1, InvoiceCategory.HOSTING, Decimal("1000")
378+
current_year, 1, InvoiceCategory.HOSTING, Decimal(1000)
377379
)
378380

379-
response = self.client.get(reverse("crm:income-year", kwargs={"year": current_year}))
381+
response = self.client.get(
382+
reverse("crm:income-year", kwargs={"year": current_year})
383+
)
380384
self.assertEqual(response.status_code, 200)
381385
self.assertContains(response, "<svg")
382386
self.assertContains(response, "</svg>")
@@ -395,19 +399,17 @@ def test_income_category_breakdown(self):
395399

396400
# Create invoices in different categories
397401
self.create_test_invoice(
398-
current_year, 1, InvoiceCategory.HOSTING, Decimal("1000")
399-
)
400-
self.create_test_invoice(
401-
current_year, 2, InvoiceCategory.SUPPORT, Decimal("2000")
402+
current_year, 1, InvoiceCategory.HOSTING, Decimal(1000)
402403
)
403404
self.create_test_invoice(
404-
current_year, 3, InvoiceCategory.DEVEL, Decimal("3000")
405-
)
406-
self.create_test_invoice(
407-
current_year, 4, InvoiceCategory.DONATE, Decimal("500")
405+
current_year, 2, InvoiceCategory.SUPPORT, Decimal(2000)
408406
)
407+
self.create_test_invoice(current_year, 3, InvoiceCategory.DEVEL, Decimal(3000))
408+
self.create_test_invoice(current_year, 4, InvoiceCategory.DONATE, Decimal(500))
409409

410-
response = self.client.get(reverse("crm:income-year", kwargs={"year": current_year}))
410+
response = self.client.get(
411+
reverse("crm:income-year", kwargs={"year": current_year})
412+
)
411413
self.assertEqual(response.status_code, 200)
412414

413415
# All categories should be shown

weblate_web/crm/views.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -374,13 +374,13 @@ def generate_svg_bar_chart(
374374
# Start SVG
375375
svg_parts = [
376376
f'<svg width="{width}" height="{height}" xmlns="http://www.w3.org/2000/svg">',
377-
'<style>',
378-
'.bar { fill: #417690; }',
379-
'.bar:hover { fill: #79aec8; }',
380-
'.label { font-family: Arial, sans-serif; font-size: 12px; }',
381-
'.value { font-family: Arial, sans-serif; font-size: 11px; fill: #666; }',
382-
'.axis { stroke: #ccc; stroke-width: 1; }',
383-
'</style>',
377+
"<style>",
378+
".bar { fill: #417690; }",
379+
".bar:hover { fill: #79aec8; }",
380+
".label { font-family: Arial, sans-serif; font-size: 12px; }",
381+
".value { font-family: Arial, sans-serif; font-size: 11px; fill: #666; }",
382+
".axis { stroke: #ccc; stroke-width: 1; }",
383+
"</style>",
384384
]
385385

386386
# Draw axes
@@ -401,17 +401,15 @@ def generate_svg_bar_chart(
401401
# Draw bars
402402
for i, (label, value) in enumerate(data.items()):
403403
x = padding + bar_spacing * (2 * i + 1)
404-
bar_height = (
405-
float(value / max_value * chart_height) if value > 0 else 0
406-
)
404+
bar_height = float(value / max_value * chart_height) if value > 0 else 0
407405
y = height - padding - bar_height
408406

409407
# Bar
410408
svg_parts.append(
411409
f'<rect x="{x}" y="{y}" width="{bar_width}" '
412410
f'height="{bar_height}" class="bar">'
413-
f'<title>{label}: {value:,.0f} CZK</title>'
414-
f'</rect>'
411+
f"<title>{label}: {value:,.0f} CZK</title>"
412+
f"</rect>"
415413
)
416414

417415
# Label

0 commit comments

Comments
 (0)