Skip to content

Latest commit

 

History

History
270 lines (183 loc) · 9.34 KB

File metadata and controls

270 lines (183 loc) · 9.34 KB

Customization Guide

This guide covers all common customization tasks for Cashew-Reports, including widget management, category configuration, CSV format, PDF export, and currency changes.


Widget Management

How do I hide a widget?

Set visible: false in its CONFIG.WIDGETS entry:

{ id: "rent_trend", visible: false, size: "third" },

Section titles auto-hide when all their content widgets are hidden. You do not need to hide them manually.

How do I change widget order?

Move the entry in the CONFIG.WIDGETS array. Widgets render in array order, top to bottom, left to right within the 12-column grid.

How do I change widget size?

Change the size field:

Size Grid columns Fits per row
"small" 3 of 12 4 widgets
"third" 4 of 12 3 widgets
"medium" 6 of 12 2 widgets
"large" 12 of 12 1 widget

How do I place a widget in a specific column?

Use the optional col field for explicit grid-column start (1-based):

{ id: "disc_split", visible: true, size: "medium", col: 1 },
{ id: "lifestyle_tax", visible: true, size: "medium", col: 7 },

Valid positions depend on size: small → 1,4,7,10 / third → 1,5,9 / medium → 1,7 / large → 1. The col field is ignored on tablet and mobile breakpoints.

How do I add a new section?

Insert a section title entry before the first widget in the section:

{ id: "section_title", visible: true, title: "My New Section" },
{ id: "my_widget_1", visible: true, size: "medium" },
{ id: "my_widget_2", visible: true, size: "medium" },

Use pageBreak: true on the section title if you want a page break before it in PDF exports.


Category Configuration

How do I change the discretionary split?

Edit the three CONFIG arrays:

DISC_CATEGORIES: ["Shopping", "Dining Out", "Entertainment"],
NON_DISC_CATEGORIES: ["Rent", "Utilities", "Insurance", "Healthcare"],
SEMI_DISC_CATEGORIES: ["Groceries", "Transport", "Subscriptions"],

Categories not in any of these three lists (and not in BURN_RATE_EXCLUDED) will fall into semi-discretionary by default.

The disc_split widget also has two special-case overrides in computeDiscSplit_():

  • Food > Eating Out is routed to discretionary (even though "Food" is in semi-disc)
  • Services > Household Staff is routed to non-discretionary

To change these, edit the if conditions in computeDiscSplit_().

How do I change expected utility bills?

Replace the EXPECTED_UTILITY_BILLS array:

EXPECTED_UTILITY_BILLS: [
  "Electricity", "Water", "Internet", "Phone", "Gas", "Streaming"
],

These must match subcategory names under your "Utility Bills" category in Cashew exactly. The widget checks for paid/upcoming/missing status for each entry.

How do I change which categories are excluded from burn rate?

Edit BURN_RATE_EXCLUDED:

BURN_RATE_EXCLUDED: ["Investment", "Balance Correction", "Payroll Deductions"],

This affects burn_rate, burn_trend, savings_rate, cat_breakdown, top_subcats, biggest_increases, and disc_split.

How do I change core income categories for savings rate?

Edit CORE_INCOME_CATEGORIES:

CORE_INCOME_CATEGORIES: ["Salary", "Passive Income", "Capital Gains", "Ad Hoc Income"],

The savings rate formula is: (sum of core income - burn) / sum of core income, trailing 3 months.

How do I change the lifestyle tax categories?

Edit computeLifestyleTax_() in Code.gs. Replace the hardcoded references:

function computeLifestyleTax_(ctx) {
  // Change these to your own "lifestyle" categories/subcategories
  var eo  = sumFilter_(ctx.expenses, ctx.currentMonth, "Food", "Eating Out");
  var pp  = sumCat_(ctx.expenses, ctx.currentMonth, "Personal Purchases");
  // ...
}

How do I change the grocery trend category?

Edit computeGroceryTrend_():

// Change "Home Essentials" and "Groceries" to your category/subcategory:
var amt = sumFilter_(ctx.expenses, m, "Home Essentials", "Groceries");

How do I change the people payments list?

Edit PEOPLE_PAYMENT_FILTERS:

PEOPLE_PAYMENT_FILTERS: [
  { category: "Services", subcategory: "Household Staff" },
  { category: "Services", subcategory: "Family Transfer" },
  { category: "Occasion", subcategory: "Gifts" },
  { category: "Occasion", subcategory: "Donations" }
]

