60 lines
2.2 KiB
Python
60 lines
2.2 KiB
Python
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})
|