refactor: separate standalone and managed room configs

- veins → shunts rename
- add cfg/standalone/ and cfg/<room>/ structure
- remove old data/*.json (moved to cfg/<room>/data/)
- update build.py and ctrl scripts
This commit is contained in:
buenosairesam
2026-01-02 17:09:58 -03:00
parent 46dc78db0e
commit 9e5cbbad1f
57 changed files with 1788 additions and 150 deletions

View File

@@ -0,0 +1,296 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>MercadoPago API (MOCK) - Configuration</title>
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #111827;
color: #e5e7eb;
padding: 20px;
}
.container { max-width: 1200px; margin: 0 auto; }
header {
background: #0071f2;
color: white;
padding: 20px;
border-radius: 8px;
margin-bottom: 24px;
}
h1 { font-size: 1.5rem; font-weight: 600; margin-bottom: 8px; }
.subtitle { opacity: 0.9; font-size: 0.875rem; }
.mock-badge {
display: inline-block;
background: white;
color: #0071f2;
padding: 4px 12px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 600;
text-transform: uppercase;
margin-left: 12px;
}
.section {
background: #1f2937;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
.section-header {
font-size: 1.1rem;
font-weight: 600;
margin-bottom: 16px;
color: #f9fafb;
}
.endpoint-list { display: flex; flex-direction: column; gap: 12px; }
.endpoint-card {
background: #374151;
border: 2px solid transparent;
border-radius: 6px;
padding: 16px;
cursor: pointer;
transition: all 0.2s;
}
.endpoint-card:hover { border-color: #0071f2; background: #4b5563; }
.endpoint-card.active { border-color: #0071f2; background: #4b5563; }
.endpoint-method {
display: inline-block;
padding: 2px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-weight: 600;
margin-right: 8px;
}
.method-post { background: #10b981; color: white; }
.method-get { background: #3b82f6; color: white; }
.endpoint-path { font-family: monospace; font-size: 0.875rem; }
.endpoint-desc { font-size: 0.75rem; color: #9ca3af; margin-top: 6px; }
.form-group { margin-bottom: 16px; }
.form-label {
display: block;
font-size: 0.875rem;
font-weight: 500;
margin-bottom: 6px;
color: #f9fafb;
}
.form-input, .form-textarea, .form-select {
width: 100%;
padding: 10px 12px;
background: #374151;
border: 1px solid #4b5563;
border-radius: 6px;
color: #e5e7eb;
font-size: 0.875rem;
}
.form-textarea { min-height: 200px; font-family: monospace; }
.form-input:focus, .form-textarea:focus, .form-select:focus {
outline: none;
border-color: #0071f2;
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 6px;
font-size: 0.875rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.btn-primary {
background: #0071f2;
color: white;
}
.btn-primary:hover { background: #005ac1; }
.btn-secondary {
background: #4b5563;
color: #e5e7eb;
margin-left: 8px;
}
.btn-secondary:hover { background: #6b7280; }
.status-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 12px;
}
.status-option {
background: #374151;
padding: 12px;
border-radius: 6px;
cursor: pointer;
border: 2px solid transparent;
}
.status-option:hover { border-color: #0071f2; }
.status-option.selected { border-color: #0071f2; background: #4b5563; }
.status-name { font-weight: 600; color: #f9fafb; margin-bottom: 4px; }
.status-desc { font-size: 0.75rem; color: #9ca3af; }
</style>
</head>
<body>
<div class="container">
<header>
<h1>MercadoPago <span class="mock-badge">MOCK</span></h1>
<div class="subtitle">Configure mock payment responses and behavior</div>
</header>
<!-- Payment Status Configuration -->
<div class="section">
<div class="section-header">Default Payment Status</div>
<p style="color: #9ca3af; margin-bottom: 16px;">Choose what status new payments should return:</p>
<div class="status-grid">
<div class="status-option selected" onclick="selectStatus('approved')">
<div class="status-name">Approved</div>
<div class="status-desc">Payment successful</div>
</div>
<div class="status-option" onclick="selectStatus('rejected')">
<div class="status-name">Rejected</div>
<div class="status-desc">Payment failed</div>
</div>
<div class="status-option" onclick="selectStatus('pending')">
<div class="status-name">Pending</div>
<div class="status-desc">Awaiting confirmation</div>
</div>
<div class="status-option" onclick="selectStatus('in_process')">
<div class="status-name">In Process</div>
<div class="status-desc">Being processed</div>
</div>
</div>
</div>
<!-- Endpoint Configuration -->
<div class="section">
<div class="section-header">Configure Endpoint Responses</div>
<div class="endpoint-list">
<div class="endpoint-card" onclick="selectEndpoint('POST', '/checkout/preferences', 'preference')">
<div>
<span class="endpoint-method method-post">POST</span>
<span class="endpoint-path">/checkout/preferences</span>
</div>
<div class="endpoint-desc">Create payment preference (Checkout Pro)</div>
</div>
<div class="endpoint-card" onclick="selectEndpoint('POST', '/v1/payments', 'payment')">
<div>
<span class="endpoint-method method-post">POST</span>
<span class="endpoint-path">/v1/payments</span>
</div>
<div class="endpoint-desc">Create payment (Checkout API)</div>
</div>
<div class="endpoint-card" onclick="selectEndpoint('GET', '/v1/payments/{id}', 'payment_get')">
<div>
<span class="endpoint-method method-get">GET</span>
<span class="endpoint-path">/v1/payments/{id}</span>
</div>
<div class="endpoint-desc">Get payment details</div>
</div>
<div class="endpoint-card" onclick="selectEndpoint('POST', '/oauth/token', 'oauth')">
<div>
<span class="endpoint-method method-post">POST</span>
<span class="endpoint-path">/oauth/token</span>
</div>
<div class="endpoint-desc">OAuth token exchange/refresh</div>
</div>
</div>
</div>
<!-- Response Editor -->
<div class="section" id="responseEditor" style="display: none;">
<div class="section-header">Edit Response</div>
<div class="form-group">
<label class="form-label">Endpoint</label>
<input class="form-input" id="endpointDisplay" readonly>
</div>
<div class="form-group">
<label class="form-label">Mock Response (JSON)</label>
<textarea class="form-textarea" id="responseJson" placeholder='{"id": "123456", "status": "approved", "_mock": "MercadoPago"}'></textarea>
</div>
<div class="form-group">
<label class="form-label">HTTP Status Code</label>
<input type="number" class="form-input" id="statusCode" value="200">
</div>
<div class="form-group">
<label class="form-label">Delay (ms)</label>
<input type="number" class="form-input" id="delay" value="0">
</div>
<div>
<button class="btn btn-primary" onclick="saveResponse()">Save Response</button>
<button class="btn btn-secondary" onclick="closeEditor()">Cancel</button>
</div>
</div>
<!-- Quick Test -->
<div class="section">
<div class="section-header">Quick Test</div>
<p style="color: #9ca3af; margin-bottom: 12px;">Test endpoint URL to hit for configured responses:</p>
<div class="form-input" style="background: #374151; user-select: all;">
http://localhost:8006/v1/payments
</div>
</div>
</div>
<script>
let selectedEndpoint = null;
let selectedPaymentStatus = 'approved';
function selectStatus(status) {
selectedPaymentStatus = status;
document.querySelectorAll('.status-option').forEach(opt => opt.classList.remove('selected'));
event.currentTarget.classList.add('selected');
}
function selectEndpoint(method, path, type) {
selectedEndpoint = {method, path, type};
document.querySelectorAll('.endpoint-card').forEach(c => c.classList.remove('active'));
event.currentTarget.classList.add('active');
document.getElementById('responseEditor').style.display = 'block';
document.getElementById('endpointDisplay').value = `${method} ${path}`;
document.getElementById('responseJson').value = getDefaultResponse(type);
}
function getDefaultResponse(type) {
const defaults = {
preference: JSON.stringify({
"id": "123456-pref-id",
"init_point": "https://www.mercadopago.com.ar/checkout/v1/redirect?pref_id=123456",
"sandbox_init_point": "https://sandbox.mercadopago.com.ar/checkout/v1/redirect?pref_id=123456",
"_mock": "MercadoPago"
}, null, 2),
payment: JSON.stringify({
"id": 123456,
"status": selectedPaymentStatus,
"status_detail": selectedPaymentStatus === 'approved' ? 'accredited' : 'cc_rejected_other_reason',
"transaction_amount": 1500,
"currency_id": "ARS",
"_mock": "MercadoPago"
}, null, 2),
payment_get: JSON.stringify({
"id": 123456,
"status": "approved",
"status_detail": "accredited",
"transaction_amount": 1500,
"_mock": "MercadoPago"
}, null, 2),
oauth: JSON.stringify({
"access_token": "APP_USR-123456-mock-token",
"token_type": "Bearer",
"expires_in": 15552000,
"refresh_token": "TG-123456-mock-refresh",
"_mock": "MercadoPago"
}, null, 2)
};
return defaults[type] || '{}';
}
function saveResponse() {
alert('Mock response saved (feature pending implementation)');
}
function closeEditor() {
document.getElementById('responseEditor').style.display = 'none';
selectedEndpoint = null;
document.querySelectorAll('.endpoint-card').forEach(c => c.classList.remove('active'));
}
</script>
</body>
</html>