jameskokoska / Cashew

πŸ’Έ An app created to help users manage a budget and purchases
https://cashewapp.web.app/
GNU General Public License v3.0
1.56k stars 221 forks source link
android budget-app budgeting finance flutter ios sql ui-design webapp

Cashew

Icon


iOS App Store Badge Google Play Badge GitHub Badge PWA Badge


Promo banner



Cashew is a full-fledged, feature-rich application designed to empower users in managing their finances effectively. Built using Flutter - with Drift's SQL package, and Firebase - this app offers a seamless and intuitive user experience across various devices. Development started in September 2021.


Features

Review Video

Cashew was featured on YouTube on 'The Best Free and Open Source Apps in 2024!' (and in the thumbnail!)


Review Video

Cashew was featured on YouTube on 'The Best Apps of 2023!'


Review Video

Cashew was featured on YouTube on 'Top Android Apps! (November 2023)'


Play Store Feature

Cashew was featured on Google Play's Editorial 'New Apps We Love' (November 2023)!


Material Apps List Feature

Cashew was featured in the Material You Apps List!

Release

Check out the official website!

This application is available on the App Store, Google Play, GitHub and as a Web App (PWA).

Changelog

Changes and progress about development is all heavily documented in GitHub commits and in the changelog

Key Features

πŸ’Έ Budget Management

πŸ’° Transaction Management

πŸ’± Financial Flexibility

πŸ”’ Enhanced Security and Accessibility

🎨 User Experience and Design

☁ Backup and Syncing

πŸ’Ώ Smart Automation

App Links

A discussion/thread on App Links (example usage and how to harness the power of App Links) can be found at this issue: https://github.com/jameskokoska/Cashew/issues/127#issuecomment-1975096357. App links allow direct navigation and automation of actions using application URLs. Some examples are below.

Changelog

Examples (for Android and iOS)

Ensure Cashew is installed on the device you are launching these URLs from.

Example 1: Create an expense transaction for 100 with the category Shopping at the current time

https://cashewapp.web.app/addTransaction?amount=-100&title=All%20the%20shopping&category=Shopping&notes=Went%20shopping

Example 2: Create an income transaction with a missing category at the current time

https://cashewapp.web.app/addTransaction?amount=100&title=Income&notes=Got%20money

Example 3: Open the add transaction page with a custom date with prefilled details

https://cashewapp.web.app/addTransactionRoute?amount=-50&title=All%20the%20shopping&notes=Went%20shopping&date=2024-03-02

Example 4: Create multiple transactions with one link using JSON

https://cashewapp.web.app/addTransaction?JSON=%7B%22transactions%22%3A%5B%7B%22amount%22%3A%22-100%22%2C%20%22notes%22%3A%22This%20is%20a%20note%22%2C%20%22category%22%3A%22Shopping%22%7D%2C%7B%22amount%22%3A%22-150%22%2C%20%22notes%22%3A%22This%20is%20a%20note%202%22%7D%5D%7D

See JSON List of Transactions below to view how the link is formatted.

Routes

Routes for Android and iOS Routes for Web App
https://cashewapp.web.app/[Endpoint here] https://budget-track.web.app/[Endpoint here]

Endpoints

Endpoint Description
/addTransaction Add a new transaction without a UI prompt (unless a category is missing).
/addTransactionRoute Open the add new transaction route with information filled in.

Parameters

