push
This commit is contained in:
104
app/services/notification_service.py
Normal file
104
app/services/notification_service.py
Normal file
@@ -0,0 +1,104 @@
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
import requests
|
||||
|
||||
from app.extensions import db
|
||||
from app.models.company import UserCompanyAccess
|
||||
from app.models.invoice import NotificationLog
|
||||
from app.models.user import User
|
||||
from app.services.mail_service import MailService
|
||||
from app.services.settings_service import SettingsService
|
||||
|
||||
|
||||
class NotificationService:
|
||||
def __init__(self, company_id=None):
|
||||
self.company_id = company_id
|
||||
|
||||
def should_notify(self, invoice):
|
||||
if SettingsService.get_effective('notify.enabled', 'false', company_id=self.company_id) != 'true':
|
||||
return False
|
||||
min_amount = Decimal(SettingsService.get_effective('notify.min_amount', '0', company_id=self.company_id) or '0')
|
||||
return Decimal(invoice.gross_amount) >= min_amount
|
||||
|
||||
def _pushover_credentials(self):
|
||||
return {
|
||||
'token': SettingsService.get_effective_secret('notify.pushover_api_token', '', company_id=self.company_id),
|
||||
'user': SettingsService.get_effective('notify.pushover_user_key', '', company_id=self.company_id),
|
||||
}
|
||||
|
||||
def _email_recipients(self):
|
||||
if not self.company_id:
|
||||
return []
|
||||
rows = (
|
||||
db.session.query(User.email)
|
||||
.join(UserCompanyAccess, UserCompanyAccess.user_id == User.id)
|
||||
.filter(UserCompanyAccess.company_id == self.company_id, User.is_blocked.is_(False))
|
||||
.order_by(User.email.asc())
|
||||
.all()
|
||||
)
|
||||
recipients = []
|
||||
seen = set()
|
||||
for (email,) in rows:
|
||||
email = (email or '').strip().lower()
|
||||
if not email or email in seen:
|
||||
continue
|
||||
seen.add(email)
|
||||
recipients.append(email)
|
||||
return recipients
|
||||
|
||||
def notify_new_invoice(self, invoice):
|
||||
if not self.should_notify(invoice):
|
||||
return []
|
||||
message = f'Nowa faktura {invoice.invoice_number} / {invoice.contractor_name} / {invoice.gross_amount} PLN'
|
||||
logs = [self._send_email_notification(invoice, message)]
|
||||
logs.append(self._send_pushover(invoice.id, message))
|
||||
return logs
|
||||
|
||||
def log_channel(self, invoice_id, channel, status, message):
|
||||
log = NotificationLog(invoice_id=invoice_id, channel=channel, status=status, message=message, sent_at=datetime.utcnow())
|
||||
db.session.add(log)
|
||||
db.session.commit()
|
||||
return log
|
||||
|
||||
def _send_email_notification(self, invoice, message):
|
||||
recipients = self._email_recipients()
|
||||
if not recipients:
|
||||
return self.log_channel(invoice.id, 'email', 'skipped', 'Brak odbiorców e-mail przypisanych do aktywnej firmy')
|
||||
|
||||
mailer = MailService(company_id=self.company_id)
|
||||
subject = f'Nowa faktura: {invoice.invoice_number}'
|
||||
body = (
|
||||
'W systemie KSeF Manager pojawiła się nowa faktura.\n\n'
|
||||
f'Numer: {invoice.invoice_number}\n'
|
||||
f'Kontrahent: {invoice.contractor_name}\n'
|
||||
f'Kwota brutto: {invoice.gross_amount} PLN\n'
|
||||
)
|
||||
|
||||
sent = 0
|
||||
errors = []
|
||||
for recipient in recipients:
|
||||
try:
|
||||
mailer.send_mail(recipient, subject, body)
|
||||
sent += 1
|
||||
except Exception as exc:
|
||||
errors.append(f'{recipient}: {exc}')
|
||||
|
||||
if sent and not errors:
|
||||
return self.log_channel(invoice.id, 'email', 'sent', f'{message} · odbiorców: {sent}')
|
||||
if sent and errors:
|
||||
return self.log_channel(invoice.id, 'email', 'error', f"Wysłano do {sent}/{len(recipients)} odbiorców. Błędy: {'; '.join(errors[:3])}")
|
||||
return self.log_channel(invoice.id, 'email', 'error', 'Nie udało się wysłać powiadomień e-mail: ' + '; '.join(errors[:3]))
|
||||
|
||||
def _send_pushover(self, invoice_id, message):
|
||||
creds = self._pushover_credentials()
|
||||
if not creds['token'] or not creds['user']:
|
||||
return self.log_channel(invoice_id, 'pushover', 'skipped', 'Brak konfiguracji Pushover')
|
||||
try:
|
||||
response = requests.post('https://api.pushover.net/1/messages.json', data={'token': creds['token'], 'user': creds['user'], 'message': message}, timeout=10)
|
||||
response.raise_for_status()
|
||||
return self.log_channel(invoice_id, 'pushover', 'sent', message)
|
||||
except Exception as exc:
|
||||
return self.log_channel(invoice_id, 'pushover', 'error', str(exc))
|
||||
|
||||
def send_test_pushover(self):
|
||||
return self._send_pushover(None, 'KSeF Manager - test Pushover')
|
||||
Reference in New Issue
Block a user