diff --git a/modules/receipt/commerce_pos_receipt.links.action.yml b/modules/receipt/commerce_pos_receipt.links.action.yml
new file mode 100644
index 0000000..2535083
--- /dev/null
+++ b/modules/receipt/commerce_pos_receipt.links.action.yml
@@ -0,0 +1,5 @@
+commerce_pos_receipt_show_action:
+  route_name: commerce_pos_receipt.show
+  title: 'Show receipt'
+  appears_on:
+    - entity.commerce_order.canonical
diff --git a/modules/receipt/commerce_pos_receipt.module b/modules/receipt/commerce_pos_receipt.module
index 43ab9ac..664d8a5 100644
--- a/modules/receipt/commerce_pos_receipt.module
+++ b/modules/receipt/commerce_pos_receipt.module
@@ -5,7 +5,7 @@
  * Contains commerce_pos_receipt.module.
  */
 
-use Drupal\commerce_price\Entity\Currency;
+use Drupal\Core\Entity\EntityInterface;
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Routing\RouteMatchInterface;
 use Drupal\Core\Url;
@@ -25,78 +25,24 @@ function commerce_pos_receipt_help($route_name, RouteMatchInterface $route_match
 }
 
 /**
- * Implements hook_theme().
+ * Implements hook_operations.
+ *
+ * @param EntityInterface $entity The order entity.
+ *
+ * @return array.
  */
