Jump to content

Add Tracking code via API, in_transit email send without replacing {followup}


movingit
 Share

Recommended Posts

Prestashop 1.6.1.15:

 

When we add a tracking code with the webservice API, we see it back in the backoffice as expected:

We use the PSWebServiceLibrary: $xml = $webService->edit(array('resource' => 'order_carriers','id'=>xxx,'putXml' => $xml->asXML()));

Conclusion: tracking code has been added succesfully.

 

After this we change the order status to "in transit" and the in_transit email is send to the customer.

Problem: The {followup} tag in the email is not replaced with the right and complete  URL.

 

When we change the tracking code in the backoffice, and save it again without changing anything, and resend the email, the email is complete with the link in stead of {followup} in the email.

 

Looks like adding the tracking code via the webservice, was not completely succesfull?

 

What can we do?

 

 

We already have changed these files according old posts found on the forum/internet:

 

Both trying to fill the {followup}  parameter because it looks like this one is not filled?

controllers/admin/AdminOrdersController.php

classes/order/OrderHistory.php

These changes had no effect.

Edited by movingit (see edit history)

Share this post


Link to post
Share on other sites

  • 3 weeks later...

I can't speak about the webservice, but the admin order controller updates the tracking number in 2 places in the database

 

1) $order->shipping_number = Tools::getValue('tracking_number');

2) $order_carrier->tracking_number = pSQL(Tools::getValue('tracking_number'));

 

That translates to the shipping_number column on the ps_orders table, and tracking_number on the ps_order_carrier table

 

When you change the order status to Shipped, Prestashop only uses the shipping_number from the orders table

 

So you should confirm that both of these columns are updated when using the webservice, but ensure that the shipping_number from the orders table is

Share this post


Link to post
Share on other sites

Unfortuniatly, this did not fix the problem.

 

Both numbers (tracking number in order_carrier and shipping number in orders) are filled in the database with an API call.

After that we change the order status succesfully, also with an API call.

This triggers the "in transit" mail to the customer, but the tracking URL still shows as {followup} 

 

If we edit the tracking code in the back office and save, without changing the code, and send the email again, the URL shows fine.

Share this post


Link to post
Share on other sites

  • 3 weeks later...

If we request order information with the API, the shipping number is filled, but in the database (orders table) the shipping number is still empy, where is the shipping code we see wehen requesting for the order details?

Share this post


Link to post
Share on other sites

In which table You are exacly looking for this tracking number? In ps_orders column shipping_number is deprecated and proper one is stored in ps_order_carrier in tracking_number

 

