first commit

This commit is contained in:
Mateusz Gruszczyński
2026-03-13 15:17:32 +01:00
commit 986ffb200a
91 changed files with 4423 additions and 0 deletions

0
app/api/__init__.py Normal file
View File

59
app/api/routes.py Normal file
View File

@@ -0,0 +1,59 @@
from __future__ import annotations
from datetime import date
from decimal import Decimal
from flask import Blueprint, abort, jsonify, request
from ..extensions import db
from ..models import AppSetting, Category, Expense, User
from ..services.audit import log_action
api_bp = Blueprint('api', __name__, url_prefix='/api')
def _require_webhook_token() -> None:
token = (request.headers.get('X-Webhook-Token') or '').strip()
expected = AppSetting.get('webhook_api_token', '') or ''
if not expected or token != expected:
abort(403)
@api_bp.route('/webhooks/expenses', methods=['POST'])
def webhook_expenses():
_require_webhook_token()
payload = request.get_json(silent=True) or {}
if not payload:
abort(400)
email = (payload.get('user_email') or '').strip().lower()
user = User.query.filter_by(email=email, is_active_user=True).first()
if not user:
abort(404)
category = None
if payload.get('category_key'):
category = Category.query.filter_by(key=str(payload['category_key']).strip().lower(), is_active=True).first()
amount = Decimal(str(payload.get('amount', '0')))
expense = Expense(
user_id=user.id,
title=(payload.get('title') or payload.get('vendor') or 'Webhook expense')[:255],
vendor=(payload.get('vendor') or '')[:255],
description=(payload.get('description') or '')[:2000],
amount=amount,
currency=(payload.get('currency') or user.default_currency or 'PLN')[:10],
purchase_date=date.fromisoformat(payload.get('purchase_date') or date.today().isoformat()),
payment_method=(payload.get('payment_method') or 'card')[:20],
tags=(payload.get('tags') or '')[:255],
recurring_period=(payload.get('recurring_period') or 'none')[:20],
status=(payload.get('status') or 'confirmed')[:20],
is_business=bool(payload.get('is_business')),
is_refund=bool(payload.get('is_refund')),
category_id=category.id if category else None,
ocr_status='webhook',
)
db.session.add(expense)
db.session.commit()
log_action('expense_webhook_created', 'expense', expense.id, user_email=user.email)
db.session.commit()
return jsonify({'status': 'ok', 'expense_id': expense.id})