- bnpl_bp.py: APLAZO/Kueski/Clip application workflow (mock) - erp_bp.py: Aspel/CONTPAQi/SAP/Odoo sync jobs (mock) - whatsapp_cloud_bp.py: Meta Cloud API webhook, messages, templates - supplier_portal_bp.py: demand by zone/branch and top-parts analytics - app.py: register all new blueprints
91 lines
3.0 KiB
Python
91 lines
3.0 KiB
Python
"""BNPL Blueprint — Buy Now Pay Later integrations (stub architecture).
|
|
|
|
Providers: APLAZO, Kueski, Clip (configured per tenant).
|
|
All endpoints are stubs with mock responses until real credentials are provided.
|
|
"""
|
|
from flask import Blueprint, request, jsonify, g
|
|
from functools import wraps
|
|
import uuid
|
|
from datetime import datetime, timedelta
|
|
|
|
bnpl_bp = Blueprint('bnpl', __name__, url_prefix='/pos/api/bnpl')
|
|
|
|
# ─── Auth helper ───
|
|
from middleware import require_auth
|
|
|
|
# ─── Mock store ───
|
|
_mock_applications = {}
|
|
|
|
|
|
@bnpl_bp.route('/providers', methods=['GET'])
|
|
@require_auth()
|
|
def list_providers():
|
|
"""List configured BNPL providers."""
|
|
return jsonify({
|
|
'providers': [
|
|
{'id': 'ap lazo', 'name': 'APLAZO', 'enabled': False, 'config_needed': ['api_key', 'merchant_id']},
|
|
{'id': 'kueski', 'name': 'Kueski Pay', 'enabled': False, 'config_needed': ['api_key', 'secret']},
|
|
{'id': 'clip', 'name': 'Clip Pagos', 'enabled': False, 'config_needed': ['api_key']},
|
|
]
|
|
})
|
|
|
|
|
|
@bnpl_bp.route('/applications', methods=['POST'])
|
|
@require_auth()
|
|
def create_application():
|
|
"""Create a BNPL application for a sale."""
|
|
data = request.get_json() or {}
|
|
sale_id = data.get('sale_id')
|
|
amount = data.get('amount')
|
|
provider = data.get('provider', 'ap lazo')
|
|
customer = data.get('customer', {})
|
|
|
|
if not sale_id or amount is None:
|
|
return jsonify({'error': 'sale_id and amount are required'}), 400
|
|
|
|
app_id = str(uuid.uuid4())
|
|
_mock_applications[app_id] = {
|
|
'id': app_id,
|
|
'sale_id': sale_id,
|
|
'provider': provider,
|
|
'amount': float(amount),
|
|
'status': 'pending',
|
|
'customer': customer,
|
|
'created_at': datetime.utcnow().isoformat(),
|
|
'expires_at': (datetime.utcnow() + timedelta(hours=24)).isoformat(),
|
|
'approval_url': f'/pos/api/bnpl/applications/{app_id}/approve',
|
|
'webhook_url': f'/pos/api/bnpl/webhook/{provider}',
|
|
}
|
|
|
|
return jsonify(_mock_applications[app_id]), 201
|
|
|
|
|
|
@bnpl_bp.route('/applications/<app_id>', methods=['GET'])
|
|
@require_auth()
|
|
def get_application(app_id):
|
|
"""Get BNPL application status."""
|
|
app = _mock_applications.get(app_id)
|
|
if not app:
|
|
return jsonify({'error': 'Application not found'}), 404
|
|
return jsonify(app)
|
|
|
|
|
|
@bnpl_bp.route('/applications/<app_id>/approve', methods=['POST'])
|
|
@require_auth()
|
|
def approve_application(app_id):
|
|
"""Mock approve an application (admin/override)."""
|
|
app = _mock_applications.get(app_id)
|
|
if not app:
|
|
return jsonify({'error': 'Application not found'}), 404
|
|
app['status'] = 'approved'
|
|
app['approved_at'] = datetime.utcnow().isoformat()
|
|
return jsonify(app)
|
|
|
|
|
|
@bnpl_bp.route('/webhook/<provider>', methods=['POST'])
|
|
def webhook(provider):
|
|
"""Receive webhooks from BNPL providers."""
|
|
data = request.get_json() or {}
|
|
# In production, verify signature per provider
|
|
return jsonify({'received': True, 'provider': provider, 'payload': data}), 200
|