I know what might be an issue which with I was struggling to. Propably API is using function setCurrentState which doesn't trigger setting email template vars and my workaround for this was creating an override for setCurrentState in override/classes/Order.php with this code if You already have some changes in this class:

 

	public function setCurrentState($id_order_state, $id_employee = 0)
	{
		if (empty($id_order_state)) {
			return false;
		}

		$history = new OrderHistory();
		$history->id_order = (int)$this->id;
		$history->id_employee = (int)$id_employee;
		$history->changeIdOrderState((int)$id_order_state, $this);
		$res = Db::getInstance()->getRow('
			SELECT `invoice_number`, `invoice_date`, `delivery_number`, `delivery_date`
			FROM `'._DB_PREFIX_.'orders`
			WHERE `id_order` = '.(int)$this->id);
		$this->invoice_date = $res['invoice_date'];
		$this->invoice_number = $res['invoice_number'];
		$this->delivery_date = $res['delivery_date'];
		$this->delivery_number = $res['delivery_number'];
		$this->update();

        if ($id_order_state == Configuration::get('PS_OS_SHIPPING')) {
            $order = new Order($history->id_order);

            if ($order->shipping_number) {
                $templateVars = array(
                    '{followup}' => $order->shipping_number,
                    '{shipping_number}' => $order->shipping_number,
                    '{order_name}' => $order->reference
                );
            }
            $history->addWithemail(true, $templateVars);
        } else {
            $history->addWithemail();
        }
	}

or download the attached file Order.php to this post, insert in override/classes/ and after that go to /cache folder and remove file class_index.php

 

For me it helped in 1.6.1.4

Order.php

Edited by hakeryk2 (see edit history)

Share this post


Link to post
Share on other sites

  • 2 weeks later...

Hello,

Unfortiniatly the override does not solve the problem.

When I add the tracking number in the backoffice everything works fine.

I believe this is triggered by this code (controllers/admin/AdminOrdersController.php):

// Update order_carrier
$order_carrier->tracking_number = pSQL(Tools::getValue('tracking_number'));
if ($order_carrier->update())
{
   // Send mail to customer
   $customer = new Customer((int)$order->id_customer);
   $carrier = new Carrier((int)$order->id_carrier, $order->id_lang);
   if (!Validate::isLoadedObject($customer))
      throw new PrestaShopException('Can\'t load Customer object');
   if (!Validate::isLoadedObject($carrier))
      throw new PrestaShopException('Can\'t load Carrier object');
   $templateVars = array(
      '{followup}' => str_replace('@', $order->shipping_number, $carrier->url),
      '{firstname}' => $customer->firstname,
      '{lastname}' => $customer->lastname,
      '{id_order}' => $order->id,
      '{shipping_number}' => $order->shipping_number,
      '{order_name}' => $order->getUniqReference()
   );
   if (@Mail::Send((int)$order->id_lang, 'in_transit', Mail::l('Package in transit', (int)$order->id_lang), $templateVars,
      $customer->email, $customer->firstname.' '.$customer->lastname, null, null, null, null,
      _PS_MAIL_DIR_, true, (int)$order->id_shop))
   {
      Hook::exec('actionAdminOrdersTrackingNumberUpdate', array('order' => $order, 'customer' => $customer, 'carrier' => $carrier), null, false, true, false, $order->id_shop);
      Tools::redirectAdmin(self::$currentIndex.'&id_order='.$order->id.'&vieworder&conf=4&token='.$this->token);
   }
   else
      $this->errors[] = Tools::displayError('An error occurred while sending an email to the customer.');
}

 

After doing this, the shipping_number in the orders table is filled.

 

I try to do the same with the following API calls (using the default PSWebserviceLibrary from GIT):

 

First add tracking code:

$xml = $webService->get(array('resource' => 'order_carriers','id'=>$carrier->order_carriers[0]->order_carrier->id));
$xml->order_carrier->tracking_number =  $p_sUrl;
$xml = $webService->edit(array('resource' => 'order_carriers','id'=>$carrier->order_carriers[0]->order_carrier->id,'putXml' => $xml->asXML()));

After that, update status:

$xml = $webService->get(array('resource' => 'order_histories?schema=blank'));
$xml->order_history->id_order = $p_iOrderID;
$xml->order_history->id_order_state = $p_iStatusID;
$xml->order_history->id_employee = $this->m_iPSUser;
unset($xml->order_history->id);
unset($xml->order_history->date_add);
$xml = $webService->add(array('resource' => 'order_histories?sendemail='.$bSendEmail,'postXml' => $xml->asXML()));

The results are:

1: Tracking code is visible in backoffice

2: status is set to right id (send)

3: In the database, shipping_number in the orders table is still empty

4: in_transit mail is send with the text: {followup}

It looks like the API call does not execute the same code in the adminOrdersController class, but does something else?

I also tried to adjust your override file with:

class Order extends OrderCore
{
   public function setCurrentState($id_order_state, $id_employee = 0)
   {
      if (empty($id_order_state)) {
         return false;
      }

      $history = new OrderHistory();
      $history->id_order = (int)$this->id;
      $history->id_employee = (int)$id_employee;
      $history->changeIdOrderState((int)$id_order_state, $this);
      $res = Db::getInstance()->getRow('
         SELECT O.invoice_number, O.invoice_date, O.delivery_number, O.delivery_date, O.id_order_carrier,C.tracking_number,V.url
         FROM '._DB_PREFIX_.'orders AS O
             LEFT JOIN '._DB_PREFIX_.'order_carrier AS C ON O.id_order= C.id_order
         WHERE O.id_order = '.(int)$this->id);
      $this->invoice_date = $res['invoice_date'];
      $this->invoice_number = $res['invoice_number'];
      $this->delivery_date = $res['delivery_date'];
      $this->delivery_number = $res['delivery_number'];
        $this->shipping_number = $res['tracking_number'];
      $this->update();

        if ($id_order_state == Configuration::get('PS_OS_SHIPPING')) {
            $order = new Order($history->id_order);
            $order_carrier = new OrderCarrier(Tools::getValue('id_order_carrier'));

            if ($order->shipping_number) {
                $templateVars = array(
                    '{followup}' => str_replace('@', $res['tracking_number'], $res['url']),
                    '{shipping_number}' => $order->shipping_number,
                    '{order_name}' => $order->reference
                );
            }
            $history->addWithemail(true, $templateVars);
        } else {
            $history->addWithemail();
        }
   }

}

But this doesn't have any effect.

If I request for order information:

  $opt = array('resource'=>'orders',
               'id'=>$p_iOrderID);
  $xml = $webService->get($opt);
  var_dump($xml);

We see that the parameter $xml->order->shipping_number is filled with the correct tracking number. The shipping number is still empty in the orders table tough. Also when we change the value in the database to for example "123" we still get the right tracking code from de order carries table in this parameter. 

To me it looks like it does not have anything to do with the shipping number, but filling the email template with right parameters. But where can I influence this?

Hope you can help me further, thanks

 

 

 

 

Edited by movingit (see edit history)

Share this post


Link to post
Share on other sites

  • 3 months later...

Hi,

 

I think I found a solution for this problem. Searching on the internet found on a integrator app called CartRover that make a fix for this.

 

https://cartrover.atlassian.net/wiki/spaces/CART/pages/34177028/Blank+Tracking+Number+-+PrestaShop

 

Will paste the solution here in case the information goes down.

 

PrestaShop server admin needs to modify two source files: Order.phpWebserviceRequest.php

Modify classes/order/Order.php:

  1. Please open PrestaShop root directory on server. Make sure that you have permission to modify PrestaShop source files.
  2. Go to classes/order directory, and open Order.php.
  3. Find function setWsShippingNumber($shipping_number) (around line 2215), and insert the following line as marked:

     

    
    public function setWsShippingNumber($shipping_number)
        {
            $id_order_carrier = Db::getInstance()->getValue('
                SELECT `id_order_carrier`
                FROM `'._DB_PREFIX_.'order_carrier`
                WHERE `id_order` = '.(int)$this->id);
            if ($id_order_carrier) {
                $order_carrier = new OrderCarrier($id_order_carrier);
                $order_carrier->tracking_number = $shipping_number;
                $this->shipping_number = $shipping_number;    // <----------Insert this line !
                $order_carrier->update();
            } else {
                $this->shipping_number = $shipping_number;
            }
            return true;
        }
  4. Find function setCurrentState($id_order_state, $id_employee = 0) (around line 1545), and add following lines to that function:

     
    public function setCurrentState($id_order_state, $id_employee = 0)
        {
            if (empty($id_order_state)) {
                return false;
            }
            $history = new OrderHistory();
            $history->id_order = (int)$this->id;
            $history->id_employee = (int)$id_employee;
            $history->changeIdOrderState((int)$id_order_state, $this);
            $res = Db::getInstance()->getRow('
                SELECT `invoice_number`, `invoice_date`, `delivery_number`, `delivery_date`
                FROM `'._DB_PREFIX_.'orders`
                WHERE `id_order` = '.(int)$this->id);
            $this->invoice_date = $res['invoice_date'];
            $this->invoice_number = $res['invoice_number'];
            $this->delivery_date = $res['delivery_date'];
            $this->delivery_number = $res['delivery_number'];
            $this->update();
     
            $carrier = new Carrier($this->id_carrier, $this->id_lang);      // <----------Insert this line !
            $template_vars = array(                                         // <----------Insert this line !
                '{shipping_number}' => $this->shipping_number,            // <----------Insert this line !
                '{followup}' => str_replace('@', $this->shipping_number, $carrier->url),   // <----------Insert this line !
            );                                                              // <----------Insert this line !
     
            $history->addWithemail(true, $template_vars);
        }

     

    '{shipping_number}' should match Tracking Number placeholder in your Email Template. 
    '{followup}' should match Tracking URL placeholder in your Email Template. 

     

  5. Make sure to save Order.php file before you close it.

 

Modify classes/webservice/WebserviceRequest.php:

  1. Go to classes/webservice directory, and open file WebserviceRequest.php.
  2. Find function saveEntityFromXml($successReturnCode) (around line 1371), and insert following lines (around line 1425):

    foreach ($xmlEntities as $xmlEntity) {
                /** @var SimpleXMLElement $xmlEntity */
                $attributes = $xmlEntity->children();
    
                /** @var ObjectModel $object */
                $retrieve_data = $this->resourceConfiguration['retrieveData'];
                if ($this->method == 'POST') {
                    $object = new $retrieve_data['className']();
                } elseif ($this->method == 'PUT') {
                    $object = new $retrieve_data['className']((int)$attributes->id);
                    if (!$object->id) {
                        $this->setError(404, 'Invalid ID', 92);
                        return false;
                    }
                }
                $this->objects[] = $object;
                $i18n = false;
                 
                if(!empty($this->resourceConfiguration['fields']['current_state'])){    // <----------Insert this line! (Around Line 1425)
                    $prop = $this->resourceConfiguration['fields']['current_state'];    // <----------Insert this line!
                    unset($this->resourceConfiguration['fields']['current_state']);     // <----------Insert this line!
                    $this->resourceConfiguration['fields']['current_state'] = $prop;    // <----------Insert this line!
                }                                                                       // <----------Insert this line!
                 
                // attributes
                foreach ($this->resourceConfiguration['fields'] as $fieldName => $fieldProperties) {
                    $sqlId = $fieldProperties['sqlId'];
    
                    if ($fieldName == 'id') {
                        $sqlId = $fieldName;
                    }
                    if (isset($attributes->$fieldName) && isset($fieldProperties['sqlId']) && (!isset($fieldProperties['i18n']) || !$fieldProperties['i18n'])) {
                        if (isset($fieldProperties['setter'])) {
     
  3. Make sure to save WebserviceRequest.php before you close it.
  4. Upload to server and clean cache.
Edited by razaro
Code without proper format (see edit history)
  • Like 1

Share this post


Link to post
Share on other sites

  • 1 year later...
  • 1 year later...

Hi I'm having an issue with Tracking URL using ShipStation.

It insets correct tracking number via Webservice, but does not overwrite the carrier URL set in Prestashop if carrier used is different from the one selected at checkout.

So for example - customer chooses Royal Mail delivery in Prestashop, but in Shipstation I elect to send it FBA. The resulting tracking URL is linkt to Royal Mail tracking with correct tracking number, but doesn't work as it's the incorrect URL.

Can the above solution help with overriding tracking URL in webservice?

Thanks

Baz

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

Cookies ensure the smooth running of our services. Using these, you accept the use of cookies. Learn More