This commit is contained in:
2021-09-10 11:59:08 +02:00
parent 554a809ba4
commit 2da6b667bc
25 changed files with 436 additions and 108 deletions

View File

@ -1234,6 +1234,64 @@ SELECT
} }
) )
def get_account_entry_categorys(user, token_info):
return dbGetMany(user, token_info, {
"statement": """
SELECT
id
,description
,overhead_relevant
FROM account_entry_category_t
ORDER BY
description
""",
"params": ()
}
)
def insert_account_entry_category(user, token_info, **args):
try:
body = args["body"]
v_description = body["description"]
v_overhead_relevant = body["overhead_relevant"]
return dbInsert(user, token_info, {
"statement": """
INSERT INTO account_entry_category_t
(
description
,overhead_relevant
) VALUES (
%s
,%s
)
RETURNING *
""",
"params": [
v_description
,v_overhead_relevant
]
})
except KeyError as e:
logger.warning("insert_account_entry_category: parameter missing: {}".format(e))
raise werkzeug.exceptions.UnprocessableEntity("parameter missing: {}".format(e))
def get_account_entry_category(user, token_info, account_entry_categoryId=None):
return dbGetOne(user, token_info, {
"statement": """
SELECT
id
,description
,overhead_relevant
FROM account_entry_category_t
WHERE id = %s
""",
"params": (account_entry_categoryId, )
}
)
def get_account_entrys(user, token_info): def get_account_entrys(user, token_info):
return dbGetMany(user, token_info, { return dbGetMany(user, token_info, {
"statement": """ "statement": """
@ -1243,6 +1301,7 @@ SELECT
,account ,account
,created_at ,created_at
,amount ,amount
,account_entry_category
FROM account_entry_t FROM account_entry_t
ORDER BY ORDER BY
amount amount
@ -1258,6 +1317,7 @@ def insert_account_entry(user, token_info, **args):
v_account = body["account"] v_account = body["account"]
v_created_at = body["created_at"] v_created_at = body["created_at"]
v_amount = body["amount"] v_amount = body["amount"]
v_account_entry_category = body["account_entry_category"]
return dbInsert(user, token_info, { return dbInsert(user, token_info, {
"statement": """ "statement": """
INSERT INTO account_entry_t INSERT INTO account_entry_t
@ -1266,11 +1326,13 @@ INSERT INTO account_entry_t
,account ,account
,created_at ,created_at
,amount ,amount
,account_entry_category
) VALUES ( ) VALUES (
%s %s
,%s ,%s
,%s ,%s
,%s ,%s
,%s
) )
RETURNING * RETURNING *
""", """,
@ -1279,6 +1341,7 @@ INSERT INTO account_entry_t
,v_account ,v_account
,v_created_at ,v_created_at
,v_amount ,v_amount
,v_account_entry_category
] ]
}) })
except KeyError as e: except KeyError as e:
@ -1295,6 +1358,7 @@ SELECT
,account ,account
,created_at ,created_at
,amount ,amount
,account_entry_category
FROM account_entry_t FROM account_entry_t
WHERE id = %s WHERE id = %s
""", """,
@ -1313,6 +1377,7 @@ SELECT
,account ,account
,created_at ,created_at
,amount ,amount
,account_entry_category
FROM account_entry_t FROM account_entry_t
WHERE account = %s WHERE account = %s
""", """,
@ -1320,6 +1385,23 @@ SELECT
} }
) )
def get_account_entry_by_account_entry_category(user, token_info, account_entry_categoryId=None):
return dbGetMany(user, token_info, {
"statement": """
SELECT
id
,description
,account
,created_at
,amount
,account_entry_category
FROM account_entry_t
WHERE account_entry_category = %s
""",
"params": (account_entry_categoryId, )
}
)
def get_notes(user, token_info): def get_notes(user, token_info):
return dbGetMany(user, token_info, { return dbGetMany(user, token_info, {
"statement": """ "statement": """

View File

@ -1175,6 +1175,65 @@ paths:
$ref: '#/components/schemas/tenancy_fee_mapping' $ref: '#/components/schemas/tenancy_fee_mapping'
security: security:
- jwt: ['secret'] - jwt: ['secret']
/v1/account_entry_categorys:
get:
tags: [ "account_entry_category" ]
summary: Return all normalized account_entry_categorys
operationId: methods.get_account_entry_categorys
responses:
'200':
description: account_entry_categorys response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/account_entry_category'
security:
- jwt: ['secret']
post:
tags: [ "account_entry_category" ]
summary: Insert a account_entry_category
operationId: methods.insert_account_entry_category
requestBody:
description: account_entry_category
content:
application/json:
schema:
$ref: '#/components/schemas/account_entry_category'
responses:
'200':
description: account_entry_category successfully inserted
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/account_entry_category'
security:
- jwt: ['secret']
/v1/account_entry_categorys/{account_entry_categoryId}:
get:
tags: [ "account_entry_category" ]
summary: Return the normalized account_entry_category with given id
operationId: methods.get_account_entry_category
parameters:
- name: account_entry_categoryId
in: path
required: true
schema:
type: integer
responses:
'200':
description: account_entry_category response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/account_entry_category'
security:
- jwt: ['secret']
/v1/account_entrys: /v1/account_entrys:
get: get:
tags: [ "account_entry" ] tags: [ "account_entry" ]
@ -1256,6 +1315,28 @@ paths:
$ref: '#/components/schemas/account_entry' $ref: '#/components/schemas/account_entry'
security: security:
- jwt: ['secret'] - jwt: ['secret']
/v1/account_entrys/account_entry_category/{account_entry_categoryId}:
get:
tags: [ "account_entry", "account_entry_category" ]
summary: Return account_entry by $account_entry_category
operationId: methods.get_account_entry_by_account_entry_category
parameters:
- name: account_entry_categoryId
in: path
required: true
schema:
type: integer
responses:
'200':
description: account_entry response
content:
'application/json':
schema:
type: array
items:
$ref: '#/components/schemas/account_entry'
security:
- jwt: ['secret']
/v1/notes: /v1/notes:
get: get:
tags: [ "note" ] tags: [ "note" ]
@ -1578,6 +1659,16 @@ components:
type: integer type: integer
fee: fee:
type: integer type: integer
account_entry_category:
description: account_entry_category
type: object
properties:
id:
type: integer
description:
type: string
overhead_relevant:
type: boolean
account_entry: account_entry:
description: account_entry description: account_entry
type: object type: object
@ -1592,6 +1683,8 @@ components:
type: string type: string
amount: amount:
type: number type: number
account_entry_category:
type: integer
note: note:
description: note description: note
type: object type: object

View File

@ -34,6 +34,9 @@ for table in schema["tables"]:
elif column["sqltype"] == 'timestamp': elif column["sqltype"] == 'timestamp':
column["apitype"] = 'string' column["apitype"] = 'string'
column["jstype"] = 'string' column["jstype"] = 'string'
elif column["sqltype"] == 'boolean':
column["apitype"] = 'boolean'
column["jstype"] = 'boolean'
elif column["sqltype"].startswith('varchar'): elif column["sqltype"].startswith('varchar'):
column["apitype"] = 'string' column["apitype"] = 'string'
column["jstype"] = 'string' column["jstype"] = 'string'

View File

@ -3,7 +3,7 @@
{ {
"name": "account", "name": "account",
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "notnull": true, "selector": 0 } { "name": "description", "sqltype": "varchar(128)", "notnull": true, "unique": true, "selector": 0 }
] ]
}, },
{ {
@ -20,13 +20,16 @@
{ "name": "phone1", "sqltype": "varchar(64)" }, { "name": "phone1", "sqltype": "varchar(64)" },
{ "name": "phone2", "sqltype": "varchar(64)" }, { "name": "phone2", "sqltype": "varchar(64)" },
{ "name": "iban", "sqltype": "varchar(64)" }, { "name": "iban", "sqltype": "varchar(64)" },
{ "name": "account", "sqltype": "integer", "notnull": true, "foreignkey": true, "immutable": true } { "name": "account", "sqltype": "integer", "notnull": true, "foreignkey": true, "immutable": true, "unique": true }
] ] ,
"tableConstraints": [
"unique(firstname, lastname)"
]
}, },
{ {
"name": "premise", "name": "premise",
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 0 }, { "name": "description", "sqltype": "varchar(128)", "selector": 0, "unique": true },
{ "name": "street", "sqltype": "varchar(128)", "notnull": true }, { "name": "street", "sqltype": "varchar(128)", "notnull": true },
{ "name": "zip", "sqltype": "varchar(10)", "notnull": true }, { "name": "zip", "sqltype": "varchar(10)", "notnull": true },
{ "name": "city", "sqltype": "varchar(128)", "notnull": true } { "name": "city", "sqltype": "varchar(128)", "notnull": true }
@ -39,12 +42,15 @@
{ "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 }, { "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 },
{ "name": "area", "sqltype": "numeric(10,2)", "notnull": true }, { "name": "area", "sqltype": "numeric(10,2)", "notnull": true },
{ "name": "flat_no", "sqltype": "integer" } { "name": "flat_no", "sqltype": "integer" }
],
"tableConstraints": [
"unique(description, premise)"
] ]
}, },
{ {
"name": "overhead_advance", "name": "overhead_advance",
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 0 }, { "name": "description", "sqltype": "varchar(128)", "selector": 0, "unique": true },
{ "name": "amount", "sqltype": "numeric(10,4)", "notnull": true, "immutable": true }, { "name": "amount", "sqltype": "numeric(10,4)", "notnull": true, "immutable": true },
{ "name": "startdate", "sqltype": "date", "selector": 1, "immutable": true }, { "name": "startdate", "sqltype": "date", "selector": 1, "immutable": true },
{ "name": "enddate", "sqltype": "date" } { "name": "enddate", "sqltype": "date" }
@ -63,6 +69,9 @@
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 1 }, { "name": "description", "sqltype": "varchar(128)", "selector": 1 },
{ "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 } { "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 }
],
"tableConstraints": [
"unique(description, premise)"
] ]
}, },
{ {
@ -70,12 +79,15 @@
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 1 }, { "name": "description", "sqltype": "varchar(128)", "selector": 1 },
{ "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 } { "name": "premise", "sqltype": "integer", "foreignkey": true, "selector": 0 }
],
"tableConstraints": [
"unique(description, premise)"
] ]
}, },
{ {
"name": "tenancy", "name": "tenancy",
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 0 }, { "name": "description", "sqltype": "varchar(128)", "selector": 0, "unique": true },
{ "name": "tenant", "sqltype": "integer", "notnull": true, "foreignkey": true, "immutable": true }, { "name": "tenant", "sqltype": "integer", "notnull": true, "foreignkey": true, "immutable": true },
{ "name": "flat", "sqltype": "integer", "notnull": false, "foreignkey": true, "immutable": true }, { "name": "flat", "sqltype": "integer", "notnull": false, "foreignkey": true, "immutable": true },
{ "name": "parking", "sqltype": "integer", "notnull": false, "foreignkey": true, "immutable": true }, { "name": "parking", "sqltype": "integer", "notnull": false, "foreignkey": true, "immutable": true },
@ -84,20 +96,21 @@
{ "name": "enddate", "sqltype": "date", "notnull": false } { "name": "enddate", "sqltype": "date", "notnull": false }
], ],
"tableConstraints": [ "tableConstraints": [
"constraint tenancy_only_one_object check ((flat is not null and parking is null and commercial_premise is null) or (flat is null and parking is not null and commercial_premise is null) or (flat is null and parking is null and commercial_premise is not null))" "check ((flat is not null and parking is null and commercial_premise is null) or (flat is null and parking is not null and commercial_premise is null) or (flat is null and parking is null and commercial_premise is not null))",
"unique(flat, parking, commercial_premise, startdate)"
] ]
}, },
{ {
"name": "fee", "name": "fee",
"columns": [ "columns": [
{ "name": "description", "sqltype": "varchar(128)", "selector": 0 }, { "name": "description", "sqltype": "varchar(128)", "selector": 0, "unique": true },
{ "name": "amount", "sqltype": "numeric(10,2)", "notnull": true, "immutable": true }, { "name": "amount", "sqltype": "numeric(10,2)", "notnull": true, "immutable": true },
{ "name": "fee_type", "sqltype": "varchar(10)", "notnull": true, "immutable": true }, { "name": "fee_type", "sqltype": "varchar(10)", "notnull": true, "immutable": true },
{ "name": "startdate", "sqltype": "date", "selector": 1, "immutable": true }, { "name": "startdate", "sqltype": "date", "selector": 1, "immutable": true },
{ "name": "enddate", "sqltype": "date" } { "name": "enddate", "sqltype": "date" }
], ],
"tableConstraints": [ "tableConstraints": [
"constraint fee_fee_type check (fee_type = 'per_area' or fee_type = 'total')" "check (fee_type = 'per_area' or fee_type = 'total')"
] ]
}, },
{ {
@ -108,6 +121,14 @@
{ "name": "fee", "sqltype": "integer", "notnull": true, "foreignkey": true } { "name": "fee", "sqltype": "integer", "notnull": true, "foreignkey": true }
] ]
}, },
{
"name": "account_entry_category",
"immutable": true,
"columns": [
{ "name": "description", "sqltype": "varchar(128)", "notnull": true, "selector": 0, "unique": true },
{ "name": "overhead_relevant", "sqltype": "boolean", "notnull": true, "default": "true" }
]
},
{ {
"name": "account_entry", "name": "account_entry",
"immutable": true, "immutable": true,
@ -115,7 +136,11 @@
{ "name": "description", "sqltype": "varchar(128)", "notnull": true }, { "name": "description", "sqltype": "varchar(128)", "notnull": true },
{ "name": "account", "sqltype": "integer", "notnull": true, "foreignkey": true }, { "name": "account", "sqltype": "integer", "notnull": true, "foreignkey": true },
{ "name": "created_at", "sqltype": "timestamp", "notnull": true, "default": "now()" }, { "name": "created_at", "sqltype": "timestamp", "notnull": true, "default": "now()" },
{ "name": "amount", "sqltype": "numeric(10,2)", "notnull": true, "selector": 0 } { "name": "amount", "sqltype": "numeric(10,2)", "notnull": true, "selector": 0 },
{ "name": "account_entry_category", "sqltype": "integer", "notnull": true, "foreignkey": true }
],
"tableConstraints": [
"unique(description, account, created_at)"
] ]
}, },
{ {

View File

@ -7,9 +7,12 @@
CREATE TABLE account_t ( CREATE TABLE account_t (
id serial not null primary key id serial not null primary key
,description varchar(128) not null ,description varchar(128) not null unique
); );
GRANT SELECT, INSERT, UPDATE ON account_t TO hv2;
GRANT SELECT, UPDATE ON account_t_id_seq TO hv2;
CREATE TABLE tenant_t ( CREATE TABLE tenant_t (
id serial not null primary key id serial not null primary key
,salutation varchar(128) ,salutation varchar(128)
@ -23,87 +26,136 @@ CREATE TABLE tenant_t (
,phone1 varchar(64) ,phone1 varchar(64)
,phone2 varchar(64) ,phone2 varchar(64)
,iban varchar(64) ,iban varchar(64)
,account integer not null references account_t (id) ,account integer not null references account_t (id) unique
,unique(firstname, lastname)
); );
GRANT SELECT, INSERT, UPDATE ON tenant_t TO hv2;
GRANT SELECT, UPDATE ON tenant_t_id_seq TO hv2;
CREATE TABLE premise_t ( CREATE TABLE premise_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128) unique
,street varchar(128) not null ,street varchar(128) not null
,zip varchar(10) not null ,zip varchar(10) not null
,city varchar(128) not null ,city varchar(128) not null
); );
GRANT SELECT, INSERT, UPDATE ON premise_t TO hv2;
GRANT SELECT, UPDATE ON premise_t_id_seq TO hv2;
CREATE TABLE flat_t ( CREATE TABLE flat_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128)
,premise integer references premise_t (id) ,premise integer references premise_t (id)
,area numeric(10,2) not null ,area numeric(10,2) not null
,flat_no integer ,flat_no integer
,unique(description, premise)
); );
GRANT SELECT, INSERT, UPDATE ON flat_t TO hv2;
GRANT SELECT, UPDATE ON flat_t_id_seq TO hv2;
CREATE TABLE overhead_advance_t ( CREATE TABLE overhead_advance_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128) unique
,amount numeric(10,4) not null ,amount numeric(10,4) not null
,startdate date ,startdate date
,enddate date ,enddate date
); );
GRANT SELECT, INSERT, UPDATE ON overhead_advance_t TO hv2;
GRANT SELECT, UPDATE ON overhead_advance_t_id_seq TO hv2;
CREATE TABLE overhead_advance_flat_mapping_t ( CREATE TABLE overhead_advance_flat_mapping_t (
id serial not null primary key id serial not null primary key
,overhead_advance integer not null references overhead_advance_t (id) ,overhead_advance integer not null references overhead_advance_t (id)
,flat integer not null references flat_t (id) ,flat integer not null references flat_t (id)
); );
GRANT SELECT, INSERT ON overhead_advance_flat_mapping_t TO hv2;
GRANT SELECT, UPDATE ON overhead_advance_flat_mapping_t_id_seq TO hv2;
CREATE TABLE parking_t ( CREATE TABLE parking_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128)
,premise integer references premise_t (id) ,premise integer references premise_t (id)
,unique(description, premise)
); );
GRANT SELECT, INSERT, UPDATE ON parking_t TO hv2;
GRANT SELECT, UPDATE ON parking_t_id_seq TO hv2;
CREATE TABLE commercial_premise_t ( CREATE TABLE commercial_premise_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128)
,premise integer references premise_t (id) ,premise integer references premise_t (id)
,unique(description, premise)
); );
GRANT SELECT, INSERT, UPDATE ON commercial_premise_t TO hv2;
GRANT SELECT, UPDATE ON commercial_premise_t_id_seq TO hv2;
CREATE TABLE tenancy_t ( CREATE TABLE tenancy_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128) unique
,tenant integer not null references tenant_t (id) ,tenant integer not null references tenant_t (id)
,flat integer references flat_t (id) ,flat integer references flat_t (id)
,parking integer references parking_t (id) ,parking integer references parking_t (id)
,commercial_premise integer references commercial_premise_t (id) ,commercial_premise integer references commercial_premise_t (id)
,startdate date not null ,startdate date not null
,enddate date ,enddate date
,constraint tenancy_only_one_object check ((flat is not null and parking is null and commercial_premise is null) or (flat is null and parking is not null and commercial_premise is null) or (flat is null and parking is null and commercial_premise is not null)) ,check ((flat is not null and parking is null and commercial_premise is null) or (flat is null and parking is not null and commercial_premise is null) or (flat is null and parking is null and commercial_premise is not null))
,unique(flat, parking, commercial_premise, startdate)
); );
GRANT SELECT, INSERT, UPDATE ON tenancy_t TO hv2;
GRANT SELECT, UPDATE ON tenancy_t_id_seq TO hv2;
CREATE TABLE fee_t ( CREATE TABLE fee_t (
id serial not null primary key id serial not null primary key
,description varchar(128) ,description varchar(128) unique
,amount numeric(10,2) not null ,amount numeric(10,2) not null
,fee_type varchar(10) not null ,fee_type varchar(10) not null
,startdate date ,startdate date
,enddate date ,enddate date
,constraint fee_fee_type check (fee_type = 'per_area' or fee_type = 'total') ,check (fee_type = 'per_area' or fee_type = 'total')
); );
GRANT SELECT, INSERT, UPDATE ON fee_t TO hv2;
GRANT SELECT, UPDATE ON fee_t_id_seq TO hv2;
CREATE TABLE tenancy_fee_mapping_t ( CREATE TABLE tenancy_fee_mapping_t (
id serial not null primary key id serial not null primary key
,tenancy integer not null references tenancy_t (id) ,tenancy integer not null references tenancy_t (id)
,fee integer not null references fee_t (id) ,fee integer not null references fee_t (id)
); );
GRANT SELECT, INSERT ON tenancy_fee_mapping_t TO hv2;
GRANT SELECT, UPDATE ON tenancy_fee_mapping_t_id_seq TO hv2;
CREATE TABLE account_entry_category_t (
id serial not null primary key
,description varchar(128) not null unique
,overhead_relevant boolean not null default true
);
GRANT SELECT, INSERT ON account_entry_category_t TO hv2;
GRANT SELECT, UPDATE ON account_entry_category_t_id_seq TO hv2;
CREATE TABLE account_entry_t ( CREATE TABLE account_entry_t (
id serial not null primary key id serial not null primary key
,description varchar(128) not null ,description varchar(128) not null
,account integer not null references account_t (id) ,account integer not null references account_t (id)
,created_at timestamp not null default now() ,created_at timestamp not null default now()
,amount numeric(10,2) not null ,amount numeric(10,2) not null
,account_entry_category integer not null references account_entry_category_t (id)
,unique(description, account, created_at)
); );
GRANT SELECT, INSERT ON account_entry_t TO hv2;
GRANT SELECT, UPDATE ON account_entry_t_id_seq TO hv2;
CREATE TABLE note_t ( CREATE TABLE note_t (
id serial not null primary key id serial not null primary key
,created_at timestamp not null default now() ,created_at timestamp not null default now()
@ -111,5 +163,9 @@ CREATE TABLE note_t (
,note varchar(4096) not null ,note varchar(4096) not null
); );
GRANT SELECT, INSERT ON note_t TO hv2;
GRANT SELECT, UPDATE ON note_t_id_seq TO hv2;

View File

@ -14,6 +14,9 @@ CREATE TABLE ${table.name}_t (
#if (('foreignkey' in $column) and $column.foreignkey) #if (('foreignkey' in $column) and $column.foreignkey)
references ${column.name}_t (id) #slurp references ${column.name}_t (id) #slurp
#end if #end if
#if (('unique' in $column) and $column.unique)
unique #slurp
#end if
#if ('default' in $column) #if ('default' in $column)
default $column.default #slurp default $column.default #slurp
#end if #end if
@ -26,6 +29,14 @@ CREATE TABLE ${table.name}_t (
#end if #end if
); );
GRANT SELECT, INSERT#slurp
#if (('immutable' not in $table) or (not $table.immutable))
, UPDATE#slurp
#end if
ON ${table.name}_t TO hv2;
GRANT SELECT, UPDATE ON ${table.name}_t_id_seq TO hv2;
#end for #end for

View File

@ -1,5 +1,6 @@
table { table {
width: 75%; width: 75%;
border-spacing: 20px;
} }
.spacer { .spacer {
@ -23,9 +24,10 @@ table {
} }
.rightaligned { .rightaligned {
justify-self: right; text-align: right;
} }
.large { .large {
font-size: large; font-size: large;
} }

View File

@ -23,6 +23,12 @@
<mat-datepicker-toggle matSuffix [for]="createdAtPicker"></mat-datepicker-toggle> <mat-datepicker-toggle matSuffix [for]="createdAtPicker"></mat-datepicker-toggle>
<mat-datepicker #createdAtPicker></mat-datepicker> <mat-datepicker #createdAtPicker></mat-datepicker>
</mat-form-field> </mat-form-field>
<mat-form-field appearance="outline">
<mat-label>Kategorie</mat-label>
<mat-select [(ngModel)]="newAccountEntry.account_entry_category" name="category" disabled="shallBeRentPayment">
<mat-option *ngFor="let p of accountEntryCategories" [value]="p.id">{{p.description}}</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Betrag (€)</mat-label> <mat-label>Betrag (€)</mat-label>
<input matInput type="number" name="amount" [(ngModel)]="newAccountEntry.amount"/> <input matInput type="number" name="amount" [(ngModel)]="newAccountEntry.amount"/>
@ -39,17 +45,25 @@
</div> </div>
<div id="secondBlock"> <div id="secondBlock">
<table mat-table [dataSource]="accountEntriesDataSource" #zftable> <table mat-table [dataSource]="accountEntriesDataSource" #zftable>
<ng-container matColumnDef="createdAt">
<th mat-header-cell *matHeaderCellDef>Datum</th>
<td mat-cell *matCellDef="let element">{{element.rawAccountEntry.created_at | date}}</td>
</ng-container>
<ng-container matColumnDef="description"> <ng-container matColumnDef="description">
<th mat-header-cell *matHeaderCellDef>Beschreibung</th> <th mat-header-cell *matHeaderCellDef>Beschreibung</th>
<td mat-cell *matCellDef="let element">{{element.description}}</td> <td mat-cell *matCellDef="let element">{{element.rawAccountEntry.description}}</td>
</ng-container> </ng-container>
<ng-container matColumnDef="amount"> <ng-container matColumnDef="amount">
<th mat-header-cell *matHeaderCellDef>Betrag</th> <th mat-header-cell *matHeaderCellDef>Betrag</th>
<td mat-cell *matCellDef="let element">{{element.amount | number:'1.2-2'}} €</td> <td mat-cell *matCellDef="let element" class="rightaligned">{{element.rawAccountEntry.amount | number:'1.2-2'}} €</td>
</ng-container> </ng-container>
<ng-container matColumnDef="createdAt"> <ng-container matColumnDef="category">
<th mat-header-cell *matHeaderCellDef>Datum</th> <th mat-header-cell *matHeaderCellDef>Kategorie</th>
<td mat-cell *matCellDef="let element">{{element.created_at | date}}</td> <td mat-cell *matCellDef="let element">{{element.accountEntryCategory}}</td>
</ng-container>
<ng-container matColumnDef="overhead_relevant">
<th mat-header-cell *matHeaderCellDef>BK relevant</th>
<td mat-cell *matCellDef="let element">{{element.overheadRelevant}}</td>
</ng-container> </ng-container>
<tr mat-header-row *matHeaderRowDef="accountEntriesDisplayedColumns"></tr> <tr mat-header-row *matHeaderRowDef="accountEntriesDisplayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: accountEntriesDisplayedColumns;"></tr> <tr mat-row *matRowDef="let row; columns: accountEntriesDisplayedColumns;"></tr>

View File

@ -1,12 +1,21 @@
import { Component, Input, OnInit, OnChanges, ViewChild } from '@angular/core'; import { Component, Input, OnInit, OnChanges, ViewChild } from '@angular/core';
import { MatButton } from '@angular/material/button'; import { MatButton } from '@angular/material/button';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { AccountEntryService, AccountService } from '../data-object-service'; import { AccountEntryCategoryService, AccountEntryService, AccountService } from '../data-object-service';
import { Account, AccountEntry, NULL_AccountEntry } from '../data-objects'; import { Account, AccountEntry, AccountEntryCategory, NULL_AccountEntry } from '../data-objects';
import { ExtApiService } from '../ext-data-object-service'; import { ExtApiService } from '../ext-data-object-service';
import { Saldo } from '../ext-data-objects'; import { Saldo } from '../ext-data-objects';
import { MessageService } from '../message.service'; import { MessageService } from '../message.service';
interface DN_AccountEntry {
rawAccountEntry: AccountEntry
accountEntryCategory: string
overheadRelevant: boolean
}
@Component({ @Component({
selector: 'app-account', selector: 'app-account',
templateUrl: './account.component.html', templateUrl: './account.component.html',
@ -15,16 +24,20 @@ import { MessageService } from '../message.service';
export class AccountComponent implements OnInit { export class AccountComponent implements OnInit {
@Input() selectedAccountId: number @Input() selectedAccountId: number
@Input() shallBeRentPayment: boolean
@ViewChild('addAccountEntryButton') addAccountEntryButton: MatButton @ViewChild('addAccountEntryButton') addAccountEntryButton: MatButton
collapse: boolean = false collapse: boolean = false
account: Account account: Account
accountEntries: AccountEntry[] accountEntries: DN_AccountEntry[]
accountEntriesDataSource: MatTableDataSource<AccountEntry> accountEntriesDataSource: MatTableDataSource<DN_AccountEntry>
accountEntriesDisplayedColumns: string[] = [ "description", "amount", "createdAt" ] accountEntriesDisplayedColumns: string[] = [ "description", "amount", "createdAt", "category", "overhead_relevant" ]
saldo: Saldo saldo: Saldo
accountEntryCategories: AccountEntryCategory[]
accountEntryCategoriesMap: Map<number, AccountEntryCategory>
accountEntryCategoriesInverseMap: Map<string, AccountEntryCategory>
newAccountEntry: AccountEntry = NULL_AccountEntry newAccountEntry: AccountEntry = NULL_AccountEntry
@ -33,6 +46,7 @@ export class AccountComponent implements OnInit {
private accountService: AccountService, private accountService: AccountService,
private accountEntryService: AccountEntryService, private accountEntryService: AccountEntryService,
private extApiService: ExtApiService, private extApiService: ExtApiService,
private accountEntryCategoryService: AccountEntryCategoryService,
private messageService: MessageService private messageService: MessageService
) { } ) { }
@ -51,12 +65,23 @@ export class AccountComponent implements OnInit {
async getAccountEntries(): Promise<void> { async getAccountEntries(): Promise<void> {
try { try {
this.accountEntries = await this.accountEntryService.getAccountEntrysByAccount(this.selectedAccountId) const rawAccountEntries = await this.accountEntryService.getAccountEntrysByAccount(this.selectedAccountId)
this.accountEntries.reverse() rawAccountEntries.reverse()
this.messageService.add(`AccountEntries: ${JSON.stringify(this.accountEntries, undefined, 4)}`) this.messageService.add(`AccountEntries: ${JSON.stringify(rawAccountEntries, undefined, 4)}`)
this.accountEntriesDataSource = new MatTableDataSource<AccountEntry>(this.accountEntries) this.accountEntries = []
for (let f of rawAccountEntries) {
this.accountEntries.push({
rawAccountEntry: f,
accountEntryCategory: this.accountEntryCategoriesMap.get(f.account_entry_category).description,
overheadRelevant: this.accountEntryCategoriesMap.get(f.account_entry_category).overhead_relevant
})
}
this.accountEntriesDataSource = new MatTableDataSource<DN_AccountEntry>(this.accountEntries)
this.saldo = await this.extApiService.getAccountSaldo(this.selectedAccountId) this.saldo = await this.extApiService.getAccountSaldo(this.selectedAccountId)
} catch (err) { } catch (err) {
throw err
this.messageService.add(`Error in getAccountEntries: ${JSON.stringify(err, undefined, 4)}`) this.messageService.add(`Error in getAccountEntries: ${JSON.stringify(err, undefined, 4)}`)
} }
} }
@ -68,7 +93,7 @@ export class AccountComponent implements OnInit {
this.messageService.add(`addAccountEntry: ${ JSON.stringify(this.newAccountEntry, undefined, 4) }`) this.messageService.add(`addAccountEntry: ${ JSON.stringify(this.newAccountEntry, undefined, 4) }`)
this.newAccountEntry = await this.accountEntryService.postAccountEntry(this.newAccountEntry) this.newAccountEntry = await this.accountEntryService.postAccountEntry(this.newAccountEntry)
this.messageService.add(`New accountEntry created: ${this.newAccountEntry.id}`) this.messageService.add(`New accountEntry created: ${this.newAccountEntry.id}`)
this.newAccountEntry = { 'account': this.account.id, 'amount': undefined, 'created_at': '', 'description': '', 'id': 0 } this.newAccountEntry = { 'account': this.account.id, 'amount': undefined, 'created_at': '', 'description': '', 'id': 0, 'account_entry_category': 0 }
this.getAccountEntries() this.getAccountEntries()
} catch (err) { } catch (err) {
this.messageService.add(`Error in addAccountEntry: ${JSON.stringify(err, undefined, 4)}`) this.messageService.add(`Error in addAccountEntry: ${JSON.stringify(err, undefined, 4)}`)
@ -77,14 +102,38 @@ export class AccountComponent implements OnInit {
} }
} }
ngOnInit(): void { async getAccountEntryCategories(): Promise<void> {
this.messageService.add(`AccountComponent.ngOnInit, account: ${this.selectedAccountId}`) try {
this.accountEntryCategories = await this.accountEntryCategoryService.getAccountEntryCategorys()
this.accountEntryCategoriesMap = new Map<number, AccountEntryCategory>()
this.accountEntryCategoriesInverseMap = new Map<string, AccountEntryCategory>()
for (let p of this.accountEntryCategories) {
this.accountEntryCategoriesMap.set(p.id, p)
this.accountEntryCategoriesInverseMap.set(p.description, p)
}
this.messageService.add(`getAccountEntryCategories: ${JSON.stringify(this.accountEntryCategories, undefined, 4)}`)
} catch (err) {
this.messageService.add(`Error in getAccountEntryCategories: ${JSON.stringify(err, undefined, 4)}`)
}
}
private async init(): Promise<void> {
this.messageService.add(`AccountComponent.init, account: ${this.selectedAccountId}`)
this.getAccount() this.getAccount()
await this.getAccountEntryCategories()
if (this.shallBeRentPayment) {
this.messageService.add('shall be rentpayment')
this.newAccountEntry.account_entry_category = this.accountEntryCategoriesInverseMap.get('Mietzahlung').id
}
}
ngOnInit(): void {
this.init()
} }
ngOnChanges(): void { ngOnChanges(): void {
this.messageService.add(`AccountComponent.ngOnChanges, account: ${this.selectedAccountId}`) this.init()
this.getAccount()
} }
} }

View File

@ -24,6 +24,7 @@ import { CommercialPremise } from './data-objects';
import { Tenancy } from './data-objects'; import { Tenancy } from './data-objects';
import { Fee } from './data-objects'; import { Fee } from './data-objects';
import { TenancyFeeMapping } from './data-objects'; import { TenancyFeeMapping } from './data-objects';
import { AccountEntryCategory } from './data-objects';
import { AccountEntry } from './data-objects'; import { AccountEntry } from './data-objects';
import { Note } from './data-objects'; import { Note } from './data-objects';
@ -421,6 +422,31 @@ export class TenancyFeeMappingService {
} }
}
@Injectable({ providedIn: 'root' })
export class AccountEntryCategoryService {
constructor(private messageService: MessageService, private http: HttpClient) { }
async getAccountEntryCategorys(): Promise<AccountEntryCategory[]> {
this.messageService.add(`AccountEntryCategoryService: get data`);
return this.http.get<AccountEntryCategory[]>(`${serviceBaseUrl}/v1/account_entry_categorys`).toPromise()
}
async getAccountEntryCategory(id: number): Promise<AccountEntryCategory> {
this.messageService.add(`AccountEntryCategoryService: get data for ${id}`);
return this.http.get<AccountEntryCategory>(`${serviceBaseUrl}/v1/account_entry_categorys/${id}`).toPromise()
}
async postAccountEntryCategory(item: AccountEntryCategory): Promise<AccountEntryCategory> {
let itemStr: string = JSON.stringify(item, undefined, 4)
this.messageService.add(`AccountEntryCategoryService: post data for ${itemStr}`);
return this.http.post<AccountEntryCategory>(`${serviceBaseUrl}/v1/account_entry_categorys`, item).toPromise()
}
} }
@Injectable({ providedIn: 'root' }) @Injectable({ providedIn: 'root' })
@ -450,6 +476,11 @@ export class AccountEntryService {
return this.http.get<AccountEntry[]>(`${serviceBaseUrl}/v1/account_entrys/account/${id}`).toPromise() return this.http.get<AccountEntry[]>(`${serviceBaseUrl}/v1/account_entrys/account/${id}`).toPromise()
} }
async getAccountEntrysByAccountEntryCategory(id: number): Promise<AccountEntry[]> {
this.messageService.add(`AccountEntryService: get data by AccountEntryCategory ${id}`);
return this.http.get<AccountEntry[]>(`${serviceBaseUrl}/v1/account_entrys/account_entry_category/${id}`).toPromise()
}
} }

