feat: company create with copy-from + fix missing fields

- Add phone_number_id and display_phone fields to create/edit form
  (were never shown or saved despite existing in the DB)
- Add phone_number_id and display_phone to CompanyRepository::save()
- New company form shows "Copiar configuración de empresa" dropdown:
  selecting an existing company pre-fills api_base_url, api_key,
  bot_type, config_json, etc. so admins only need to change
  the name and phone_number_id

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-06-28 17:47:16 -05:00
co-authored by Claude Sonnet 4.6
parent 838cc651b2
commit 84afeb598c
2 changed files with 86 additions and 14 deletions
+85 -13
View File
@@ -992,6 +992,8 @@ HTML;
$cv = fn(string $k, string $d = '') => self::h($company[$k] ?? $d);
$name = $cv('name');
$display_name = $cv('display_name');
$phone_number_id = $cv('phone_number_id');
$display_phone = $cv('display_phone');
$api_base_url = $cv('api_base_url');
$api_key = $cv('api_key');
$config_json = $cv('config_json');
@@ -1207,6 +1209,22 @@ ROW;
EP;
}
// For "copy from" dropdown on new company form
$copyOpts = '';
if (!$isEdit) {
foreach (CompanyRepository::findAll(true) as $co) {
$cid = (int)$co['id'];
$cn = self::h($co['name']);
$copyOpts .= "<option value=\"{$cid}\">{$cn}</option>";
}
}
$allCompaniesJson = !$isEdit
? json_encode(
array_column(CompanyRepository::findAll(true), null, 'id'),
JSON_UNESCAPED_UNICODE | JSON_HEX_TAG
)
: '{}';
$tabsHtml = $isEdit ? <<<HTML
<div style="display:flex;gap:0;border-bottom:1px solid #e5e7eb;margin-bottom:20px">
<button class="tab-btn" id="tb-general" onclick="showTab('general')">General</button>
@@ -1235,53 +1253,78 @@ HTML : '';
<form method="POST" action="/admin/company/save">
HTML;
if ($isEdit) echo '<input type="hidden" name="id" value="' . $id . '">';
if (!$isEdit && $copyOpts !== '') echo <<<COPY
<div class="form-group" style="background:#f0f4ff;border:1px solid #c7d7ff;border-radius:8px;padding:14px;margin-bottom:18px">
<label style="font-weight:700;color:#0b3d91">📋 Copiar configuración de empresa existente</label>
<div style="display:flex;gap:10px;align-items:center;margin-top:8px;flex-wrap:wrap">
<select id="copyFromSel" style="flex:1;min-width:200px">
<option value="">— Selecciona empresa a copiar —</option>
{$copyOpts}
</select>
<button type="button" class="btn-secondary" onclick="copyFromCompany()">Copiar campos</button>
</div>
<div style="font-size:11px;color:#6b7280;margin-top:6px">Copia API URL, API Key, tipo de bot, configuración JSON y endpoints. Podrás editar cada campo antes de guardar.</div>
</div>
COPY;
echo <<<HTML
<div class="form-row">
<div class="form-group">
<label>Nombre *</label>
<input type="text" name="name" value="{$name}" required placeholder="Comercializadora ABC">
<label>Nombre interno *</label>
<input type="text" name="name" id="f_name" value="{$name}" required placeholder="palmas_norte">
<div class="hint">Identificador único, sin espacios</div>
</div>
<div class="form-group">
<label>Nombre mostrado</label>
<input type="text" name="display_name" value="{$display_name}" placeholder="ABC S.A.">
<input type="text" name="display_name" id="f_display_name" value="{$display_name}" placeholder="Palmas Norte S.A.">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>WhatsApp Phone Number ID *</label>
<input type="text" name="phone_number_id" id="f_phone_number_id" value="{$phone_number_id}" required placeholder="384710295638401" style="font-family:monospace">
<div class="hint">ID del número en Meta / WhatsApp Business API</div>
</div>
<div class="form-group">
<label>Teléfono mostrado</label>
<input type="text" name="display_phone" id="f_display_phone" value="{$display_phone}" placeholder="+57 300 123 4567">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>API Base URL *</label>
<input type="text" name="api_base_url" value="{$api_base_url}" required placeholder="https://erp.empresa.com/api/">
<input type="text" name="api_base_url" id="f_api_base_url" value="{$api_base_url}" required placeholder="https://erp.empresa.com/api/">
<div class="hint">Base URL del ERP de esta empresa</div>
</div>
<div class="form-group">
<label>API Key</label>
<input type="text" name="api_key" value="{$api_key}" placeholder="Token Bearer">
<input type="text" name="api_key" id="f_api_key" value="{$api_key}" placeholder="Token Bearer">
</div>
</div>
<div class="form-row">
<div class="form-group">
<label>Usuarios activos en ERP</label>
<input type="number" name="erp_active_users" value="{$erp_active_users}" min="0" placeholder="0">
<div class="hint">Define los l&iacute;mites de n&uacute;meros WA. Se actualiza con sincronizaci&oacute;n ERP.</div>
<input type="number" name="erp_active_users" id="f_erp_active_users" value="{$erp_active_users}" min="0" placeholder="0">
<div class="hint">Define los l&iacute;mites de n&uacute;meros WA.</div>
</div>
<div class="form-group">
<label>Tipo de Bot</label>
<select name="bot_type">{$botOptions}</select>
<select name="bot_type" id="f_bot_type">{$botOptions}</select>
</div>
</div>
<div style="display:flex;gap:20px;margin-bottom:14px;flex-wrap:wrap">
<label style="display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer">
<input type="checkbox" name="requires_approval" value="1" {$reqAprChecked}> Requiere aprobaci&oacute;n manual
<input type="checkbox" name="requires_approval" id="f_requires_approval" value="1" {$reqAprChecked}> Requiere aprobaci&oacute;n manual
</label>
<label style="display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer">
<input type="checkbox" name="is_active" value="1" {$isActChecked}> Activa
<input type="checkbox" name="is_active" id="f_is_active" value="1" {$isActChecked}> Activa
</label>
</div>
<div class="form-group">
<label>Configuraci&oacute;n JSON adicional</label>
<textarea name="config_json" rows="5" style="font-family:monospace;font-size:12px">{$config_json}</textarea>
<label>Configuraci&oacute;n JSON (bot: men&uacute;s, flujos, etc.)</label>
<textarea name="config_json" id="f_config_json" rows="6" style="font-family:monospace;font-size:12px">{$config_json}</textarea>
</div>
<div style="display:flex;gap:10px;padding-top:16px;border-top:1px solid #e5e7eb">
<button type="submit" class="btn-primary">Guardar</button>
<button type="submit" class="btn-primary">💾 Guardar</button>
<a href="/admin/companies" class="btn-secondary">Cancelar</a>
</div>
</form>
@@ -1290,6 +1333,35 @@ HTML;
</div>
HTML;
if (!$isEdit) {
echo <<<SCRIPT
<script>
const ALL_COMPANIES = {$allCompaniesJson};
function copyFromCompany() {
const sel = document.getElementById('copyFromSel');
const cid = parseInt(sel.value);
if (!cid) return;
const c = ALL_COMPANIES[cid];
if (!c) return;
const set = (id, val) => { const el = document.getElementById(id); if (el) el.value = val || ''; };
set('f_display_name', c.display_name || '');
set('f_api_base_url', c.api_base_url || '');
set('f_api_key', c.api_key || '');
set('f_erp_active_users', c.erp_active_users || 0);
set('f_config_json', c.config_json || '');
const bt = document.getElementById('f_bot_type');
if (bt) bt.value = c.bot_type || 'normal';
const ra = document.getElementById('f_requires_approval');
if (ra) ra.checked = !!c.requires_approval;
const ia = document.getElementById('f_is_active');
if (ia) ia.checked = !!c.is_active;
document.getElementById('f_name').focus();
sel.value = '';
}
</script>
SCRIPT;
}
if ($isEdit) {
echo <<<HTML
<!-- Tab Números WhatsApp -->