如何在 Magento2 中以发票 pdf 格式添加 'echo' 的简单消息?
How to add a simple message by 'echo' in invoice pdf format in Magento2?
我已经从 magento2 销售订单的发票选项生成了发票单,并得到了截图以供参考,请看截图:https://prnt.sc/tje4zn
这是发票pdf的文件路径:/vendor/magento/module-sales/Model/Order/Pdf/AbstractPdf.php下面是文件代码,
<?php
namespace Magento\Sales\Model\Order\Pdf;
use Magento\Framework\App\Filesystem\DirectoryList;
/**
* Sales Order PDF abstract model
*/
abstract class AbstractPdf extends \Magento\Framework\DataObject
{
public $y;
protected $_renderers = [];
const XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID = 'sales_pdf/invoice/put_order_id';
const XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID = 'sales_pdf/shipment/put_order_id';
const XML_PATH_SALES_PDF_CREDITMEMO_PUT_ORDER_ID = 'sales_pdf/creditmemo/put_order_id';
protected $_pdf;
abstract public function getPdf();
protected $_paymentData;
protected $string;
protected $_localeDate;
protected $_scopeConfig;
protected $_mediaDirectory;
protected $_rootDirectory;
protected $_pdfConfig;
protected $_pdfTotalFactory;
protected $_pdfItemsFactory;
protected $inlineTranslation;
protected $addressRenderer;
public function __construct(
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\Stdlib\StringUtils $string,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Framework\Filesystem $filesystem,
Config $pdfConfig,
\Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
\Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
\Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
array $data = []
) {
$this->addressRenderer = $addressRenderer;
$this->_paymentData = $paymentData;
$this->_localeDate = $localeDate;
$this->string = $string;
$this->_scopeConfig = $scopeConfig;
$this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->_rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
$this->_pdfConfig = $pdfConfig;
$this->_pdfTotalFactory = $pdfTotalFactory;
$this->_pdfItemsFactory = $pdfItemsFactory;
$this->inlineTranslation = $inlineTranslation;
parent::__construct($data);
}
public function widthForStringUsingFontSize($string, $font, $fontSize)
{
$drawingString = '"libiconv"' == ICONV_IMPL ? iconv(
'UTF-8',
'UTF-16BE//IGNORE',
$string
) : @iconv(
'UTF-8',
'UTF-16BE',
$string
);
$characters = [];
for ($i = 0; $i < strlen($drawingString); $i++) {
$characters[] = ord($drawingString[$i++]) << 8 | ord($drawingString[$i]);
}
$glyphs = $font->glyphNumbersForCharacters($characters);
$widths = $font->widthsForGlyphs($glyphs);
$stringWidth = array_sum($widths) / $font->getUnitsPerEm() * $fontSize;
return $stringWidth;
}
public function getAlignRight($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize, $padding = 5)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + $columnWidth - $width - $padding;
}
public function getAlignCenter($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + round(($columnWidth - $width) / 2);
}
protected function insertLogo(&$page, $store = null)
{
$this->y = $this->y ? $this->y : 815;
$image = $this->_scopeConfig->getValue(
'sales/identity/logo',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$store
);
if ($image) {
$imagePath = '/sales/store/logo/' . $image;
if ($this->_mediaDirectory->isFile($imagePath)) {
$image = \Zend_Pdf_Image::imageWithPath($this->_mediaDirectory->getAbsolutePath($imagePath));
$top = 830;
//top border of the page
$widthLimit = 270;
//half of the page width
$heightLimit = 270;
//assuming the image is not a "skyscraper"
$width = $image->getPixelWidth();
$height = $image->getPixelHeight();
//preserving aspect ratio (proportions)
$ratio = $width / $height;
if ($ratio > 1 && $width > $widthLimit) {
$width = $widthLimit;
$height = $width / $ratio;
} elseif ($ratio < 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $height * $ratio;
} elseif ($ratio == 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $widthLimit;
}
$y1 = $top - $height;
$y2 = $top;
$x1 = 25;
$x2 = $x1 + $width;
//coordinates after transformation are rounded by Zend
$page->drawImage($image, $x1, $y1, $x2, $y2);
$this->y = $y1 - 10;
}
}
}
protected function _formatAddress($address)
{
$return = [];
foreach (explode('|', $address) as $str) {
foreach ($this->string->split($str, 45, true, true) as $part) {
if (empty($part)) {
continue;
}
$return[] = $part;
}
}
return $return;
}
protected function _calcAddressHeight($address)
{
$y = 0;
foreach ($address as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 55, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$y += 15;
}
}
}
return $y;
}
protected function insertOrder(&$page, $obj, $putOrderId = true)
{
if ($obj instanceof \Magento\Sales\Model\Order) {
$shipment = null;
$order = $obj;
} elseif ($obj instanceof \Magento\Sales\Model\Order\Shipment) {
$shipment = $obj;
$order = $shipment->getOrder();
}
$this->y = $this->y ? $this->y : 815;
$top = $this->y;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->drawRectangle(25, $top, 570, $top - 55);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->setDocHeaderCoordinates([25, $top, 570, $top - 55]);
$this->_setFontRegular($page, 10);
if ($putOrderId) {
$page->drawText(__('Order No # ') . $order->getRealOrderId(), 35, $top -= 30, 'UTF-8');
$top +=15;
}
$top -=30;
$page->drawText(
__('Order Date: ') .
$this->_localeDate->formatDate(
$this->_localeDate->scopeDate(
$order->getStore(),
$order->getCreatedAt(),
true
),
\IntlDateFormatter::MEDIUM,
false
),
35,
$top,
'UTF-8'
);
$top -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $top, 275, $top - 25);
$page->drawRectangle(275, $top, 570, $top - 25);
/* Calculate blocks info */
/* Billing Address */
$billingAddress = $this->_formatAddress($this->addressRenderer->format($order->getBillingAddress(), 'pdf'));
/* Payment */
$paymentInfo = $this->_paymentData->getInfoBlock($order->getPayment())->setIsSecureMode(true)->toPdf();
$paymentInfo = htmlspecialchars_decode($paymentInfo, ENT_QUOTES);
$payment = explode('{{pdf_row_separator}}', $paymentInfo);
foreach ($payment as $key => $value) {
if (strip_tags(trim($value)) == '') {
unset($payment[$key]);
}
}
reset($payment);
/* Shipping Address and Method */
if (!$order->getIsVirtual()) {
/* Shipping Address */
$shippingAddress = $this->_formatAddress($this->addressRenderer->format($order->getShippingAddress(), 'pdf'));
$shippingMethod = $order->getShippingDescription();
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontBold($page, 12);
$page->drawText(__('Billed to:'), 35, $top - 15, 'UTF-8');
if (!$order->getIsVirtual()) {
$page->drawText(__('Shipped/Delivery to:'), 285, $top - 15, 'UTF-8');
} else {
$page->drawText(__('Payment Method:'), 285, $top - 15, 'UTF-8');
}
$addressesHeight = $this->_calcAddressHeight($billingAddress);
if (isset($shippingAddress)) {
$addressesHeight = max($addressesHeight, $this->_calcAddressHeight($shippingAddress));
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$page->drawRectangle(25, $top - 25, 570, $top - 33 - $addressesHeight);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontRegular($page, 10);
$this->y = $top - 40;
$addressesStartY = $this->y;
foreach ($billingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 35, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = $this->y;
if (!$order->getIsVirtual()) {
$this->y = $addressesStartY;
foreach ($shippingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = min($addressesEndY, $this->y);
$this->y = $addressesEndY;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 275, $this->y - 25);
$page->drawRectangle(275, $this->y, 570, $this->y - 25);
$this->y -= 15;
$this->_setFontBold($page, 12);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$page->drawText(__('Payment Method'), 35, $this->y, 'UTF-8');
$page->drawText(__('Shipping Method:'), 285, $this->y, 'UTF-8');
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$paymentLeft = 35;
$yPayments = $this->y - 15;
} else {
$yPayments = $addressesStartY;
$paymentLeft = 285;
}
foreach ($payment as $value) {
if (trim($value) != '') {
//Printing "Payment Method" lines
$value = preg_replace('/<br[^>]*>/i', "\n", $value);
foreach ($this->string->split($value, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), $paymentLeft, $yPayments, 'UTF-8');
$yPayments -= 15;
}
}
}
if ($order->getIsVirtual()) {
// replacement of Shipments-Payments rectangle block
$yPayments = min($addressesEndY, $yPayments);
$page->drawLine(25, $top - 25, 25, $yPayments);
$page->drawLine(570, $top - 25, 570, $yPayments);
$page->drawLine(25, $yPayments, 570, $yPayments);
$this->y = $yPayments - 15;
} else {
$topMargin = 15;
$methodStartY = $this->y;
$this->y -= 15;
foreach ($this->string->split($shippingMethod, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
$yShipments = $this->y;
$totalShippingChargesText = "(" . __(
'Total Shipping Charges'
) . " " . $order->formatPriceTxt(
$order->getShippingAmount()
) . ")";
$page->drawText($totalShippingChargesText, 285, $yShipments - $topMargin, 'UTF-8');
$yShipments -= $topMargin + 10;
$tracks = [];
if ($shipment) {
$tracks = $shipment->getAllTracks();
}
if (count($tracks)) {
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
$page->drawLine(400, $yShipments, 400, $yShipments - 10);
//$page->drawLine(510, $yShipments, 510, $yShipments - 10);
$this->_setFontRegular($page, 9);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
//$page->drawText(__('Carrier'), 290, $yShipments - 7 , 'UTF-8');
$page->drawText(__('Title'), 290, $yShipments - 7, 'UTF-8');
$page->drawText(__('Number'), 410, $yShipments - 7, 'UTF-8');
$yShipments -= 20;
$this->_setFontRegular($page, 8);
foreach ($tracks as $track) {
$maxTitleLen = 45;
$endOfTitle = strlen($track->getTitle()) > $maxTitleLen ? '...' : '';
$truncatedTitle = substr($track->getTitle(), 0, $maxTitleLen) . $endOfTitle;
$page->drawText($truncatedTitle, 292, $yShipments, 'UTF-8');
$page->drawText($track->getNumber(), 410, $yShipments, 'UTF-8');
$yShipments -= $topMargin - 5;
}
} else {
$yShipments -= $topMargin - 5;
}
$currentY = min($yPayments, $yShipments);
$page->drawLine(25, $methodStartY, 25, $currentY);
$page->drawLine(25, $currentY, 570, $currentY);
$page->drawLine(570, $currentY, 570, $methodStartY);
$this->y = $currentY;
$this->y -= 15;
}
}
public function insertDocumentNumber(\Zend_Pdf_Page $page, $text)
{
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$docHeader = $this->getDocHeaderCoordinates();
$page->drawText($text, 35, $docHeader[1] - 15, 'UTF-8');
}
protected function _sortTotalsList($a, $b)
{
if (!isset($a['sort_order']) || !isset($b['sort_order'])) {
return 0;
}
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return $a['sort_order'] > $b['sort_order'] ? 1 : -1;
}
protected function _getTotalsList()
{
$totals = $this->_pdfConfig->getTotals();
usort($totals, [$this, '_sortTotalsList']);
$totalModels = [];
foreach ($totals as $totalInfo) {
$class = empty($totalInfo['model']) ? null : $totalInfo['model'];
$totalModel = $this->_pdfTotalFactory->create($class);
$totalModel->setData($totalInfo);
$totalModels[] = $totalModel;
}
return $totalModels;
}
protected function insertTotals($page, $source)
{
$order = $source->getOrder();
$totals = $this->_getTotalsList();
$lineBlock = ['lines' => [], 'height' => 15];
foreach ($totals as $total) {
$total->setOrder($order)->setSource($source);
if ($total->canDisplay()) {
$total->setFontSize(10);
foreach ($total->getTotalsForDisplay() as $totalData) {
$lineBlock['lines'][] = [
[
'text' => $totalData['label'],
'feed' => 475,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold',
],
[
'text' => $totalData['amount'],
'feed' => 565,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold'
],
];
}
}
}
$this->y -= 20;
$page = $this->drawLineBlocks($page, [$lineBlock]);
return $page;
}
protected function _parseItemDescription($item)
{
$matches = [];
$description = $item->getDescription();
if (preg_match_all('/<li.*?>(.*?)<\/li>/i', $description, $matches)) {
return $matches[1];
}
return [$description];
}
protected function _beforeGetPdf()
{
$this->inlineTranslation->suspend();
}
protected function _afterGetPdf()
{
$this->inlineTranslation->resume();
}
protected function _formatOptionValue($value, $order)
{
$resultValue = '';
if (is_array($value)) {
if (isset($value['qty'])) {
$resultValue .= sprintf('%d', $value['qty']) . ' x ';
}
$resultValue .= $value['title'];
if (isset($value['price'])) {
$resultValue .= " " . $order->formatPrice($value['price']);
}
return $resultValue;
} else {
return $value;
}
}
protected function _initRenderer($type)
{
$rendererData = $this->_pdfConfig->getRenderersPerProduct($type);
foreach ($rendererData as $productType => $renderer) {
$this->_renderers[$productType] = ['model' => $renderer, 'renderer' => null];
}
}
protected function _getRenderer($type)
{
if (!isset($this->_renderers[$type])) {
$type = 'default';
}
if (!isset($this->_renderers[$type])) {
throw new \Magento\Framework\Exception\LocalizedException(__('We found an invalid renderer model.'));
}
if ($this->_renderers[$type]['renderer'] === null) {
$this->_renderers[$type]['renderer'] = $this->_pdfItemsFactory->get($this->_renderers[$type]['model']);
}
return $this->_renderers[$type]['renderer'];
}
public function getRenderer($type)
{
return $this->_getRenderer($type);
}
protected function _drawItem(\Magento\Framework\DataObject $item, \Zend_Pdf_Page $page, \Magento\Sales\Model\Order $order)
{
$type = $item->getOrderItem()->getProductType();
$renderer = $this->_getRenderer($type);
$renderer->setOrder($order);
$renderer->setItem($item);
$renderer->setPdf($this);
$renderer->setPage($page);
$renderer->setRenderedModel($this);
$renderer->draw();
return $renderer->getPage();
}
protected function _setFontRegular($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerif.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontBold($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifBold.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontItalic($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifItalic.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setPdf(\Zend_Pdf $pdf)
{
$this->_pdf = $pdf;
return $this;
}
protected function _getPdf()
{
if (!$this->_pdf instanceof \Zend_Pdf) {
throw new \Magento\Framework\Exception\LocalizedException(__('Please define the PDF object before using.'));
}
return $this->_pdf;
}
public function newPage(array $settings = [])
{
$pageSize = !empty($settings['page_size']) ? $settings['page_size'] : \Zend_Pdf_Page::SIZE_A4;
$page = $this->_getPdf()->newPage($pageSize);
$this->_getPdf()->pages[] = $page;
$this->y = 800;
return $page;
}
public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSettings = [])
{
foreach ($draw as $itemsProp) {
if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
throw new \Magento\Framework\Exception\LocalizedException(
__('We don\'t recognize the draw line data. Please define the "lines" array.')
);
}
$lines = $itemsProp['lines'];
$height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
if (empty($itemsProp['shift'])) {
$shift = 0;
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$top = 0;
foreach ($column['text'] as $part) {
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$shift += $maxHeight;
}
$itemsProp['shift'] = $shift;
}
if ($this->y - $itemsProp['shift'] < 15) {
$page = $this->newPage($pageSettings);
}
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
$top = 0;
foreach ($column['text'] as $part) {
if ($this->y - $lineSpacing < 15) {
$page = $this->newPage($pageSettings);
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
}
$feed = $column['feed'];
$textAlign = empty($column['align']) ? 'left' : $column['align'];
$width = empty($column['width']) ? 0 : $column['width'];
switch ($textAlign) {
case 'right':
if ($width) {
$feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
} else {
$feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
}
break;
case 'center':
if ($width) {
$feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
}
break;
default:
break;
}
$page->drawText($part, $feed, $this->y - $top, 'UTF-8');
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$this->y -= $maxHeight;
}
}
return $page;
}
}
我想在文件末尾回显简单的文本消息,例如 <?php echo "NOTE: This is not a GST invoice. This is a packing slip only."; ?>
请帮助我如何将此消息添加到 pdf 发票格式,正如我在上面的屏幕截图中提到的那样。
非常感谢。
假设您有一个自定义 MyCompany_Invoice
模块:
将以下内容放入 MyCompany/Invoice/etc/di.xml
:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Sales\Model\Order\Pdf\Invoice" type="MyCompany\Invoice\Model\Order\Pdf\InvoicePdf"/>
</config>
现在创建 MyCompany\Invoice\Model\Order\Pdf\InvoicePdf.php
:
<?php
namespace MyCompany\Invoice\Model\Order\Pdf;
use \Magento\Sales\Model\Order\Pdf\Invoice;
class InvoicePdf extends Invoice
{
/**
* We only need to override the getPdf of Invoice,
* most of this method is copied directly from parent class
*
* @param array $invoices
* @return \Zend_Pdf
*/
public function getPdf($invoices = []) {
$this->_beforeGetPdf();
$this->_initRenderer('invoice');
$pdf = new \Zend_Pdf();
$this->_setPdf($pdf);
$style = new \Zend_Pdf_Style();
$this->_setFontBold($style, 10);
foreach ($invoices as $invoice) {
if ($invoice->getStoreId()) {
$this->_localeResolver->emulate($invoice->getStoreId());
$this->_storeManager->setCurrentStore($invoice->getStoreId());
}
$page = $this->newPage();
$order = $invoice->getOrder();
/* Add image */
$this->insertLogo($page, $invoice->getStore());
/* Add address */
$this->insertAddress($page, $invoice->getStore());
/* Add head */
$this->insertOrder(
$page,
$order,
$this->_scopeConfig->isSetFlag(
self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$order->getStoreId()
)
);
/* Add document text and number */
$this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
/* Add table */
$this->_drawHeader($page);
/* Add body */
foreach ($invoice->getAllItems() as $item) {
if ($item->getOrderItem()->getParentItem()) {
continue;
}
/* Draw item */
$this->_drawItem($item, $page, $order);
$page = end($pdf->pages);
}
/* Add totals */
$this->insertTotals($page, $invoice);
if ($invoice->getStoreId()) {
$this->_localeResolver->revert();
}
// draw custom notice
$this->drawNotice($page);
}
$this->_afterGetPdf();
return $pdf;
}
/**
* draw notice below content
*
* @param \Zend_Pdf_Page $page
*/
protected function drawNotice(\Zend_Pdf_Page $page) {
$iFontSize = 10; // font size
$iColumnWidth = 520; // whole page width
$iWidthBorder = 260; // half page width
$sNotice = "NOTE: This is not a GST invoice. This is a packing slip only."; // your message
$iXCoordinateText = 30;
$sEncoding = 'UTF-8';
$this->y -= 10; // move down on page
try {
$oFont = $this->_setFontRegular($page, $iFontSize);
$iXCoordinateText = $this->getAlignCenter($sNotice, $iXCoordinateText, $iColumnWidth, $oFont, $iFontSize); // center text coordinate
$page->setLineColor(new \Zend_Pdf_Color_Rgb(1, 0, 0)); // red lines
$iXCoordinateBorder = $iXCoordinateText - 10; // border is wider than text
// draw top border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw text
$this->y -= 15; // further down
$page->drawText($sNotice, $iXCoordinateText, $this->y, $sEncoding);
$this->y -= 10; // further down
// draw bottom border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw left border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder, $this->y + 25 /* back to first line */);
// draw right border
$page->drawLine($iXCoordinateBorder + $iWidthBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y + 25 /* back to first line */);
$this->y -= 10;
} catch (\Exception $exception) {
// handle
}
}
/**
* Draw header for item table
*
* @param \Zend_Pdf_Page $page
* @return void
*/
protected function _drawHeader(\Zend_Pdf_Page $page)
{
/* Add table head */
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 570, $this->y - 15);
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));
//columns headers
$lines[0][] = ['text' => __('Products'), 'feed' => 35];
$lines[0][] = ['text' => __('SKU'), 'feed' => 290, 'align' => 'right'];
// custom column
$lines[0][] = ['text' => __('HSN'), 'feed' => 290, 'align' => 'right'];
$lines[0][] = ['text' => __('Qty'), 'feed' => 435, 'align' => 'right'];
$lines[0][] = ['text' => __('Price'), 'feed' => 360, 'align' => 'right'];
$lines[0][] = ['text' => __('Tax'), 'feed' => 495, 'align' => 'right'];
$lines[0][] = ['text' => __('Subtotal'), 'feed' => 565, 'align' => 'right'];
$lineBlock = ['lines' => $lines, 'height' => 5];
$this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->y -= 20;
}
}
让我知道您是否需要模块工作所需的其他文件的内容,或者是否有任何不适合您的地方。
我还没有尝试更改文本颜色,因此您可能需要自己寻找解决方案。
编辑:添加自定义 header
我已经从 magento2 销售订单的发票选项生成了发票单,并得到了截图以供参考,请看截图:https://prnt.sc/tje4zn
这是发票pdf的文件路径:/vendor/magento/module-sales/Model/Order/Pdf/AbstractPdf.php下面是文件代码,
<?php
namespace Magento\Sales\Model\Order\Pdf;
use Magento\Framework\App\Filesystem\DirectoryList;
/**
* Sales Order PDF abstract model
*/
abstract class AbstractPdf extends \Magento\Framework\DataObject
{
public $y;
protected $_renderers = [];
const XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID = 'sales_pdf/invoice/put_order_id';
const XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID = 'sales_pdf/shipment/put_order_id';
const XML_PATH_SALES_PDF_CREDITMEMO_PUT_ORDER_ID = 'sales_pdf/creditmemo/put_order_id';
protected $_pdf;
abstract public function getPdf();
protected $_paymentData;
protected $string;
protected $_localeDate;
protected $_scopeConfig;
protected $_mediaDirectory;
protected $_rootDirectory;
protected $_pdfConfig;
protected $_pdfTotalFactory;
protected $_pdfItemsFactory;
protected $inlineTranslation;
protected $addressRenderer;
public function __construct(
\Magento\Payment\Helper\Data $paymentData,
\Magento\Framework\Stdlib\StringUtils $string,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Framework\Filesystem $filesystem,
Config $pdfConfig,
\Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
\Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
\Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
array $data = []
) {
$this->addressRenderer = $addressRenderer;
$this->_paymentData = $paymentData;
$this->_localeDate = $localeDate;
$this->string = $string;
$this->_scopeConfig = $scopeConfig;
$this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
$this->_rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
$this->_pdfConfig = $pdfConfig;
$this->_pdfTotalFactory = $pdfTotalFactory;
$this->_pdfItemsFactory = $pdfItemsFactory;
$this->inlineTranslation = $inlineTranslation;
parent::__construct($data);
}
public function widthForStringUsingFontSize($string, $font, $fontSize)
{
$drawingString = '"libiconv"' == ICONV_IMPL ? iconv(
'UTF-8',
'UTF-16BE//IGNORE',
$string
) : @iconv(
'UTF-8',
'UTF-16BE',
$string
);
$characters = [];
for ($i = 0; $i < strlen($drawingString); $i++) {
$characters[] = ord($drawingString[$i++]) << 8 | ord($drawingString[$i]);
}
$glyphs = $font->glyphNumbersForCharacters($characters);
$widths = $font->widthsForGlyphs($glyphs);
$stringWidth = array_sum($widths) / $font->getUnitsPerEm() * $fontSize;
return $stringWidth;
}
public function getAlignRight($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize, $padding = 5)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + $columnWidth - $width - $padding;
}
public function getAlignCenter($string, $x, $columnWidth, \Zend_Pdf_Resource_Font $font, $fontSize)
{
$width = $this->widthForStringUsingFontSize($string, $font, $fontSize);
return $x + round(($columnWidth - $width) / 2);
}
protected function insertLogo(&$page, $store = null)
{
$this->y = $this->y ? $this->y : 815;
$image = $this->_scopeConfig->getValue(
'sales/identity/logo',
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$store
);
if ($image) {
$imagePath = '/sales/store/logo/' . $image;
if ($this->_mediaDirectory->isFile($imagePath)) {
$image = \Zend_Pdf_Image::imageWithPath($this->_mediaDirectory->getAbsolutePath($imagePath));
$top = 830;
//top border of the page
$widthLimit = 270;
//half of the page width
$heightLimit = 270;
//assuming the image is not a "skyscraper"
$width = $image->getPixelWidth();
$height = $image->getPixelHeight();
//preserving aspect ratio (proportions)
$ratio = $width / $height;
if ($ratio > 1 && $width > $widthLimit) {
$width = $widthLimit;
$height = $width / $ratio;
} elseif ($ratio < 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $height * $ratio;
} elseif ($ratio == 1 && $height > $heightLimit) {
$height = $heightLimit;
$width = $widthLimit;
}
$y1 = $top - $height;
$y2 = $top;
$x1 = 25;
$x2 = $x1 + $width;
//coordinates after transformation are rounded by Zend
$page->drawImage($image, $x1, $y1, $x2, $y2);
$this->y = $y1 - 10;
}
}
}
protected function _formatAddress($address)
{
$return = [];
foreach (explode('|', $address) as $str) {
foreach ($this->string->split($str, 45, true, true) as $part) {
if (empty($part)) {
continue;
}
$return[] = $part;
}
}
return $return;
}
protected function _calcAddressHeight($address)
{
$y = 0;
foreach ($address as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 55, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$y += 15;
}
}
}
return $y;
}
protected function insertOrder(&$page, $obj, $putOrderId = true)
{
if ($obj instanceof \Magento\Sales\Model\Order) {
$shipment = null;
$order = $obj;
} elseif ($obj instanceof \Magento\Sales\Model\Order\Shipment) {
$shipment = $obj;
$order = $shipment->getOrder();
}
$this->y = $this->y ? $this->y : 815;
$top = $this->y;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.45));
$page->drawRectangle(25, $top, 570, $top - 55);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->setDocHeaderCoordinates([25, $top, 570, $top - 55]);
$this->_setFontRegular($page, 10);
if ($putOrderId) {
$page->drawText(__('Order No # ') . $order->getRealOrderId(), 35, $top -= 30, 'UTF-8');
$top +=15;
}
$top -=30;
$page->drawText(
__('Order Date: ') .
$this->_localeDate->formatDate(
$this->_localeDate->scopeDate(
$order->getStore(),
$order->getCreatedAt(),
true
),
\IntlDateFormatter::MEDIUM,
false
),
35,
$top,
'UTF-8'
);
$top -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $top, 275, $top - 25);
$page->drawRectangle(275, $top, 570, $top - 25);
/* Calculate blocks info */
/* Billing Address */
$billingAddress = $this->_formatAddress($this->addressRenderer->format($order->getBillingAddress(), 'pdf'));
/* Payment */
$paymentInfo = $this->_paymentData->getInfoBlock($order->getPayment())->setIsSecureMode(true)->toPdf();
$paymentInfo = htmlspecialchars_decode($paymentInfo, ENT_QUOTES);
$payment = explode('{{pdf_row_separator}}', $paymentInfo);
foreach ($payment as $key => $value) {
if (strip_tags(trim($value)) == '') {
unset($payment[$key]);
}
}
reset($payment);
/* Shipping Address and Method */
if (!$order->getIsVirtual()) {
/* Shipping Address */
$shippingAddress = $this->_formatAddress($this->addressRenderer->format($order->getShippingAddress(), 'pdf'));
$shippingMethod = $order->getShippingDescription();
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontBold($page, 12);
$page->drawText(__('Billed to:'), 35, $top - 15, 'UTF-8');
if (!$order->getIsVirtual()) {
$page->drawText(__('Shipped/Delivery to:'), 285, $top - 15, 'UTF-8');
} else {
$page->drawText(__('Payment Method:'), 285, $top - 15, 'UTF-8');
}
$addressesHeight = $this->_calcAddressHeight($billingAddress);
if (isset($shippingAddress)) {
$addressesHeight = max($addressesHeight, $this->_calcAddressHeight($shippingAddress));
}
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$page->drawRectangle(25, $top - 25, 570, $top - 33 - $addressesHeight);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->_setFontRegular($page, 10);
$this->y = $top - 40;
$addressesStartY = $this->y;
foreach ($billingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 35, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = $this->y;
if (!$order->getIsVirtual()) {
$this->y = $addressesStartY;
foreach ($shippingAddress as $value) {
if ($value !== '') {
$text = [];
foreach ($this->string->split($value, 45, true, true) as $_value) {
$text[] = $_value;
}
foreach ($text as $part) {
$page->drawText(strip_tags(ltrim($part)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
}
}
$addressesEndY = min($addressesEndY, $this->y);
$this->y = $addressesEndY;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 275, $this->y - 25);
$page->drawRectangle(275, $this->y, 570, $this->y - 25);
$this->y -= 15;
$this->_setFontBold($page, 12);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$page->drawText(__('Payment Method'), 35, $this->y, 'UTF-8');
$page->drawText(__('Shipping Method:'), 285, $this->y, 'UTF-8');
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$paymentLeft = 35;
$yPayments = $this->y - 15;
} else {
$yPayments = $addressesStartY;
$paymentLeft = 285;
}
foreach ($payment as $value) {
if (trim($value) != '') {
//Printing "Payment Method" lines
$value = preg_replace('/<br[^>]*>/i', "\n", $value);
foreach ($this->string->split($value, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), $paymentLeft, $yPayments, 'UTF-8');
$yPayments -= 15;
}
}
}
if ($order->getIsVirtual()) {
// replacement of Shipments-Payments rectangle block
$yPayments = min($addressesEndY, $yPayments);
$page->drawLine(25, $top - 25, 25, $yPayments);
$page->drawLine(570, $top - 25, 570, $yPayments);
$page->drawLine(25, $yPayments, 570, $yPayments);
$this->y = $yPayments - 15;
} else {
$topMargin = 15;
$methodStartY = $this->y;
$this->y -= 15;
foreach ($this->string->split($shippingMethod, 45, true, true) as $_value) {
$page->drawText(strip_tags(trim($_value)), 285, $this->y, 'UTF-8');
$this->y -= 15;
}
$yShipments = $this->y;
$totalShippingChargesText = "(" . __(
'Total Shipping Charges'
) . " " . $order->formatPriceTxt(
$order->getShippingAmount()
) . ")";
$page->drawText($totalShippingChargesText, 285, $yShipments - $topMargin, 'UTF-8');
$yShipments -= $topMargin + 10;
$tracks = [];
if ($shipment) {
$tracks = $shipment->getAllTracks();
}
if (count($tracks)) {
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineWidth(0.5);
$page->drawRectangle(285, $yShipments, 510, $yShipments - 10);
$page->drawLine(400, $yShipments, 400, $yShipments - 10);
//$page->drawLine(510, $yShipments, 510, $yShipments - 10);
$this->_setFontRegular($page, 9);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
//$page->drawText(__('Carrier'), 290, $yShipments - 7 , 'UTF-8');
$page->drawText(__('Title'), 290, $yShipments - 7, 'UTF-8');
$page->drawText(__('Number'), 410, $yShipments - 7, 'UTF-8');
$yShipments -= 20;
$this->_setFontRegular($page, 8);
foreach ($tracks as $track) {
$maxTitleLen = 45;
$endOfTitle = strlen($track->getTitle()) > $maxTitleLen ? '...' : '';
$truncatedTitle = substr($track->getTitle(), 0, $maxTitleLen) . $endOfTitle;
$page->drawText($truncatedTitle, 292, $yShipments, 'UTF-8');
$page->drawText($track->getNumber(), 410, $yShipments, 'UTF-8');
$yShipments -= $topMargin - 5;
}
} else {
$yShipments -= $topMargin - 5;
}
$currentY = min($yPayments, $yShipments);
$page->drawLine(25, $methodStartY, 25, $currentY);
$page->drawLine(25, $currentY, 570, $currentY);
$page->drawLine(570, $currentY, 570, $methodStartY);
$this->y = $currentY;
$this->y -= 15;
}
}
public function insertDocumentNumber(\Zend_Pdf_Page $page, $text)
{
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(1));
$this->_setFontRegular($page, 10);
$docHeader = $this->getDocHeaderCoordinates();
$page->drawText($text, 35, $docHeader[1] - 15, 'UTF-8');
}
protected function _sortTotalsList($a, $b)
{
if (!isset($a['sort_order']) || !isset($b['sort_order'])) {
return 0;
}
if ($a['sort_order'] == $b['sort_order']) {
return 0;
}
return $a['sort_order'] > $b['sort_order'] ? 1 : -1;
}
protected function _getTotalsList()
{
$totals = $this->_pdfConfig->getTotals();
usort($totals, [$this, '_sortTotalsList']);
$totalModels = [];
foreach ($totals as $totalInfo) {
$class = empty($totalInfo['model']) ? null : $totalInfo['model'];
$totalModel = $this->_pdfTotalFactory->create($class);
$totalModel->setData($totalInfo);
$totalModels[] = $totalModel;
}
return $totalModels;
}
protected function insertTotals($page, $source)
{
$order = $source->getOrder();
$totals = $this->_getTotalsList();
$lineBlock = ['lines' => [], 'height' => 15];
foreach ($totals as $total) {
$total->setOrder($order)->setSource($source);
if ($total->canDisplay()) {
$total->setFontSize(10);
foreach ($total->getTotalsForDisplay() as $totalData) {
$lineBlock['lines'][] = [
[
'text' => $totalData['label'],
'feed' => 475,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold',
],
[
'text' => $totalData['amount'],
'feed' => 565,
'align' => 'right',
'font_size' => $totalData['font_size'],
'font' => 'bold'
],
];
}
}
}
$this->y -= 20;
$page = $this->drawLineBlocks($page, [$lineBlock]);
return $page;
}
protected function _parseItemDescription($item)
{
$matches = [];
$description = $item->getDescription();
if (preg_match_all('/<li.*?>(.*?)<\/li>/i', $description, $matches)) {
return $matches[1];
}
return [$description];
}
protected function _beforeGetPdf()
{
$this->inlineTranslation->suspend();
}
protected function _afterGetPdf()
{
$this->inlineTranslation->resume();
}
protected function _formatOptionValue($value, $order)
{
$resultValue = '';
if (is_array($value)) {
if (isset($value['qty'])) {
$resultValue .= sprintf('%d', $value['qty']) . ' x ';
}
$resultValue .= $value['title'];
if (isset($value['price'])) {
$resultValue .= " " . $order->formatPrice($value['price']);
}
return $resultValue;
} else {
return $value;
}
}
protected function _initRenderer($type)
{
$rendererData = $this->_pdfConfig->getRenderersPerProduct($type);
foreach ($rendererData as $productType => $renderer) {
$this->_renderers[$productType] = ['model' => $renderer, 'renderer' => null];
}
}
protected function _getRenderer($type)
{
if (!isset($this->_renderers[$type])) {
$type = 'default';
}
if (!isset($this->_renderers[$type])) {
throw new \Magento\Framework\Exception\LocalizedException(__('We found an invalid renderer model.'));
}
if ($this->_renderers[$type]['renderer'] === null) {
$this->_renderers[$type]['renderer'] = $this->_pdfItemsFactory->get($this->_renderers[$type]['model']);
}
return $this->_renderers[$type]['renderer'];
}
public function getRenderer($type)
{
return $this->_getRenderer($type);
}
protected function _drawItem(\Magento\Framework\DataObject $item, \Zend_Pdf_Page $page, \Magento\Sales\Model\Order $order)
{
$type = $item->getOrderItem()->getProductType();
$renderer = $this->_getRenderer($type);
$renderer->setOrder($order);
$renderer->setItem($item);
$renderer->setPdf($this);
$renderer->setPage($page);
$renderer->setRenderedModel($this);
$renderer->draw();
return $renderer->getPage();
}
protected function _setFontRegular($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerif.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontBold($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifBold.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setFontItalic($object, $size = 7)
{
$font = \Zend_Pdf_Font::fontWithPath(
$this->_rootDirectory->getAbsolutePath('lib/internal/GnuFreeFont/FreeSerifItalic.ttf')
);
$object->setFont($font, $size);
return $font;
}
protected function _setPdf(\Zend_Pdf $pdf)
{
$this->_pdf = $pdf;
return $this;
}
protected function _getPdf()
{
if (!$this->_pdf instanceof \Zend_Pdf) {
throw new \Magento\Framework\Exception\LocalizedException(__('Please define the PDF object before using.'));
}
return $this->_pdf;
}
public function newPage(array $settings = [])
{
$pageSize = !empty($settings['page_size']) ? $settings['page_size'] : \Zend_Pdf_Page::SIZE_A4;
$page = $this->_getPdf()->newPage($pageSize);
$this->_getPdf()->pages[] = $page;
$this->y = 800;
return $page;
}
public function drawLineBlocks(\Zend_Pdf_Page $page, array $draw, array $pageSettings = [])
{
foreach ($draw as $itemsProp) {
if (!isset($itemsProp['lines']) || !is_array($itemsProp['lines'])) {
throw new \Magento\Framework\Exception\LocalizedException(
__('We don\'t recognize the draw line data. Please define the "lines" array.')
);
}
$lines = $itemsProp['lines'];
$height = isset($itemsProp['height']) ? $itemsProp['height'] : 10;
if (empty($itemsProp['shift'])) {
$shift = 0;
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$top = 0;
foreach ($column['text'] as $part) {
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$shift += $maxHeight;
}
$itemsProp['shift'] = $shift;
}
if ($this->y - $itemsProp['shift'] < 15) {
$page = $this->newPage($pageSettings);
}
foreach ($lines as $line) {
$maxHeight = 0;
foreach ($line as $column) {
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
if (!is_array($column['text'])) {
$column['text'] = [$column['text']];
}
$lineSpacing = !empty($column['height']) ? $column['height'] : $height;
$top = 0;
foreach ($column['text'] as $part) {
if ($this->y - $lineSpacing < 15) {
$page = $this->newPage($pageSettings);
$font = $this->setFont($page, $column);
$fontSize = $column['font_size'];
}
$feed = $column['feed'];
$textAlign = empty($column['align']) ? 'left' : $column['align'];
$width = empty($column['width']) ? 0 : $column['width'];
switch ($textAlign) {
case 'right':
if ($width) {
$feed = $this->getAlignRight($part, $feed, $width, $font, $fontSize);
} else {
$feed = $feed - $this->widthForStringUsingFontSize($part, $font, $fontSize);
}
break;
case 'center':
if ($width) {
$feed = $this->getAlignCenter($part, $feed, $width, $font, $fontSize);
}
break;
default:
break;
}
$page->drawText($part, $feed, $this->y - $top, 'UTF-8');
$top += $lineSpacing;
}
$maxHeight = $top > $maxHeight ? $top : $maxHeight;
}
$this->y -= $maxHeight;
}
}
return $page;
}
}
我想在文件末尾回显简单的文本消息,例如 <?php echo "NOTE: This is not a GST invoice. This is a packing slip only."; ?>
请帮助我如何将此消息添加到 pdf 发票格式,正如我在上面的屏幕截图中提到的那样。
非常感谢。
假设您有一个自定义 MyCompany_Invoice
模块:
将以下内容放入 MyCompany/Invoice/etc/di.xml
:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="Magento\Sales\Model\Order\Pdf\Invoice" type="MyCompany\Invoice\Model\Order\Pdf\InvoicePdf"/>
</config>
现在创建 MyCompany\Invoice\Model\Order\Pdf\InvoicePdf.php
:
<?php
namespace MyCompany\Invoice\Model\Order\Pdf;
use \Magento\Sales\Model\Order\Pdf\Invoice;
class InvoicePdf extends Invoice
{
/**
* We only need to override the getPdf of Invoice,
* most of this method is copied directly from parent class
*
* @param array $invoices
* @return \Zend_Pdf
*/
public function getPdf($invoices = []) {
$this->_beforeGetPdf();
$this->_initRenderer('invoice');
$pdf = new \Zend_Pdf();
$this->_setPdf($pdf);
$style = new \Zend_Pdf_Style();
$this->_setFontBold($style, 10);
foreach ($invoices as $invoice) {
if ($invoice->getStoreId()) {
$this->_localeResolver->emulate($invoice->getStoreId());
$this->_storeManager->setCurrentStore($invoice->getStoreId());
}
$page = $this->newPage();
$order = $invoice->getOrder();
/* Add image */
$this->insertLogo($page, $invoice->getStore());
/* Add address */
$this->insertAddress($page, $invoice->getStore());
/* Add head */
$this->insertOrder(
$page,
$order,
$this->_scopeConfig->isSetFlag(
self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID,
\Magento\Store\Model\ScopeInterface::SCOPE_STORE,
$order->getStoreId()
)
);
/* Add document text and number */
$this->insertDocumentNumber($page, __('Invoice # ') . $invoice->getIncrementId());
/* Add table */
$this->_drawHeader($page);
/* Add body */
foreach ($invoice->getAllItems() as $item) {
if ($item->getOrderItem()->getParentItem()) {
continue;
}
/* Draw item */
$this->_drawItem($item, $page, $order);
$page = end($pdf->pages);
}
/* Add totals */
$this->insertTotals($page, $invoice);
if ($invoice->getStoreId()) {
$this->_localeResolver->revert();
}
// draw custom notice
$this->drawNotice($page);
}
$this->_afterGetPdf();
return $pdf;
}
/**
* draw notice below content
*
* @param \Zend_Pdf_Page $page
*/
protected function drawNotice(\Zend_Pdf_Page $page) {
$iFontSize = 10; // font size
$iColumnWidth = 520; // whole page width
$iWidthBorder = 260; // half page width
$sNotice = "NOTE: This is not a GST invoice. This is a packing slip only."; // your message
$iXCoordinateText = 30;
$sEncoding = 'UTF-8';
$this->y -= 10; // move down on page
try {
$oFont = $this->_setFontRegular($page, $iFontSize);
$iXCoordinateText = $this->getAlignCenter($sNotice, $iXCoordinateText, $iColumnWidth, $oFont, $iFontSize); // center text coordinate
$page->setLineColor(new \Zend_Pdf_Color_Rgb(1, 0, 0)); // red lines
$iXCoordinateBorder = $iXCoordinateText - 10; // border is wider than text
// draw top border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw text
$this->y -= 15; // further down
$page->drawText($sNotice, $iXCoordinateText, $this->y, $sEncoding);
$this->y -= 10; // further down
// draw bottom border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y);
// draw left border
$page->drawLine($iXCoordinateBorder, $this->y, $iXCoordinateBorder, $this->y + 25 /* back to first line */);
// draw right border
$page->drawLine($iXCoordinateBorder + $iWidthBorder, $this->y, $iXCoordinateBorder + $iWidthBorder, $this->y + 25 /* back to first line */);
$this->y -= 10;
} catch (\Exception $exception) {
// handle
}
}
/**
* Draw header for item table
*
* @param \Zend_Pdf_Page $page
* @return void
*/
protected function _drawHeader(\Zend_Pdf_Page $page)
{
/* Add table head */
$this->_setFontRegular($page, 10);
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0.93, 0.92, 0.92));
$page->setLineColor(new \Zend_Pdf_Color_GrayScale(0.5));
$page->setLineWidth(0.5);
$page->drawRectangle(25, $this->y, 570, $this->y - 15);
$this->y -= 10;
$page->setFillColor(new \Zend_Pdf_Color_Rgb(0, 0, 0));
//columns headers
$lines[0][] = ['text' => __('Products'), 'feed' => 35];
$lines[0][] = ['text' => __('SKU'), 'feed' => 290, 'align' => 'right'];
// custom column
$lines[0][] = ['text' => __('HSN'), 'feed' => 290, 'align' => 'right'];
$lines[0][] = ['text' => __('Qty'), 'feed' => 435, 'align' => 'right'];
$lines[0][] = ['text' => __('Price'), 'feed' => 360, 'align' => 'right'];
$lines[0][] = ['text' => __('Tax'), 'feed' => 495, 'align' => 'right'];
$lines[0][] = ['text' => __('Subtotal'), 'feed' => 565, 'align' => 'right'];
$lineBlock = ['lines' => $lines, 'height' => 5];
$this->drawLineBlocks($page, [$lineBlock], ['table_header' => true]);
$page->setFillColor(new \Zend_Pdf_Color_GrayScale(0));
$this->y -= 20;
}
}
让我知道您是否需要模块工作所需的其他文件的内容,或者是否有任何不适合您的地方。
我还没有尝试更改文本颜色,因此您可能需要自己寻找解决方案。
编辑:添加自定义 header