PickupPdf.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. <?php
  2. /**
  3. * Refer to LICENSE.txt distributed with the Temando Shipping module for notice of license
  4. */
  5. namespace Temando\Shipping\Model\Pickup\Pdf;
  6. use Magento\Framework\App\Config\ScopeConfigInterface;
  7. use Magento\Framework\DataObject;
  8. use Magento\Framework\DataObjectFactory;
  9. use Magento\Framework\Exception\LocalizedException;
  10. use Magento\Framework\Filesystem;
  11. use Magento\Framework\Locale\ResolverInterface;
  12. use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
  13. use Magento\Framework\Stdlib\StringUtils;
  14. use Magento\Framework\Translate\Inline\StateInterface;
  15. use Magento\Payment\Helper\Data;
  16. use Magento\Sales\Api\Data\OrderInterface;
  17. use Magento\Sales\Model\Order;
  18. use Magento\Sales\Model\Order\Address\Renderer;
  19. use Magento\Sales\Model\Order\Item;
  20. use Magento\Sales\Model\Order\Pdf\AbstractPdf;
  21. use Magento\Sales\Model\Order\Pdf\Config;
  22. use Magento\Sales\Model\Order\Pdf\Items\AbstractItems;
  23. use Magento\Sales\Model\Order\Pdf\ItemsFactory;
  24. use Magento\Sales\Model\Order\Pdf\Total\Factory;
  25. use Magento\Store\Model\StoreManagerInterface;
  26. use Temando\Shipping\Model\Location\OrderAddressFactory;
  27. use Temando\Shipping\Model\Pickup\PickupManagementFactory;
  28. use Temando\Shipping\Model\PickupInterface;
  29. /**
  30. * Temando Pickup Order PDF model
  31. *
  32. * @package Temando\Shipping\Model
  33. * @author Benjamin Heuer <benjamin.heuer@netresearch.de>
  34. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  35. * @link http://www.temando.com/
  36. */
  37. class PickupPdf extends AbstractPdf
  38. {
  39. /**
  40. * @var StoreManagerInterface
  41. */
  42. private $storeManager;
  43. /**
  44. * @var ResolverInterface
  45. */
  46. private $localeResolver;
  47. /**
  48. * @var BarcodeLayout
  49. */
  50. private $barcodeLayout;
  51. /**
  52. * @var PickupItemRendererFactory
  53. */
  54. private $itemRendererFactory;
  55. /**
  56. * @var DataObjectFactory
  57. */
  58. private $dataObjectFactory;
  59. /**
  60. * @var PickupManagementFactory
  61. */
  62. private $pickupManagementFactory;
  63. /**
  64. * @var OrderAddressFactory
  65. */
  66. private $orderAddressFactory;
  67. /**
  68. * @param Data $paymentData
  69. * @param StringUtils $string
  70. * @param ScopeConfigInterface $scopeConfig
  71. * @param Filesystem $filesystem
  72. * @param Config $pdfConfig
  73. * @param Factory $pdfTotalFactory
  74. * @param ItemsFactory $pdfItemsFactory
  75. * @param TimezoneInterface $localeDate
  76. * @param StateInterface $inlineTranslation
  77. * @param Renderer $addressRenderer
  78. * @param StoreManagerInterface $storeManager
  79. * @param ResolverInterface $localeResolver
  80. * @param BarcodeLayout $barcodeLayout
  81. * @param PickupItemRendererFactory $itemRendererFactory
  82. * @param DataObjectFactory $dataObjectFactory
  83. * @param PickupManagementFactory $pickupManagementFactory
  84. * @param OrderAddressFactory $orderAddressFactory
  85. * @param mixed[] $data
  86. */
  87. public function __construct(
  88. Data $paymentData,
  89. StringUtils $string,
  90. ScopeConfigInterface $scopeConfig,
  91. Filesystem $filesystem,
  92. Config $pdfConfig,
  93. Factory $pdfTotalFactory,
  94. ItemsFactory $pdfItemsFactory,
  95. TimezoneInterface $localeDate,
  96. StateInterface $inlineTranslation,
  97. Renderer $addressRenderer,
  98. StoreManagerInterface $storeManager,
  99. ResolverInterface $localeResolver,
  100. BarcodeLayout $barcodeLayout,
  101. PickupItemRendererFactory $itemRendererFactory,
  102. DataObjectFactory $dataObjectFactory,
  103. PickupManagementFactory $pickupManagementFactory,
  104. OrderAddressFactory $orderAddressFactory,
  105. array $data = []
  106. ) {
  107. $this->storeManager = $storeManager;
  108. $this->localeResolver = $localeResolver;
  109. $this->barcodeLayout = $barcodeLayout;
  110. $this->itemRendererFactory = $itemRendererFactory;
  111. $this->dataObjectFactory = $dataObjectFactory;
  112. $this->pickupManagementFactory = $pickupManagementFactory;
  113. $this->orderAddressFactory = $orderAddressFactory;
  114. parent::__construct(
  115. $paymentData,
  116. $string,
  117. $scopeConfig,
  118. $filesystem,
  119. $pdfConfig,
  120. $pdfTotalFactory,
  121. $pdfItemsFactory,
  122. $localeDate,
  123. $inlineTranslation,
  124. $addressRenderer,
  125. $data
  126. );
  127. }
  128. /**
  129. * @return DataObject
  130. */
  131. private function getPickupDetails()
  132. {
  133. /** @var PickupInterface $pickup */
  134. $pickup = $this->getData('pickup');
  135. /** @var OrderInterface | Order $order */
  136. $order = $this->getData('order');
  137. $pickupLocation = $pickup->getPickupLocation();
  138. /** @var \Magento\Sales\Model\Order\Address $deliveryAddress */
  139. $deliveryAddress = $this->orderAddressFactory->createFromShipmentLocation($pickupLocation);
  140. $deliveryAddress->unsetData('firstname');
  141. $deliveryAddress->setData('lastname', $pickupLocation->getName());
  142. $deliveryAddress->setParentId($order->getEntityId());
  143. $order->setData('addresses', [$order->getBillingAddress(), $deliveryAddress]);
  144. $pickupItems = $pickup->getItems();
  145. /** @var Item[] $orderItems */
  146. $orderItems = $order->getItems();
  147. $pickupManagement = $this->pickupManagementFactory->create(['pickups' => $this->getData('pickups')]);
  148. if ($pickupManagement->canPrepare($pickup->getPickupId())) {
  149. $pickupItems = $pickupManagement->getOpenItems($orderItems);
  150. }
  151. $items = [];
  152. foreach ($pickupItems as $sku => $qty) {
  153. foreach ($orderItems as $key => $orderItem) {
  154. if ($orderItem->getData('sku') != $sku) {
  155. continue;
  156. }
  157. $itemData['data'] = [
  158. 'name' => $orderItem->getData('name'),
  159. 'qty' => $qty,
  160. 'sku' => $sku,
  161. 'order_item' => $orderItem,
  162. ];
  163. $items[] = $this->dataObjectFactory->create($itemData);
  164. unset($orderItems[$key]);
  165. break;
  166. }
  167. }
  168. $pickupDetails = [
  169. 'store_id' => $order->getStoreId(),
  170. 'order' => $order,
  171. 'store' => $order->getStore(),
  172. 'items' => $items,
  173. 'pickup_id' => $pickup->getPickupId(),
  174. 'increment_id' => $order->getIncrementId(),
  175. ];
  176. return $this->dataObjectFactory->create(['data' => $pickupDetails]);
  177. }
  178. /**
  179. * Draw table header for product items
  180. *
  181. * @param \Zend_Pdf_Page $page
  182. *
  183. * @return void
  184. * @throws LocalizedException
  185. */
  186. private function drawHeader(\Zend_Pdf_Page $page)
  187. {
  188. /* Add table head */
  189. $this->_setFontRegular($page, 10);
  190. $page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
  191. $page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
  192. $page->setLineWidth(0.5);
  193. $page->drawRectangle(25, $this->y, 570, $this->y - 15);
  194. $this->y -= 10;
  195. $page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));
  196. //columns headers
  197. $lines[0][] = ['text' => __('Products'), 'feed' => 100];
  198. $lines[0][] = ['text' => __('Qty'), 'feed' => 35];
  199. $lines[0][] = ['text' => __('SKU'), 'feed' => 565, 'align' => 'right'];
  200. $lineBlock = ['lines' => $lines, 'height' => 10];
  201. $this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
  202. $page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
  203. $this->y -= 20;
  204. }
  205. /**
  206. * Draw a pickup ID barcode.
  207. *
  208. * The Code128 gets drawn into the order info section of the packing slip.
  209. * Size and position can be adjusted using the layout data object.
  210. *
  211. * @see BarcodeLayout
  212. *
  213. * @param \Zend_Pdf $pdf
  214. * @param string $pickupId
  215. * @throws \Zend\Barcode\Exception\ExceptionInterface
  216. */
  217. private function drawBarcode(\Zend_Pdf $pdf, $pickupId)
  218. {
  219. /** @var BarcodeRenderer $renderer */
  220. $renderer = \Zend\Barcode\Barcode::factory(
  221. 'code128',
  222. BarcodeRenderer::class,
  223. [
  224. 'text' => sprintf('PID%s', $pickupId),
  225. 'font' => $this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerif.ttf'),
  226. ],
  227. [
  228. 'topOffset' => $this->barcodeLayout->getOffsetTop(),
  229. 'leftOffset' => $this->barcodeLayout->getOffsetLeft(),
  230. 'moduleSize' => $this->barcodeLayout->getModuleSize(),
  231. ]
  232. );
  233. $renderer->setResource($pdf);
  234. $renderer->draw();
  235. }
  236. /**
  237. * Retrieve renderer model
  238. *
  239. * @param string $type
  240. *
  241. * @return AbstractItems
  242. * @throws LocalizedException
  243. */
  244. protected function _getRenderer($type)
  245. {
  246. if (!isset($this->_renderers[$type])) {
  247. $type = 'default';
  248. }
  249. if (!isset($this->_renderers[$type])) {
  250. throw new \Magento\Framework\Exception\LocalizedException(__('We found an invalid renderer model.'));
  251. }
  252. if ($this->_renderers[$type]['renderer'] === null) {
  253. $this->_renderers[$type]['renderer'] = $this->itemRendererFactory->create();
  254. }
  255. return $this->_renderers[$type]['renderer'];
  256. }
  257. /**
  258. * Return PDF document
  259. *
  260. * @return \Zend_Pdf
  261. * @throws LocalizedException
  262. * @throws \Zend_Pdf_Exception
  263. */
  264. public function getPdf()
  265. {
  266. $pickupData = $this->getPickupDetails();
  267. $this->_beforeGetPdf();
  268. $this->_initRenderer('pickup');
  269. $pdf = new \Zend_Pdf();
  270. $this->_setPdf($pdf);
  271. $style = new \Zend_Pdf_Style();
  272. $this->_setFontBold($style, 10);
  273. if ($pickupData->getData('store_id')) {
  274. $this->localeResolver->emulate($pickupData->getData('store_id'));
  275. $this->storeManager->setCurrentStore($pickupData->getData('store_id'));
  276. }
  277. $page = $this->newPage();
  278. $order = $pickupData->getData('order');
  279. /* Add image */
  280. $this->insertLogo($page, $pickupData->getData('store'));
  281. /* Add address */
  282. $this->insertAddress($page, $pickupData->getData('store'));
  283. /* Add head */
  284. $this->insertOrder(
  285. $page,
  286. $pickupData->getData('order'),
  287. $this->_scopeConfig->isSetFlag(
  288. self::XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID,
  289. \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
  290. $order->getStoreId()
  291. )
  292. );
  293. /* Add document text and number */
  294. $this->insertDocumentNumber($page, __('Pickup # ') . $pickupData->getData('pickup_id'));
  295. /* Add table */
  296. $this->drawHeader($page);
  297. /* Add body */
  298. /** @var DataObject $item */
  299. foreach ($pickupData->getData('items') as $item) {
  300. if ($item->getData('order_item')->getParentItem()) {
  301. continue;
  302. }
  303. /* Draw item */
  304. $this->_drawItem($item, $page, $order);
  305. $page = end($pdf->pages);
  306. }
  307. try {
  308. $this->drawBarcode($this->_getPdf(), $pickupData->getData('pickup_id'));
  309. $this->_afterGetPdf();
  310. } catch (\Zend\Barcode\Exception\ExceptionInterface $exception) {
  311. $this->_afterGetPdf();
  312. }
  313. if ($pickupData->getData('store_id')) {
  314. $this->localeResolver->revert();
  315. }
  316. return $pdf;
  317. }
  318. /**
  319. * Create new page and assign to PDF object
  320. *
  321. * @param array $settings
  322. *
  323. * @return \Zend_Pdf_Page
  324. * @throws LocalizedException
  325. */
  326. public function newPage(array $settings = [])
  327. {
  328. /* Add new table head */
  329. $page = $this->_getPdf()->newPage(\Zend_Pdf_Page::SIZE_A4);
  330. $this->_getPdf()->pages[] = $page;
  331. $this->y = 800;
  332. if (!empty($settings['table_header'])) {
  333. $this->drawHeader($page);
  334. }
  335. return $page;
  336. }
  337. }