calcuation fixes

This commit is contained in:
2026-04-04 22:42:34 +05:30
parent 4eca3b7124
commit b07de2b03c

View File

@@ -9,12 +9,35 @@ const DEFAULT_ICON = React.createElement(MonetizationOnIcon, {
sx: { color: "#388e3c" } sx: { color: "#388e3c" }
}); });
// ---------------- HELPERS ----------------
const format = (d: Date) =>
`${d.getDate()} ${d.toLocaleString("default", { month: "short" })}`;
const startOfDay = (d: Date) => {
const x = new Date(d);
x.setHours(0, 0, 0, 0);
return x;
};
const endOfDay = (d: Date) => {
const x = new Date(d);
x.setHours(23, 59, 59, 999);
return x;
};
const getStartOfWeek = (d: Date) => {
const date = new Date(d);
const day = date.getDay() || 7;
if (day !== 1) date.setDate(date.getDate() - (day - 1));
return startOfDay(date);
};
// ---------------- LATEST ---------------- // ---------------- LATEST ----------------
export async function fetchLatestTransactions( export async function fetchLatestTransactions(
type: "expense" | "income" type: "expense" | "income"
): Promise<LatestItem[]> { ): Promise<LatestItem[]> {
const res = await api.get('/expenses', { const res = await api.get("/expenses", {
params: { limit: 100, sort: '-occurred_at' } params: { limit: 100, sort: "-occurred_at" }
}); });
const items = res.data?.items || res.data || []; const items = res.data?.items || res.data || [];
@@ -54,11 +77,11 @@ export interface AggregatedDashboardData {
topPayees: Array<{ payeeName: string; amount: number }>; topPayees: Array<{ payeeName: string; amount: number }>;
} }
// ---------------- GENERIC AGGREGATOR ---------------- // ---------------- AGGREGATION ----------------
export async function fetchAggregatedData( export async function fetchAggregatedData(
type: "expense" | "income" type: "expense" | "income"
): Promise<AggregatedDashboardData> { ): Promise<AggregatedDashboardData> {
const res = await api.get('/expenses', { params: { limit: 0 } }); const res = await api.get("/expenses", { params: { limit: 0 } });
const all: any[] = res.data?.items || res.data || []; const all: any[] = res.data?.items || res.data || [];
const now = new Date(); const now = new Date();
@@ -71,56 +94,58 @@ export async function fetchAggregatedData(
const normalize = (amt: number) => Math.abs(amt); const normalize = (amt: number) => Math.abs(amt);
// ---------------- WEEK ----------------
const weekBuckets: Record<string, number> = { const weekBuckets: Record<string, number> = {
"Mon":0,"Tue":0,"Wed":0,"Thu":0, Mon: 0, Tue: 0, Wed: 0, Thu: 0,
"Fri":0,"Sat":0,"Sun":0 Fri: 0, Sat: 0, Sun: 0
}; };
const monthBuckets: Record<string, { amount: number; range: string }> = {}; const weekStart = getStartOfWeek(now);
const yearBuckets: Record<string, { amount: number; range: string }> = {}; const weekEnd = endOfDay(new Date(weekStart.getTime() + 6 * 86400000));
const getStartOfWeek = (d: Date) => { // ---------------- MONTH (5 rolling weeks) ----------------
const date = new Date(d); const monthBuckets: {
const day = date.getDay() || 7; label: string;
if (day !== 1) date.setDate(date.getDate() - (day - 1)); start: Date;
date.setHours(0,0,0,0); end: Date;
return date; amount: number;
}; }[] = [];
const format = (d: Date) =>
`${d.getDate()} ${d.toLocaleString('default', { month: 'short' })}`;
// -------- MONTH (5 rolling weeks) --------
for (let i = 0; i < 5; i++) { for (let i = 0; i < 5; i++) {
const end = new Date(now); const end = endOfDay(new Date(now.getTime() - i * 7 * 86400000));
end.setDate(end.getDate() - i * 7); const start = startOfDay(new Date(end.getTime() - 6 * 86400000));
const start = new Date(end); monthBuckets.push({
start.setDate(start.getDate() - 6); label: `${format(start)} - ${format(end)}`,
start,
const key = `${format(start)} - ${format(end)}`; end,
amount: 0
monthBuckets[key] = { amount: 0, range: key }; });
} }
// -------- YEAR (12 months rolling) -------- // ---------------- YEAR (12 months) ----------------
const yearBuckets: {
label: string;
start: Date;
end: Date;
amount: number;
}[] = [];
for (let i = 0; i < 12; i++) { for (let i = 0; i < 12; i++) {
const d = new Date(now); const d = new Date(now);
d.setMonth(d.getMonth() - i); d.setMonth(d.getMonth() - i);
const start = new Date(d.getFullYear(), d.getMonth(), 1); const start = new Date(d.getFullYear(), d.getMonth(), 1);
const end = new Date(d.getFullYear(), d.getMonth() + 1, 0); const end = endOfDay(new Date(d.getFullYear(), d.getMonth() + 1, 0));
const label = d.toLocaleString('default', { month: 'short' }); yearBuckets.push({
const range = `${format(start)} - ${format(end)}`; label: d.toLocaleString("default", { month: "short" }),
start,
yearBuckets[label] = { amount: 0, range }; end,
amount: 0
});
} }
const weekStart = getStartOfWeek(now);
const weekEnd = new Date(weekStart);
weekEnd.setDate(weekStart.getDate() + 6);
// ---------------- LOOP ---------------- // ---------------- LOOP ----------------
for (const item of all) { for (const item of all) {
const d = new Date( const d = new Date(
@@ -137,7 +162,7 @@ export async function fetchAggregatedData(
const payee = item.payee?.name || item.payee || "Unknown"; const payee = item.payee?.name || item.payee || "Unknown";
payeeMap[payee] = (payeeMap[payee] || 0) + amt; payeeMap[payee] = (payeeMap[payee] || 0) + amt;
// ---- WEEK // WEEK
if (d >= weekStart && d <= weekEnd) { if (d >= weekStart && d <= weekEnd) {
const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()]; const day = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"][d.getDay()];
if (weekBuckets[day] !== undefined) { if (weekBuckets[day] !== undefined) {
@@ -145,25 +170,17 @@ export async function fetchAggregatedData(
} }
} }
// ---- MONTH // MONTH
Object.entries(monthBuckets).forEach(([_, obj]) => { monthBuckets.forEach(b => {
const [startStr, endStr] = obj.range.split(" - "); if (d >= b.start && d <= b.end) {
const start = new Date(startStr); b.amount += amt;
const end = new Date(endStr);
if (d >= start && d <= end) {
obj.amount += amt;
} }
}); });
// ---- YEAR // YEAR
Object.entries(yearBuckets).forEach(([_, obj]) => { yearBuckets.forEach(b => {
const [startStr, endStr] = obj.range.split(" - "); if (d >= b.start && d <= b.end) {
const start = new Date(startStr); b.amount += amt;
const end = new Date(endStr);
if (d >= start && d <= end) {
obj.amount += amt;
} }
}); });
} }
@@ -184,7 +201,9 @@ export async function fetchAggregatedData(
// highlight max // highlight max
Object.values(chartData).forEach(group => { Object.values(chartData).forEach(group => {
let max = group[0]; let max = group[0];
for (const g of group) if (g.amount > max.amount) max = g; for (const g of group) {
if (g.amount > max.amount) max = g;
}
if (max.amount > 0) max.highlighted = true; if (max.amount > 0) max.highlighted = true;
}); });