Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow reporting by a list of order numbers #104

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions codeception.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
bootstrap: bootstrap.php
paths:
tests: tests
output: tests/_output
Expand Down
22 changes: 18 additions & 4 deletions console/jobs/CreateReportJob.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ class CreateReportJob extends BaseObject implements RetryableJobInterface
const TTR = 600; // in seconds

/**
* @var int $customer
* @var int[] $customer_ids array of customer IDs.
* Limits the orders to one or more customers.
*/
public int $customer;
public array $customer_ids;

/**
* @var int $userId
Expand All @@ -49,6 +50,12 @@ class CreateReportJob extends BaseObject implements RetryableJobInterface
*/
public bool $items;

/**
* @var array|null if set, the report will be generated on order numbers instead of date range.
*/
public ?array $order_nrs = null;


/**
* @inheritDoc
*/
Expand Down Expand Up @@ -77,8 +84,6 @@ public function isFailed(int $currentAttempt): int
protected function processReport(): string
{
$ordersQuery = \frontend\models\Order::find()
->where(['customer_id' => $this->customer])
->andWhere(['between', 'created_date', $this->start_date, $this->end_date])
->with(
[
'items',
Expand All @@ -91,6 +96,15 @@ protected function processReport(): string
)
->orderBy('created_date');

if (is_array($this->order_nrs)) {
$ordersQuery->where(['customer_reference' => $this->order_nrs]);
} else {
$ordersQuery->andWhere(['between', 'created_date', $this->start_date, $this->end_date]);
}
// limit access by customer
$ordersQuery->andWhere(['IN', 'customer_id', $this->customer_ids]);


$dir = Yii::getAlias('@console') . '/runtime/reports/';
FileHelper::createDirectory($dir);
$filename = time() . '_' . $this->user_id . "_report.csv";
Expand Down
41 changes: 18 additions & 23 deletions frontend/controllers/ReportController.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
namespace frontend\controllers;

use Yii;
use console\jobs\CreateReportJob;
use frontend\models\Customer;
use frontend\models\forms\ReportForm;
use frontend\models\User;
use yii\filters\AccessControl;

/**
* Class ReportController
Expand All @@ -20,7 +18,7 @@ public function behaviors()
{
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'class' => AccessControl::class,
'rules' => [
[
'allow' => true,
Expand All @@ -34,40 +32,37 @@ public function behaviors()
/**
* Index for creating CSV report
*
* @return string|void
* @throws \yii\base\InvalidConfigException
*/
public function actionIndex()
public function actionIndex($scenario = null)
{
$model = new ReportForm();

// select model scenario from GET or POST
$model->scenario = ReportForm::SCENARIO_BY_DATE;
$scenario = $this->request->post('scenario', $scenario);
if (in_array($scenario, [ReportForm::SCENARIO_BY_DATE, ReportForm::SCENARIO_BY_ORDER_NR])) {
$model->scenario = $scenario;
}

// Generate Report
if (Yii::$app->request->post()) {
if ($this->request->post()) {
$model->load(Yii::$app->request->post());
// Always set for beginning of day and end of day for query
$model->start_date = Yii::$app->formatter->asDate($model->start_date, 'php:Y-m-d 00:00:00');
$model->end_date = Yii::$app->formatter->asDate($model->end_date, 'php:Y-m-d 23:59:59');

Yii::$app->queue->push(new CreateReportJob([
'customer' => $model->customer,
'user_id' => Yii::$app->user->id,
'user_email' => User::findone(['id' => Yii::$app->user->id])->email,
'start_date' => $model->start_date,
'end_date' => $model->end_date,
'items' => $model->items,
]));
if ($model->validate()) {

Yii::$app->getSession()->setFlash('success', 'The report is being generated. Please check your email in a few minutes.');
}
$model->pushReportQueueJob();

Yii::$app->getSession()->setFlash('success', 'The report is being generated. Please check your email in a few minutes.');
return $this->redirect(['report/index', 'scenario' => $model->scenario]);
}
}

return $this->render(
'index',
[
'model' => $model,
'customers' => Yii::$app->user->identity->isAdmin
? Customer::getList()
: Yii::$app->user->identity->getCustomerList(),
'customers' => $model->getCustomerList(),
]
);
}
Expand Down
95 changes: 88 additions & 7 deletions frontend/models/forms/ReportForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

namespace frontend\models\forms;

use console\jobs\CreateReportJob;
use frontend\models\Customer;
use Yii;
use yii\base\InvalidCallException;
use yii\base\Model;

/**
Expand All @@ -17,28 +19,107 @@
*/
class ReportForm extends Model
{
public const SCENARIO_BY_DATE = 'date';
public const SCENARIO_BY_ORDER_NR = 'order_nr';

public $start_date;
public $end_date;
public $customer;
public $items = true;
public $order_nrs;


public function rules()
{
return [
[['start_date', 'end_date', 'customer'], 'required'],
[['items'], 'boolean'],
[['start_date', 'end_date', 'customer'], 'default', 'value' => null],
[['start_date', 'end_date', 'customer'], 'required', 'on' => self::SCENARIO_BY_DATE],

['start_date', 'date', 'on' => self::SCENARIO_BY_DATE,
'timestampAttribute' => 'start_date',
// Always set for beginning of day and end of day for query
'timestampAttributeFormat' => 'php:Y-m-d 00:00:00'
],
['end_date', 'date', 'on' => self::SCENARIO_BY_DATE,
'timestampAttribute' => 'end_date',
// Always set for beginning of day and end of day for query
'timestampAttributeFormat' => 'php:Y-m-d 23:59:59'
],

['end_date', 'compare', 'operator' => '>=', 'compareAttribute' => 'start_date', 'on' => self::SCENARIO_BY_DATE, 'enableClientValidation' => false],

[
'customer',
'in',
'range' => array_keys(
Yii::$app->user->identity->isAdmin
? Customer::getList()
: Yii::$app->user->identity->getCustomerList()
),
'range' => array_keys($this->getCustomerList()),
'on' => self::SCENARIO_BY_DATE
],

[['order_nrs'], 'required', 'on' => self::SCENARIO_BY_ORDER_NR],

[['items'], 'boolean'],
];
}

public function attributeLabels()
{
return [
'order_nrs' => 'Order Numbers',
];
}

public function scenarios()
{
return [
self::SCENARIO_BY_DATE => ['start_date', 'end_date', 'customer', 'items'],
self::SCENARIO_BY_ORDER_NR => ['order_nrs', 'items'],
];
}

public function getOrderNrs()
{
return preg_split('~[;,\s]+~', $this->order_nrs, -1, PREG_SPLIT_NO_EMPTY);
}

private $_customerList;
/**
* @return array
*/
public function getCustomerList(): array
{
if ($this->_customerList !== null) {
return $this->_customerList;
}
return $this->_customerList = Yii::$app->user->identity->isAdmin
? Customer::getList()
: Yii::$app->user->identity->getCustomerList();
}

public function pushReportQueueJob()
{
switch ($this->scenario) {
case self::SCENARIO_BY_DATE:
$job = new CreateReportJob([
'customer_ids' => [$this->customer],
'start_date' => $this->start_date,
'end_date' => $this->end_date,
'items' => $this->items,
]);
break;
case self::SCENARIO_BY_ORDER_NR:
$job = new CreateReportJob([
'order_nrs' => $this->getOrderNrs(),
'customer_ids' => array_keys($this->getCustomerList()),
'items' => $this->items,
]);
break;
default:
throw new InvalidCallException('Unknown model scenario: ' . $this->scenario);
}

$job->user_id = Yii::$app->user->id;
$job->user_email = Yii::$app->user->identity->email;

Yii::$app->queue->push($job);
}
}
56 changes: 56 additions & 0 deletions frontend/views/report/_tabDate.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

use frontend\assets\DatePickerAsset;
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;

/* @var $this yii\web\View */
/* @var $model \frontend\models\forms\ReportForm */
/* @var $form ActiveForm */
/* @var $customers array of customers */

DatePickerAsset::register($this);
$this->registerJs('
// Datepicker
$(\'.date\').datepicker({
todayBtn : \'linked\',
keyboardNavigation : false,
forceParse : false,
autoclose : true,
format : \'mm/dd/yyyy\',
todayHighlight : true,
});');
?>

<?php $form = ActiveForm::begin(); ?>

<p>
Choose the date range below.
We will generate a CSV file for you after clicking export.
</p>

<?= Html::hiddenInput('scenario', \frontend\models\forms\ReportForm::SCENARIO_BY_DATE) ?>

<?= $form->field($model, 'start_date', [
'inputTemplate' =>
'<div class="input-group date"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>{input}</div>',
'inputOptions' => ['autocomplete' => 'off']
])->textInput([
'value' => (isset($model->start_date)) ? Yii::$app->formatter->asDate($model->start_date) : '',
]); ?>
<?= $form->field($model, 'end_date', [
'inputTemplate' =>
'<div class="input-group date"><span class="input-group-addon"><span class="glyphicon glyphicon-calendar"></span></span>{input}</div>',
'inputOptions' => ['autocomplete' => 'off']
])->textInput([
'value' => (isset($model->end_date)) ? Yii::$app->formatter->asDate($model->end_date) : '',
]); ?>
<?php echo $form->field($model, 'customer')->dropdownList($customers, ['prompt' => ' Please select']); ?>

<?php echo $form->field($model, 'items')->checkbox(['id' => 'include_items_date'])->label('Include items in report?'); ?>

<div class="form-group">
<?= Html::submitButton('Export', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>
31 changes: 31 additions & 0 deletions frontend/views/report/_tabOrderNr.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

use frontend\assets\DatePickerAsset;
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;

/* @var $this yii\web\View */
/* @var $model \frontend\models\forms\ReportForm */
/* @var $form ActiveForm */

?>

<?php $form = ActiveForm::begin(); ?>

<p>
Enter a list of order numbers below.
Order numbers can be separated by <code>,</code>, <code>;</code> or spaces and newlines.<br>
We will generate a CSV file for you after clicking export.
</p>

<?= Html::hiddenInput('scenario', \frontend\models\forms\ReportForm::SCENARIO_BY_ORDER_NR) ?>

<?php echo $form->field($model, 'order_nrs')->textarea(['rows' => 10]) ?>

<?php echo $form->field($model, 'items')->checkbox(['id' => 'include_items_order_nr'])->label('Include items in report?'); ?>

<div class="form-group">
<?= Html::submitButton('Export', ['class' => 'btn btn-primary']) ?>
</div>

<?php ActiveForm::end(); ?>
Loading