Skip to content

Commit c363301

Browse files
committed
Initial commit
1 parent 5cdfcca commit c363301

File tree

18 files changed

+873
-2
lines changed

18 files changed

+873
-2
lines changed

Api/OrderListInterface.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
/**
3+
* ManiyaTech
4+
*
5+
* @author Milan Maniya
6+
* @package ManiyaTech_OrderApi
7+
*/
8+
9+
namespace ManiyaTech\OrderApi\Api;
10+
11+
interface OrderListInterface
12+
{
13+
/**
14+
* Get order list with grand total as configured threshold and within defined date range
15+
*
16+
* @return \Magento\Sales\Api\Data\OrderInterface[]|array
17+
*/
18+
public function getOrders(): array;
19+
}
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
<?php
2+
/**
3+
* ManiyaTech
4+
*
5+
* @author Milan Maniya
6+
* @package ManiyaTech_OrderApi
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace ManiyaTech\OrderApi\Console\Command;
12+
13+
use Magento\Framework\App\State;
14+
use Symfony\Component\Console\Command\Command;
15+
use Symfony\Component\Console\Input\InputInterface;
16+
use Symfony\Component\Console\Output\OutputInterface;
17+
use ManiyaTech\OrderApi\Model\OrderList;
18+
19+
class OrderListCommand extends Command
20+
{
21+
/**
22+
* @var OrderList
23+
*/
24+
private OrderList $orderList;
25+
26+
/**
27+
* @var State
28+
*/
29+
private State $appState;
30+
31+
/**
32+
* OrderListCommand Constructor.
33+
*
34+
* @param OrderList $orderList Provides filtered order data.
35+
* @param State $appState Sets the Magento application area.
36+
*/
37+
public function __construct(
38+
OrderList $orderList,
39+
State $appState
40+
) {
41+
$this->orderList = $orderList;
42+
$this->appState = $appState;
43+
parent::__construct();
44+
}
45+
46+
/**
47+
* Configure the CLI command.
48+
*
49+
* @return void
50+
*/
51+
protected function configure(): void
52+
{
53+
$grandTotalThreshold = $this->orderList->getConfigValue(OrderList::XML_PATH_GRAND_TOTAL);
54+
$days = $this->orderList->getConfigValue(OrderList::XML_PATH_EXPORT_DAYS);
55+
56+
$description = sprintf(
57+
'List orders with total > %s from last %s days (store timezone)',
58+
$grandTotalThreshold,
59+
$days
60+
);
61+
62+
$this->setName('order:orderlist')->setDescription($description);
63+
}
64+
65+
/**
66+
* Execute the command.
67+
*
68+
* @param InputInterface $input Input interface.
69+
* @param OutputInterface $output Output interface.
70+
* @return int Exit code.
71+
*/
72+
protected function execute(InputInterface $input, OutputInterface $output): int
73+
{
74+
try {
75+
$this->appState->setAreaCode('adminhtml');
76+
} catch (\Throwable $e) {
77+
$output->writeln("<error>Error: {$e->getMessage()}</error>");
78+
}
79+
80+
if (!$this->orderList->isModuleEnabled()) {
81+
$output->writeln('<info>Please enable the module in configuration first.</info>');
82+
return Command::SUCCESS;
83+
}
84+
85+
$orders = $this->orderList->getOrders();
86+
87+
if (empty($orders)) {
88+
$output->writeln('<info>No orders found for the given criteria.</info>');
89+
return Command::SUCCESS;
90+
}
91+
92+
foreach ($orders as $order) {
93+
$output->writeln(str_repeat('-', 50));
94+
$output->writeln("Order ID : {$order['increment_id']}");
95+
$output->writeln("Customer Name : " . ($order['billing_name'] ?? 'N/A'));
96+
$output->writeln("Total Amount : {$order['grand_total']}");
97+
$output->writeln("Status : " . ($order['order_status'] ?? 'N/A'));
98+
$output->writeln("Date : " . ($order['order_date'] ?? 'N/A'));
99+
$output->writeln("Payment Method : " . ($order['payment_title'] ?? $order['payment_method'] ?? 'N/A'));
100+
$output->writeln("Shipping Desc : " . ($order['shipping_description'] ?? 'N/A'));
101+
$output->writeln("Shipping Amt : " . ($order['shipping_amount'] ?? '0'));
102+
$output->writeln("Shipping Incl : " . ($order['shipping_incl_tax'] ?? '0'));
103+
}
104+
105+
return Command::SUCCESS;
106+
}
107+
}

