314 lines
12 KiB
PHP
314 lines
12 KiB
PHP
<?php
|
|
|
|
namespace Stemcell\Sales\Model\Order\Email\Attachment;
|
|
|
|
use Magento\Framework\App\Filesystem\DirectoryList;
|
|
use Magento\Framework\Exception\FileSystemException;
|
|
use Magento\Framework\Exception\LocalizedException;
|
|
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
|
|
use Magento\Framework\UrlInterface;
|
|
use \PhpOffice\PhpSpreadsheet\IOFactory;
|
|
use PhpOffice\PhpSpreadsheet\Reader\Exception;
|
|
use Magento\Framework\App\ObjectManager;
|
|
use Magento\Framework\Filesystem;
|
|
use Magento\Sales\Model\ResourceModel\Order\Item;
|
|
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
|
use Psr\Log\LoggerInterface;
|
|
use Stemcell\Customer\Api\Data\SalespersonInterface;
|
|
use Stemcell\Sales\Model\Order\Email\Sender\OrderSender;
|
|
|
|
class Order
|
|
{
|
|
private Item\Collection $itemCollection;
|
|
private Filesystem\DirectoryList $directoryList;
|
|
private Filesystem\Directory\WriteInterface $directory;
|
|
private \Magento\Store\Model\StoreManagerInterface $storeManager;
|
|
|
|
protected SalespersonInterface $salesperson;
|
|
|
|
protected OrderSender $orderSender;
|
|
|
|
protected \Magento\Sales\Model\Order $order;
|
|
|
|
/**
|
|
* @var \Magento\Sales\Model\Order\Item[]
|
|
*/
|
|
protected array $orderItems;
|
|
/**
|
|
* @throws FileSystemException
|
|
*/
|
|
public function __construct(
|
|
Filesystem $filesystem,
|
|
Item\Collection $itemCollection,
|
|
Filesystem\DirectoryList $directoryList,
|
|
\Magento\Store\Model\StoreManagerInterface $storeManager,
|
|
protected LoggerInterface $logger,
|
|
protected TimezoneInterface $timezone
|
|
) {
|
|
$this->itemCollection = $itemCollection;
|
|
$this->directoryList = $directoryList;
|
|
$this->storeManager = $storeManager;
|
|
$this->directory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
|
|
}
|
|
|
|
/**
|
|
* @return string[]
|
|
*/
|
|
protected function getHeaders() {
|
|
return [
|
|
'订单编号',
|
|
'订单金额',
|
|
'经销商',
|
|
'销售',
|
|
'下单时间',
|
|
'订单状态',
|
|
'货号',
|
|
'商品名称',
|
|
'经销商价格(¥)',
|
|
'数量',
|
|
'CD号',
|
|
'Quote号',
|
|
'折扣',
|
|
'总金额(¥)',
|
|
'订货账户',
|
|
'账户名称',
|
|
'PI SAP ID',
|
|
// '最终用户单位',
|
|
// 'PI',
|
|
// '最终使用人',
|
|
// '联系电话',
|
|
// '邮箱地址',
|
|
'终端类型',
|
|
'备注',
|
|
'订单备注',
|
|
];
|
|
}
|
|
|
|
protected function getOrderStatusLabel(\Magento\Sales\Model\Order $order)
|
|
{
|
|
try {
|
|
return $order->getStatusLabel();
|
|
} catch (LocalizedException $e) {
|
|
$this->logger->critical(
|
|
sprintf(
|
|
'获取订单:: %s 的status: %s label失败, 原因:%s',
|
|
$order->getIncrementId(),
|
|
$order->getStatus(),
|
|
$e->getMessage()
|
|
)
|
|
);
|
|
}
|
|
return '';
|
|
}
|
|
|
|
public function getCurrentTimezoneTime(string $time)
|
|
{
|
|
try {
|
|
$time = $this->timezone->date(new \DateTime($time))->format('Y-m-d H:i:s');
|
|
} catch (\Exception $e) {
|
|
$this->logger->critical('发给销售的邮件附件在做数据转换时异常: ' . $e->getMessage());
|
|
}
|
|
return $time;
|
|
}
|
|
|
|
/**
|
|
* 同一笔订单,可能因为用户在购物车给不同商品选择的账户(lab)不一样,这时对应的销售(salesperson)可能不一样,
|
|
* 因此同一个订单需要根据销售来拆分,这就导致同一个订单可能发多个邮件给不同的销售。因此这个的order_items并不是订单的全部items。
|
|
* 此数据来源于\Stemcell\Sales\Observer\SalespersonNotify。
|
|
* 故此,grand_total的不能用order的grand total
|
|
* @param \Magento\Sales\Model\Order\Item $orderItem
|
|
* @param array $fields
|
|
* @return array
|
|
*/
|
|
public function getRowData(\Magento\Sales\Model\Order\Item $orderItem, array $fields): array
|
|
{
|
|
$row = [];
|
|
foreach ($fields as $column) {
|
|
|
|
$value = match ($column) {
|
|
'booking_account' => $orderItem->getData('booking_account'),
|
|
'user_type' => $orderItem->getData('user_type') == 0 ? '终端' : '二级经销商',
|
|
'customer_discount_percent' => $this->getCustomerDiscountPercent($orderItem),
|
|
'grand_total' => $this->getGrandTotal(),
|
|
'price' => number_format($orderItem->getData('price'), 2),
|
|
'row_total' => $this->getRowTotal($orderItem),
|
|
'status' => $this->getOrderStatusLabel($orderItem->getOrder()),
|
|
'salesperson_name' => $orderItem->getData('salesperson_name'),
|
|
'created_at' => $this->getCurrentTimezoneTime($orderItem->getData('created_at')),
|
|
'name' => $this->getProductName($orderItem),
|
|
default => $orderItem->getData($column),
|
|
};
|
|
|
|
if ($value!=null && trim($value)=='-') $value = null;
|
|
$row[] = $value;
|
|
}
|
|
|
|
return $row;
|
|
}
|
|
|
|
protected function getProductName(\Magento\Sales\Model\Order\Item $orderItem): string
|
|
{
|
|
return $orderItem->getProductOptionByCode('simple_name')?? $orderItem->getName();
|
|
}
|
|
protected function getCustomerDiscountPercent(\Magento\Sales\Model\Order\Item $orderItem): string
|
|
{
|
|
$discountPercent = $orderItem->getData('customer_discount_percent');
|
|
return $discountPercent == 0 ? '' : number_format($discountPercent, 2).'%';
|
|
}
|
|
|
|
protected function getRowTotal(\Magento\Sales\Model\Order\Item $orderItem): string
|
|
{
|
|
return number_format($orderItem->getRowTotal(), 2);
|
|
}
|
|
|
|
/**
|
|
* @return int[]
|
|
*/
|
|
protected function getOrderItemsId(): array
|
|
{
|
|
return array_map(function (\Magento\Sales\Model\Order\Item $item){
|
|
return $item->getItemId();
|
|
}, $this->order->getAllVisibleItems());
|
|
}
|
|
|
|
protected function getGrandTotal(): string
|
|
{
|
|
return '¥'.number_format($this->order->getGrandTotal(), 2);
|
|
}
|
|
/**
|
|
* @return Item\Collection
|
|
*/
|
|
protected function getCollection(array $ordersId) {
|
|
$this->itemCollection->addFieldToSelect([
|
|
'sku', 'name', 'price', 'qty_ordered', 'cd', 'quote', 'customer_discount_percent', 'row_total', 'lab_code',
|
|
// 'company', 'user',
|
|
'pi_sap_id',
|
|
// 'user_tel', 'user_email',
|
|
'note', 'user_type', 'order_id', 'product_options'
|
|
])
|
|
->addFieldToFilter('main_table.item_id', ['in'=>$this->getOrderItemsId()])
|
|
->addFieldToFilter('main_table.parent_item_id', ['null' => true])
|
|
->getSelect()
|
|
->join(
|
|
'sales_order',
|
|
'main_table.order_id=sales_order.entity_id',
|
|
[
|
|
'increment_id', 'grand_total', 'customer_firstname', 'created_at', 'status', 'sales_order.salesperson_id',
|
|
'customer_note'
|
|
]
|
|
)
|
|
->joinLeft(
|
|
'salesperson',
|
|
'salesperson.salesperson_id=sales_order.salesperson_id',
|
|
[
|
|
'salesperson_name' => 'salesperson.name'
|
|
|
|
]
|
|
)->joinLeft(
|
|
'lab',
|
|
'lab.lab_id=main_table.lab_id',
|
|
[
|
|
'lab_code' => 'lab.lab_code',
|
|
'booking_account' => 'lab.booking_account',
|
|
'pi_sap_id' => 'lab.pi_sap_id',
|
|
]
|
|
);
|
|
$this->logger->debug('create order attachment sql: '.$this->itemCollection->getSelectSql(true));
|
|
return $this->itemCollection;
|
|
}
|
|
|
|
protected function getFields() {
|
|
return [
|
|
'increment_id', 'grand_total', 'customer_firstname', 'salesperson_name', 'created_at', 'status', 'sku',
|
|
'name', 'price', 'qty_ordered', 'cd', 'quote', 'customer_discount_percent',
|
|
'row_total', 'lab_code', 'booking_account', 'pi_sap_id',
|
|
// 'company', 'pi', 'user', 'user_tel', 'user_email',
|
|
'user_type', 'note', 'customer_note'
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param \Magento\Sales\Model\Order $order
|
|
* @return string
|
|
*/
|
|
protected function getShippingAddress(\Magento\Sales\Model\Order $order)
|
|
{
|
|
$address = $order->getShippingAddress();
|
|
return '收货地址: '.$address->getRegion() . ' ' . $address->getCity() . ' '
|
|
. implode(' ', $address->getStreet());
|
|
}
|
|
/**
|
|
* @param \Magento\Sales\Model\Order $order
|
|
* @param OrderSender $orderSender
|
|
* @return string
|
|
* @throws FileSystemException
|
|
* @throws \PhpOffice\PhpSpreadsheet\Exception
|
|
* @throws \PhpOffice\PhpSpreadsheet\Writer\Exception
|
|
*/
|
|
public function getFile(\Magento\Sales\Model\Order $order, OrderSender $orderSender)
|
|
{
|
|
$this->order = $order;
|
|
$this->orderSender = $orderSender;
|
|
$name = md5(microtime());
|
|
$file = 'attachment/'. $name . '.xlsx';
|
|
|
|
$fields = $this->getFields();
|
|
|
|
$this->directory->create('attachment');
|
|
$filePath = $this->directoryList->getPath(UrlInterface::URL_TYPE_MEDIA).'/'.$file;
|
|
|
|
$ordersId = [$order->getId()];
|
|
|
|
$collection = $this->getCollection($ordersId);
|
|
|
|
$dataGroupByOrderId = [];
|
|
foreach ($collection as $item) {
|
|
/* @var $item \Magento\Sales\Model\Order\Item */
|
|
$dataGroupByOrderId[$item->getData('salesperson_id')][] = $this->getRowData($item, $fields);
|
|
}
|
|
$styles = [
|
|
'alignment' => [
|
|
'vertical' => \PhpOffice\PhpSpreadsheet\Style\Alignment::VERTICAL_CENTER,
|
|
'horizontal' => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,
|
|
],
|
|
];
|
|
$rowIndex = 2;
|
|
$spreadSheet = new Spreadsheet();
|
|
$writer = IOFactory::createWriter($spreadSheet, IOFactory::WRITER_XLSX);
|
|
$worksheet = $spreadSheet->getActiveSheet();
|
|
$columnIndex = 'A';
|
|
foreach ($this->getHeaders() as $row) {
|
|
$cell = $worksheet->getCell($columnIndex.'1');
|
|
$cell->getAppliedStyle()->applyFromArray($styles);
|
|
$cell->setValue($row);
|
|
$columnIndex++;
|
|
}
|
|
$worksheet->getRowDimension(1)->setRowHeight(20);
|
|
foreach ($dataGroupByOrderId as $rows) {
|
|
$rowCount = count($rows);
|
|
$mergeColumnsIndex = ['A', 'B', 'C', 'D', 'E', 'F', 'T'];
|
|
foreach ($mergeColumnsIndex as $index) {
|
|
$worksheet->mergeCells($index.$rowIndex.':'.$index.$rowIndex+$rowCount-1);
|
|
}
|
|
foreach ($rows as $row) {
|
|
$columnIndex = 'A';
|
|
foreach ($row as $value) {
|
|
$worksheet->getColumnDimension($columnIndex)->setWidth(15);
|
|
$worksheet->getRowDimension($rowIndex)->setRowHeight(20);
|
|
$cell = $worksheet->getCell($columnIndex.$rowIndex);
|
|
$cell->getAppliedStyle()->applyFromArray($styles);
|
|
$cell->setValue($value);
|
|
$columnIndex++;
|
|
}
|
|
$rowIndex++;
|
|
}
|
|
}
|
|
$worksheet->mergeCells("A{$rowIndex}:$columnIndex{$rowIndex}");
|
|
$worksheet->setCellValue("A{$rowIndex}", $this->getShippingAddress($order));
|
|
$writer->save($filePath);
|
|
$content = $this->directory->readFile($filePath);
|
|
$this->directory->delete($filePath);
|
|
return $content;
|
|
}
|
|
}
|