mirror of
https://github.com/Findus23/invoices.git
synced 2024-09-19 15:13:47 +02:00
commit
cb9f3481c6
3 changed files with 147 additions and 10 deletions
137
README.md
Normal file
137
README.md
Normal file
|
@ -0,0 +1,137 @@
|
|||
# Invoices
|
||||
To generate invoices, you need multiple local configs. Your own information
|
||||
should be present in `from.yaml`, the person (or company) you write the invoice
|
||||
to should be present as a file in `recipients/<rname>.yaml`, where `rname` is
|
||||
the selector. The specific information about this invoice should be in
|
||||
`config.yaml`.
|
||||
|
||||
## Your own information: from.yaml
|
||||
Have a file called `from.yaml` with your own information structured like this:
|
||||
|
||||
### Field descriptions
|
||||
| Field | Type | description |
|
||||
|:---|:---:|:---|
|
||||
| `name` | string | Your full name. |
|
||||
| `address` | string | Your Address. Both street and number. |
|
||||
| `zip` | int | Your area ZIP code. |
|
||||
| `city` | string | The city you live in. |
|
||||
| `cityShort` | string | Shortened version of your city name. |
|
||||
| `countryDE` | strang | Name of your country in German, used for an invoice in German. |
|
||||
| `countryEN` | strang | Name of your country in English, used for an invoice in English. |
|
||||
| `IBAN` | string | The IBAN of your bank account. |
|
||||
| `BIC` | string | The BIC of your bank account. |
|
||||
| `bank` | string | The name of your bank. |
|
||||
| `phone` | string | Optional. Your phone number. |
|
||||
| `email` | string | Optional. Your mail address. |
|
||||
| `url` | string | Optional. Your homepage. |
|
||||
|
||||
### Example
|
||||
```from.yaml
|
||||
name: <name>
|
||||
address: <address>
|
||||
zip: <zip>
|
||||
city: <name of city>
|
||||
cityShort: <short name of city>
|
||||
countryDE: Deutschland
|
||||
countryEN: Germany
|
||||
IBAN: <IBAN>
|
||||
BIC: <BIC>
|
||||
bank: <name of bank>
|
||||
```
|
||||
|
||||
It's no big deal to leave some of the fields empty.
|
||||
|
||||
## Clients: recipients/\<rname\>.yaml
|
||||
For every clients `rname`, have a `recipients/<rname>.yaml` file structured
|
||||
like this:
|
||||
|
||||
### Field descriptions
|
||||
| Field | Type | description |
|
||||
|:---|:---:|:---|
|
||||
| `name` | string | Your clients name. |
|
||||
| `address` | string | Your clients business address. Both street and number. |
|
||||
| `zip` | int | ZIP code of your clients address. |
|
||||
| `city` | string | City correlating to the zip code. |
|
||||
| `country` | string | Country of your clients business address. |
|
||||
|
||||
### Example
|
||||
```recipients/<rname>.yaml
|
||||
name: <name>
|
||||
address: <address>
|
||||
zip: <zip>
|
||||
city: <city>
|
||||
country: <country>
|
||||
```
|
||||
|
||||
|
||||
## Config: config.yaml
|
||||
The main config is in a file called `config.yaml`:
|
||||
|
||||
### Field descriptions
|
||||
| Field | Type | description |
|
||||
|:---|:---:|:---|
|
||||
| `title` | string | Title of the invoice. |
|
||||
| `description` | string | Description of the work you did. |
|
||||
| `range` | string | Timeframe during which you accumulated the given number of hours. |
|
||||
| `hours` | int | Number of hours you worked for the given timeframe and client. |
|
||||
| `default_recipient` | string | Filename (before the `.yaml`) of your default client. |
|
||||
| `last_id` | int | Since invoices need to have unique IDs, this number will be increased by one. After that, the config will be written back to the file. This deletes any prior comments. |
|
||||
| `invoice_dir` | string | Directory in which the invoice will be generated. Needs to exist prior to execution. |
|
||||
| `default_hourly_rate` | int | The hourly rate you bill for in this receipt. |
|
||||
| `bank_fee` | int | Optional. Amount of bank fees you can invoice. |
|
||||
|
||||
### Example
|
||||
```config.yaml
|
||||
title: <invoice title>
|
||||
description: <work description>
|
||||
range: <timeframe in which you worked>
|
||||
hours: <hours worked>
|
||||
default_recipient: <rname>
|
||||
last_id: <int>
|
||||
invoice_dir: invoice # directory needs to exist
|
||||
default_hourly_rate: <int>
|
||||
```
|
||||
|
||||
## Structure
|
||||
The directory structure of where you execute this script should look something
|
||||
like this:
|
||||
```
|
||||
$ tree
|
||||
.
|
||||
├── invoice # content is generated, but folder needs to exist
|
||||
│ ├── <id>
|
||||
│ └── <id>
|
||||
├── recipients
|
||||
│ ├── <rname>.yaml
|
||||
│ └── <rname>.yaml
|
||||
├── from.yaml
|
||||
└── config.yaml
|
||||
```
|
||||
|
||||
## Setup
|
||||
Make sure to install poetry first.
|
||||
|
||||
### Nix
|
||||
`nix-env -iA nixpkgs.poetry`
|
||||
|
||||
### Other
|
||||
According to [their website](https://python-poetry.org/docs/#installation),
|
||||
this is the recommended way of installation:
|
||||
`curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python`
|
||||
|
||||
### Install dependencies
|
||||
Make sure to switch to a virtual environment prior to installing dependencies.
|
||||
```
|
||||
$ virtualenv -p python3 .venv
|
||||
$ source .venv/bin/activate
|
||||
$ poetry install # install dependencies
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
$ python main.py create
|
||||
... # you will be asked for details and further information interactively
|
||||
$ python main.py compile
|
||||
```
|
14
main.py
14
main.py
|
@ -22,19 +22,19 @@ def create_invoice():
|
|||
config["last_id"] = current_id
|
||||
invoice.locale = ask("locale", "set", set=["de", "en"], default="de")
|
||||
invoice.id = ask("id", "int", default=current_id)
|
||||
invoice.title = ask("title")
|
||||
invoice.title = ask("title", default=config["title"])
|
||||
invoice.recipient = ask("recipient", "set", set=get_possible_recipents(), default=config["default_recipient"])
|
||||
invoice.date = ask("date", "date", default="today")
|
||||
invoice.description = ask("description")
|
||||
invoice.range = ask("range")
|
||||
invoice.description = ask("description", default=config["description"])
|
||||
invoice.range = ask("range", default=config["range"])
|
||||
|
||||
if invoice.mode == "single":
|
||||
invoice.price = ask("price", "money")
|
||||
|
||||
elif invoice.mode == "hourly":
|
||||
invoice.hours = ask("hours", "int")
|
||||
invoice.minutes = ask("minutes", "int")
|
||||
invoice.per_hour = ask("per hour", "money", default=config["default_hourly_rate"])
|
||||
invoice.hours = ask("hours", "int", default=config["hours"])
|
||||
invoice.minutes = ask("minutes", "int", default="0")
|
||||
invoice.per_hour = ask("rate per hour", "money", default=config["default_hourly_rate"])
|
||||
directory = invoice_dir + "/" + str(invoice.id)
|
||||
if os.path.exists(directory):
|
||||
if not ask("overwrite", "boolean"):
|
||||
|
@ -115,7 +115,7 @@ def compile_invoice(id):
|
|||
fh.write(template.render(section1='Long Form', section2='Short Form', **data))
|
||||
os.chdir(directory)
|
||||
for _ in range(2):
|
||||
subprocess.check_call(['pdflatex', '{name}.tex'.format(name=translate("invoice"))])
|
||||
subprocess.check_call(['pdflatex', '-interaction=nonstopmode', '{name}.tex'.format(name=translate("invoice"))])
|
||||
print(directory)
|
||||
remove_tmp_files(translate("invoice"))
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
%\setkomavar{fromlogo}{\includegraphics[height=3.2cm]{template/header.jpg}}
|
||||
|
||||
|
||||
\setkomavar{frombank}{Sparkasse Krems\separ IBAN: \VAR{from.IBAN}\separ BIC: \VAR{from.BIC}}
|
||||
\setkomavar{frombank}{\VAR{from.bank}\separ IBAN: \VAR{from.IBAN}\separ BIC: \VAR{from.BIC}}
|
||||
%TODO: Linie über
|
||||
\setkomavar{firstfoot}{\centering\color{Gray}\scriptsize\Name\separ\Address\separ\ZIP~\City\\
|
||||
\usekomavar{fromphone}\separ\usekomavar{fromemail}\separ\usekomavar{fromurl}\\\usekomavar{frombank}}
|
||||
|
@ -82,8 +82,8 @@
|
|||
|
||||
% Begin document
|
||||
\begin{document}
|
||||
\begin{letter}{\VAR{to.name} \\ \VAR{to.address} \\ \VAR{to.plz}~\VAR{to.ort}
|
||||
\BLOCK{if to.country!="Österreich"}\\\VAR{to.country}\BLOCK{endif}}
|
||||
\begin{letter}{\VAR{to.name} \\ \VAR{to.address} \\ \VAR{to.zip}~\VAR{to.city}
|
||||
\\\VAR{to.country}}
|
||||
\setkomavar{title}{\VAR{invoice.title}}
|
||||
\opening{}
|
||||
|
||||
|
|
Loading…
Reference in a new issue