Change email send to the administrator of the opencart store when they get an order

This Opencart tutorial shows how to change and customize emails send out to the store administrator when they get the new order in the OpenCart store. Normally Opencart just sends an email with fewer details like below:

You have received an order.

Order ID: 1088
Date Added: 11/02/2019
Order Status: Complete

Products
1x .... $0.00

Order Totals
Sub-Total: $0.00
Total: $0.00

Let’s change that email to send full details like the one that customers get.

Change admin order alert email

Open catalog/controller/mail/order.php and remove the alert method and replace it with the below alert method.

// Admin Alert Mail
public function alert(&$route, &$args) {
    if (isset($args[0])) {
        $order_id = $args[0];
    } else {
        $order_id = 0;
    }
    
    if (isset($args[1])) {
        $order_status_id = $args[1];
    } else {
        $order_status_id = 0;
    }	
    
    if (isset($args[2])) {
        $comment = $args[2];
    } else {
        $comment = '';
    }
    
    if (isset($args[3])) {
        $notify = $args[3];
    } else {
        $notify = '';
    }

    $order_info = $this->model_checkout_order->getOrder($order_id);
    
    if ($order_info && !$order_info['order_status_id'] && $order_status_id && in_array('order', (array)$this->config->get('config_mail_alert'))) {	

        // Check for any downloadable products
    $download_status = false;

    $order_products = $this->model_checkout_order->getOrderProducts($order_info['order_id']);
    
    foreach ($order_products as $order_product) {
        // Check if there are any linked downloads
        $product_download_query = $this->db->query("SELECT COUNT(*) AS total FROM `" . DB_PREFIX . "product_to_download` WHERE product_id = '" . (int)$order_product['product_id'] . "'");

        if ($product_download_query->row['total']) {
            $download_status = true;
        }
    }
    
    // Load the language for any mails that might be required to be sent out
    $language = new Language($order_info['language_code']);
    $language->load($order_info['language_code']);
    $language->load('mail/order_add');
$this->load->language('mail/order_alert');

    // HTML Mail
    $data['title'] = sprintf($language->get('text_subject'), $order_info['store_name'], $order_info['order_id']);

    $data['text_greeting'] = sprintf($language->get('text_greeting'), $order_info['store_name']);
    $data['text_link'] = $language->get('text_link');
    $data['text_download'] = $language->get('text_download');
    $data['text_order_detail'] = $language->get('text_order_detail');
    $data['text_instruction'] = $language->get('text_instruction');
    $data['text_order_id'] = $language->get('text_order_id');
    $data['text_date_added'] = $language->get('text_date_added');
    $data['text_payment_method'] = $language->get('text_payment_method');
    $data['text_shipping_method'] = $language->get('text_shipping_method');
    $data['text_email'] = $language->get('text_email');
    $data['text_telephone'] = $language->get('text_telephone');
    $data['text_ip'] = $language->get('text_ip');
    $data['text_order_status'] = $language->get('text_order_status');
    $data['text_payment_address'] = $language->get('text_payment_address');
    $data['text_shipping_address'] = $language->get('text_shipping_address');
    $data['text_product'] = $language->get('text_product');
    $data['text_model'] = $language->get('text_model');
    $data['text_quantity'] = $language->get('text_quantity');
    $data['text_price'] = $language->get('text_price');
    $data['text_total'] = $language->get('text_total');
    $data['text_footer'] = $language->get('text_footer');

    $data['logo'] = $order_info['store_url'] . 'image/' . $this->config->get('config_logo');
    $data['store_name'] = $order_info['store_name'];
    $data['store_url'] = $order_info['store_url'];
    $data['customer_id'] = $order_info['customer_id'];
    $data['link'] = $order_info['store_url'] . 'index.php?route=account/order/info&order_id=' . $order_info['order_id'];

    if ($download_status) {
        $data['download'] = $order_info['store_url'] . 'index.php?route=account/download';
    } else {
        $data['download'] = '';
    }

    $data['order_id'] = $order_info['order_id'];
    $data['date_added'] = date($language->get('date_format_short'), strtotime($order_info['date_added']));
    $data['payment_method'] = $order_info['payment_method'];
    $data['shipping_method'] = $order_info['shipping_method'];
    $data['email'] = $order_info['email'];
    $data['telephone'] = $order_info['telephone'];
    $data['ip'] = $order_info['ip'];

    $order_status_query = $this->db->query("SELECT * FROM " . DB_PREFIX . "order_status WHERE order_status_id = '" . (int)$order_status_id . "' AND language_id = '" . (int)$order_info['language_id'] . "'");

    if ($order_status_query->num_rows) {
        $data['order_status'] = $order_status_query->row['name'];
    } else {
        $data['order_status'] = '';
    }

    if ($comment && $notify) {
        $data['comment'] = nl2br($comment);
    } else {
        $data['comment'] = '';
    }

    if ($order_info['payment_address_format']) {
        $format = $order_info['payment_address_format'];
    } else {
        $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
    }

    $find = array(
        '{firstname}',
        '{lastname}',
        '{company}',
        '{address_1}',
        '{address_2}',
        '{city}',
        '{postcode}',
        '{zone}',
        '{zone_code}',
        '{country}'
    );

    $replace = array(
        'firstname' => $order_info['payment_firstname'],
        'lastname'  => $order_info['payment_lastname'],
        'company'   => $order_info['payment_company'],
        'address_1' => $order_info['payment_address_1'],
        'address_2' => $order_info['payment_address_2'],
        'city'      => $order_info['payment_city'],
        'postcode'  => $order_info['payment_postcode'],
        'zone'      => $order_info['payment_zone'],
        'zone_code' => $order_info['payment_zone_code'],
        'country'   => $order_info['payment_country']
    );

    $data['payment_address'] = str_replace(array("\r\n", "\r", "\n"), '<br />', preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), '<br />', trim(str_replace($find, $replace, $format))));

    if ($order_info['shipping_address_format']) {
        $format = $order_info['shipping_address_format'];
    } else {
        $format = '{firstname} {lastname}' . "\n" . '{company}' . "\n" . '{address_1}' . "\n" . '{address_2}' . "\n" . '{city} {postcode}' . "\n" . '{zone}' . "\n" . '{country}';
    }

    $find = array(
        '{firstname}',
        '{lastname}',
        '{company}',
        '{address_1}',
        '{address_2}',
        '{city}',
        '{postcode}',
        '{zone}',
        '{zone_code}',
        '{country}'
    );

    $replace = array(
        'firstname' => $order_info['shipping_firstname'],
        'lastname'  => $order_info['shipping_lastname'],
        'company'   => $order_info['shipping_company'],
        'address_1' => $order_info['shipping_address_1'],
        'address_2' => $order_info['shipping_address_2'],
        'city'      => $order_info['shipping_city'],
        'postcode'  => $order_info['shipping_postcode'],
        'zone'      => $order_info['shipping_zone'],
        'zone_code' => $order_info['shipping_zone_code'],
        'country'   => $order_info['shipping_country']
    );

    $data['shipping_address'] = str_replace(array("\r\n", "\r", "\n"), '<br />', preg_replace(array("/\s\s+/", "/\r\r+/", "/\n\n+/"), '<br />', trim(str_replace($find, $replace, $format))));

    $this->load->model('tool/upload');

    // Products
    $data['products'] = array();

    foreach ($order_products as $order_product) {
        $option_data = array();

        $order_options = $this->model_checkout_order->getOrderOptions($order_info['order_id'], $order_product['order_product_id']);

        foreach ($order_options as $order_option) {
            if ($order_option['type'] != 'file') {
                $value = $order_option['value'];
            } else {
                $upload_info = $this->model_tool_upload->getUploadByCode($order_option['value']);

                if ($upload_info) {
                    $value = $upload_info['name'];
                } else {
                    $value = '';
                }
            }

            $option_data[] = array(
                'name'  => $order_option['name'],
                'value' => (utf8_strlen($value) > 20 ? utf8_substr($value, 0, 20) . '..' : $value)
            );
        }

        $data['products'][] = array(
            'name'     => $order_product['name'],
            'model'    => $order_product['model'],
            'option'   => $option_data,
            'quantity' => $order_product['quantity'],
            'price'    => $this->currency->format($order_product['price'] + ($this->config->get('config_tax') ? $order_product['tax'] : 0), $order_info['currency_code'], $order_info['currency_value']),
            'total'    => $this->currency->format($order_product['total'] + ($this->config->get('config_tax') ? ($order_product['tax'] * $order_product['quantity']) : 0), $order_info['currency_code'], $order_info['currency_value'])
        );
    }

    // Vouchers
    $data['vouchers'] = array();

    $order_vouchers = $this->model_checkout_order->getOrderVouchers($order_info['order_id']);

    foreach ($order_vouchers as $order_voucher) {
        $data['vouchers'][] = array(
            'description' => $order_voucher['description'],
            'amount'      => $this->currency->format($order_voucher['amount'], $order_info['currency_code'], $order_info['currency_value']),
        );
    }

    // Order Totals
    $data['totals'] = array();
    
    $order_totals = $this->model_checkout_order->getOrderTotals($order_info['order_id']);

    foreach ($order_totals as $order_total) {
        $data['totals'][] = array(
            'title' => $order_total['title'],
            'text'  => $this->currency->format($order_total['value'], $order_info['currency_code'], $order_info['currency_value']),
        );
    }

    $this->load->model('setting/setting');
    
    $from = $this->model_setting_setting->getSettingValue('config_email', $order_info['store_id']);
    
    if (!$from) {
        $from = $this->config->get('config_email');
    }


        $mail = new Mail($this->config->get('config_mail_engine'));
        $mail->parameter = $this->config->get('config_mail_parameter');
        $mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
        $mail->smtp_username = $this->config->get('config_mail_smtp_username');
        $mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
        $mail->smtp_port = $this->config->get('config_mail_smtp_port');
        $mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');

        $mail->setTo($this->config->get('config_email'));
        $mail->setFrom($this->config->get('config_email'));
        $mail->setSender(html_entity_decode($order_info['store_name'], ENT_QUOTES, 'UTF-8'));
        $mail->setSubject(html_entity_decode(sprintf($this->language->get('text_subject'), $this->config->get('config_name'), $order_info['order_id']), ENT_QUOTES, 'UTF-8'));
        $mail->setHtml($this->load->view('mail/order_alert', $data));
        $mail->send();

        // Send to additional alert emails
        $emails = explode(',', $this->config->get('config_mail_alert_email'));

        foreach ($emails as $email) {
            if ($email && filter_var($email, FILTER_VALIDATE_EMAIL)) {
                $mail->setTo($email);
                $mail->send();
            }
        }
    }
}

