Files
stemcell/app/code/Stemcell/Sales/Model/Export/ConvertToCsv.php
T
2026-09-15 10:26:34 +08:00

263 lines
9.7 KiB
PHP

<?php
namespace Stemcell\Sales\Model\Export;
use Magento\Framework\Exception\FileSystemException;
use Magento\Framework\Exception\LocalizedException;
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 Magento\Ui\Component\MassAction\Filter;
use Magento\Ui\Model\Export\MetadataProvider;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use Psr\Log\LoggerInterface;
class ConvertToCsv extends \Magento\Ui\Model\Export\ConvertToCsv
{
private Item\Collection $itemCollection;
private Filesystem\DirectoryList $directoryList;
public function __construct(
Filesystem $filesystem,
Filter $filter,
MetadataProvider $metadataProvider,
Item\Collection $itemCollection,
Filesystem\DirectoryList $directoryList,
protected LoggerInterface $logger,
$pageSize = 200
) {
parent::__construct($filesystem, $filter, $metadataProvider, $pageSize);
$this->itemCollection = $itemCollection;
$this->directoryList = $directoryList;
}
/**
* @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 '';
}
/**
* @param \Magento\Sales\Model\Order\Item $orderItem
* @param array $fields
* @return array
*/
public function getRowData(\Magento\Sales\Model\Order\Item $orderItem, array $fields): array
{
$timezone = ObjectManager::getInstance()->get(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class);
$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' => '¥'.number_format($orderItem->getData('grand_total'), 2),
'price' => number_format(floatval($orderItem->getPrice()), 2),
'status' => $this->getOrderStatusLabel($orderItem->getOrder()),
'row_total' => $this->getRowTotal($orderItem),
'name' => $orderItem->getProductOptionByCode('simple_name')?? $orderItem->getName(),
'created_at' => $timezone->date($orderItem->getData($column))->format('Y-m-d H:i:s'),
default => $orderItem->getData($column),
};
if ($value!=null && trim($value)=='-') $value = null;
$row[] = $value;
}
return $row;
}
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 Item\Collection
*/
protected function getCollection(array $ordersId) {
$this->itemCollection->addFieldToSelect([
'sku', 'name', 'qty_ordered', 'row_total', 'cd', 'quote', 'lab_code', 'company', 'user', 'pi', 'pi_sap_id',
'user_tel', 'user_email', 'note', 'user_type', 'order_id', 'price', 'customer_discount_percent', 'product_options'
])
->addFieldToFilter('main_table.order_id', ['in'=>$ordersId])
->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', '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',
]
);
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'
];
}
/**
* @throws FileSystemException
* @throws LocalizedException
* @throws Exception
* @throws \PhpOffice\PhpSpreadsheet\Exception
*/
public function getCsvFile()
{
/* @var $logger LoggerInterface */
$logger = ObjectManager::getInstance()->get(LoggerInterface::class);
/* @var $component \Magento\Ui\Component\Listing */
$component = $this->filter->getComponent();
// md5() here is not for cryptographic use.
// phpcs:ignore Magento2.Security.InsecureFunction
$name = md5(microtime());
$file = 'export/'. $component->getName() . $name . '.xlsx';
$this->filter->prepareComponent($component);
$this->filter->applySelectionOnTargetProvider();
/* @var $dataProvider \Magento\Framework\View\Element\UiComponent\DataProvider\DataProvider */
$dataProvider = $component->getContext()->getDataProvider();
$fields = $this->getFields();
$this->directory->create('export');
$filePath = $this->directoryList->getPath('var').'/'.$file;
$dataProvider->setLimit(0, 100);
$ordersId = [];
$items = $dataProvider->getSearchResult()->getItems();
foreach ($items as $item) {
/* @var $item \Magento\Framework\View\Element\UiComponent\DataProvider\Document */
$ordersId[] = $item->getId();
}
$collection = $this->getCollection($ordersId);
$dataGroupByOrderId = [];
foreach ($collection as $item) {
/* @var $item \Magento\Sales\Model\Order\Item */
$dataGroupByOrderId[$item->getOrderId()][] = $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, '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);
krsort($dataGroupByOrderId);
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++;
}
}
$writer->save($filePath);
return [
'type' => 'filename',
'value' => $file,
'rm' => true // can delete file after use
];
}
}