feat(api): add BNPL, ERP, WhatsApp Cloud, Supplier Portal stubs
- 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
This commit is contained in:
90
pos/blueprints/bnpl_bp.py
Normal file
90
pos/blueprints/bnpl_bp.py
Normal file
@@ -0,0 +1,90 @@
|
||||
"""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
|
||||
Reference in New Issue
Block a user