Parameter Description Required Default
amount The amount of the transaction. If negative, it represents an expense; if positive, it represents income. No 0
title The title of the transaction. If an associated title is found and the category is not set, the associated title's category will be used. No Empty string
notes The notes associated with the transaction. No Empty string
date The date of the transaction. Supported string formats can be found in the getCommonDateFormats() method here. No Current time
category The name of the category to add the transaction to. Executes a name search, takes the first entry, not case sensitive. No Prompt user
subcategory The name of the subcategory to add the transaction to. If provided, it overwrites the category if a subcategory is found under a main category. Executes a name search, takes the first entry, not case sensitive. No None
account The name of the account. Executes a name search, takes the first entry, not case sensitive. No Primary account
JSON A list of JSON objects of transactions. If provided, Cashew will import a list/multiple transactions at once. Each JSON object in the list can use any of the aforementioned parameters. The JSON object should be keyed with transactions followed by the list of objects. See the example below. No None
Detailed Parameters The following is a list of all and additional (not fully supported) parameters that can be passed in. They are ordered in terms of precedence, the parameters at the top will be parsed before the ones below. Therefore, overlapping fields will be proceeded by the first parameter. **Class:** related parameters will have the same class. **Standalone parameters:** only this parameter will be used, all other parameters will be ignored. App link parsing can be found [here](https://github.com/jameskokoska/Cashew/blob/main/budget/lib/widgets/util/deepLinks.dart). | Class | Parameter | Description | Required | Default | Standalone | | ----- | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | --------------- | ---------- | | a | `messageToParse` | Uses a scanner template to parse the passed in message. Only `date` or `dateCreated` can be passed along with this standalone parameter. All other fields will be constructed by the scanner template. Scanner templates are not enabled in Cashew by default. To enable this feature, enable `Notification Transactions` debug feature. | None | None | Yes | | b | `JSON` | Description in the above table. | No | None | Yes | | c | `subcategoryPk` | The primary key of the subcategory entry within the database. | No | None | | c | `subcategory` | Description in the above table. | No | None | | c | `categoryPk` | The primary key of the category entry within the database. | No | Prompt user | | c | `category` | Description in the above table. | No | Prompt user | | d | `walletPk` | The primary key of the wallet entry within the database. | No | Primary account | | d | `account` | Description in the above table. | No | Primary account | | d | `wallet` | Same as `account`. | No | Primary account | | e | `date` | Description in the above table. | No | Current time | | e | `dateCreated` | Same as `date`. | No | Current time | | f | `amount` | Description in the above table. | No | 0 | | g | `title` | Description in the above table. | No | Empty string | | g | `name` | Same as `title`. | No | Empty string | | h | `notes` | Description in the above table. | No | Empty string | | h | `note` | Same as `notes`. | No | Empty string |

JSON List of Transactions

The input JSON for addTransaction and addTransactionRoute should follow the following format:

{
  "transactions":[
    { ... },
    { ... },
    { ... }
  ]
}

As an example:

{
  "transactions": [
    {
      "amount": "-100",
      "notes": "This is a note",
      "category": "Shopping"
    },
    {
      "amount": "-150",
      "notes": "This is a note 2"
    }
  ]
}

Don't forget to encode the JSON in the URL as JSON uses invalid URI characters. Once encoded, the output link would look something like:

https://cashewapp.web.app/addTransaction?JSON=%7B%22transactions%22%3A%5B%7B%22amount%22%3A%22-100%22%2C%20%22notes%22%3A%22This%20is%20a%20note%22%2C%20%22category%22%3A%22Shopping%22%7D%2C%7B%22amount%22%3A%22-150%22%2C%20%22notes%22%3A%22This%20is%20a%20note%202%22%7D%5D%7D

Troubleshooting

Android

If you get redirected to the website instead of the Cashew app, your device may not be correctly set up to open App Links. Ensure Cashew can open its respective app link. On your Android device head to your device settings, 'Default apps', 'Opening links' and ensure Cashew has permission to open from the domain cashewapp.web.app under 'Supported web addresses'. This may be disabled by default if you did not install a Google Play signed copy of Cashew (i.e. downloaded from GitHub). This is because Cashew now uses App Links which need to be verified as per Android 12+ requirements with an app's signature public key. Alternatively, you can use a redirect application such as LinkSheet which can manage which apps open when certain links are activated.

Testing

Using ADB for Android

You can use ADB to test app links. For example

adb shell am start -a android.intent.action.VIEW -d "https://cashewapp.web.app/addTransaction?amount=-70\&title=Grocery%20Shopping\&date=2024-03-02\&category=Food\&subcategory=Groceries\&notes=Bought%20fruits%20and%20vegetables\&account=test"

Using links

You can click links and open them with Cashew. See the example section above to test.

Bundled Packages

This repository contains, bundled in, modified versions of the discontinued packages listed below. They can be found in the folder /budget/packages

Translations

The translations are available here: https://docs.google.com/spreadsheets/d/1QQqt28cmrby6JqxLm-oxUXCuM3alniLJ6IRhcPJDOtk/edit?usp=sharing. If you would like to help translate, please reach out on email: dapperappdeveloper@gmail.com

To Update Translations

  1. Run budget\assets\translations\generate-translations.py
  2. Restart the application

Developer Notes

Pull Requests and Contributions

Unfortunately, I am currently not accepting contributions due to licensing and credits. Since this application turns some profits, I want to avoid any muddy water when it comes to compensation for contributions. You are free to submit an issue and I can consider it!

Android Release

Note: required Android SDK.

iOS Release

Note: requires MacOS.

Firebase Deployment

Note: required Firebase.

GitHub release

Scripts

deploy_and_build_windows.bat

open_release_builds.bat

update_translations.bat

Develop Wirelessly on Android

Migrate Database

  1. Make any database changes to the schema and tables
  2. Bump the schema version
    • Change int schemaVersionGlobal = ...+1 in tables.dart
  3. Make sure you are in application root directory
    • cd .\budget\
  4. Generate database code
    • Run dart run build_runner build
  5. Export the new schema
  6. Generate step-by-step migrations
    • Run dart run drift_dev schema steps drift_schemas/ lib\database\schema_versions.dart
  7. Implement migration strategy
    • Edit await stepByStep(...) function in tables.dart and add the migration strategy for the new version migration

Get Platform

Push Route

Wallets vs. Accounts

Objectives vs. Goals

Long Term Loans