-function commerce_pos_receipt_theme() {
-  return [
-    'commerce_pos_receipt' => [
-      'variables' => ['commerce_payment' => NULL],
-    ],
-  ];
-}
-
-/**
- * Implements template_preprocess_HOOK().
- */
-function commerce_pos_receipt_preprocess_commerce_pos_receipt(&$variables) {
-  /* @var \Drupal\commerce_payment\Entity\Payment $commerce_payment */
-  $commerce_payment = &$variables['commerce_payment'];
-
-  /* @var \Drupal\commerce_order\Entity\Order $order */
-  $order = $commerce_payment->getOrder();
-
-  $number_formatter_factory = \Drupal::service('commerce_price.number_formatter_factory');
-  $number_formatter = $number_formatter_factory->createInstance();
-
-  $sub_total_price = $order->getSubtotalPrice();
-  $currency = Currency::load($sub_total_price->getCurrencyCode());
-  $formatted_amount = $number_formatter->formatCurrency($sub_total_price->getNumber(), $currency);
-
-  $items = $order->getItems();
-  foreach ($items as $item) {
-    $totals[] = [$item->getTitle(), $item->getAdjustedTotalPrice()];
-  }
-
-  $totals[] = ['Subtotal', $formatted_amount];
-
-  // Commerce appears to have a bug where if not adjustments exist, it will
-  // return a 0 => null array, which will still trigger a foreach loop.
-  foreach ($order->collectAdjustments() as $key => $adjustment) {
-    if (!empty($adjustment)) {
-      $amount = $adjustment->getAmount();
-      $currency = Currency::load($amount->getCurrencyCode());
-      $formatted_amount = $number_formatter->formatCurrency($amount->getNumber(), $currency);
-
-      $totals[] = [
-        $adjustment->getLabel(),
-        $formatted_amount,
-      ];
-    }
+function commerce_pos_receipt_entity_operation(EntityInterface $entity) {
+  $operations = [];
+
+  if ($entity->getEntityTypeId() == 'commerce_order') {
+    $operations['show_receipt'] = [
+      'title' => t('Show receipt'),
+      'url' => Url::fromRoute('commerce_pos_receipt.show', ['commerce_order' => $entity->id()]),
+      'weight' => 50,
+    ];
   }
 
-  // Collecting the total price on the cart.
-  $total_price = $order->getTotalPrice();
-  $currency = Currency::load($amount->getCurrencyCode());
-  $formatted_amount = $number_formatter->formatCurrency($total_price->getNumber(), $currency);
-
-  $totals[] = ['Total', $formatted_amount];
-  $totals[] = ['Payment', $commerce_payment->getState()->getLabel()];
-
-  $config = Drupal::config('commerce_pos_receipt.settings');
-  $variables['receipt'] = [
-    'header' => [
-      '#markup' => check_markup($config->get('header'), $config->get('header_format')),
-    ],
-    'body' => [
-      '#type' => 'table',
-      '#rows' => $totals,
-    ],
-    'footer' => [
-      '#markup' => check_markup($config->get('footer'), $config->get('footer_format')),
-    ],
-  ];
-
-  // $variables['#attached']['library'][] = 'commerce/pos-receipt';.
+  return $operations;
 }
 
 /**
@@ -111,14 +57,16 @@ function commerce_pos_receipt_form_commerce_pos_alter(&$form, FormStateInterface
     '#markup' => '<div id="commerce-pos-receipt"></div>',
   ];
 
+  // @todo How to get orderId? Hard coded for now.
+  $ajax_url = URL::fromRoute('commerce_pos_receipt.ajax', ['commerce_order' => 3], [
+    'attributes' => [
+      'class' => ['use-ajax'],
+    ],
+  ]);
   $form['receipt']['reprint'] = [
-    '#title' => t('reprint receipt'),
+    '#title' => t('Reprint receipt'),
     '#type' => 'link',
-    '#url' => URL::fromRoute('commerce_pos_receipt.print', ['commerce_payment' => 1], [
-      'attributes' => [
-        'class' => ['use-ajax'],
-      ],
-    ]),
+    '#url' => $ajax_url,
   ];
 
 }
diff --git a/modules/receipt/commerce_pos_receipt.routing.yml b/modules/receipt/commerce_pos_receipt.routing.yml
index d27ff02..c975e5b 100644
--- a/modules/receipt/commerce_pos_receipt.routing.yml
+++ b/modules/receipt/commerce_pos_receipt.routing.yml
@@ -1,15 +1,26 @@
-commerce_pos_receipt.print:
-  path: '/admin/commerce/pos/{commerce_payment}/print-receipt'
+commerce_pos_receipt.ajax:
+  path: '/admin/commerce/pos/{commerce_order}/ajax-receipt'
   defaults:
-    _controller: '\Drupal\commerce_pos_receipt\Controller\PrintController::printReceipt'
-    _title: 'Print Transaction Receipt'
+    _controller: '\Drupal\commerce_pos_receipt\Controller\PrintController::ajaxReceipt'
+    _title: 'Order Receipt'
   options:
     parameters:
-      commerce_payment:
-        type: 'entity:commerce_payment'
+      commerce_order:
+        type: 'entity:commerce_order'
   requirements:
-    _custom_access: '\Drupal\commerce_pos_receipt\Controller\PrintController::access'
-    commerce_order: \d+
+    _permission: 'administer commerce_order'
+
+commerce_pos_receipt.show:
+  path: '/admin/commerce/pos/{commerce_order}/show-receipt'
+  defaults:
+    _controller: '\Drupal\commerce_pos_receipt\Controller\PrintController::showReceipt'
+    _title: 'Order Receipt'
+  options:
+    parameters:
+      commerce_order:
+        type: 'entity:commerce_order'
+  requirements:
+    _permission: 'administer commerce_order'
 
 commerce_pos_receipt.settings:
   path: '/admin/commerce/config/pos/receipt'
diff --git a/modules/receipt/src/Controller/PrintController.php b/modules/receipt/src/Controller/PrintController.php
index 81e076b..6c0e9b1 100644
--- a/modules/receipt/src/Controller/PrintController.php
+++ b/modules/receipt/src/Controller/PrintController.php
@@ -2,12 +2,11 @@
 
 namespace Drupal\commerce_pos_receipt\Controller;
 
-use Drupal\Core\Access\AccessResult;
+use Drupal\commerce_order\Entity\OrderInterface;
+use Drupal\commerce_price\Entity\Currency;
 use Drupal\Core\Ajax\AjaxResponse;
 use Drupal\Core\Ajax\ReplaceCommand;
 use Drupal\Core\Controller\ControllerBase;
-use Drupal\Core\Session\AccountInterface;
-use Drupal\commerce_payment\Entity\Payment;
 
 /**
  * Class PrintController.
@@ -15,41 +14,79 @@ use Drupal\commerce_payment\Entity\Payment;
 class PrintController extends ControllerBase {
 
   /**
-   * An access callback.
+   * A controller callback.
    */
-  public function access(AccountInterface $account, Payment $commerce_payment) {
-    $access = FALSE;
+  public function ajaxReceipt(OrderInterface $commerce_order) {
+    $renderer = \Drupal::service('renderer');
 
-    if ($account->hasPermission('administer commerce pos')) {
-      $access = TRUE;
-    }
-    else {
-      if ($account->hasPermission('process commerce pos sales')) {
-        // TODO assume this is a temporary override for testing?
-        if (TRUE) {
-          $access = TRUE;
-        }
-      }
-    }
+    $build = $this->showReceipt($commerce_order);
+
+    $response = new AjaxResponse();
+    $response->addCommand(new ReplaceCommand('#commerce-pos-receipt', $renderer->render($build)));
 
-    return AccessResult::allowedIf($access);
+    return $response;
   }
 
   /**
    * A controller callback.
    */
-  public function printReceipt(Payment $commerce_payment) {
-    $renderer = \Drupal::service('renderer');
+  public function showReceipt(OrderInterface $commerce_order) {
 
-    $receipt = [
-      '#theme' => 'commerce_pos_receipt',
-      '#commerce_payment' => $commerce_payment,
-    ];
+    $number_formatter_factory = \Drupal::service('commerce_price.number_formatter_factory');
+    $number_formatter = $number_formatter_factory->createInstance();
 
-    $response = new AjaxResponse();
-    $response->addCommand(new ReplaceCommand('#commerce-pos-receipt', $renderer->render($receipt)));
+    $sub_total_price = $commerce_order->getSubtotalPrice();
+    $currency = Currency::load($sub_total_price->getCurrencyCode());
+    $formatted_amount = $number_formatter->formatCurrency($sub_total_price->getNumber(), $currency);
 
-    return $response;
+    $items = $commerce_order->getItems();
+    foreach ($items as $item) {
+      $totals[] = [$item->getTitle(), $item->getAdjustedTotalPrice()];
+    }
+
+    $totals[] = ['Subtotal', $formatted_amount];
+
+    // Commerce appears to have a bug where if not adjustments exist, it will
+    // return a 0 => null array, which will still trigger a foreach loop.
+    foreach ($commerce_order->collectAdjustments() as $key => $adjustment) {
+      if (!empty($adjustment)) {
+        $amount = $adjustment->getAmount();
+        $currency = Currency::load($amount->getCurrencyCode());
+        $formatted_amount = $number_formatter->formatCurrency($amount->getNumber(), $currency);
+
+        $totals[] = [
+          $adjustment->getLabel(),
+          $formatted_amount,
+        ];
+      }
+    }
+
+    // Collecting the total price on the cart.
+    $total_price = $commerce_order->getTotalPrice();
+    $formatted_amount = $number_formatter->formatCurrency($total_price->getNumber(), $currency);
+    $totals[] = ['Total', $formatted_amount];
+
+    $payment_storage = \Drupal::entityTypeManager()->getStorage('commerce_payment');
+    $payments = $payment_storage->loadMultipleByOrder($commerce_order);
+    foreach ($payments as $payment) {
+      $totals[] = ['Payment', $payment->getState()->getLabel()];
+    }
+
+    $config = \Drupal::config('commerce_pos_receipt.settings');
+    $build['receipt'] = [
+      'header' => [
+        '#markup' => check_markup($config->get('header'), $config->get('header_format')),
+      ],
+      'body' => [
+        '#type' => 'table',
+        '#rows' => $totals,
+      ],
+      'footer' => [
+        '#markup' => check_markup($config->get('footer'), $config->get('footer_format')),
+      ],
+    ];
+
+    return $build;
   }
 
 }
