2022-01-06 23:16:34 +01:00
|
|
|
from db import dbGetMany, dbGetOne
|
2021-12-19 14:17:44 +01:00
|
|
|
import datetime
|
|
|
|
from loguru import logger
|
2022-01-06 23:16:34 +01:00
|
|
|
from decimal import *
|
2022-01-29 13:42:58 +01:00
|
|
|
from utils import getParam
|
|
|
|
from Cheetah.Template import Template
|
2022-04-25 14:44:56 +02:00
|
|
|
import xlsxwriter
|
|
|
|
from dateutil.relativedelta import relativedelta
|
2022-01-29 14:40:14 +01:00
|
|
|
|
|
|
|
EPSILON = Decimal('0.000000001')
|
|
|
|
|
2021-12-19 14:17:44 +01:00
|
|
|
def perform(dbh, params):
|
2022-01-29 13:42:58 +01:00
|
|
|
year = getParam(params, 'year', datetime.datetime.today().year)
|
2021-12-19 14:17:44 +01:00
|
|
|
startDate = datetime.datetime(year, 1, 1, 0, 0, 0)
|
|
|
|
endDate = datetime.datetime(year, 12, 31, 23, 59, 59)
|
|
|
|
premises = (1, 2)
|
|
|
|
|
2022-01-29 14:40:14 +01:00
|
|
|
houses = {}
|
|
|
|
for premise in premises:
|
|
|
|
# get overhead sums by object, category and timespan
|
|
|
|
overheadItems = dbGetMany(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
2022-04-01 12:04:33 +02:00
|
|
|
select (coalesce(sum(ae.amount), 0::numeric(10,2)) * -1) as sum,
|
2022-01-29 14:40:14 +01:00
|
|
|
aec.description as category,
|
|
|
|
aec.considerminusarea as considerminusarea
|
|
|
|
from account_t a,
|
|
|
|
premise_t p,
|
|
|
|
account_entry_t ae,
|
|
|
|
account_entry_category_t aec
|
|
|
|
where p.account = a.id and
|
|
|
|
ae.account = a.id and
|
|
|
|
aec.overhead_relevant = 't' and
|
|
|
|
ae.account_entry_category = aec.id and
|
|
|
|
ae.fiscal_year = %(year)s and
|
|
|
|
p.id = %(premise)s
|
|
|
|
group by category, considerminusarea
|
|
|
|
union
|
|
|
|
select 0 as sum,
|
|
|
|
aec.description as category,
|
|
|
|
aec.considerminusarea as considerminusarea
|
|
|
|
from account_t a,
|
|
|
|
premise_t p,
|
|
|
|
account_entry_t ae,
|
|
|
|
account_entry_category_t aec
|
|
|
|
where p.account = a.id and
|
|
|
|
ae.account = a.id and
|
|
|
|
aec.overhead_relevant = 't' and
|
2022-04-25 12:22:39 +02:00
|
|
|
aec.id not in (select distinct account_entry_category from account_entry_t where fiscal_year = %(year)s and account = p.account) and
|
2022-01-29 14:40:14 +01:00
|
|
|
ae.fiscal_year = %(year)s and
|
|
|
|
p.id = %(premise)s
|
|
|
|
group by category, considerminusarea
|
|
|
|
union
|
|
|
|
select 120 as sum,
|
2022-04-01 12:04:33 +02:00
|
|
|
'16. Waschmaschine' as category,
|
2022-01-29 14:40:14 +01:00
|
|
|
false as considerminusarea
|
|
|
|
from premise_t
|
|
|
|
where id = %(premise)s
|
|
|
|
order by category
|
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"year": year,
|
|
|
|
"premise": premise
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
# get areas and factors
|
|
|
|
totalArea = {}
|
|
|
|
flatArea = dbGetOne(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
|
|
|
select
|
|
|
|
sum(f.area) as flat_area
|
|
|
|
from
|
|
|
|
premise_t p,
|
|
|
|
flat_t f
|
|
|
|
where
|
|
|
|
f.premise = p.id and
|
|
|
|
p.id = %(premise)s
|
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"premise": premise
|
|
|
|
}
|
2022-01-24 18:06:10 +01:00
|
|
|
}
|
2022-01-29 14:40:14 +01:00
|
|
|
)
|
|
|
|
totalArea['flat_area'] = flatArea['flat_area']
|
|
|
|
|
|
|
|
commercialArea = dbGetOne(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
|
|
|
select
|
|
|
|
coalesce(sum(c.area), 0) as commercial_area
|
|
|
|
from
|
|
|
|
premise_t p full outer join commercial_premise_t c on c.premise = p.id
|
|
|
|
where
|
|
|
|
p.id = %(premise)s
|
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"premise": premise
|
|
|
|
}
|
2022-01-24 18:06:10 +01:00
|
|
|
}
|
2022-01-29 14:40:14 +01:00
|
|
|
)
|
|
|
|
totalArea['commercial_area'] = commercialArea['commercial_area']
|
|
|
|
|
|
|
|
minusAreaAndDetails = dbGetOne(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
|
|
|
select
|
|
|
|
p.minus_area as minus_area,
|
|
|
|
p.id as house_id,
|
|
|
|
p.description as house
|
|
|
|
from
|
|
|
|
premise_t p
|
|
|
|
where
|
|
|
|
p.id = %(premise)s
|
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"premise": premise
|
|
|
|
}
|
2022-01-24 18:06:10 +01:00
|
|
|
}
|
2022-01-29 14:40:14 +01:00
|
|
|
)
|
|
|
|
totalArea['minus_area'] = minusAreaAndDetails['minus_area']
|
|
|
|
details = { 'id': minusAreaAndDetails['house_id'], 'description': minusAreaAndDetails['house'] }
|
|
|
|
|
|
|
|
totalArea['other_area'] = totalArea['commercial_area'] + totalArea['minus_area']
|
|
|
|
totalArea['total_area'] = totalArea['flat_area'] + totalArea['other_area']
|
|
|
|
totalArea['flat_factor'] = totalArea['flat_area'] / totalArea['total_area']
|
|
|
|
totalArea['other_factor'] = totalArea['other_area'] / totalArea['total_area']
|
|
|
|
totalArea['factor_check'] = totalArea['flat_factor'] + totalArea['other_factor']
|
|
|
|
|
|
|
|
totalSum = Decimal('0')
|
|
|
|
flatSum = Decimal('0')
|
|
|
|
otherSum = Decimal('0')
|
|
|
|
for overheadItem in overheadItems:
|
|
|
|
totalSum += overheadItem['sum']
|
|
|
|
overheadItem['flat_part'] = overheadItem['sum'] * totalArea['flat_factor'] if overheadItem['considerminusarea'] else overheadItem['sum']
|
|
|
|
flatSum += overheadItem['flat_part']
|
|
|
|
overheadItem['other_part'] = overheadItem['sum'] * totalArea['other_factor'] if overheadItem['considerminusarea'] else Decimal('0')
|
|
|
|
otherSum += overheadItem['other_part']
|
|
|
|
|
|
|
|
verifyDifference = totalSum - flatSum - otherSum
|
|
|
|
logger.debug(f"{totalSum=}, {verifyDifference=}")
|
|
|
|
if abs(verifyDifference) > EPSILON:
|
|
|
|
raise Exception(f"Verify Difference is too large: {premise=}, {verifyDifference=}")
|
|
|
|
|
|
|
|
umlageAusfallWagnis = flatSum * Decimal('0.02')
|
|
|
|
flatSum2 = flatSum + umlageAusfallWagnis
|
|
|
|
|
|
|
|
partByMonthArea = flatSum2 / Decimal('12') / totalArea['flat_area']
|
|
|
|
|
|
|
|
houses[details['id']] = {
|
|
|
|
'details': details,
|
|
|
|
'areas': totalArea,
|
|
|
|
'overhead_items': overheadItems,
|
|
|
|
'flat_sum': flatSum,
|
|
|
|
'flat_sum_2': flatSum2,
|
|
|
|
'other_sum': otherSum,
|
|
|
|
'total_sum': totalSum,
|
|
|
|
'umlage_ausfall_wagnis': umlageAusfallWagnis,
|
|
|
|
'part_by_montharea': partByMonthArea,
|
|
|
|
'year': year }
|
|
|
|
|
|
|
|
|
|
|
|
logger.info(f"{houses=}")
|
|
|
|
|
|
|
|
|
|
|
|
printOverviews = getParam(params, 'printOverviews', True)
|
|
|
|
if printOverviews:
|
|
|
|
overviewTemplate = getParam(params, 'overviewTemplate', 'betriebskostenuebersicht.tmpl')
|
|
|
|
overviewPrefix = getParam(params, 'overviewPrefix', 'overview')
|
|
|
|
overviewSuffix = getParam(params, 'overviewSuffix', 'tex')
|
|
|
|
|
|
|
|
for house in houses.values():
|
|
|
|
logger.debug(f"Processing item: {house}")
|
2022-04-01 12:04:33 +02:00
|
|
|
outputFile = f"./output/{overviewPrefix}-{house['details']['id']}.{overviewSuffix}"
|
2022-01-29 14:40:14 +01:00
|
|
|
tmpl = Template(file=overviewTemplate, searchList=[ house ])
|
|
|
|
logger.debug(tmpl)
|
|
|
|
with open(outputFile, 'w') as f:
|
|
|
|
f.write(str(tmpl))
|
2022-01-24 18:06:10 +01:00
|
|
|
|
2022-01-29 15:43:50 +01:00
|
|
|
|
2022-01-06 23:16:34 +01:00
|
|
|
|
|
|
|
|
2022-04-25 14:44:56 +02:00
|
|
|
|
2022-01-06 23:16:34 +01:00
|
|
|
# get flat tenants by object and timespan with paid overhead and due overhead
|
|
|
|
tenants = dbGetMany(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
|
|
|
select t.id as tenant_id,
|
2022-01-29 13:42:58 +01:00
|
|
|
t.salutation as tenant_salutation,
|
2022-01-06 23:16:34 +01:00
|
|
|
t.firstname as tenant_firstname,
|
|
|
|
t.lastname as tenant_lastname,
|
2022-01-29 13:42:58 +01:00
|
|
|
t.address1 as tenant_address1,
|
|
|
|
t.address2 as tenant_address2,
|
|
|
|
t.address3 as tenant_address3,
|
|
|
|
t.zip as tenant_zip,
|
|
|
|
t.city as tenant_city,
|
2022-01-06 23:16:34 +01:00
|
|
|
f.id as flat_id,
|
|
|
|
f.description as flat,
|
2022-01-29 13:42:58 +01:00
|
|
|
f.area as flat_area,
|
2022-01-06 23:16:34 +01:00
|
|
|
p.id as house_id,
|
|
|
|
p.description as house,
|
|
|
|
ty.startdate as startdate,
|
|
|
|
ty.enddate as enddate,
|
2022-04-25 14:44:56 +02:00
|
|
|
t.account as tenant_account,
|
|
|
|
fe.amount as fee,
|
|
|
|
fe.fee_type as fee_type
|
2022-01-06 23:16:34 +01:00
|
|
|
from tenant_t t,
|
|
|
|
premise_t p,
|
|
|
|
flat_t f,
|
2022-04-25 14:44:56 +02:00
|
|
|
tenancy_t ty,
|
|
|
|
tenancy_fee_mapping_t tyfm,
|
|
|
|
fee_t fe
|
2022-01-06 23:16:34 +01:00
|
|
|
where ty.tenant = t.id and
|
|
|
|
ty.flat = f.id and
|
|
|
|
ty.startdate <= %(startDate)s and
|
|
|
|
(ty.enddate >= %(endDate)s or ty.enddate is null) and
|
|
|
|
f.premise = p.id and
|
2022-04-25 14:44:56 +02:00
|
|
|
p.id in %(premises)s and
|
|
|
|
tyfm.tenancy = ty.id and
|
|
|
|
tyfm.fee = fe.id
|
2022-01-06 23:16:34 +01:00
|
|
|
order by house_id, tenant_id
|
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"startDate": startDate,
|
|
|
|
"endDate": endDate,
|
|
|
|
"premises": premises
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2022-01-29 13:42:58 +01:00
|
|
|
letters = []
|
2022-01-06 23:16:34 +01:00
|
|
|
for tenant in tenants:
|
2022-01-29 13:42:58 +01:00
|
|
|
letter = {}
|
2022-01-06 23:16:34 +01:00
|
|
|
|
|
|
|
paidTotal = dbGetOne(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
2022-04-25 14:44:56 +02:00
|
|
|
SELECT sum(amount) AS sum
|
2022-01-06 23:16:34 +01:00
|
|
|
FROM account_entry_t
|
|
|
|
WHERE account = %(account)s AND
|
|
|
|
account_entry_category = 2 AND
|
2022-01-24 18:06:10 +01:00
|
|
|
fiscal_year = %(year)s
|
2022-01-06 23:16:34 +01:00
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"account": tenant['tenant_account'],
|
2022-01-24 18:06:10 +01:00
|
|
|
"year": year
|
2022-01-06 23:16:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
2022-01-29 13:42:58 +01:00
|
|
|
tenant['paid_total'] = paidTotal['sum']
|
|
|
|
|
2022-01-06 23:16:34 +01:00
|
|
|
receivableFee = dbGetOne(
|
|
|
|
dbh,
|
|
|
|
{
|
|
|
|
"statement":
|
|
|
|
"""
|
2022-04-25 14:44:56 +02:00
|
|
|
SELECT sum(amount) * -1 AS sum
|
2022-01-06 23:16:34 +01:00
|
|
|
FROM account_entry_t
|
|
|
|
WHERE account = %(account)s AND
|
|
|
|
account_entry_category = 3 AND
|
2022-01-24 18:06:10 +01:00
|
|
|
fiscal_year = %(year)s
|
2022-01-06 23:16:34 +01:00
|
|
|
""",
|
|
|
|
"params": {
|
|
|
|
"account": tenant['tenant_account'],
|
2022-01-24 18:06:10 +01:00
|
|
|
"year": year
|
2022-01-06 23:16:34 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)
|
2022-01-29 13:42:58 +01:00
|
|
|
tenant['receivable_fee'] = receivableFee['sum']
|
2022-04-25 14:44:56 +02:00
|
|
|
|
|
|
|
delta = relativedelta((tenant['enddate'] or datetime.date(year, 12, 31)), (tenant['startdate'] if (tenant['startdate'].year == year) else datetime.date(year, 1, 1)))
|
|
|
|
tenant['rent_time'] = delta.months if delta.days == 0 else delta.months + 1
|
2022-01-06 23:16:34 +01:00
|
|
|
|
2022-01-29 13:42:58 +01:00
|
|
|
tenant['paid_overhead'] = paidTotal['sum'] - receivableFee['sum']
|
|
|
|
|
|
|
|
letter['tenant'] = tenant
|
|
|
|
letter['year'] = year
|
2022-01-29 19:37:09 +01:00
|
|
|
letter['flat_area'] = houses[tenant['house_id']]['areas']['flat_area']
|
2022-01-29 15:43:50 +01:00
|
|
|
letter['receivable_overhead'] = tenant['flat_area'] * houses[tenant['house_id']]['part_by_montharea'] * tenant['rent_time']
|
|
|
|
letter['unbalanced_overhead'] = tenant['paid_overhead'] - letter['receivable_overhead']
|
|
|
|
letter['unbalanced_overhead_unsigned'] = abs(letter['unbalanced_overhead'])
|
2022-01-29 18:35:58 +01:00
|
|
|
letter['total_overhead'] = houses[tenant['house_id']]['flat_sum_2']
|
2022-01-29 13:42:58 +01:00
|
|
|
|
|
|
|
letters.append(letter)
|
|
|
|
|
|
|
|
logger.info(f"{letter=}")
|
|
|
|
|
|
|
|
|
2022-01-29 15:43:50 +01:00
|
|
|
printLetters = getParam(params, 'printLetters', True)
|
2022-01-29 13:42:58 +01:00
|
|
|
if printLetters:
|
|
|
|
letterTemplate = getParam(params, 'letterTemplate', 'jahresabrechnung.tmpl')
|
|
|
|
letterPrefix = getParam(params, 'letterPrefix', 'letter')
|
|
|
|
letterSuffix = getParam(params, 'letterSuffix', 'tex')
|
2022-01-06 23:16:34 +01:00
|
|
|
|
2022-01-29 13:42:58 +01:00
|
|
|
for letter in letters:
|
|
|
|
logger.debug(f"Processing item: {letter}")
|
2022-04-01 10:59:52 +02:00
|
|
|
outputFile = f"./output/{letterPrefix}-{letter['tenant']['tenant_id']}.{letterSuffix}"
|
2022-01-29 13:42:58 +01:00
|
|
|
tmpl = Template(file=letterTemplate, searchList=[ letter ])
|
|
|
|
logger.debug(tmpl)
|
|
|
|
with open(outputFile, 'w') as f:
|
|
|
|
f.write(str(tmpl))
|
2022-01-06 23:16:34 +01:00
|
|
|
|
2022-04-25 14:44:56 +02:00
|
|
|
if printOverviews:
|
|
|
|
tenantsOverviewPrefix = getParam(params, 'tenantsOverviewPrefix', 'tenantsOverview')
|
|
|
|
tenantsOverviewSuffix = getParam(params, 'tenantsOverviewSuffix', 'xlsx')
|
|
|
|
|
|
|
|
logger.debug(f"Processing letters: {letters}")
|
|
|
|
outputFile = f"./output/{tenantsOverviewPrefix}-{year}.{tenantsOverviewSuffix}"
|
|
|
|
|
|
|
|
workbook = xlsxwriter.Workbook(outputFile)
|
|
|
|
worksheet = workbook.add_worksheet()
|
|
|
|
|
|
|
|
worksheet.write(0, 0, 'id')
|
|
|
|
worksheet.write(0, 1, 'lastname')
|
|
|
|
worksheet.write(0, 2, 'firstname')
|
|
|
|
worksheet.write(0, 3, 'house')
|
|
|
|
worksheet.write(0, 4, 'overhead_part_by_montharea')
|
|
|
|
worksheet.write(0, 5, 'flat')
|
|
|
|
worksheet.write(0, 6, 'flat_area')
|
|
|
|
worksheet.write(0, 7, 'fee')
|
|
|
|
worksheet.write(0, 8, 'rent_time')
|
|
|
|
worksheet.write(0, 9, 'paid_total')
|
|
|
|
worksheet.write(0, 10, 'receivable_fee')
|
|
|
|
worksheet.write(0, 11, 'paid_overhead')
|
|
|
|
worksheet.write(0, 12, 'receivable_overhead')
|
|
|
|
worksheet.write(0, 13, 'unbalanced_overhead')
|
|
|
|
|
|
|
|
row = 1
|
|
|
|
|
|
|
|
for entry in letters:
|
|
|
|
worksheet.write(row, 0, entry['tenant']['tenant_id'])
|
|
|
|
worksheet.write(row, 1, entry['tenant']['tenant_lastname'])
|
|
|
|
worksheet.write(row, 2, entry['tenant']['tenant_firstname'])
|
|
|
|
worksheet.write(row, 3, entry['tenant']['house'])
|
|
|
|
worksheet.write(row, 4, houses[entry['tenant']['house_id']]['part_by_montharea'])
|
|
|
|
worksheet.write(row, 5, entry['tenant']['flat'])
|
|
|
|
worksheet.write(row, 6, entry['tenant']['flat_area'])
|
|
|
|
worksheet.write(row, 7, entry['tenant']['fee'])
|
|
|
|
worksheet.write(row, 8, entry['tenant']['rent_time'])
|
|
|
|
worksheet.write(row, 9, entry['tenant']['paid_total'])
|
|
|
|
worksheet.write(row, 10, entry['tenant']['receivable_fee'])
|
|
|
|
worksheet.write(row, 11, entry['tenant']['paid_overhead'])
|
|
|
|
worksheet.write(row, 12, entry['receivable_overhead'])
|
|
|
|
worksheet.write(row, 13, entry['unbalanced_overhead'])
|
|
|
|
row += 1
|
|
|
|
|
|
|
|
workbook.close()
|
2021-12-19 14:17:44 +01:00
|
|
|
|