Cron/Orders.php

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<?php
2+
/**
3+
* ManiyaTech
4+
*
5+
* @author Milan Maniya
6+
* @package ManiyaTech_OrderApi
7+
*/
8+
9+
declare(strict_types=1);
10+
11+
namespace ManiyaTech\OrderApi\Cron;
12+
13+
use Magento\Framework\App\Filesystem\DirectoryList;
14+
use Magento\Framework\Filesystem\Driver\File as FileDriver;
15+
use Magento\Framework\Filesystem\Glob;
16+
use Psr\Log\LoggerInterface;
17+
use PhpOffice\PhpSpreadsheet\Spreadsheet;
18+
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
19+
use PhpOffice\PhpSpreadsheet\Cell\Coordinate;
20+
use ManiyaTech\OrderApi\Model\OrderList;
21+
22+
class Orders
23+
{
24+
/**
25+
* @var OrderList
26+
*/
27+
private OrderList $orderList;
28+
29+
/**
30+
* @var DirectoryList
31+
*/
32+
private DirectoryList $directoryList;
33+
34+
/**
35+
* @var LoggerInterface
36+
*/
37+
private LoggerInterface $logger;
38+
39+
/**
40+
* @var FileDriver
41+
*/
42+
private FileDriver $fileDriver;
43+
44+
/**
45+
* Orders constructor.
46+
*
47+
* @param OrderList $orderList
48+
* @param DirectoryList $directoryList
49+
* @param LoggerInterface $logger
50+
* @param FileDriver $fileDriver
51+
*/
52+
public function __construct(
53+
OrderList $orderList,
54+
DirectoryList $directoryList,
55+
LoggerInterface $logger,
56+
FileDriver $fileDriver
57+
) {
58+
$this->orderList = $orderList;
59+
$this->directoryList = $directoryList;
60+
$this->logger = $logger;
61+
$this->fileDriver = $fileDriver;
62+
}
63+
64+
/**
65+
* Export orders to Excel file.
66+
*
67+
* @return void
68+
*/
69+
public function exportOrders(): void
70+
{
71+
try {
72+
if (!$this->orderList->isModuleEnabled()) {
73+
return;
74+
}
75+
76+
$orders = $this->orderList->getOrders();
77+
$days = $this->orderList->getConfigValue(OrderList::XML_PATH_EXPORT_DAYS);
78+
79+
if (empty($orders)) {
80+
$this->logger->info(__('No orders to export in last %1 days.', $days));
81+
return;
82+
}
83+
84+
$spreadsheet = new Spreadsheet();
85+
$sheet = $spreadsheet->getActiveSheet();
86+
87+
// Set headers
88+
$headers = [
89+
'Increment ID', 'Billing Name', 'Grand Total', 'Status', 'Order Date',
90+
'Payment Title', 'Shipping Method', 'Shipping Description',
91+
'Shipping Amount', 'Shipping Incl Tax'
92+
];
93+
94+
$sheet->fromArray($headers, null, 'A1');
95+
$highestColumn = $sheet->getHighestColumn();
96+
$sheet->getStyle("A1:{$highestColumn}1")->getFont()->setBold(true);
97+
98+
foreach ($headers as $index => $header) {
99+
$columnLetter = Coordinate::stringFromColumnIndex($index + 1);
100+
$sheet->getColumnDimension($columnLetter)->setAutoSize(true);
101+
}
102+
103+
// Fill order data
104+
$row = 2;
105+
foreach ($orders as $order) {
106+
$sheet->fromArray([
107+
$order['increment_id'] ?? '',
108+
$order['billing_name'] ?? '',
109+
$order['grand_total'] ?? '',
110+
$order['order_status'] ?? '',
111+
$order['order_date'] ?? '',
112+
$order['payment_title'] ?? '',
113+
$order['shipping_method'] ?? '',
114+
$order['shipping_description'] ?? '',
115+
$order['shipping_amount'] ?? '',
116+
$order['shipping_incl_tax'] ?? ''
117+
], null, "A{$row}");
118+
$row++;
119+
}
120+
121+
$exportDir = $this->directoryList->getPath(DirectoryList::VAR_DIR) . '/exportorder';
122+
123+
if (!$this->fileDriver->isDirectory($exportDir)) {
124+
$this->fileDriver->createDirectory($exportDir, 0775);
125+
}
126+
127+
$fileName = $exportDir . '/order_export_' . date('d-m-Y_h:i_A') . '.xlsx';
128+
$writer = new Xlsx($spreadsheet);
129+
$writer->save($fileName);
130+
131+
$this->logger->info(__('Order export completed: %1', $fileName));
132+
} catch (\Throwable $e) {
133+
$this->logger->error(__('ExportOrders Cron Error: %1', $e->getMessage()));
134+
}
135+
}
136+
137+
/**
138+
* Delete older export files, keep only latest 5.
139+
*
140+
* @return void
141+
*/
142+
public function deleteOldFiles(): void
143+
{
144+
try {
145+
if (!$this->orderList->isModuleEnabled()) {
146+
return;
147+
}
148+
149+
$directory = $this->directoryList->getPath(DirectoryList::VAR_DIR) . '/exportorder';
150+
$pattern = $directory . '/order_export_*.xlsx';
151+
$files = Glob::glob($pattern);
152+
153+
usort($files, function ($a, $b) {
154+
return $this->fileDriver->stat($b)['mtime'] <=> $this->fileDriver->stat($a)['mtime'];
155+
});
156+
157+
$oldFiles = array_slice($files, 5); // Keep 5 latest
158+
159+
foreach ($oldFiles as $file) {
160+
if ($this->fileDriver->isFile($file)) {
161+
$this->fileDriver->deleteFile($file);
162+
$filename = (new \SplFileInfo($file))->getFilename();
163+
$this->logger->info(__('Deleted old export file: %1', $filename));
164+
}
165+
}
166+
} catch (\Throwable $e) {
167+
$this->logger->error(__('DeleteOldFiles Cron Error: %1', $e->getMessage()));
168+
}
169+
}
170+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
/**
3+
* ManiyaTech
4+
*
5+
* @author Milan Maniya
6+
* @package ManiyaTech_OrderApi
7+
*/
8+
9+
namespace ManiyaTech\OrderApi\Model\Config\Source;
10+
11+
use Magento\Framework\Option\ArrayInterface;
12+
13+
class DeleteExportFile implements ArrayInterface
14+
{
15+
public const EVERY_1_D = '0 0 * * *';
16+
public const EVERY_1_W = '0 0 * * 0';
17+
public const EVERY_1_M = '0 0 1 * *';
18+
19+
/**
20+
* Return array of options
21+
*
22+
* @return array
23+
*/
24+
public function toOptionArray()
25+
{
26+
return [
27+
self::EVERY_1_D => __('Everyday'),
28+
self::EVERY_1_W => __('Weekly'),
29+
self::EVERY_1_M => __('Monthly'),
30+
];
31+
}
32+
}

Model/Config/Source/ExportDays.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
/**
3+
* ManiyaTech
4+
*
5+
* @author Milan Maniya
6+
* @package ManiyaTech_OrderApi
7+
*/
8+
9+
namespace ManiyaTech\OrderApi\Model\Config\Source;
10+
11+
use Magento\Framework\Option\ArrayInterface;
12+
13+
class ExportDays implements ArrayInterface
14+
{
15+
/**
16+
* Return array of options (1 - 30)
17+
*
18+
* @return array
19+
*/
20+
public function toOptionArray(): array
21+
{
22+
$options = [];
23+
for ($i = 1; $i <= 30; $i++) {
24+
$options[] = ['value' => $i, 'label' => __("$i Day(s)")];
25+
}
26+
27+
return $options;
28+
}
29+
}

0 commit comments

Comments
 (0)