Then go to catalog/view/theme/YOUR_THEME/template/mail/order_mail.twig and remove all the code and replace with the following codes:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>{{ title }}</title>
</head>
<body style="font-family: Arial, Helvetica, sans-serif; font-size: 12px; color: #000000;">
<div style="width: 680px;"><a href="{{ store_url }}" title="{{ store_name }}"><img src="{{ logo }}" alt="{{ store_name }}" style="margin-bottom: 20px; border: none;" /></a>
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_greeting }}</p>
  
  {% if download %}
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_download }}</p>
  <p style="margin-top: 0px; margin-bottom: 20px;"><a href="{{ download }}">{{ download }}</a></p>
  <{% endif %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;" colspan="2">{{ text_order_detail }}</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"><b>{{ text_order_id }}</b> {{ order_id }}<br />
          <b>{{ text_date_added }}</b> {{ date_added }}<br />
          <b>{{ text_payment_method }}</b> {{ payment_method }}<br />
          {% if shipping_method %} <b>{{ text_shipping_method }}</b> {{ shipping_method }}
          {% endif %}</td>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"><b>{{ text_email }}</b> {{ email }}<br />
          <b>{{ text_telephone }}</b> {{ telephone }}<br />
          <b>{{ text_ip }}</b> {{ ip }}<br />
          <b>{{ text_order_status }}</b> {{ order_status }}<br /></td>
      </tr>
    </tbody>
  </table>
  {% if comment %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_instruction }}</td>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ comment }}</td>
      </tr>
    </tbody>
  </table>
  {% endif %}
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_payment_address }}</td>
        {% if shipping_address %}
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_shipping_address }}</td>
        {% endif %} </tr>
    </thead>
    <tbody>
      <tr>
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ payment_address }}</td>
        {% if shipping_address %}
        <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ shipping_address }}</td>
        {% endif %} </tr>
    </tbody>
  </table>
  <table style="border-collapse: collapse; width: 100%; border-top: 1px solid #DDDDDD; border-left: 1px solid #DDDDDD; margin-bottom: 20px;">
    <thead>
      <tr>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_product }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: left; padding: 7px; color: #222222;">{{ text_model }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_quantity }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_price }}</td>
        <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; background-color: #EFEFEF; font-weight: bold; text-align: right; padding: 7px; color: #222222;">{{ text_total }}</td>
      </tr>
    </thead>
    <tbody>
    
    {% for product in products %}
    <tr>
      <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ product.name }}
        {% for option in product.option %}<br />
         <small> - {{ option.name }}: {{ option.value }}</small>{% endfor %}</td>
      <td style="font-size: 12px; border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ product.model }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.quantity }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.price }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ product.total }}</td>
    </tr>
    {% endfor %}
    {% for voucher in vouchers %}
    <tr>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;">{{ voucher.description }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: left; padding: 7px;"></td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">1</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ voucher.amount }}</td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ voucher.amount }}</td>
    </tr>
    {% endfor %}
      </tbody>
    
    <tfoot>
    
    {% for total in totals %}
    <tr>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;" colspan="4"><b>{{ total.title }}:</b></td>
      <td style="font-size: 12px;	border-right: 1px solid #DDDDDD; border-bottom: 1px solid #DDDDDD; text-align: right; padding: 7px;">{{ total.text }}</td>
    </tr>
    {% endfor %}
      </tfoot>
    
  </table>
  <p style="margin-top: 0px; margin-bottom: 20px;">{{ text_footer }}</p>
