diff --git a/public/userarea/create_fixed_fields.php b/public/userarea/create_fixed_fields.php
index 57eae375..bc4b7496 100644
--- a/public/userarea/create_fixed_fields.php
+++ b/public/userarea/create_fixed_fields.php
@@ -23,19 +23,17 @@ if ((int)$stmt->fetchColumn() > 0) {
}
/**
- * FIXED FIELDS STANDARD (no UI selection)
- * is_manual always 1
- * is_visible_import default 1
+ * FIXED FIELDS STANDARD
*/
$fixedFields = [
- // fixed_field_key, data_type
- ['ClienteResponsabile', 'INT'],
- ['ClienteFornitore', 'INT'],
- ['ClienteAnalisi', 'INT'],
- ['MoltiplicatorePrezzo', 'INT'],
- ['AnagraficaCertestObject', 'INT'],
+ ['ClienteResponsabile', 'INT'],
+ ['ClienteFornitore', 'INT'],
+ ['ClienteAnalisi', 'INT'],
+ ['ClienteFatturazione', 'INT'], // ← NUOVO
+ ['MoltiplicatorePrezzo', 'INT'],
+ ['AnagraficaCertestObject', 'INT'],
['AnagraficaCertestService', 'INT'],
- ['ConsegnaRichiesta', 'DATE'],
+ ['ConsegnaRichiesta', 'DATE'],
];
@@ -43,12 +41,11 @@ try {
$pdo->beginTransaction();
$ins = $pdo->prepare("
- INSERT INTO template_fixed_mapping
- (template_id, fixed_field_key, is_manual, data_type, is_required, default_value, is_visible_import)
- VALUES
- (:template_id, :fixed_field_key, 1, :data_type, 1, NULL, 1)
-");
-
+ INSERT INTO template_fixed_mapping
+ (template_id, fixed_field_key, is_manual, data_type, is_required, default_value, is_visible_import)
+ VALUES
+ (:template_id, :fixed_field_key, 1, :data_type, 1, NULL, 1)
+ ");
foreach ($fixedFields as $f) {
$ins->execute([
@@ -58,16 +55,15 @@ try {
]);
}
-
$pdo->commit();
// Return rows (for client render)
$stmt = $pdo->prepare("
- SELECT id, template_id, fixed_field_key, is_manual, data_type, is_required, default_value, is_visible_import
- FROM template_fixed_mapping
- WHERE template_id = ?
- ORDER BY id ASC
-");
+ SELECT id, template_id, fixed_field_key, is_manual, data_type, is_required, default_value, is_visible_import
+ FROM template_fixed_mapping
+ WHERE template_id = ?
+ ORDER BY id ASC
+ ");
$stmt->execute([$templateId]);
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
diff --git a/public/userarea/gridRenderer.js b/public/userarea/gridRenderer.js
index e03185e8..8a169383 100644
--- a/public/userarea/gridRenderer.js
+++ b/public/userarea/gridRenderer.js
@@ -110,6 +110,9 @@
ids.add(String(val));
}
}
+ if (row.fixedFields && row.fixedFields.ClienteFatturazione) {
+ ids.add(String(row.fixedFields.ClienteFatturazione));
+ }
});
// Batch resolve via single request per ID
@@ -156,33 +159,50 @@
return textA.localeCompare(textB, "it", { sensitivity: "base" });
});
}
- // Select2 AJAX config for client selects
- const clientSelect2Config = {
- placeholder: "Search client...",
- allowClear: true,
- width: "100%",
- minimumInputLength: 0,
- sorter: sortSelect2ResultsByStart,
- dropdownCssClass: "select2-dropdown-smaller",
- ajax: {
- url: "search_clienti.php",
- dataType: "json",
- delay: 150,
- data: function (params) {
- return { q: params.term || "", limit: 20 };
- },
- processResults: function (data) {
- const results = (data.results || []).map((item) => ({
- ...item,
- text: formatClientLabel(item),
- }));
-
- return { results: results };
- },
- cache: true,
- },
+ // Mappa: quale filtro Inattivo applicare per ogni campo cliente
+ const clientFieldTipoMap = {
+ ClienteFornitore: "attivo",
+ ClienteAnalisi: "attivo",
+ ClienteFatturazione: "inattivo",
};
+ // Select2 AJAX config factory for client selects (parametrizzata su "tipo")
+ function clientSelect2ConfigFor(tipo) {
+ return {
+ placeholder: "Search client...",
+ allowClear: true,
+ width: "100%",
+ minimumInputLength: 0,
+ sorter: sortSelect2ResultsByStart,
+ dropdownCssClass: "select2-dropdown-smaller",
+ ajax: {
+ url: "search_clienti.php",
+ dataType: "json",
+ delay: 150,
+ data: function (params) {
+ const d = { q: params.term || "", limit: 20 };
+ if (tipo) d.tipo = tipo;
+ return d;
+ },
+ processResults: function (data) {
+ const results = (data.results || []).map((item) => ({
+ ...item,
+ text: formatClientLabel(item),
+ }));
+
+ return { results: results };
+ },
+ cache: true,
+ },
+ };
+ }
+
+ // Helper: inizializza Select2 su un elemento leggendo il tipo da data-client-tipo
+ function initClientSelect2(el) {
+ const tipo = el.dataset.clientTipo || "";
+ $(el).select2(clientSelect2ConfigFor(tipo));
+ }
+
async function loadClientData() {
// No longer loads all clients — AJAX Select2 handles search
// Just resolve names for pre-selected values
@@ -215,6 +235,7 @@
getParams: (cid) => ({ id_cliente: cid }),
},
ClienteFornitore: { source: "clients" },
+ ClienteFatturazione: { source: "clients" },
ClienteAnalisi: { source: "clients" },
};
@@ -536,6 +557,7 @@
sel.className =
"cell-input dropdown-select client-select searchable-client fornitore-select";
sel.dataset.currentValue = row.cliente_fornitore_id || "";
+ sel.dataset.clientTipo = "attivo";
sel.innerHTML = buildClientOptionsHTML(
row.cliente_fornitore_id,
);
@@ -631,12 +653,13 @@
if (config && config.source === "clients") {
const reqCls = col.isRequired ? " required-input" : "";
const req = col.isRequired ? " required" : "";
+ const tipo = clientFieldTipoMap[col.key] || "";
let opts = '';
if (value) {
const label = clientNameCache[value] || value;
opts += ``;
}
- return ``;
+ return ``;
}
// Select — build from cache
@@ -1070,7 +1093,7 @@
``;
} else if (col.type === "cliente_fornitore_id") {
cell.innerHTML =
- `` +
+ `` +
``;
} else if (col.type === "fixed" && col.dataType === "DATE") {
cell.innerHTML =
@@ -1079,8 +1102,9 @@
} else if (col.type === "fixed") {
const isApiField = !!fixedFieldApiConfig[col.key];
if (isApiField) {
+ const tipo = clientFieldTipoMap[col.key] || "";
cell.innerHTML =
- `` +
+ `` +
``;
} else {
cell.innerHTML =
@@ -1115,12 +1139,12 @@
const clientSel = document.getElementById("clientSelect");
if (clientSel) {
clientSel.innerHTML = buildClientOptionsHTML(meta.defaultIdclient);
- $(clientSel).select2(clientSelect2Config);
+ initClientSelect2(clientSel);
}
const fornitSel = document.getElementById("clienteFornitoreSelect");
if (fornitSel) {
fornitSel.innerHTML = buildClientOptionsHTML("");
- $(fornitSel).select2(clientSelect2Config);
+ initClientSelect2(fornitSel);
}
// Fixed field selects in top row
@@ -1130,7 +1154,7 @@
// Client-sourced → init as AJAX Select2
if (config && config.source === "clients") {
- $(sel).select2(clientSelect2Config);
+ initClientSelect2(sel);
return;
}
@@ -1583,7 +1607,7 @@
$(this)
.find(".searchable-client:not(.select2-hidden-accessible)")
.each(function () {
- $(this).select2(clientSelect2Config);
+ initClientSelect2(this);
});
$(this)
.find(".searchable-dropdown:not(.select2-hidden-accessible)")
diff --git a/public/userarea/imported.php b/public/userarea/imported.php
index 3ba13d9c..247fb490 100644
--- a/public/userarea/imported.php
+++ b/public/userarea/imported.php
@@ -147,6 +147,7 @@ $desiredOrder = [
'ClienteResponsabile',
'ClienteFornitore',
'ClienteAnalisi',
+ 'ClienteFatturazione',
'AnagraficaCertestObject',
'AnagraficaCertestService',
'MoltiplicatorePrezzo',
@@ -181,6 +182,7 @@ $fixedAliasMap = [
'ClienteResponsabile' => 'cliente_responsabile_id',
'ClienteFornitore' => 'cliente_fornitore_id',
'ClienteAnalisi' => 'clienteAnalisi',
+ 'ClienteFatturazione' => 'ClienteFatturazione',
'MoltiplicatorePrezzo' => 'moltiplicatore_prezzo_id',
'AnagraficaCertestObject' => 'anagrafica_certest_object_id',
'AnagraficaCertestService' => 'anagrafica_certest_service_id',
@@ -285,6 +287,21 @@ $gridColumns[] = ['type' => 'idclient', 'key' => 'idclient', 'label' => 'Client'
// 4. Cliente Fornitore
$gridColumns[] = ['type' => 'cliente_fornitore_id', 'key' => 'cliente_fornitore_id', 'label' => $slugMapping['ClienteFornitore'] ?? 'ClienteFornitore', 'width' => 300];
+// 4b. Fatturazione Avanzata — subito dopo Cliente Fornitore
+foreach ($fixedFields as $f) {
+ if ($f['fixed_field_key'] === 'ClienteFatturazione') {
+ $gridColumns[] = [
+ 'type' => 'fixed',
+ 'key' => 'ClienteFatturazione',
+ 'label' => 'Fatturazione avanzata',
+ 'dataType' => $f['data_type'],
+ 'isRequired' => (bool)$f['is_required'],
+ 'width' => 180,
+ ];
+ break;
+ }
+}
+
// 5. Other custom fields in schema order
foreach ($allMappings as $mapping) {
if (
@@ -321,7 +338,18 @@ $gridColumns[] = ['type' => 'tracking', 'key' => 'tracking', 'label' => 'Trackin
// 10. Fixed fields (with importreferencecode/filename/importdate after ConsegnaRichiesta)
foreach ($fixedFields as $f) {
$key = $f['fixed_field_key'];
- $label = $slugMapping[$key] ?? $key;
+
+ if ($key === 'ClienteFatturazione') continue; // già renderizzata al punto 4b
+
+ // Cambia solo il titolo della colonna ClienteAnalisi
+ if ($key === 'ClienteAnalisi') {
+ $label = 'Buyer';
+ } elseif ($key === 'ClienteFatturazione') {
+ $label = 'Fatturazione avanzata';
+ } else {
+ $label = $slugMapping[$key] ?? $key;
+ }
+
$gridColumns[] = [
'type' => 'fixed',
'key' => $key,
@@ -330,6 +358,7 @@ foreach ($fixedFields as $f) {
'isRequired' => (bool)$f['is_required'],
'width' => 180,
];
+
if ($key === 'ConsegnaRichiesta') {
$gridColumns[] = ['type' => 'static', 'key' => 'importreferencecode', 'label' => $slugMapping['importreferencecode'] ?? 'Import Reference Code', 'width' => 150, 'editable' => false];
$gridColumns[] = ['type' => 'static', 'key' => 'filename_import', 'label' => $slugMapping['filename_import'] ?? 'File', 'width' => 150, 'editable' => false];
diff --git a/public/userarea/mapping_template_xls_scheme2.php b/public/userarea/mapping_template_xls_scheme2.php
index e516f559..78c44167 100644
--- a/public/userarea/mapping_template_xls_scheme2.php
+++ b/public/userarea/mapping_template_xls_scheme2.php
@@ -627,6 +627,7 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
'ClienteResponsabile',
'ClienteFornitore',
'ClienteAnalisi',
+ 'ClienteFatturazione',
'MoltiplicatorePrezzo',
'AnagraficaCertestObject',
'AnagraficaCertestService'
@@ -2183,11 +2184,11 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
'ClienteResponsabile',
'ClienteFornitore',
'ClienteAnalisi',
+ 'ClienteFatturazione', // ← AGGIUNGI QUESTA RIGA
'MoltiplicatorePrezzo',
'AnagraficaCertestObject',
'AnagraficaCertestService'
];
-
tbody.innerHTML = rows.map(r => {
const type = String(r.data_type || '').toUpperCase();
const dv = r.default_value ?? '';
@@ -2491,11 +2492,22 @@ $apiSampleJson = $template['api_sample_json'] ?? '';
})).filter(x => x.id != null && x.label);
}
- if (key === 'ClienteFornitore' || key === 'ClienteAnalisi') {
+ if (key === 'ClienteFornitore' || key === 'ClienteAnalisi' || key === 'ClienteFatturazione') {
const j = await fetchJson('get_clienti.php');
const list = normalizeList(j, key);
- return list.map(x => ({
+ const isInattivo = (x) => {
+ const v = x.Inattivo;
+ return v === true || v === 1 || v === '1' || v === 'true';
+ };
+
+ // Fornitore e Analisi: solo clienti ATTIVI (Inattivo = false)
+ // Fatturazione: solo clienti INATTIVI (Inattivo = true)
+ const filtered = (key === 'ClienteFatturazione') ?
+ list.filter(isInattivo) :
+ list.filter(x => !isInattivo(x));
+
+ return filtered.map(x => ({
id: x.IdCliente ?? x.Id ?? x.id,
label: formatClientLabel(x)
})).filter(x => x.id != null && x.label);
diff --git a/public/userarea/schemi_base_response.json b/public/userarea/schemi_base_response.json
index 4e39ea75..7a627e30 100644
--- a/public/userarea/schemi_base_response.json
+++ b/public/userarea/schemi_base_response.json
@@ -730,8 +730,8 @@
{
"IdSchemaCustomFields": 177,
"ConteggioClienti": 0,
- "Nome": "Phoebe philo ACC",
- "Descrizione": "(scarpe, borse, cinture, occhiali, gioielleria)\r\n"
+ "Nome": "Phoebe Philo ",
+ "Descrizione": "\r\n\r\n"
},
{
"IdSchemaCustomFields": 178,
@@ -815,7 +815,7 @@
"IdSchemaCustomFields": 191,
"ConteggioClienti": 0,
"Nome": "KIABI",
- "Descrizione": "Schema per il cliente Kiabi\r\n"
+ "Descrizione": "Schema per il cliente Kiabi\r\n\r\n"
},
{
"IdSchemaCustomFields": 192,
@@ -900,6 +900,12 @@
"ConteggioClienti": 0,
"Nome": "Chanel Flammability",
"Descrizione": "Schema per Chanel Flammability\r\n"
+ },
+ {
+ "IdSchemaCustomFields": 206,
+ "ConteggioClienti": 0,
+ "Nome": "COLDWATER CREEK",
+ "Descrizione": "\r\n"
}
]
}
\ No newline at end of file
diff --git a/public/userarea/search_clienti.php b/public/userarea/search_clienti.php
index 5f008847..ff498cdd 100644
--- a/public/userarea/search_clienti.php
+++ b/public/userarea/search_clienti.php
@@ -19,6 +19,14 @@ $q = mb_strtolower(trim($_GET['q'] ?? ''));
$limit = max(1, min(50, intval($_GET['limit'] ?? 20)));
$id = isset($_GET['id']) ? intval($_GET['id']) : null;
+$tipo = $_GET['tipo'] ?? ''; // 'attivo' | 'inattivo' | '' (nessun filtro)
+
+function isInattivo(array $c): bool
+{
+ $v = $c['Inattivo'] ?? false;
+ return $v === true || $v === 1 || $v === '1' || $v === 'true';
+}
+
function formatClientLabel(array $client): string
{
$name = trim($client['Nominativo'] ?? '');
@@ -49,7 +57,7 @@ try {
$api = VisualLimsApiClient::getInstance();
$params = [
- '$select' => 'IdCliente,Nominativo,CodiceCliente',
+ '$select' => 'IdCliente,Nominativo,CodiceCliente,Inattivo',
'$orderby' => 'Nominativo asc'
];
@@ -64,6 +72,14 @@ try {
$clients = $data['value'] ?? [];
+ // Filtro tipo, applicato SOLO alla ricerca, non al lookup per id
+ $searchClients = $clients;
+ if ($tipo === 'attivo') {
+ $searchClients = array_values(array_filter($clients, fn($c) => !isInattivo($c)));
+ } elseif ($tipo === 'inattivo') {
+ $searchClients = array_values(array_filter($clients, fn($c) => isInattivo($c)));
+ }
+
// If requesting by specific ID, used for loading selected value
if ($id !== null) {
foreach ($clients as $c) {
@@ -88,7 +104,7 @@ try {
// Search by query
$results = [];
- foreach ($clients as $c) {
+ foreach ($searchClients as $c) {
$name = trim($c['Nominativo'] ?? '');
$code = trim($c['CodiceCliente'] ?? '');