spliit-app / spliit Goto Github PK
View Code? Open in Web Editor NEWFree and Open Source Alternative to Splitwise. Share expenses with your friends and family.
Home Page: https://spliit.app
License: MIT License
Free and Open Source Alternative to Splitwise. Share expenses with your friends and family.
Home Page: https://spliit.app
License: MIT License
hi!
really loving and appreciating this project.
i was wondering whether recurring expenses are a feature that you'd consider adding.
with that, transitioning from splitwise would be a no-brainer, for me and i'm assuming for others.
thanks so much
Hi! I'm loving the app so far and already managed to get a couple of friends on board.
I would like to contribute to the project not only with issues and feature requests, but also monetarily, in order to cover the hosting expenses and ensure the continuity of the project!
I haven't found any way of doing so, is there any? Otherwise I think adding a link on https://spliit.app/ or here on GitHub would be a good idea :)
Hello,
I apologise if this is the wrong place to post this, but I saw this announced on Reddit and I'm very excited to use it. Thank you so much for creating it!
I was wondering whether it would be a lot to ask for a docker container version? It might be easier for a lot of people rather than trying to set up a database and app separately.
Thank you so much!
Would be good to see the location of the transaction as you click on the expense for further details on a map. This could be by adding the location in Realtime using the devices GPS, or adding the location afterwards by providing a location.
The first time you open a group, you should be able to tell which participant you are, so that the app can display participants and expenses accordingly (e.g. selecting you as default when creating an expense).
Clicking on export as JSON opens a new tab but then no download is started.
I tried it on Firefox and Safari, on both I got the same behavior.
The server responds with an HTTP 500
.
Since #63 it is possible to attach images to expenses. Might be interested to attach other kind of documents (PDF, doc, video…). Uploading the file is not a problem (you can upload anything to S3), but to see the files, an Image
tag is used. We’d need to cover other behavior for other files (with a preview, ability to download…).
Would love to be able to see the running balance of all the groups which share the same participants.
Currently it seems balances must be viewed separately, individually. Different groups don't sum their balances to show overall total balance with same participants.
I would love to see an option for setting starting/carryover balances when making a new group. This would be particularly useful for folks migrating from other cost splitting apps. I am potentially interested in contributing this once I get up to speed on the structure of the project.
Marking a group as favorite (stored locally) should make it appear at the top of the recent groups list.
First of all, thanks so much for making this app <3
I would like my shared expense data to be encrypted when stored in the database (either via your hosted implementation or my own).
I’ve had a newb scan of the code and can’t tell if the data stored is encrypted?
if it’s not, how about few fields as possible, perhaps the following?
With an optional passcode/phrase entered on group creation (or later) that encrypts and decrypts the above information for the viewing/interacting user.
The passcode/phrase is shared along with the group url (ideally separately 😅), and entered by a user when using the app (not sure how often though?).
I can certainly have a go at introducing this, however may take me awhile :)
I personally need to look for old expenses often. One of the annoyingly premium features of Splitwise is searching for expenses - it would be nice to have some sort of search on the expenses list page.
FEATURE REQUEST: Ability to select different currency for each transaction, similar to splitwise. And choose the currency for reimbursment
Maybe I'm missing something, but it seems that you cannot join groups (only create them) from an PWA app?
Installed the PWA on my iPhone and group page tells me to open a link with a group or create a new one, but I have no way of opening the link inside the PWA.
Maybe there could be a button which opens a box where you can paste the link or id of a group in order to get it to load in the PWA?
Hi,
not an issue, but is there an available way to contribute to translate the website in other languages ? I'm French and I'd love to contribute to get the website in a French translation :)
Thanks,
cress
It would be nice to be able to split an expense unevenly:
Hey there. Cool project. As a test, I created a new expense and gave it the value 19.15
. The UI then showed this as having a value of 19.14
. This is a very common problem in JavaScript.
In the expense list, now that we store the expense date (#17), we can group them by date.
The expense list can be slow when displaying several hundreds of transactions. It would make sense to paginate transactions, i.e. either:
My preference is on option 1, but open to discussion.
This issue occurs because the special characters are not properly escaped when used in a regular expression pattern.
Steps to reproduce:
(
or [
in the expenses search field.Similarly to what Splitwise offers, the idea would be to be able to tell that an expense is related to a certain category.
Would be useful for importing expenses from Splitwise too (#22).
Hello!
I've really enjoyed using spliit for the past few months. I originally found it because I was searching for an alternative to Splitwise once they started to only allow you to enter 3 expenses a day on a free-plan. I was even happier when I realized that this project was open source and I could help contribute! That being said, would love to help out!
My feature request is to some how make it easier to see which of the spliit groups are "settled up". On the "groups" page, all the groups keep changing order based on which one I viewed most recently and it's hard to remember which ones are "settled up" and which ones are still "awaiting reimbursements" or I am still adding expenses to.
I had a few different ideas:
I also saw issue (#9) and while I think that it's nice that this could help clean up the db and save space, it's also nice to have a historical record of all past groups and those expenses so you can refer back to see which expenses were included in each group.
I found this project after searching for alternatives to Splitwise. They've recently implemented a limitation that allows only four (4) expense submissions per day before requiring a paid upgrade, which I find unacceptable.
I'd be open to contributing to this project. My idea is to utilize React Native to maintain a single codebase for building apps for both iOS and Android platforms. We could use Native Wind to ensure consistent styling across both platforms.
When splitting by amount, my keyboard does not have a period to express decimals. I’m using the latest version of iOS and the default keyboard.
To make entering purchases easier, a model (like donut-base-finetuned-cord-v2, demo) could be wired up to provide automatic receipt scanning.
Depending on how big of a model it is, you might be able to run inference entirely client side with ONNX Runtime Web or similar.
Allow an expense to have multiple payers. This would make it easier to split bills that are paid by multiple people in a single transaction. Currently, managing this scenario requires creating individual expenses for each payer, which can be a bit of a hassle. I am not aware of any other workaround for this scenario.
With the current defaults (no participant checked), at least one interaction with the participant list is necessary to be able to save an expense. I have to "select all" participants almost every time.
Considering there is no use case where saving without any interactions is possible, having the expense split evenly across all group members may be a better default.
Hi,
the split calculation seems to be wrong. I'm getting almost 60€ difference when comparing to other splitting apps or manual calculation.
All expenses are split evenly. It should result in 246.60€ to be paid from PersonA to PersonB.
The balances tab shows 299.58€ for some reason:
Suggested reimbursements shows the same amount.
The expenses:
{
"id": "iOEPN60AFdBDcY5AxzG6i",
"name": "Expenses",
"currency": "€",
"expenses": [
{
"expenseDate": "2024-01-03T00:00:00.000Z",
"title": "A",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 7400,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-03T00:00:00.000Z",
"title": "B",
"category": {
"grouping": "Life",
"name": "Insurance"
},
"amount": 6700,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-07T00:00:00.000Z",
"title": "C",
"category": {
"grouping": "Home",
"name": "Pets"
},
"amount": 5772,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-08T00:00:00.000Z",
"title": "D",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 996,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-13T00:00:00.000Z",
"title": "E",
"category": {
"grouping": "Home",
"name": "Household Supplies"
},
"amount": 525,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-17T00:00:00.000Z",
"title": "F",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 6634,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
},
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-17T00:00:00.000Z",
"title": "G",
"category": {
"grouping": "Entertainment",
"name": "Sports"
},
"amount": 16000,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-16T00:00:00.000Z",
"title": "H",
"category": {
"grouping": "Food and Drink",
"name": "Dining Out"
},
"amount": 5500,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-12T00:00:00.000Z",
"title": "I",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 1800,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-19T00:00:00.000Z",
"title": "J",
"category": {
"grouping": "Transportation",
"name": "Hotel"
},
"amount": 19000,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-19T00:00:00.000Z",
"title": "K",
"category": {
"grouping": "Uncategorized",
"name": "General"
},
"amount": 16000,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-20T00:00:00.000Z",
"title": "L",
"category": {
"grouping": "Food and Drink",
"name": "Dining Out"
},
"amount": 3800,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-20T00:00:00.000Z",
"title": "M",
"category": {
"grouping": "Transportation",
"name": "Parking"
},
"amount": 500,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-20T00:00:00.000Z",
"title": "N",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 700,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-20T00:00:00.000Z",
"title": "O",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 1498,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-20T00:00:00.000Z",
"title": "P",
"category": {
"grouping": "Uncategorized",
"name": "General"
},
"amount": 10600,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-21T00:00:00.000Z",
"title": "Q",
"category": {
"grouping": "Food and Drink",
"name": "Dining Out"
},
"amount": 3500,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-21T00:00:00.000Z",
"title": "R",
"category": {
"grouping": "Transportation",
"name": "Parking"
},
"amount": 400,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-21T00:00:00.000Z",
"title": "S",
"category": {
"grouping": "Food and Drink",
"name": "Dining Out"
},
"amount": 2000,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-23T00:00:00.000Z",
"title": "T",
"category": {
"grouping": "Home",
"name": "Maintenance"
},
"amount": 32625,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-24T00:00:00.000Z",
"title": "U",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 1600,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-22T00:00:00.000Z",
"title": "V",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 1920,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-17T00:00:00.000Z",
"title": "W",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 1240,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-17T00:00:00.000Z",
"title": "X",
"category": {
"grouping": "Entertainment",
"name": "Sports"
},
"amount": 14040,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-28T00:00:00.000Z",
"title": "Y",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 695,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-27T00:00:00.000Z",
"title": "Z",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 7816,
"paidById": "Slo8FjtEEdkP2p6NqN6OB",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-02-01T00:00:00.000Z",
"title": "1",
"category": {
"grouping": "Food and Drink",
"name": "Food and Drink"
},
"amount": 1580,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 1
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 1
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-05T00:00:00.000Z",
"title": "2",
"category": {
"grouping": "Food and Drink",
"name": "Groceries"
},
"amount": 698,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
},
{
"expenseDate": "2024-01-08T00:00:00.000Z",
"title": "3",
"category": {
"grouping": "Home",
"name": "Household Supplies"
},
"amount": 2091,
"paidById": "A-ieqXKmKJZXu3XJpGLo4",
"paidFor": [
{
"participantId": "A-ieqXKmKJZXu3XJpGLo4",
"shares": 100
},
{
"participantId": "Slo8FjtEEdkP2p6NqN6OB",
"shares": 100
}
],
"isReimbursement": false,
"splitMode": "EVENLY"
}
],
"participants": [
{
"id": "A-ieqXKmKJZXu3XJpGLo4",
"name": "PersonA"
},
{
"id": "Slo8FjtEEdkP2p6NqN6OB",
"name": "PersonB"
}
]
}
Would love to be able to share a link that loads multiple groups.
Currently, only individual group links can be shared, and so participants which have multiple groups together must click multiple links each time loading the app.
Since #63, users can attach images to expenses, but they can be stored only on S3. If someone has the need to store images somewhere else (locally, on an FTP server…), feel free to comment here with your need and we’ll see how to implement it.
I was looking into if I could get minio working over s3 locally without too many issues (I couldn't, but I'll leave that for another time).
I did notice however that the path is just the filename as root in the bucket, which will start causing issues. I have already done some rudimentary tests and found that images do overwrite each other if they share the same name between expenses, and I believe that it also does between groups.
image.jpg
to it.image.jpg
is in the root, so far so good.image.jpg
to itimage.jpg
.This is generally not great, as you might end up seeing the images belonging to someone else, and may have your own images overwritten as well.
I have a few suggestions on how to solve the issue, any or all might be used to alleviate the problem:
NEFJA5--IBHFY3L99D0r4/image.jpg
)2024-01-29T19:48:39.961269--image.jpg
/ image--809ee38c-6da7-44c2-a34d-54a6802c658a.jpg
I would generally recommend the prefix of group_id, and also just renaming the image to the image ID.
This will allow you to not run into weird issues with filenames (unsure what they might be, but I guess you could use weird chars in filenames that cause issues somehow) but also easily remove all images of a group if it is deleted, both manually and via the CLI/API, even if you lose access to the database somehow.
This will also allow image paths not to be in risk of colliding.
EDIT: I see now that there was an update while I was testing :) will close this issue
Would be great to have the ability to add the date of the transaction onto the Expense.
With this the homepage of the group should then be sorted by date.
This should also be broken down by months but still remain on the same page.
i.e
January 2024
3rd - Transition 1- £50
2nd - Transition 2 - $23
1st - Transition 3 - £45
Break
December 2023
31st - Transition - 4 £44
21st - Transition - 5 £123
4th - Transition - 6 £12
Break
November 2023
Is there a reason all IDs are long alphanumeric strings? It makes DB queries and joins pretty inefficient, and will likely impact performance as the number of ids increase. I don't see a disadvantage to using integer IDs for most (if not all) primary key IDs
@scastiel
A way to see the history of who created a transaction, updated it, what was the update, etc.
Of course, since there's no user account, it might be a challenge to implement it right now. But maybe consider it as a feature request for the future.
HI, first of all, thanks for this app, I've been using it for a while and works great!
I have two questions related to group deletion:
As Spliit is open source, I think it would be nice if it was easy to deploy it anywhere easily.
This means:
Curious to know if anyone has this need or suggestions about implementation. Feel free to give your two cents here 😉
Currently the time in all expense dates defaults to 00:00:00.000
. This causes some awkward ordering in the expenses overview when adding expenses on the same day: expenses added earlier might appear after expenses added later.
An easy fix would be to store the time. Perhaps then it would also be appropriate to have a time picker for the expense date.
Can we add the "simplify debts" function that splitwise has?
The way it works is if Bob owes Jack $10 and Jack owes Anna $10.
When simplify debts is toggled on, then we can simplify the debts where Bob just owes Anna $10. Pretty prime function that splitwise has.
Let me know if we need some UX work for this. Otherwise we just copy what splitwise has done 😊
Splitwise offers an "Export as spreadsheet" feature. It would be useful to be able to import this data into Spliit for continuity of groups that were created before.
Splitwise exports CSV files with the following headers:
Date | Description | Category | Cost | Currency | UserA | UserB | ... |
---|
Values in the User columns are calculated as (Paid - Owe). For example, if UserA paid $100 for an item whose cost was split evenly, UserA's entry would be $100 - $50 = $50 and UserB's would be $0 - $50 = -$50.
Date | Description | Category | Cost | Currency | UserA | UserB |
---|---|---|---|---|---|---|
2024-01-01 | Something | General | 100.00 | USD | 50.00 | -50.00 |
The final row is the total balance per user, which is the column sum for that user. There is no need to import this, but for the record, a positive value represents that the user "gets back" some amount, whereas a negative value represents that the user "owes" the amount.
This would require #6, at least the ability to split unevenly by dollar amount.
I'd suggest matching users by column name and error if a match isn't found; it's very easy to edit the CSV file if the name needs to be changed, no need to create new UI for it.
As a user, I would like to be able to attach files to expenses.
Typical use cases:
On a mobile device, receipts can be added from the gallery, or from the camera directly (I believe the mobile operating systems can handle that case directly).
As I user, I want to:
The first version would simply store the files directly on the same host the server is running.
On a technical level, ideally the directory/folder where the attachments are stored should be configurable (with an env variable).
Later, we could implement more storage mechanisms (FTP, SFTP, S3, etc.)
[edited to better reflect the requirement]
When a branch is merged to main, could this be triggered a workflow to generate a versioned release archive? This will aid local (and potentially homeassistant) deployments.
Also, great that this has been moved into its own organisation - lends itself well to keeping related repositories together!
Just a quick heads-up, the font color in dark mode seems to be off:
Originally posted by @dmlls in #40 (comment)
When filling the date using the keyboard, if more than 4 digits are inserted in the year field (obviously by mistake ;) ), the app crashes and shows the following error:
Application error: a client-side exception has occurred (see the browser console for more information).
The same happens if I type 0
as the first digit in any of the date fields.
This is from Firefox 121.0 (Ubuntu)
Thanks for the excellent app!
One thing I liked about splitwise is the ability to download a json file of all the expenses. It'd be nice to have this feature here.
Automating the category selection would allow users to input and categorize their expenses faster and more reliably. Imagine a user typing their expense title, and based on their input, a category gets selected for them.
Two approaches of implementing this could be:
Implementing the AI option would allow categorization of many more titles than the keyword approach. It would also increase the running cost of spliit. Starting out with an implementation of keyword based mapping will be more economical. However, usability may be limited considering the range of possible titles.
I would be happy to give either of these approaches a try, with AI being my preference. Are you interested in such a feature? If yes, which approach are you leaning towards?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.