View File

@ -173,12 +173,24 @@ export const NULL_TenancyFeeMapping: TenancyFeeMapping = {
,fee: undefined ,fee: undefined
} }
export interface AccountEntryCategory {
id: number
description: string
overhead_relevant: boolean
}
export const NULL_AccountEntryCategory: AccountEntryCategory = {
id: 0
,description: ''
,overhead_relevant: false
}
export interface AccountEntry { export interface AccountEntry {
id: number id: number
description: string description: string
account: number account: number
created_at: string created_at: string
amount: number amount: number
account_entry_category: number
} }
export const NULL_AccountEntry: AccountEntry = { export const NULL_AccountEntry: AccountEntry = {
id: 0 id: 0
@ -186,6 +198,7 @@ export const NULL_AccountEntry: AccountEntry = {
,account: undefined ,account: undefined
,created_at: '' ,created_at: ''
,amount: undefined ,amount: undefined
,account_entry_category: undefined
} }
export interface Note { export interface Note {

View File

@ -17,6 +17,8 @@ export const NULL_$JsNameConverter($table.name): $JsNameConverter($table.name) =
'' ''
#else if $column.jstype == "number" #else if $column.jstype == "number"
undefined undefined
#else if $column.jstype == "boolean"
false
#end if #end if
#end for #end for
} }

View File

@ -25,11 +25,11 @@
</div><div> </div><div>
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Fläche</mat-label> <mat-label>Fläche</mat-label>
<input matInput name="area" [(ngModel)]="flat.area"/> <input type="number" matInput name="area" [(ngModel)]="flat.area"/>
</mat-form-field> </mat-form-field>
<mat-form-field appearance="outline"> <mat-form-field appearance="outline">
<mat-label>Wohnungsnummer</mat-label> <mat-label>Wohnungsnummer</mat-label>
<input matInput name="flat_no" [(ngModel)]="flat.flat_no"/> <input type="number" matInput name="flat_no" [(ngModel)]="flat.flat_no"/>
</mat-form-field> </mat-form-field>
</div> </div>
<button #submitButton type="submit" mat-raised-button color="primary">Speichern</button> <button #submitButton type="submit" mat-raised-button color="primary">Speichern</button>

View File

@ -4,7 +4,7 @@ import { MatSelect } from '@angular/material/select';
import { MatTableDataSource } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { FlatService, OverheadAdvanceFlatMappingService, OverheadAdvanceService, PremiseService } from '../data-object-service'; import { FlatService, OverheadAdvanceFlatMappingService, OverheadAdvanceService, PremiseService } from '../data-object-service';
import { Flat, OverheadAdvance, OverheadAdvanceFlatMapping, Premise } from '../data-objects'; import { Flat, NULL_Flat, NULL_Premise, OverheadAdvance, OverheadAdvanceFlatMapping, Premise } from '../data-objects';
import { ExtApiService } from '../ext-data-object-service'; import { ExtApiService } from '../ext-data-object-service';
import { MessageService } from '../message.service'; import { MessageService } from '../message.service';
@ -15,21 +15,9 @@ import { MessageService } from '../message.service';
}) })
export class FlatDetailsComponent implements OnInit { export class FlatDetailsComponent implements OnInit {
flat: Flat = { flat: Flat = NULL_Flat
id: 0,
description: '',
premise: 0,
area: 0.0,
flat_no: 0
}
premise: Premise = { premise: Premise = NULL_Premise
id: 0,
description: '',
street: '',
zip: '',
city: ''
}
premises: Premise[] premises: Premise[]
mappedOverheadAdvances: OverheadAdvance[] mappedOverheadAdvances: OverheadAdvance[]

View File

@ -1,3 +0,0 @@
table {
width: 75%;
}

View File

@ -20,7 +20,7 @@
</ng-container> </ng-container>
<ng-container matColumnDef="area"> <ng-container matColumnDef="area">
<th mat-header-cell *matHeaderCellDef>Wohnfläche</th> <th mat-header-cell *matHeaderCellDef>Wohnfläche</th>
<td mat-cell *matCellDef="let element">{{element.flat.area}}</td> <td mat-cell *matCellDef="let element">{{element.flat.area | number:'1.2-2'}}</td>
</ng-container> </ng-container>
<ng-container matColumnDef="flat_no"> <ng-container matColumnDef="flat_no">
<th mat-header-cell *matHeaderCellDef>Wohnungsnummer</th> <th mat-header-cell *matHeaderCellDef>Wohnungsnummer</th>

View File

@ -1,3 +0,0 @@
table {
width: 75%;
}

View File

@ -1,8 +0,0 @@
table {
width: 75%;
}
.spacer {
flex: 1 1 auto;
}

View File

@ -1,8 +0,0 @@
table {
width: 75%;
}
.spacer {
flex: 1 1 auto;
}

View File

@ -16,10 +16,6 @@
z-index: 1; z-index: 1;
} }
.spacer {
flex: 1 1 auto;
}
.gittagversion { .gittagversion {
font-size: x-small; font-size: x-small;
margin-right: 5em; margin-right: 5em;

View File

@ -1,11 +1,3 @@
table {
width: 75%;
}
.spacer {
flex: 1 1 auto;
}
#addEntryfield { #addEntryfield {
margin-right: 15px; margin-right: 15px;
} }

View File

@ -1,8 +0,0 @@
table {
width: 75%;
}
.spacer {
flex: 1 1 auto;
}

View File

@ -1,11 +1,3 @@
table {
width: 75%;
}
.spacer {
flex: 1 1 auto;
}
#setenddatefield { #setenddatefield {
margin-right: 15px; margin-right: 15px;
} }

View File

@ -208,6 +208,6 @@
</mat-card-content> </mat-card-content>
</mat-card> </mat-card>
<app-account [selectedAccountId]="tenant.account"></app-account> <app-account [selectedAccountId]="tenant.account" [shallBeRentPayment]="true"></app-account>
</section> </section>

View File

@ -3,7 +3,16 @@
html, body { height: 100%; } html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
table {
width: 75%;
border-spacing: 20px;
}
.spacer {
flex: 1 1 auto;
}
.defaultCard { .defaultCard {
margin: 5px; margin: 5px;
} }