• Moderatore

    SOLVED (apparently)

    Probabilmente nei test precedenti sbagliavo qualcosa, ma ripensando a come salvare i campi subito dopo la creazione ordine, ho ritentato la strada dell'hook woocommerce_thankyou. A quanto pare funziona, come avrebbe dovuto fin dall'inizio. Ecco come ho risolto, aggiornando i campi automaticamente alla creazione dell'ordine:

    add_filter('woocommerce_thankyou', 'aggiorna_campi_acf');
    function aggiorna_campi_acf( $order_id ){
        update_field('ritiro_prenotato', '0', $order_id);
        update_field('spedizione_prenotata', '0', $order_id);
        update_field('url_tracciamento', 'foo', $order_id);
        update_field('data_prevista_ritiro', 'foo', $order_id);
        update_field('codice_tracciamento', '0', $order_id);
    }
    

    Avevo già testato questa strada, ma probabilmente ero un attimo invornito e avevo fatto qualche errore nel codice.

    Grazie per il supporto @overclokk e @shazarak! Anche solo parlare del problema è servito moltissimo a inquadrarlo meglio!
    Il lato negativo del lavorare da casa da soli è la mancanza di confronto con i colleghi!


  • Moderatore

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    @overclokk
    No, non ho una versione in locale, sto recuperando i dati dagli ordini in arrivo e all'occorrenza faccio un ordine.

    Devi avere una versione in locale in sviluppo, sempre, ti velocizza il lavoro prima di tutto e ti permette di sperimentare senza buttare giù il server, lavorare su un sito su server remoto non è ottimale, un conto è se devi modificare opzioni da pannelli vari, un altro è quando devi mettere mano al codice, con la seconda se io non ho accesso per scaricare sulla mia macchina il sito non prendo neanche il lavoro.

    Poi chi ti assicura che effettuato l'ordine si arrivi sempre alla thank you page? Ovvero che l'evento woocommerce_thankyou venga sempre eseguito (scatenato)? Non ne hai la certezza al 100% e quindi in quelle poche volte che l'evento non viene eseguito non ci sarà nessun update e i fields saranno vuoti, per questo dicevo che devi sempre avere un valore di default e lanciare una eccezione in caso qualcosa vada storto, poi prendi l'eccezione e la trasformi in una risposta nella quale inserirai il messaggio di cosa sia successo, questo ti permette di vedere il messaggio json della risposta e risalire al problema.

    Poi altra cosa, chi ti assicura che $order_id sia realmente un order_id? Nessuno, quindi devi validare questo valore, sempre, specialmente quando devi salvare roba sul db, ovvero devi essere sicuro che quel valore sia corretto, idem per gli altri valori vale lo stesso discorso, nel tuo caso sono hardcodati e potresti anche non validare ma in tutti gli altri casi si valida.


    g.lanzi 1 Risposta
  • Moderatore

    @overclokk ha detto in WooCommerce API: ordine senza alcuni metadati:

    Poi chi ti assicura che effettuato l'ordine si arrivi sempre alla thank you page? Ovvero che l'evento woocommerce_thankyou venga sempre eseguito (scatenato)? Non ne hai la certezza al 100% e quindi in quelle poche volte che l'evento non viene eseguito non ci sarà nessun update e i fields saranno vuoti,

    Cosa potrebbe impedire che woocommerce_thankyou sia triggerato? Un errore? Per questo ho un controllo sull'algoritmo che verifica se i campi ci siano e che siano popolati con i valori di default. Se non lo sono, ci pensa lui stesso.

    per questo dicevo che devi sempre avere un valore di default e lanciare una eccezione in caso qualcosa vada storto, poi prendi l'eccezione e la trasformi in una risposta nella quale inserirai il messaggio di cosa sia successo, questo ti permette di vedere il messaggio json della risposta e risalire al problema.

    I valori di default ci sono. Aggiornarli mi serve solo per averli presenti nelle API. Se non li aggiorno e richiamo l'ordine via API, i campi ACF non ci sono.

    @overclokk ha detto in WooCommerce API: ordine senza alcuni metadati:

    Poi altra cosa, chi ti assicura che $order_id sia realmente un order_id? Nessuno, quindi devi validare questo valore, sempre, specialmente quando devi salvare roba sul db, ovvero devi essere sicuro che quel valore sia corretto, idem per gli altri valori vale lo stesso discorso, nel tuo caso sono hardcodati e potresti anche non validare ma in tutti gli altri casi si valida.

    Mi puoi fare un esempio di validazione nel caso che ho scritto sopra? Sono ignorante in materia e imparo volentieri qualcosa si nuovo.


    overclokk 1 Risposta
  • Moderatore

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Cosa potrebbe impedire che woocommerce_thankyou sia triggerato? Un errore? Per questo ho un controllo sull'algoritmo che verifica se i campi ci siano e che siano popolati con i valori di default. Se non lo sono, ci pensa lui stesso.

    Non lo so, metti che venga persa la connessione proprio nel momento di redirect, metti che il sito vada down, metti che crashi il browser e così via, quando ci sono più di uno step non farei affidamento al successo dello step successivo.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    I valori di default ci sono. Aggiornarli mi serve solo per averli presenti nelle API. Se non li aggiorno e richiamo l'ordine via API, i campi ACF non ci sono.

    Non ci sono se no non avresti bisogno di aggiornarli.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Mi puoi fare un esempio di validazione nel caso che ho scritto sopra? Sono ignorante in materia e imparo volentieri qualcosa si nuovo.

    Dipende da cosa vuoi che sia order_id, se vuoi che sia un integer allora verifichi che sia tale, poi considera che WP in generale ti può passare la qualunque, in id, un post, un \WP_Error, null, unicorni ecc.

    In quel contesto devi vedere cosa indica la documentazione di WC e ACF, ovvero cosa realmente ti passa WC e cosa realmente vuole ACF come valore, immagino o un post o un post_id almeno, quindi almeno un check su questi che farai all'inizio, se i valori ritornati non sono corretti ritorni subito e fai in modo di segnalartelo nella risposta json o in un log file o dove preferisci.

    Ad ogni modo bisogna vedere a monte perché vengono passati campi vuoti.


    shazarak g.lanzi 2 Risposte
  • User Attivo

    @overclokk scusami domanda, come si fa a lavorare in locale con Integromat? nel senso che se provo ad usare il modulo Woocommerce per creare la connessione con api key e secret, mi chiede l'url del sito e se gli do il localhost e simili questo ovviamente non si collega e non mi fa procedere


    overclokk 1 Risposta
  • Moderatore

    @shazarak Ma infatti in locale non devi lavorare con servizi esterni, mai, (anche se possibile), tu devi creare un test che verifichi che la risposta che esce dal sito sia quella giusta, per questo parlo di unit test.

    Purtroppo nel mondo WP gli unit test non sono conosciuti abbastanza, se ti sposti su altri framework (qualsiasi) e chiedi cosa sia uno unit test ti rispondono subito.


    shazarak 1 Risposta
  • Moderatore

    Prima o poi mi ci metterò e farò video su questi concetti.


  • User Attivo

    @overclokk ahhhhhh ! capito ottimo grazie 🙂
    edit: forse qualcosa di simile, l'altro giorno ho usato https://www.postman.com/ con la app Postman Agent che mi collega il localhost al web , pero devo studiare meglio tutto il discorso


  • Moderatore

    Secondo quanto suggerito da @overclokk, il codice aggiornato non è molto diverso:

    add_filter('woocommerce_thankyou', 'aggiorna_campi_acf');
    function aggiorna_campi_acf( $order_id ){
        $order = wc_get_order( $order_id );
        update_field('ritiro_prenotato', '0', $order);
        update_field('spedizione_prenotata', '0', $order);
        update_field('url_tracciamento', 'foo', $order);
        update_field('data_prevista_ritiro', 'foo', $order);
        update_field('codice_tracciamento', '0', $order);
    }
    

    Il recupero dell'Id ordine è usato in questo modo negli esempi stessi di WooCommerce in un caso analogo. L'uso di update_field è conforme alla documentazione di ACF. Adesso non dovrei avere problemi. Se la thank you page non viene visualizzata, ma l'ordine creato, come detto anche prima, ho un filtro nell'algoritmo che coglie questa cosa e pone rimedio.

    I campi sono creati da ACF e il plugin ha questo comportamento per cui non salva i campi a meno che non venga usata l'azione acf/save_post, che però non scatta alla creazione dell'ordine, ma quando viene salvato il post. (https://www.advancedcustomfields.com/resources/acf-save_post/).

    Quindi, il fatto che i metadati ACF non siano subito disponibili è un comportamento atteso, che ho aggirato con lo snippet qui sopra.

    Per quello che riguarda i test, sono stati effettuati in un sito di test con le medesime impostazioni, da cui venivano estratti i dati ordine tramite API. Forse non la più elegante delle soluzioni, ma in fondo funzionale :-). Quello che potevo testare senza scrivere codice che avrebbe potuto rompere il sito, lo facevo in produzione.

    @overclokk se farai dei video sui test, li seguirò volentieri.


    overclokk 1 Risposta
  • Moderatore

    @g-lanzi Proviamo in questo modo:

    Per esempio la funzione wc_get_order( $the_order = false ) mi ritorna @return bool|WC_Order|WC_Order_Refund vedi che già qui abbiamo 3 controlli da fare:

    https://woocommerce.github.io/code-reference/files/woocommerce-includes-wc-order-functions.html#source-view.78

    Idem avremmo dovuto fare per $order_id, usare wc_get_order non ti da nessuna sicurezza sul risultato, troppe variabili, puoi benissimo rimanere su $order_id e fare il check su questo, ora so che la documentazione ti dice così ma siccome io non mi fido di nessuno e voglio essere sicuro al limite della paranoia che il risultato sia quello aspettato verifico tutto, come ho detto sono paranoico ma questo mi assicura di lavorare meno dopo.

    Torniamo a cosa vogliamo che sia $order_id, cosa ci promette la documentazione? Ci promette un integer o un post? Se parliamo di \WC_Order ci promette un integer https://woocommerce.github.io/code-reference/classes/WC-Data.html#method_get_id

    Quindi o mettiamo un type nella signature, int in questo caso:

    function aggiorna_campi_acf( int $order_id ) {}
    

    Ma questo ti potrebbe generare un TypeError da PHP https://www.php.net/manual/en/class.typeerror.php

    Che però sarebbe il sistema best practice.

    O fai un banalissimo:

    
    function aggiorna_campi_acf( $order_id ){
        if( ! \is_int( $order_id ) ) {
          // E qui ritorni un errore o qualcosa che ti indichi il problema
          // Non fare altro, ritorna subito
        }
          ... il resto del tuo codice
    }
    

    Poi abbiamo il caso che l'ID sia 0, e come sappiamo 0 non esiste come post quindi devo controllare anche questo, raro ma può capitare.

    Volendo potresti fare un casting di $order_id su int:

    
    function aggiorna_campi_acf( $order_id ){
        $order_id= (int) $order_id;
        ... il resto del tuo codice
    }
    

    In quest'ultimo caso verifica che l'ìID non sia 0 perche se ti passano valori strani hai uno 0.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Adesso non dovrei avere problemi.

    Non possiamo saperlo.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Se la thank you page non viene visualizzata, ma l'ordine creato, come detto anche prima, ho un filtro nell'algoritmo che coglie questa cosa e pone rimedio.

    A che livello hai questo check?

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    I campi sono creati da ACF e il plugin ha questo comportamento per cui non salva i campi a meno che non venga usata l'azione acf/save_post, che però non scatta alla creazione dell'ordine, ma quando viene salvato il post. (https://www.advancedcustomfields.com/resources/acf-save_post/).

    Tutti i fields sono slavati al salvataggio del post, è un comportamento normale di WP, ma quindi sono a livello di prodotto e non di ordine? Perché i fields che l'utente compila (indirizzo e così via) vengono salvati ad ogni ordine.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Quindi, il fatto che i metadati ACF non siano subito disponibili è un comportamento atteso, che ho aggirato con lo snippet qui sopra.

    Ma tu lo aggiri a valle, non a monte. se tu metti un default nella risposta non hai neanche bisogno di salvare nulla.

    @g-lanzi ha detto in WooCommerce API: ordine senza alcuni metadati:

    Per quello che riguarda i test, sono stati effettuati in un sito di test con le medesime impostazioni, da cui venivano estratti i dati ordine tramite API. Forse non la più elegante delle soluzioni, ma in fondo funzionale :-). Quello che potevo testare senza scrivere codice che avrebbe potuto rompere il sito, lo facevo in produzione.

    Quelli non sono i test di cui parlo, io dico questo genere di test fatti per esempio con PHPUnit https://phpunit.de/