Files
ksef_app/app/settings/routes.py
Mateusz Gruszczyński 35571df778 push
2026-03-13 11:03:13 +01:00

263 lines
14 KiB
Python

import base64
from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import current_user, login_required
from app.extensions import db
from app.forms.settings import (
AppearanceSettingsForm,
CompanyForm,
KSeFSettingsForm,
MailSettingsForm,
NfzModuleSettingsForm,
NotificationSettingsForm,
UserForm,
)
from app.models.company import Company
from app.models.setting import AppSetting
from app.models.user import User
from app.services.company_service import CompanyService
from app.services.ksef_service import RequestsKSeFAdapter
from app.services.mail_service import MailService
from app.services.notification_service import NotificationService
from app.services.settings_service import SettingsService
def _can_manage_company_settings(user, company_id):
if not company_id or not getattr(user, 'is_authenticated', False):
return False
if getattr(user, 'role', '') not in {'admin', 'operator'}:
return False
return user.company_access_level(company_id) == 'full'
bp = Blueprint('settings', __name__, url_prefix='/settings')
KSEF_ENV_TO_URL = {
'prod': RequestsKSeFAdapter.ENVIRONMENT_URLS['prod'],
'test': RequestsKSeFAdapter.ENVIRONMENT_URLS['test'],
}
def _resolve_ksef_environment(company_id=None, user_id=None):
env = (SettingsService.get_effective('ksef.environment', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user') or '').strip().lower()
if env in KSEF_ENV_TO_URL:
return env
base_url = (SettingsService.get_effective('ksef.base_url', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user') or '').strip().lower()
if 'api-test.ksef.mf.gov.pl' in base_url:
return 'test'
return 'prod'
@bp.route('/', methods=['GET', 'POST'])
@login_required
def index():
company = CompanyService.get_current_company()
company_id = company.id if company else None
user_id = current_user.id
company_read_only = AppSetting.get(f'company.{company_id}.app.read_only_mode', 'false') == 'true' if company_id else False
effective_read_only = SettingsService.read_only_enabled(company_id=company_id) if company_id else False
global_read_only = AppSetting.get('app.read_only_mode', 'false') == 'true'
user_read_only = bool(company_id and current_user.is_company_readonly(company_id))
can_manage_company_settings = _can_manage_company_settings(current_user, company_id)
ksef_mode = SettingsService.get_preference('ksef', default='user', user_id=user_id)
mail_mode = SettingsService.get_preference('mail', default='global', user_id=user_id)
notify_mode = SettingsService.get_preference('notify', default='global', user_id=user_id)
nfz_mode = SettingsService.get_preference('modules', default='global', user_id=user_id)
ksef_form = KSeFSettingsForm(
prefix='ksef',
source_mode=ksef_mode,
environment=_resolve_ksef_environment(company_id=company_id, user_id=user_id),
auth_mode=SettingsService.get_effective('ksef.auth_mode', 'token', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'),
client_id=SettingsService.get_effective('ksef.client_id', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'),
)
mail_form = MailSettingsForm(
prefix='mail',
source_mode=mail_mode,
server=SettingsService.get_effective('mail.server', '', company_id=company_id, user_id=user_id),
port=SettingsService.get_effective('mail.port', '587', company_id=company_id, user_id=user_id),
username=SettingsService.get_effective('mail.username', '', company_id=company_id, user_id=user_id),
sender=SettingsService.get_effective('mail.sender', '', company_id=company_id, user_id=user_id),
security_mode=(SettingsService.get_effective('mail.security_mode', '', company_id=company_id, user_id=user_id) or ('tls' if SettingsService.get_effective('mail.tls', 'true', company_id=company_id, user_id=user_id) == 'true' else 'none')),
)
notify_form = NotificationSettingsForm(
prefix='notify',
source_mode=notify_mode,
pushover_user_key=SettingsService.get_effective('notify.pushover_user_key', '', company_id=company_id, user_id=user_id),
min_amount=SettingsService.get_effective('notify.min_amount', '0', company_id=company_id, user_id=user_id),
quiet_hours=SettingsService.get_effective('notify.quiet_hours', '', company_id=company_id, user_id=user_id),
enabled=SettingsService.get_effective('notify.enabled', 'false', company_id=company_id, user_id=user_id) == 'true',
)
appearance_form = AppearanceSettingsForm(prefix='appearance', theme_preference=current_user.theme_preference or 'light')
nfz_form = NfzModuleSettingsForm(prefix='nfz', source_mode=nfz_mode, enabled=SettingsService.get_effective('modules.nfz_enabled', 'false', company_id=company_id, user_id=user_id) == 'true')
company_form = CompanyForm(
prefix='company',
name=company.name if company else '',
tax_id=company.tax_id if company else '',
sync_enabled=company.sync_enabled if company else False,
sync_interval_minutes=company.sync_interval_minutes if company else 60,
bank_account=company.bank_account if company else '',
read_only_mode=company_read_only,
)
user_form = UserForm(prefix='user')
user_form.company_id.choices = [(0, '— wybierz firmę —')] + [(c.id, c.name) for c in Company.query.order_by(Company.name).all()]
if ksef_form.submit.data and ksef_form.validate_on_submit():
SettingsService.set_preference('ksef', ksef_form.source_mode.data, user_id=user_id)
if ksef_form.source_mode.data == 'user':
submitted_base_url = (request.form.get('ksef-base_url') or '').strip().lower()
environment = (ksef_form.environment.data or ('test' if 'api-test.ksef.mf.gov.pl' in submitted_base_url else 'prod')).lower()
if environment not in KSEF_ENV_TO_URL:
environment = 'prod'
effective_base_url = submitted_base_url or KSEF_ENV_TO_URL[environment]
data = {
'ksef.environment': environment,
'ksef.base_url': effective_base_url,
'ksef.auth_mode': ksef_form.auth_mode.data,
'ksef.client_id': (ksef_form.client_id.data or '').strip(),
}
if ksef_form.token.data:
data['ksef.token'] = (ksef_form.token.data.strip(), True)
if ksef_form.certificate_file.data:
uploaded = ksef_form.certificate_file.data
content = uploaded.read()
if content:
data['ksef.certificate_name'] = (uploaded.filename or '').strip()
data['ksef.certificate_data'] = (base64.b64encode(content).decode('ascii'), True)
SettingsService.set_many_user(data, user_id=user_id)
if company_id:
SettingsService.set_many(data, company_id=company_id)
flash('Zapisano indywidualne ustawienia KSeF.', 'success')
else:
flash('Włączono współdzielony profil KSeF dla aktywnej firmy.', 'success')
return redirect(url_for('settings.index'))
if mail_form.submit.data and mail_form.validate_on_submit():
SettingsService.set_preference('mail', mail_form.source_mode.data, user_id=user_id)
if mail_form.source_mode.data == 'user':
SettingsService.set_many_user({
'mail.server': mail_form.server.data or '',
'mail.port': mail_form.port.data or '587',
'mail.username': mail_form.username.data or '',
'mail.password': (mail_form.password.data or '', True),
'mail.sender': mail_form.sender.data or '',
'mail.security_mode': mail_form.security_mode.data or 'tls',
'mail.tls': str((mail_form.security_mode.data or 'tls') == 'tls').lower(),
}, user_id=user_id)
flash('Zapisano indywidualne ustawienia SMTP.', 'success')
else:
flash('Włączono globalne ustawienia SMTP.', 'success')
return redirect(url_for('settings.index'))
if mail_form.test_submit.data and mail_form.validate_on_submit():
SettingsService.set_preference('mail', mail_form.source_mode.data, user_id=user_id)
recipient = mail_form.test_recipient.data or current_user.email
result = MailService(company_id=company_id).send_test_mail(recipient)
flash(f'Test maila: {result["status"]}.', 'info')
return redirect(url_for('settings.index'))
if notify_form.submit.data and notify_form.validate_on_submit():
SettingsService.set_preference('notify', notify_form.source_mode.data, user_id=user_id)
if notify_form.source_mode.data == 'user':
SettingsService.set_many_user({
'notify.pushover_user_key': notify_form.pushover_user_key.data or '',
'notify.pushover_api_token': (notify_form.pushover_api_token.data or '', True),
'notify.min_amount': notify_form.min_amount.data or '0',
'notify.quiet_hours': notify_form.quiet_hours.data or '',
'notify.enabled': str(bool(notify_form.enabled.data)).lower(),
}, user_id=user_id)
flash('Zapisano indywidualne powiadomienia.', 'success')
else:
flash('Włączono globalne powiadomienia.', 'success')
return redirect(url_for('settings.index'))
if notify_form.test_submit.data and notify_form.validate_on_submit():
SettingsService.set_preference('notify', notify_form.source_mode.data, user_id=user_id)
log = NotificationService(company_id=company_id).send_test_pushover()
flash(f'Test Pushover: {log.status}.', 'info')
return redirect(url_for('settings.index'))
if appearance_form.submit.data and appearance_form.validate_on_submit():
current_user.theme_preference = appearance_form.theme_preference.data
db.session.commit()
flash('Zapisano ustawienia wyglądu.', 'success')
return redirect(url_for('settings.index'))
if nfz_form.submit.data and nfz_form.validate_on_submit():
SettingsService.set_preference('modules', nfz_form.source_mode.data, user_id=user_id)
if nfz_form.source_mode.data == 'user':
SettingsService.set_many_user({'modules.nfz_enabled': str(bool(nfz_form.enabled.data)).lower()}, user_id=user_id)
flash('Zapisano indywidualne ustawienia modułu NFZ.', 'success')
else:
flash('Włączono globalne ustawienia modułu NFZ.', 'success')
return redirect(url_for('settings.index'))
if can_manage_company_settings and company_form.submit.data and company_form.validate_on_submit():
target = company or Company()
target.name = company_form.name.data
target.tax_id = company_form.tax_id.data or ''
target.sync_enabled = bool(company_form.sync_enabled.data)
target.sync_interval_minutes = company_form.sync_interval_minutes.data or 60
target.bank_account = (company_form.bank_account.data or '').strip()
db.session.add(target)
db.session.flush()
AppSetting.set(f'company.{target.id}.app.read_only_mode', 'true' if company_form.read_only_mode.data else 'false')
db.session.commit()
if not company:
CompanyService.assign_user(current_user, target, 'full', switch_after=True)
else:
CompanyService.switch_company(target.id)
flash('Zapisano firmę i harmonogram.', 'success')
return redirect(url_for('settings.index'))
users = User.query.order_by(User.name).all() if current_user.role == 'admin' else []
companies = Company.query.order_by(Company.name).all() if current_user.role == 'admin' else []
read_only_reasons = []
if global_read_only:
read_only_reasons.append('globalny tryb tylko odczytu')
if company_read_only:
read_only_reasons.append('blokada ustawiona dla tej firmy')
if user_read_only:
read_only_reasons.append('Twoje uprawnienia do firmy są tylko do odczytu')
certificate_name = SettingsService.get_effective('ksef.certificate_name', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user')
token_configured = bool(SettingsService.get_effective_secret('ksef.token', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'))
certificate_configured = bool(SettingsService.get_effective_secret('ksef.certificate_data', '', company_id=company_id, user_id=user_id, scope_name='ksef', user_default='user'))
company_token_configured = bool(SettingsService.get_secret('ksef.token', '', company_id=company_id)) if company_id else False
company_certificate_name = SettingsService.get('ksef.certificate_name', '', company_id=company_id) if company_id else ''
company_certificate_configured = bool(SettingsService.get_secret('ksef.certificate_data', '', company_id=company_id)) if company_id else False
ksef_environment = _resolve_ksef_environment(company_id=company_id, user_id=user_id)
return render_template(
'settings/index.html',
company=company,
ksef_form=ksef_form,
mail_form=mail_form,
notify_form=notify_form,
appearance_form=appearance_form,
nfz_form=nfz_form,
nfz_enabled=SettingsService.get_effective('modules.nfz_enabled', 'false', company_id=company_id, user_id=user_id) == 'true',
company_form=company_form,
user_form=user_form,
users=users,
companies=companies,
certificate_name=certificate_name,
token_configured=token_configured,
certificate_configured=certificate_configured,
company_certificate_name=company_certificate_name,
company_token_configured=company_token_configured,
company_certificate_configured=company_certificate_configured,
company_read_only=company_read_only,
effective_read_only=effective_read_only,
global_read_only=global_read_only,
user_read_only=user_read_only,
can_manage_company_settings=can_manage_company_settings,
read_only_reasons=read_only_reasons,
ksef_environment=ksef_environment,
ksef_mode=ksef_mode,
mail_mode=mail_mode,
notify_mode=notify_mode,
nfz_mode=nfz_mode,
)