Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

This script is not working #1

Closed
ajay-ca opened this issue Jan 22, 2025 · 5 comments · Fixed by #2
Closed

This script is not working #1

ajay-ca opened this issue Jan 22, 2025 · 5 comments · Fixed by #2

Comments

@ajay-ca
Copy link

ajay-ca commented Jan 22, 2025

I am trying to switch from the Paisa app to the Cashew app and I came across your script from this issue. I cloned your repo and attempted to convert the JSON file. But it is showing this error:

$ python paisa-to-cashew.py --input ~/Downloads/paisa_backup_25_01_21_15_43.json 
Error: The file /home/ubuntu/Downloads/paisa_backup_25_01_21_15_43.json is not a valid JSON file.

Looks like the JSON is encrypted, and your script decrypts that JSON. Am I missing something or is the script not working anymore?

Here is a screenshot of the contents of the JSON file:

contents of the JSON file

@FosRexx
Copy link
Owner

FosRexx commented Jan 22, 2025

It seems the script is outdated and no longer works as intended.

The JSON file is not encrypted—it's simply Base64-encoded. You can easily decode it using any Base64 decoder, such as this online Base64 decoder. Updating the script to handle the decoding automatically would be straightforward.

However, the real issue lies in the fact that the backup JSON format has changed. The format for backups in Paisa v7.x.x differs from the one used in v6.x.x. Since this script was originally written for v6.x.x, it no longer functions correctly with the newer versions. Unfortunately, adapting the script for v7.x.x would require more substantial changes than minor tweaks, and I currently don't have the time or motivation to make those updates. As it stands, the script is broken for now.

You might consider using the CSV import feature in Cashew. It allows you to map the headers from another app’s CSV backup to Cashew’s CSV format for importing data. However, I recall this method being somewhat unreliable, so your results may vary.

@ajay-ca ajay-ca closed this as completed Jan 23, 2025
@FosRexx FosRexx reopened this Jan 23, 2025
@FosRexx
Copy link
Owner

FosRexx commented Jan 23, 2025

Lets leave the issue open, we can close it if/when its fixed.

@ataraxia-admail
Copy link
Contributor

Hi, i have submitted a change as a short term solution for the broken script, please review it

@FosRexx
Copy link
Owner

FosRexx commented Jan 30, 2025

Wow, that was easier than I expected! Maybe I should have looked into it a bit more. Anyway, thanks to @ataraxia-admail (and Deepseek I guess)! I tested the changes on a small backup, and everything seems to be working fine. Unfortunately, I no longer have my old Paisa backup file, so I can't confirm if the issue is fully resolved. Someone with a larger backup will need to verify that.

@FosRexx FosRexx closed this as completed Jan 30, 2025
@BurnoutDV
Copy link

BurnoutDV commented Feb 4, 2025

As I am really angry at Paisa devs right now and see this while passing. I wrote an AndroMoney Conversion Script for the current 8.3.4 Version of the backup. This isnt all that helpful for you right now, but i wrote some helper dataclass that might be of use:

import uuid
from datetime import datetime, timedelta, date
from decimal import Decimal, InvalidOperation
from dataclasses import dataclass, asdict

@dataclass
class upo: # universal paisa object
    """
    It seems the paisa dev was a bit lazy, and the exported json contains every possible descriptor for
    every kind of objects. This is basically the python representation of it
    """
    modelType: str
    id: uuid.UUID
    name: str
    time: datetime = datetime.now()
    transactionTime: datetime = datetime.now()
    tagId: uuid.UUID | None = None
    description: str | None = None
    bankName: str | None = None
    expiryDateTime: datetime | None = None
    amount: Decimal | None = None
    accountId: uuid.UUID | None = None
    categoryId: uuid.UUID | None = None
    fromAccountId: uuid.UUID | None = None
    toAccountId: uuid.UUID | None = None
    parentId: uuid.UUID | None = None
    icon: int = 0
    color: int = 0
    isAccountExcluded: bool = False
    isCompleted: bool = False
    type: str = "expense"
    categoryType: str = "expense"
    loanType: str = "lending"
    accountType: str = "cash"
    budgetPeriod: str = "daily"
    budgetType: str = "category"
    budgetId: uuid.UUID | None = None
    spentAmount: Decimal | None = None
    lastTrackingUpdate: DateTime | None = None
    sortOrder: int = 0
    goalType: str = "saving"
    goalId: uuid.UUID | None = None
    subscriptionPeriod: str | None = None # might be something other than str
    isAutoRenewing: bool = False
    recurringPeriod: str | None = None
    isRecurringTransaction: bool = False
    status: str = "active"
    accountNumber: str | None = None

    def dict(self) -> dict:
        """
        Export as json exportable dictionary, mostly to get DateTime and Decimal under control
        :return: dict
        """
        ids = ["id", "tagId", "accountId", "categoryId", "parentId", "budgetId", "goalId", "fromAccountId", "toAccountId"]
        dates = ["time", "transactionTime", "expiryDateTime", "lastTrackingUpdate"]
        decimal = ["amount"]
        as_dict = {}
        for k,v in asdict(self).items():
            if v and k in ids:
                as_dict[k] = str(v) # correct format?
            elif v and k in dates:
                as_dict[k] = v.isoformat(timespec="milliseconds")
            elif ( v or v == 0 ) and k in decimal:
                as_dict[k] = float(v) # this is basically the most annoying part when handling money
            else:
                as_dict[k] = v
        return as_dict

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants