Skip to content

Commit

Permalink
Merge pull request #15 from sanghunjlee/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
sanghunjlee authored Dec 8, 2023
2 parents 9913470 + 5a9c94e commit f02051e
Show file tree
Hide file tree
Showing 17 changed files with 472 additions and 27 deletions.
61 changes: 51 additions & 10 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,14 +1,55 @@
/.venv
/.vscode
**/__pycache__
# environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# vs code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history

# django
/project
/static
*.log
*.pot
*.pyc
__pycache__
db.sqlite3
media

# python
*.py[cod]
*$py.class

# js
node_modules
package-lock.json

# distribution / packaging
.Python build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
*.manifest
*.spec

# backup
*.bak

# build
*.egg-info
/build
/dist
README_*.md
70 changes: 68 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,63 @@

---

## Getting Started

### Install required packages

```bash
pip install -r requirement.txt
```

### Set up the `SECRET_KEY`

First, create a `.env` file in the root directory (same level as the `manage.py`)

Access the Python interactive shell by running the following in the terminal

```bash
(env) $ python manage.py shell
```

In the shell, import the `get_random_secret_key()` function from `django.core.management.utils`

```python
>>> from django.core.management.utils import get_random_secret_key
```

Use the function to generate the secret key

```python
>>> get_random_secret_key()
somerandomkeygenerated
```

Copy this secret key and set it as `SECRET_KEY` value in the `.env` file

```env
SECRET_KEY='somerandomkeygenerated'
```

### Start the development server

Now you can run the development server by running the following

```bash
(env) $ python manage.py runserver
```

Optionally you can provide a specific port

```bash
(env) $ python manage.py runserver 8000
```

### Open the `/gbill` app

Access the app by going to the `/gbill` page of the server. (e.g. http://localhost:8000/gbill)

---

## Project Description

This is an app designed to split bills amongst other people by using the **minimal** number of transactions.
Expand Down Expand Up @@ -55,7 +112,16 @@ And thus, we conclude there is no discrepancy for method 2 despite at a glance i

## To-Do's
- [ ] CLI Feature
- [x] Convert tkinter gui to ~~flask~~ django
- ~~[ ] Implement Docker~~
- [x] Convert tkinter gui to django
- [ ] Export result as PDF, PNG, and TXT
- [ ] Implement more graphs to show accounting data
- [ ] Implement users & saving/loading & sharing bill info

<details>
<Summary>Trashed ideas</summary>

- Implement Docker
- Convert to Flask (instead of Django)


</details>
7 changes: 5 additions & 2 deletions gbill/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class Meta:
widgets = {
'payee': forms.Select(attrs={'class': 'person-select'}),
'desc': forms.TextInput(attrs={'class': 'label-text-form', 'readOnly': 'readOnly', 'ondblClick': 'this.readOnly=!this.readOnly'}),
'amount': forms.NumberInput(attrs={'class': 'number-form', 'step': '0.01', 'min': '0'}),
'amount': forms.NumberInput(attrs={'class': 'number-form','id': 'total-amount', 'step': '0.01', 'min': '0'}),
}

class BillForm(forms.ModelForm):
Expand All @@ -25,7 +25,10 @@ class Meta:
}

desc = forms.CharField(required=False, widget=forms.TextInput(attrs={'class': 'desc-form'}))
amount = forms.DecimalField(required=False, widget=forms.NumberInput(attrs={'class': 'number-form', 'step': '0.01', 'min': '0'}))
amount = forms.DecimalField(
required=False,
widget=forms.NumberInput(attrs={'class': 'number-form','id': 'total-amount', 'step': '0.01', 'min': '0'})
)

def __init__(self, *args, **kwargs) -> None:
super(BillForm, self).__init__(*args, **kwargs)
Expand Down
33 changes: 28 additions & 5 deletions gbill/static/gbill/style.css → gbill/static/gbill/css/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ div.title-right {
flex: 30;
min-width: fit-content;
}
div.inline {
width: 100%;
display: inline-block;
padding: 4px;
box-sizing: border-box;
}
div#auto-calc-container {
float: right;
}

