Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
4391cc1d8b
|
|||
b346cc07d0
|
|||
169795c16e
|
|||
25f6de1c11 | |||
1c6fe0dd16 | |||
2a0bda012b | |||
5ca2f16757 | |||
292886f834 | |||
3debcf6c2d
|
29
cli/AccountStatement.py
Normal file
29
cli/AccountStatement.py
Normal file
@ -0,0 +1,29 @@
|
||||
from db import dbGetMany
|
||||
from loguru import logger
|
||||
import datetime
|
||||
import iso8601
|
||||
from utils import getParam
|
||||
from Cheetah.Template import Template
|
||||
|
||||
def perform(dbh, params):
|
||||
year = getParam(params, 'year', datetime.datetime.today().year)
|
||||
|
||||
accountEntries = dbGetMany(
|
||||
dbh,
|
||||
{
|
||||
"statement": "SELECT * FROM account_statement_v WHERE fiscal_year = %(year)s",
|
||||
"params": {
|
||||
'year': year
|
||||
}
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
template = getParam(params, 'template', 'accountStatement.tmpl')
|
||||
prefix = getParam(params, 'prefix', 'accountStatement')
|
||||
suffix = getParam(params, 'suffix', 'tex')
|
||||
input = { 'year': year, 'entries': accountEntries }
|
||||
outputFile = f"{prefix}-{year}.{suffix}"
|
||||
tmpl = Template(file=template, searchList=[ input ])
|
||||
with open(outputFile, 'w') as f:
|
||||
f.write(str(tmpl))
|
37
cli/accountStatement.tmpl
Normal file
37
cli/accountStatement.tmpl
Normal file
@ -0,0 +1,37 @@
|
||||
\documentclass[10pt]{article}
|
||||
\usepackage{german}
|
||||
\usepackage{eurosym}
|
||||
\usepackage[a4paper, landscape=true, left=2cm, right=2cm, top=2cm]{geometry}
|
||||
\usepackage{icomma}
|
||||
\usepackage{longtable}
|
||||
\usepackage{color}
|
||||
\setlength{\parindent}{0pt}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\subsection*{Kontoauszug $year}
|
||||
|
||||
\begin{longtable}{rrp{5cm}rrrp{3cm}l}
|
||||
\bf{id} & \bf{createdAt} & \bf{description} & \bf{amount} & \bf{documentNo} & \bf{fiscalYear} & \bf{category} & \bf{account} \\ \hline
|
||||
\endfirsthead
|
||||
\bf{id} & \bf{createdAt} & \bf{description} & \bf{amount} & \bf{documentNo} & \bf{fiscalYear} & \bf{category} & \bf{account} \\ \hline
|
||||
\endhead
|
||||
\hline \multicolumn{8}{r}{\em{to be continued}}
|
||||
\endfoot
|
||||
\hline
|
||||
\endlastfoot
|
||||
|
||||
#for $entry in $entries
|
||||
\tt{$entry['id']} & \tt{$entry['created_at']} & \tt{$entry['description']} & #slurp
|
||||
#if not $entry['income']
|
||||
\textcolor{red}{#slurp
|
||||
#end if
|
||||
\tt{$entry['amount']}#slurp
|
||||
#if not $entry['income']
|
||||
}#slurp
|
||||
#end if
|
||||
& \tt{$entry['document_no']} & \tt{$entry['fiscal_year']} & \tt{$entry['category']} & \tt{{ $entry['account'].replace('_', '\\textunderscore ') }} \\
|
||||
#end for
|
||||
\end{longtable}
|
||||
|
||||
\end{document}
|
17
schema/account-statement.sql
Normal file
17
schema/account-statement.sql
Normal file
@ -0,0 +1,17 @@
|
||||
create or replace view account_statement_v as
|
||||
select ae.id as id,
|
||||
ae.description as description,
|
||||
ae.created_at::timestamp::date as created_at,
|
||||
ae.amount as amount,
|
||||
ae.document_no as document_no,
|
||||
ae.fiscal_year as fiscal_year,
|
||||
aec.description as category,
|
||||
aec.income as income,
|
||||
ac.description as account
|
||||
from account_entry_t ae,
|
||||
account_entry_category_t aec,
|
||||
account_t ac
|
||||
where ae.account_entry_category = aec.id and
|
||||
ae.account = ac.id and
|
||||
aec.id not in (3, 4)
|
||||
order by created_at;
|
120
schema/changes02.sql
Normal file
120
schema/changes02.sql
Normal file
@ -0,0 +1,120 @@
|
||||
CREATE TABLE account_entry_reference_t (
|
||||
id serial not null primary key,
|
||||
account integer not null references account_t (id),
|
||||
account_entry integer not null references account_entry_t (id)
|
||||
);
|
||||
|
||||
|
||||
CREATE OR REPLACE VIEW joined_account_entry_t AS
|
||||
SELECT ae.id as id,
|
||||
ae.description as description,
|
||||
ae.account as account,
|
||||
ae.created_at as created_at,
|
||||
ae.amount as amount,
|
||||
ae.account_entry_category as account_entry_category,
|
||||
ae.document_no as document_no,
|
||||
ae.fiscal_year as fiscal_year,
|
||||
false as is_reference,
|
||||
0 as base_account
|
||||
FROM account_entry_t ae
|
||||
UNION
|
||||
SELECT ae.id as id,
|
||||
ae.description as description,
|
||||
aer.account as account,
|
||||
ae.created_at as created_at,
|
||||
ae.amount as amount,
|
||||
ae.account_entry_category as account_entry_category,
|
||||
ae.document_no as document_no,
|
||||
ae.fiscal_year as fiscal_year,
|
||||
true as is_reference,
|
||||
ae.account as base_account
|
||||
FROM account_entry_t ae,
|
||||
account_entry_reference_t aer
|
||||
WHERE ae.id = aer.account_entry;
|
||||
|
||||
update account_t set description = 'fallback_account' where id = 33;
|
||||
delete from account_t where id = 32;
|
||||
|
||||
insert into account_t (id, description) values (1000, 'ledger');
|
||||
|
||||
update account_entry_t set amount = amount * -1.0 where account=33;
|
||||
update account_entry_t set amount = amount * -1.0 where account in (34,35,36,37);
|
||||
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
entry_id integer;
|
||||
BEGIN
|
||||
RAISE NOTICE 'Start migration';
|
||||
|
||||
FOR entry_id IN
|
||||
SELECT id
|
||||
FROM account_entry_t
|
||||
WHERE account IN (33,34,35,36,37)
|
||||
LOOP
|
||||
RAISE NOTICE 'About to migrate entry %', entry_id;
|
||||
INSERT INTO account_entry_reference_t (account, account_entry) VALUES (1000, entry_id);
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
update account_entry_t
|
||||
set description = 'Miete ' || extract(year from created_at)::text || ' ' || to_char(to_date(extract(month from created_at)::text, 'MM'), 'Month')
|
||||
where account_entry_category = 2 and description = 'Miete';
|
||||
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
entry RECORD;
|
||||
tenant RECORD;
|
||||
BEGIN
|
||||
RAISE NOTICE 'Start migration of tenant accounts';
|
||||
|
||||
FOR entry IN
|
||||
SELECT id, description, account
|
||||
FROM account_entry_t
|
||||
WHERE account_entry_category = 2
|
||||
LOOP
|
||||
RAISE NOTICE 'About to migrate entry %', entry.id;
|
||||
INSERT INTO account_entry_reference_t (account, account_entry) VALUES (1000, entry.id);
|
||||
SELECT *
|
||||
INTO tenant
|
||||
FROM tenant_t
|
||||
WHERE account = entry.account;
|
||||
RAISE NOTICE 'Tenant: % %', tenant.firstname, tenant.lastname;
|
||||
UPDATE account_entry_t
|
||||
SET description = description || ' ' || tenant.firstname || ' ' || tenant.lastname
|
||||
WHERE id = entry.id;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION maintain_ledger()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
tenant RECORD;
|
||||
adjusted_description text;
|
||||
BEGIN
|
||||
IF ((NEW.description = 'Miete') AND (NEW.account_entry_category = 2)) THEN
|
||||
SELECT firstname, lastname
|
||||
INTO tenant
|
||||
FROM tenant_t
|
||||
WHERE account = NEW.account;
|
||||
adjusted_description := 'Miete ' || extract(year from NEW.created_at)::text || ' ' || to_char(to_date(extract(month from NEW.created_at)::text, 'MM'), 'Month') || tenant.firstname || ' ' || tenant.lastname;
|
||||
UPDATE account_entry_t
|
||||
SET description = adjusted_description
|
||||
WHERE id = NEW.id;
|
||||
END IF;
|
||||
|
||||
INSERT INTO account_entry_reference_t (account, account_entry) VALUES (1000, NEW.id);
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER maintain_ledger_trigger
|
||||
AFTER INSERT ON account_entry_t
|
||||
FOR EACH ROW
|
||||
WHEN (NEW.account != 1000 AND NEW.account_entry_category NOT IN (3, 4))
|
||||
EXECUTE FUNCTION maintain_ledger();
|
@ -20,9 +20,9 @@
|
||||
<mat-label>Betrag (€)</mat-label>
|
||||
<input matInput type="number" name="amount" ngModel/>
|
||||
</mat-form-field>
|
||||
<mat-form-field appearance="outline" *ngIf="!shallBeRentPayment">
|
||||
<mat-form-field appearance="outline">
|
||||
<mat-label>Beschreibung</mat-label>
|
||||
<input matInput name="description" [disabled]="shallBeRentPayment" ngModel/>
|
||||
<input matInput name="description" ngModel/>
|
||||
</mat-form-field>
|
||||
<button #addAccountEntryButton type="submit" mat-raised-button color="primary">Buchung speichern</button>
|
||||
</form>
|
||||
|
@ -99,7 +99,7 @@ export class AccountComponent implements OnInit {
|
||||
description: formData.value.description,
|
||||
account: this.account.id,
|
||||
created_at: formData.value.createdAt,
|
||||
fiscal_year: formData.value.fiscalYear,
|
||||
fiscal_year: this.presetFiscalYear.value,
|
||||
amount: formData.value.amount,
|
||||
id: 0,
|
||||
document_no: uniquenumber.number,
|
||||
@ -147,8 +147,8 @@ export class AccountComponent implements OnInit {
|
||||
|
||||
private async init(): Promise<void> {
|
||||
let currentDate = new Date()
|
||||
let y = currentDate.getFullYear().toString()
|
||||
this.presetFiscalYear = new FormControl(`${y}`)
|
||||
let y = currentDate.getFullYear()
|
||||
this.presetFiscalYear = new FormControl(y)
|
||||
this.messageService.add(`AccountComponent.init, account: ${this.selectedAccountId}`)
|
||||
this.getAccount()
|
||||
await this.getAccountEntryCategories()
|
||||
|
@ -1,5 +1,5 @@
|
||||
// export const serviceBaseUrl = "https://api.hv.nober.de";
|
||||
// export const serviceBaseUrl = "http://172.16.10.38:5000";
|
||||
export const serviceBaseUrl = "http://localhost:8080"
|
||||
export const serviceBaseUrl = "http://172.16.3.96:8080";
|
||||
// export const serviceBaseUrl = "http://localhost:8080"
|
||||
export const authserviceBaseUrl = "https://authservice.hottis.de"
|
||||
export const applicationId = "hv2"
|
||||
|
@ -5,30 +5,6 @@
|
||||
</mat-card-title>
|
||||
</mat-card-header>
|
||||
<mat-card-content>
|
||||
<mat-accordion>
|
||||
<mat-expansion-panel (opened)="collapseExpenseDetails = true"
|
||||
(closed)="collapseExpenseDetails = false">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Ausgaben
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
<div>Betriebskosten-relevante Ausgaben nicht hier sondern im Betriebskostenkonto unter "Meine Häuser" erfassen.</div>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-account #expenseAccountComponent [selectedAccountId]="expenseAccountId" [shallBeRentPayment]="false"></app-account>
|
||||
</mat-expansion-panel>
|
||||
<mat-expansion-panel (opened)="collapseIncomeDetails = true"
|
||||
(closed)="collapseIncomeDetails = false">
|
||||
<mat-expansion-panel-header>
|
||||
<mat-panel-title>
|
||||
Einnahmen
|
||||
</mat-panel-title>
|
||||
<mat-panel-description>
|
||||
</mat-panel-description>
|
||||
</mat-expansion-panel-header>
|
||||
<app-account #incomeAccountComponent [selectedAccountId]="incomeAccountId" [shallBeRentPayment]="false"></app-account>
|
||||
</mat-expansion-panel>
|
||||
</mat-accordion>
|
||||
<app-account #fallbackAccountComponent [selectedAccountId]="fallbackAccountId" [shallBeRentPayment]="false"></app-account>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
@ -11,16 +11,11 @@ import { MessageService } from '../message.service';
|
||||
})
|
||||
export class LedgerComponent implements OnInit {
|
||||
|
||||
incomeAccount: Account
|
||||
incomeAccountId: number
|
||||
expenseAccount: Account
|
||||
expenseAccountId: number
|
||||
fallbackAccount: Account
|
||||
fallbackAccountId: number
|
||||
|
||||
collapseIncomeDetails: boolean = false
|
||||
collapseExpenseDetails: boolean = false
|
||||
|
||||
@ViewChild('incomeAccountComponent') incomeAccountComponent: AccountComponent
|
||||
@ViewChild('expenseAccountComponent') expenseAccountComponent: AccountComponent
|
||||
@ViewChild('fallbackAccountComponent') fallbackAccountComponent: AccountComponent
|
||||
|
||||
|
||||
constructor(
|
||||
@ -30,9 +25,8 @@ export class LedgerComponent implements OnInit {
|
||||
|
||||
async getAccount(): Promise<void> {
|
||||
try {
|
||||
this.messageService.add("Trying to load ledger account")
|
||||
this.incomeAccount = await this.extApiService.getAccountByDescription('LedgerIncome')
|
||||
this.expenseAccount = await this.extApiService.getAccountByDescription('LedgerExpense')
|
||||
this.messageService.add("Trying to load fallback account")
|
||||
this.fallbackAccount = await this.extApiService.getAccountByDescription('fallback_account')
|
||||
this.messageService.add("Account loaded")
|
||||
} catch (err) {
|
||||
this.messageService.add(JSON.stringify(err, undefined, 4))
|
||||
@ -41,8 +35,7 @@ export class LedgerComponent implements OnInit {
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
await this.getAccount()
|
||||
this.incomeAccountId = this.incomeAccount.id
|
||||
this.expenseAccountId = this.expenseAccount.id
|
||||
this.fallbackAccountId = this.fallbackAccount.id
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user