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; } }