div#persons {
display: flex;
flex-wrap: wrap;
Expand Down Expand Up @@ -367,15 +377,28 @@ body {
font-family: Helvetica;
background-color: rgb(64, 64, 64);
}
button {
width: 100%;
padding: 2px;
margin-top: 2px;
margin-bottom: 2px;
button[type="button"] {
font-family: inherit;
font-size: inherit;
color: inherit;
border-radius: 8px;
border: 2px solid rgb(64, 64, 64);
padding: 4px 8px;
background-color: white;
color: rgb(64, 64, 64);
transition: all 0.5s ease-in-out;
}
button[type="button"]:hover {
background-color: rgb(64, 64, 64);
color: white;
transition: all 0.5s ease-in-out;
}
button[type="button"]:focus {
border-color: aqua;
outline: none;
}


form {
margin-bottom: 0px;
}
Expand Down
60 changes: 60 additions & 0 deletions gbill/static/gbill/js/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
function doOper(op, a, b) {
switch (op) {
case '+':
return (parseFloat(a) + parseFloat(b)).toFixed(4);
case '-':
return (parseFloat(a) - parseFloat(b)).toFixed(4);
case '*':
return (parseFloat(a) * parseFloat(b)).toFixed(4);
case '/':
return (parseFloat(a) / parseFloat(b)).toFixed(4);
default:
return null;
}
}
function doEval(s) {
// Evaluate equations with operators: +, -, *, /
// Any other operator will cause incorrect calculation or an error

var numbers = s.split(new RegExp('[\\+\\-\\/\\*]'));
var operators = s.split(new RegExp('[.0-9]')).filter(function (op) {
return op !== '';
});

while (operators.length > 0) {
let index = operators.findIndex(function (op) {
return op === '*' || op ==='/';
});
if (index == -1) {
index = operators.findIndex(function (op) {
return op === '+' || op === '-';
});
}
if (index == -1) {
break;
}
let result = doOper(operators[index], numbers[index], numbers[index+1]);
numbers[index] = result;
numbers.splice(index+1, 1);
operators.splice(index, 1);
}
return parseFloat(numbers.join('')).toFixed(3);
}

function autoCalc () {
const totalAmount = document.getElementById("total-amount").value;
const itemAmountDivs = document.getElementsByClassName("f-amount");
if (itemAmountDivs.length > 0) {
const autoAmount = (parseFloat(totalAmount) / (itemAmountDivs.length - 1 )).toFixed(2);
for (let itemAmountDiv of itemAmountDivs) {
let itemAmountElems = itemAmountDiv.getElementsByTagName("input");
if (itemAmountElems.length > 0) {
itemAmountElems[0].value = autoAmount;
}
}
}
}

exports._test = {
doEval: doEval
}
9 changes: 7 additions & 2 deletions gbill/templates/gbill/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" />

<link rel="stylesheet" href="{% static 'gbill/style.css' %}" />
<script src="{% static 'script.js' %}"></script>
<link rel="stylesheet" href="{% static 'gbill/css/style.css' %}" />

<title>Create new bill | gBill</title>
</head>
Expand Down Expand Up @@ -50,6 +49,11 @@
</div>
</div>
<div class="ddiv">
<div class="inline">
<div id="auto-calc-container">
<button type="button" id="auto-calc" onClick="autoCalc()">Auto Calc</button>
</div>
</div>
<fieldset>
<legend>Items</legend>
{{ formset.management_form }}
Expand Down Expand Up @@ -79,5 +83,6 @@
</div>
</form>
</div>
<script src="{% static 'gbill/js/script.js' %}"></script>
</body>
</html>
8 changes: 7 additions & 1 deletion gbill/templates/gbill/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8" />
<meta name="viewport" />

<link rel="stylesheet" href="{% static 'gbill/style.css' %}" />
<link rel="stylesheet" href="{% static 'gbill/css/style.css' %}" />

<title>{{ bill }} | gBill</title>
</head>
Expand Down Expand Up @@ -40,6 +40,11 @@
{{ form.amount }}
</fieldset>
</div>
<div class="inline">
<div id="auto-calc-container">
<button type="button" id="auto-calc" onClick="autoCalc()">Auto Calc</button>
</div>
</div>
<fieldset>
<legend>Items</legend>
<div>
Expand Down Expand Up @@ -79,5 +84,6 @@
</div>
</form>
</div>
<script src="{% static 'gbill/js/script.js' %}"></script>
</body>
</html>
2 changes: 1 addition & 1 deletion gbill/templates/gbill/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<meta charset="utf-8" />
<meta name="viewport" />

<link rel="stylesheet" href="{% static 'gbill/style.css' %}" />
<link rel="stylesheet" href="{% static 'gbill/css/style.css' %}" />

<title>Dashboard | gBill</title>
</head>
Expand Down
5 changes: 2 additions & 3 deletions gbill/templates/gbill/invoice.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
<meta charset="utf-8" />
<meta name="viewport" />

<link rel="stylesheet" href="{% static 'gbill/style.css' %}" />
<script src="{% static 'script.js' %}"></script>

<link rel="stylesheet" href="{% static 'gbill/css/style.css' %}" />

<title>Invoice | gBill</title>
</head>

Expand Down
3 changes: 2 additions & 1 deletion gbill/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,8 @@ def post(self, request, *args, **kwargs):
data.pop('DELETE')
Item.objects.create(**data)
return HttpResponseRedirect(reverse('gbill:index'))



if "add_new_item" in request.POST:
ItemCreateFormSet.extra += 1
formset = ItemCreateFormSet(request.POST)
Expand Down
Loading

0 comments on commit f02051e

Please sign in to comment.