263 lines
14 KiB
Python
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,
|
|
)
|