Installazione
Requisiti
Magento 2.4.x — testato su 2.4.9, compatibile con le release 2.4.* precedenti. PHP 8.1–8.5. Richiede codingrow/module-core (installato automaticamente come dipendenza Composer) per il menu admin condiviso Codingrow e la validazione della licenza.
Passaggi di installazione
- Aggiungi le credenziali che riceverai via email a
auth.jsonnella root del tuo progetto Magento:{ "http-basic": { "repo.codingrow.com": { "username": "...", "password": "..." } } } composer config repositories.codingrow composer https://repo.codingrow.comcomposer require codingrow/module-oetibin/magento module:enable Codingrow_Oetibin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush- Incolla la tua chiave di licenza in Admin → Stores → Configuration → Codingrow → Order Export & Tracking Import → License → Chiave di licenza, salva, poi
bin/magento cache:flush. - Nello stesso gruppo General della stessa sezione, imposta Abilita modulo su "Yes" — il modulo viene distribuito abilitato a livello Magento ma funzionalmente spento, quindi non esporta nulla finché non lo attivi esplicitamente.
- Crea il tuo primo profilo in Codingrow → Order Export & Tracking Import → Export Profiles — vedi Profili qui sotto.
L'intero admin dei profili, il generatore di mapping, il log ed ogni email di notifica sono disponibili in 7 lingue, selezionate automaticamente in base alla lingua di ciascun utente admin:
Configurazione admin
La configurazione è in Stores → Configuration → Codingrow Extensions → Order Export & Tracking Import (Licenza più le impostazioni export/tracking). I profili di export e il loro mapping campi / condizioni trigger si gestiscono dalla griglia Order Export dedicata.
Disinstallazione
composer remove codingrow/module-oeti poi
bin/magento setup:upgrade && bin/magento setup:di:compile && bin/magento cache:flush.
I profili e il log di esportazioni/tracking (codingrow_oeti_profile,
codingrow_oeti_log, codingrow_oeti_tracking_log) non vengono mai eliminati automaticamente —
usa prima Esporta profilo se vuoi conservare una copia
della configurazione del tuo profilo.
Guida utente
Profili
Tutto nel modulo è organizzato attorno ai profili, elencati in Codingrow → Order Export & Tracking Import → Export Profiles. Ogni profilo è completamente indipendente: ha un proprio nome, un proprio interruttore abilitato/disabilitato, i propri stati trigger, la propria destinazione (canale + formato), il proprio mapping dei campi e la propria riga nel log delle esportazioni — puoi far girare fianco a fianco tutti i profili che vuoi (uno per fornitore, uno per corriere, uno per un ERP interno), e disabilitare o eliminare uno di essi non influisce mai sugli altri.
Un profilo disabilitato (Profilo abilitato = "No") non esporta mai nulla, sia che venga attivato automaticamente, dall'azione manuale o dal comando CLI — questo è indipendente dall'interruttore Abilita modulo a livello di modulo in System Config, che agisce come un unico interruttore master per spegnere tutti i profili in una volta.
Canali & formati
Ogni profilo sceglie un canale (dove viene consegnato il payload) e un formato (come viene serializzato) — le due scelte sono indipendenti, quindi qualsiasi formato funziona con qualsiasi canale.
| Canale | Uso tipico | Impostazioni chiave |
|---|---|---|
| REST API | Invia il payload come richiesta HTTP a un webservice | URL di destinazione, metodo HTTP (GET/POST/PUT/PATCH), autenticazione (Nessuna, HTTP Basic, Bearer token), secondi minimi tra le richieste (rate limiting, 1 secondo di default) |
| FTP / SFTP | Carica il payload come file su un server remoto | Host, porta (21 di default), username, password, percorso remoto, FTPS opzionale (TLS esplicito), modalità passiva |
| File locale | Scrive il payload in un file sotto il
pub/media/ di questo store, da far prelevare a un sistema esterno via HTTP |
Sottocartella — il file finisce sotto
pub/media/codingrow_oeti/<sottocartella>/ (sottocartella di
default: "default") |
Formati: JSON, XML o CSV, scelti indipendentemente dal canale sopra — lo stesso mapping dei campi (vedi sotto) guida tutti e tre, il formato cambia solo il modo in cui viene serializzato.
Mapping dei campi
La scheda Mapping è una tabella di righe, ognuna che collega un target (il
nome del campo nell'output — un punto indica un livello di annidamento, es.
customer.email) a un percorso sorgente scelto da un menu a tendina
con ogni campo disponibile di ordine/cliente/articolo. Le righe vuote vengono ignorate al
salvataggio.
Le righe vengono lette dall'alto verso il basso nella stessa forma dell'output stesso: prima un modello opzionale di Header, poi le righe di mapping a livello ordine, poi eventuali Repeat blocks (vedi sotto), e infine un modello opzionale di Footer.
Trasformazioni
Ogni riga di mapping può applicare una trasformazione al valore sorgente prima che venga scritto nel campo target:
| Trasformazione | Cosa fa |
|---|---|
| Nessuna | Copia diretta del valore del percorso sorgente (torna a "Default value" quando la sorgente è vuota). |
| Valore statico | Ignora del tutto la sorgente, scrive sempre il testo fisso in "Value". |
| Rimuovi tag HTML | Rimuove il markup HTML dal valore sorgente — utile per un nome o una descrizione prodotto che porta con sé formattazione residua. |
| Template di testo | Testo libero con placeholder, es.
{order.shipping_address.firstname} {order.shipping_address.lastname}.
All'interno di un placeholder è disponibile anche una funzione:
striphtml{path} (equivalente alla trasformazione Rimuovi tag HTML,
utilizzabile inline) e substr{path,N} (elimina i primi N caratteri, es.
substr{order.some_code,3}). |
| Cerca e sostituisci | Cerca il testo "Search" all'interno del valore sorgente (senza distinzione tra maiuscole e minuscole) e lo sostituisce con "Value" esattamente come indicato. |
| Numero | Serializza il valore come un numero JSON reale
invece che come stringa tra virgolette — usalo quando la destinazione valida il TIPO del
campo in modo rigoroso (una quantità inviata come stringa grezza da database
"1.0000" viene rifiutata da alcune API, mentre 1.0 come
numero reale viene accettato). Questa non è di proposito
l'impostazione predefinita per i campi che sembrano numerici: attivarla ovunque
eliminerebbe silenziosamente gli zeri iniziali da cose come un CAP o un codice articolo,
quindi è una scelta opt-in per ogni riga, non un comportamento automatico. |
La stessa sintassi {path} / striphtml{} / substr{}
usata nelle righe Template di testo è disponibile anche nelle righe dei Repeat block e
nell'Header/Footer opzionale del profilo.
Blocchi ripetuti
Un blocco ripetuto costruisce un array annidato nell'output — il caso più comune è una voce per ogni articolo dell'ordine. Ogni blocco ha una Block output key (dove viene scritto l'array nell'output) e una source collection (su cosa itera, es. gli articoli dell'ordine), più il proprio set di righe di mapping sottostanti, valutate una volta per elemento con "current" ristretto a quell'elemento — quindi il percorso sorgente di una riga dentro un blocco ripetuto si riferisce ai campi dell'articolo corrente, non dell'ordine nel suo insieme.
items, source collection
"Order items", e due righe (sku ← SKU dell'articolo corrente, qty
← quantità dell'articolo corrente) produce:
{
"items": [
{ "sku": "43241", "qty": 2 }
]
}
Un profilo può definire un numero qualsiasi di blocchi ripetuti indipendenti — ad esempio
uno per l'elenco articoli e uno separato per un elenco di sconti applicati.
Condizioni trigger
La scheda General include un generatore di condizioni AND/OR annidabili — la stessa interfaccia
ad albero delle Cart Price Rules di Magento (un link "Add" su ogni gruppo per aggiungere una
condizione o un sottogruppo annidato, un'icona di rimozione su ogni nodo) — che decide
sia quali righe d'ordine il profilo esporta effettivamente sia se
il profilo esporta l'ordine oppure no. Ogni condizione confronta un attributo prodotto (es.
sku, un attributo personalizzato "supplier code", price...) con un
valore, con un operatore: uguale a/diverso da, contiene/non contiene, inizia con/finisce con,
maggiore di/minore di (o uguale a), è vuoto/non è vuoto.
Le condizioni all'interno di un gruppo si combinano con ALL (AND) o ANY (OR), e i gruppi
possono annidarsi dentro altri gruppi — ad esempio sku contains "ABC" OR (supplier_code =
"Supplier2" AND price > 10). Nessuna condizione configurata = nessun filtro, ogni riga
viene esportata (come il vecchio "Only supplier items" = "No" prima della versione 1.3.0).
Uso tipico con più fornitori in dropshipping: un profilo per fornitore,
ciascuno con la propria condizione (es. Profilo A: supplier_code = "Supplier1",
Profilo B: supplier_code = "Supplier2") — un ordine che contiene articoli di
entrambi i fornitori attiva correttamente entrambi i profili in parallelo, ciascuno esportando
solo le righe che gli appartengono. Se nessuna riga soddisfa le condizioni di un dato profilo,
quel profilo semplicemente non esporta quell'ordine (vedi lo stato log "Skipped" più sotto) —
non è un errore.
Ogni attributo usato in una condizione diventa automaticamente disponibile come campo
mappabile nel payload (items.attributes.<code>, vedi Mapping dei campi
sopra). Quando le condizioni escludono righe da un ordine, l'anteprima
live mostra un avviso esplicito che indica quante righe sono state escluse e perché — così
un payload vuoto o più corto del previsto non è mai una sorpresa silenziosa.
Anteprima live
Il pulsante Preview nella pagina di modifica del profilo costruisce un profilo temporaneo, mai salvato, a partire da qualsiasi cosa sia attualmente nel form — incluse modifiche non ancora salvate — e lo esegue su un ordine reale che scegli, attraverso esattamente lo stesso percorso di codice usato per un'esportazione vera. Il risultato è il payload JSON/XML/CSV letterale che quell'ordine produrrebbe, così puoi correggere il mapping prima ancora di attivare il profilo, invece di scoprirlo da un'esportazione reale fallita.
Trigger & deduplica
Il menu a selezione multipla Stato trigger nella scheda General elenca quali stati dell'ordine avviano un'esportazione automatica per quel profilo (Ctrl/Cmd-click per selezionarne più di uno) — viene controllato solo dal trigger automatico basato su evento; l'azione manuale dalla griglia e il comando CLI lo ignorano di proposito, dato che attivare l'esportazione a mano è già di per sé la scelta deliberata di esportare indipendentemente dallo stato. L'azione manuale "Export via Codingrow Order Export" sulla griglia Sales > Orders esegue in un click ogni profilo abilitato sugli ordini selezionati — le Condizioni trigger proprie di ciascun profilo decidono cosa viene effettivamente inviato, esattamente come nel trigger automatico.
Ogni tentativo viene scritto nel log di quel profilo (vedi sotto), e il log è anche ciò che previene i duplicati: lo stesso ordine non viene mai esportato due volte automaticamente dallo stesso profilo, qualunque cosa succeda all'ordine in seguito (ulteriori modifiche, cambi di stato avanti e indietro). Se serve un reinvio vero e proprio — dopo aver risolto un problema lato destinazione, ad esempio — usa Reinvio forzato, che aggira esplicitamente questa protezione.
Importazione tracking
Una scheda Tracking Import per profilo (disattivata di default) esegue una verifica automatica per ordine — ridisegnata nella v1.5.0. Ogni ordine esportato con successo da questo profilo che ha ancora articoli da spedire, e che non è più vecchio di 45 giorni, viene interrogato singolarmente per il proprio stato di spedizione; per gli articoli segnalati come spediti crea una spedizione nativa Magento con il relativo numero di tracking, riutilizzando le Condizioni trigger proprie del profilo per sapere quali articoli dell'ordine gli appartengono. Non c'è alcuna finestra a date bulk — il modello è rigorosamente una richiesta per ogni ordine aperto a ogni giro.
Un ordine ancora non spedito completamente dopo 45 giorni esce dal giro automatico: viene scritto una sola volta nel log con esito Timeout (più un'eventuale email), così non interroga il fornitore all'infinito.
Request. La metà superiore della scheda definisce la chiamata in uscita:
| Campo | Significato |
|---|---|
| Check endpoint URL | URL di base dell'endpoint di stato del fornitore, senza alcuna query string. |
| HTTP method | GET o POST. |
| Poll frequency (minutes) | Ogni quanto gira il cron di questo profilo. |
| Minimum seconds between requests | Rate limit tra le singole chiamate per-ordine di uno stesso giro (default 1s; 0 = nessun limite). |
| Different authentication than the profile | Se No (default) la verifica riusa le credenziali del canale del profilo; impostandolo su Sì l'endpoint di tracking ha una propria autenticazione. |
| Request parameters | Una griglia di righe Name + Type + Value, una per ogni parametro inviato all'endpoint (vedi i cinque tipi di parametro qui sotto). |
| Request preview (JSON) | Anteprima live della chiamata esatta; il pulsante Send test request accanto esegue una chiamata HTTP reale, e incollando un esempio di richiesta nell'anteprima le righe dei parametri si ricostruiscono da esso. |
Ogni riga di Request parameters sceglie uno di cinque Type di valore:
| Type | Valore inviato |
|---|---|
| Fixed value | Il testo letterale inserito in Value. |
| Today | La data odierna (Y-m-d). |
| Order export date | La data in cui quell'ordine è stato esportato. |
| Mapped export field | Il valore che l'export ha calcolato per un target scelto di quell'ordine — es. il riferimento ordine del fornitore. |
| Template | Testo libero con la funzione date{N} (oggi ±N
giorni), es. date{-7}. |
Response mapping. La metà inferiore mappa la risposta del fornitore. Non scrivi mai i percorsi della risposta a mano: ottieni una risposta reale — con Send test request, oppure incollando una risposta catturata nel riquadro Response sample — e ogni tendina qui sotto si popola dai campi effettivamente trovati in quella risposta.
| Campo | Significato |
|---|---|
| Reference field | Quale target di Order Export contiene il riferimento d'ordine (catturato a ogni tentativo di esportazione, riuscito o fallito). |
| Order match field in response | Il campo della risposta con cui confrontarlo per individuare l'ordine giusto. |
| Tracking number / Tracking URL | Campi della risposta che contengono il numero di tracking e, se presente, il suo link cliccabile. |
| Carrier code / Carrier name | Campi della risposta che contengono il codice del corriere e la sua etichetta. |
| Multiple tracking numbers for this shipment | Toggle per i fornitori che restituiscono più di un numero di tracking per spedizione; mostra Tracking numbers: collection (l'array delle voci di tracking) e Tracking numbers: value path in each element (dove si trova il numero dentro ogni voce). |
| Shipped items: collection | L'array nella risposta che elenca gli articoli spediti. |
| Shipped items: SKU path in each element / Shipped items: quantity path in each element | Dove si trovano il codice articolo e la quantità spedita dentro ogni elemento di quell'array. |
| Item matching attribute | L'attributo prodotto con cui riconoscere gli articoli del fornitore, dato che i fornitori riportano il proprio codice, non lo SKU Magento. |
Spedizioni parziali. Se un ordine ha articoli di più fornitori (o un fornitore spedisce in più riprese), ogni verifica crea una spedizione solo per gli articoli effettivamente segnalati come spediti in quel momento, mai oltre quanto resta ancora da spedire — quindi un ordine che finisce legittimamente per avere più spedizioni nel tempo è il comportamento previsto, non un bug.
Email al cliente. Quando il fornitore fornisce un link di tracking cliccabile (un URL, non solo un numero), il cliente riceve un'email con un pulsante "Track your package" invece della semplice email nativa Magento (che mostrerebbe solo il numero, senza un link cliccabile per un corriere che Magento non riconosce nativamente). Quando il fornitore non fornisce alcun URL, viene usata l'email nativa standard, invariata.
Migrazione automatica. I profili già configurati con la versione precedente vengono migrati automaticamente all'aggiornamento — nessuna riconfigurazione necessaria.
Nessuna azione manuale è necessaria in condizioni normali: le verifiche per ordine vengono eseguite da sole in background al ritmo configurato (il cron di Magento deve essere attivo, come per qualsiasi attività pianificata).
https://codingrow.com/sample-tracking.jsonOpenAPI:
https://codingrow.com/sample-api.openapi.yamlLog & Force resend
Dalla versione 1.4.0 il log non è più suddiviso per profilo (una scheda Log dentro ogni profilo). Un'unica pagina Log (pulsante sulla griglia Export Profiles) elenca gli ordini — non i singoli tentativi — uno per riga, paginati, con l'ultimo stato di esportazione e l'ultimo stato di tracking affiancati: un unico colpo d'occhio su un ordine anche quando sono coinvolti più profili/fornitori.
Cliccando su View full history si apre lo storico completo di quell'ordine, diviso in due sezioni — Export log e Tracking log — ognuna con ogni tentativo/verifica di ogni profilo coinvolto, con una riga dettagli espandibile (payload esatto della richiesta inviata, corpo della risposta ricevuta) e, sul lato esportazioni, un pulsante Force resend per ogni riga.
Sul lato esportazioni un tentativo è Success, Error o Skipped. Skipped non è un errore: nessun articolo dell'ordine soddisfaceva le Condizioni trigger di quel profilo, quindi non è stato inviato nulla — utile con più profili/fornitori per capire a colpo d'occhio perché un dato profilo non ha esportato un dato ordine. Sul lato tracking, una verifica fallita di solito significa solo che il fornitore non ha ancora segnalato nulla di spedito per quegli articoli; viene ritentata automaticamente alla verifica successiva, senza bisogno di alcuna azione manuale.
Il Force resend di una riga fallita o Skipped (solo lato esportazioni) riesegue subito l'esportazione per quell'esatto ordine attraverso quell'esatto profilo, ignorando la protezione anti-duplicati — una finestra di conferma lo spiega chiaramente prima, dato che è un'azione deliberata, disponibile sia dalla pagina Log principale sia dal dettaglio dell'ordine. Il tracking non ha un equivalente manuale di "force check": la prossima verifica pianificata ci riprova semplicemente.
Email di notifica errore
Due impostazioni della scheda General controllano le notifiche di errore, indipendentemente dal log (che registra sempre ogni tentativo a prescindere da queste impostazioni): Destinatari notifica (uno o più indirizzi email, separati da virgola — lascia vuoto per non inviare nulla) e Invia email per (quali eventi attivano una notifica).
Il corpo dell'email include l'errore effettivo restituito dalla destinazione, non solo una
generica riga di stato HTTP: quando il corpo della risposta è JSON interpretabile con un campo
message, quel messaggio viene riportato testualmente (es. "Destination returned
HTTP 422 - Minimum product quantity is 1.0"); altrimenti viene incluso il corpo grezzo della
risposta, troncato a 500 caratteri — così la causa reale è visibile direttamente dalla casella
di posta, senza aprire il log.
Importa / Esporta profilo
Il pulsante Esporta profilo nella pagina di modifica di un profilo scarica l'intera configurazione — impostazioni generali, destinazione, righe di mapping e blocchi ripetuti — come un unico file JSON, con le credenziali della destinazione escluse di proposito, così il file è sicuro da conservare, condividere con il supporto o includere in un deployment. Il pulsante Importa profilo nella griglia Export Profiles ricrea un profilo a partire da un file di questo tipo — l'uso tipico è spostare un profilo da uno store di staging/demo alla produzione, o conservare un backup di un mapping di cui sei soddisfatto prima di continuare a sperimentare. Le credenziali vanno sempre reinserite a mano dopo un'importazione, dato che non erano mai presenti nel file.
Licenza
Una licenza per dominio, inserita in Admin → Stores → Configuration → Codingrow → Order Export & Tracking Import → License → Chiave di licenza. Include tutti gli aggiornamenti per quel dominio. Devi passare a un dominio diverso (staging → produzione, o una migrazione del sito)? Il tuo primo cambio dominio è gratuito e istantaneo dalla tua pagina account — nessuna attesa, nessun ticket necessario. Dal secondo cambio in poi, un cambio è consentito una volta all'anno. Puoi anche richiedere un rimborso entro 30 giorni dall'acquisto, autonomamente, dalla stessa pagina account.