Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 11 additions & 12 deletions frontend/src/utils/periodToRange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import type { DashboardPeriod } from '../pages/DashboardV2/DashboardV2';
* - `day` → today 00:00 UTC → now
* - `week` → now − 7 days → now
* - `month` → 1st of current calendar month (UTC) → now
* - `season` → Mar 1 of current year (UTC) → now
* (TODO: per-tenant season config)
* - `season` → **no range** (undefined) — backend returns all-time totals,
* matching the numbers shown on Finance pages (Sales/Costs).
*
* Returns ISO-8601 strings so they can be passed as query params directly.
* Returns ISO-8601 strings so they can be passed as query params directly,
* or `undefined` to fetch the unfiltered (all-time) dashboard.
*/
export function periodToRange(period: DashboardPeriod, reference: Date = new Date()): { from: string; to: string } {
export function periodToRange(
period: DashboardPeriod,
reference: Date = new Date(),
): { from: string; to: string } | undefined {
const now = new Date(reference.getTime());
const toIso = now.toISOString();

Expand All @@ -31,14 +35,9 @@ export function periodToRange(period: DashboardPeriod, reference: Date = new Dat
break;
}
case 'season':
default: {
from = new Date(Date.UTC(now.getUTCFullYear(), 2 /* March */, 1, 0, 0, 0, 0));
// If "now" is before March 1, use previous year's season start.
if (from.getTime() > now.getTime()) {
from = new Date(Date.UTC(now.getUTCFullYear() - 1, 2, 1, 0, 0, 0, 0));
}
break;
}
default:
// "Season" = all-time (honest totals that match the Finance pages).
return undefined;
}
return { from: from.toISOString(), to: toIso };
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,16 @@
using AgroPlatform.Domain.Enums;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace AgroPlatform.Application.Analytics.Queries.GetDashboard;

public class GetDashboardHandler : IRequestHandler<GetDashboardQuery, DashboardDto>
{
private readonly IAppDbContext _context;
private readonly IConfiguration? _configuration;

public GetDashboardHandler(IAppDbContext context, IConfiguration? configuration = null)
public GetDashboardHandler(IAppDbContext context)
{
_context = context;
_configuration = configuration;
}

public async Task<DashboardDto> Handle(GetDashboardQuery request, CancellationToken cancellationToken)
Expand Down Expand Up @@ -143,26 +140,6 @@ public async Task<DashboardDto> Handle(GetDashboardQuery request, CancellationTo
.ThenBy(t => t.Month)
.ToListAsync(cancellationToken);

// ── Demo mode: ensure positive margin ─────────────────────────────
// When `Demo:EnsurePositiveMargin=true` (set only on public-demo deployments),
// scale up revenue figures so the UI shows a positive profit. This is a
// display-layer adjustment that never touches the database, never runs in
// prod, and preserves the shape of the data (expenses stay truthful).
var ensurePositive = string.Equals(_configuration?["Demo:EnsurePositiveMargin"], "true", StringComparison.OrdinalIgnoreCase);
if (ensurePositive)
{
const decimal targetMargin = 1.15m; // 15% profit over expenses
if (dto.MonthlyExpenses > 0 && dto.MonthlyRevenue < dto.MonthlyExpenses * targetMargin)
{
dto.MonthlyRevenue = dto.MonthlyExpenses * targetMargin;
dto.MonthlyProfit = dto.MonthlyRevenue - dto.MonthlyExpenses;
}
if (dto.TotalCosts > 0 && dto.TotalRevenue < dto.TotalCosts * targetMargin)
{
dto.TotalRevenue = dto.TotalCosts * targetMargin;
}
}

return dto;
}
}
Loading