</div>
</body>
</html>

With these changes, you can get the customized full detail email for Admin as well.

If you want to change the email design for the affiliate alert, affiliate welcome email, forgotten password email, order notification to the customer, order alert to store administrator, edit order alert, register alert, register notification to the customer, transaction alert, voucher alert, you can change them at catalog/view/theme/YOUR_TEME/template/mail where you can change your design as per your need.

Let us know if you find any difficulties or need any help from us. Likewise, you can see other Opencart tips and tricks.

Previous articleHow can we remove index.php?route= in OpenCart for contact, home and other
Next articleFree Automated Testing and monitoring of Opencart functionalities and sites

7 COMMENTS

  1. Thank you, I have been looking for this solution for months and you have helped me a lot of funcinou perfectly, serial legal after creating an extension I believe will facilitate many people’s lives thank you.

  2. Hi.
    I am trying to apply this modification but my Opecart does not have the file below:
    catalog / view / theme / YOUR_THEME / template / mail / order_mail.twig

    In thema it does not exist, and in default / basic there are only these other files:

    order_add.twig
    order_alert.twig
    order_edit.twig

    What appears to contain the same as the order.twig file is the order_add.twig. I can change this, or I must create an order.twig in the mail directory of the template (which does not currently exist).

    Thank you for your help.

  3. Thank you,
    Tested it several times with a big hope from scratch just in case i missed something but no way.
    New email coming just as a plain text of old one. I still think i missed something.
    🙁

  4. /catalog/controller/mail/order.php product href
    $data[‘products’][] = array(
    ‘name’ => $order_product[‘name’],
    ‘model’ => $order_product[‘model’],
    ‘href’ => $order_info[‘store_url’] . ‘/index.php/?route=product/product&product_id=’ . $order_product[‘product_id’],
    ‘option’ => $option_data,
    ‘quantity’ => $order_product[‘quantity’],
    ‘price’ => $this->currency->format($order_product[‘price’] + ($this->config->get(‘config_tax’) ? $order_product[‘tax’] : 0), $order_info[‘currency_code’], $order_info[‘currency_value’]),
    ‘total’ => $this->currency->format($order_product[‘total’] + ($this->config->get(‘config_tax’) ? ($order_product[‘tax’] * $order_product[‘quantity’]) : 0), $order_info[‘currency_code’], $order_info[‘currency_value’])
    );

    and

    /catalog/view/theme/default/template/mail/order_alert.twig
    {{ product.name }}

  5. Hello,

    I have one more question:
    I want the design for the order_alert to be identical to the one from order_add. What the clients receive, I also receive as an admin.
    Can you help me with this aspect?

    I don’t have order_mail – catalog/view/theme/YOUR_THEME/template/mail/order_mail.twig
    order_alert.twig
    order_add.twig
    order_edit.twig

    I’m using the Journal 3 theme.

    Please help me.

LEAVE A REPLY

Please enter your comment!
Please enter your name here