Add or remove entries as needed. Each entry is a { category, subcategory } pair.


CSV Format

The dashboard reads Cashew's standard Outbox CSV export. The key columns used are:

Column Used for Notes
date Month grouping, date display Parsed with new Date()
amount Transaction amount Filled = settled/actual transaction
amount unpaid Expected amount Used as fallback when amount is empty
type Transaction type upcoming and subscription with empty amount → upcoming; everything else → actual
title Transaction description Used by rent_trend for property matching (AJH/NJH in title)
income true / false Separates income from expenses
category name Primary grouping Must match CONFIG category names exactly
subcategory name Secondary grouping Must match CONFIG subcategory names exactly
color Category color 0XFFRRGGBB format → converted to #RRGGBB for bar colors

Unused columns (present in CSV but ignored): account, currency, note, icon, emoji, budget, objective, transaction id, last modified.

Actual vs Upcoming logic

  • amount filled → actual transaction (settled, paid)
  • amount empty + type is "upcoming" or "subscription" → upcoming (expected, not yet paid)
  • amount empty + type is anything else (e.g., "default") → actual (unsettled but real, e.g., salary/deductions that appear before settlement)
  • Upcoming transactions are used only by the utility_bills widget (to show "upcoming" status for expected bills)

Data source configuration

The CSV filename and Drive folder are configured at the top of Code.gs:

CSV_FOLDER_NAME: "Cashew",
CSV_FILENAME: "outbox.csv",

The script searches for a folder named "Cashew" on your Drive, then finds the file named "outbox.csv" inside it. If not found, it falls back to searching for cashew_outbox.csv in the root of Drive.


PDF Export

Click "Save as PDF" in the dashboard header. The flow is:

  1. Client calls google.script.run.exportPdfToSnapshots(month)
  2. Server re-runs loadAndCompute_() with pdfMode=true
  3. The static-render CSS class is applied, which:
    • Hides all <canvas> elements and shows .chart-fallback bars instead
    • Expands all drill-down panels
    • Shows all hidden table rows
    • Hides expand buttons and toggle hints
  4. The HTML is converted to PDF via Utilities.newBlob().getAs("application/pdf")
  5. The PDF is saved to /Cashew/Snapshots/ on Drive (folder is auto-created)
  6. A link to the saved file opens in a new tab

Page breaks

Section titles with pageBreak: true in CONFIG get page-break-before: always in the PDF. The default config has page breaks before "Spending Patterns" and "Income & Savings".

Ctrl+P (browser print)

The dashboard also supports Ctrl+P / Cmd+P for direct browser printing. The @media print CSS rules apply the same static-render behavior as PDF mode.


Currency and Locale

How do I change the currency symbol?

The fmt_() function in Code.gs formats amounts with the ₹ symbol and Indian comma grouping (1,23,456). To change:

function fmt_(n) {
  n = Math.round(n || 0);
  var neg = n < 0; if (neg) n = -n;
  var s = n.toString();
  // Standard grouping (1,234,567):
  s = s.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
  // Change "$" to your currency symbol:
  return (neg ? "-" : "") + "$" + s;
}

Also update fK_() if you want a currency prefix on abbreviated chart labels:

function fK_(n) {
  n = Math.round(n || 0);
  return n >= 1000 ? "$" + (n / 1000).toFixed(1) + "k" : "$" + n.toString();
}

And update the client-side fK() function in Dashboard.html (used in chart tooltips and value labels).


Month Navigation

The dashboard supports month navigation via URL parameter or the picker in the header:

URL What it shows
.../exec Latest month in the CSV (default)
.../exec?month=2026-03 March 2026 specifically
.../exec?month=2025-11 November 2025 specifically

The month picker arrows navigate to adjacent months. Each navigation is a full page reload (GAS re-reads the CSV and re-computes for the requested month).

If the requested month has no data in the CSV, the dashboard shows zeros for that month.


Updating the Dashboard

What changed What to do Re-deploy needed?
Transaction data (new CSV) Replace the file in Drive No -- dashboard reads the latest on every load
Widget visibility/order/size Edit CONFIG.WIDGETS in Code.gs Yes (new version)
Category classifications Edit CONFIG arrays in Code.gs Yes (new version)
Colors, layout, CSS Edit Dashboard.html Yes (new version)
Add a new widget Edit Code.gs (+ Dashboard.html if chart) Yes (new version)

Re-deploy steps: Deploy → Manage deployments → pencil icon → Version: "New version" → Deploy. The same URL serves the updated code. Do not create a new deployment (that generates a different URL).