Skip to content

Commit

Permalink
get last month summary
Browse files Browse the repository at this point in the history
  • Loading branch information
KimHak-mb committed Sep 15, 2023
1 parent bb3f771 commit a8d9b7d
Show file tree
Hide file tree
Showing 11 changed files with 616 additions and 0 deletions.
126 changes: 126 additions & 0 deletions src/Controller/ProductsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
<?php
declare(strict_types=1);

namespace App\Controller;
use Cake\I18n\FrozenTime;

/**
* Products Controller
*
* @property \App\Model\Table\ProductsTable $Products
* @method \App\Model\Entity\Product[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class ProductsController extends AppController
{
/**
* Index method
*
* @return \Cake\Http\Response|null|void Renders view
*/
public function index()
{
$products = $this->paginate($this->Products);

$this->set(compact('products'));
}

/**
* View method
*
* @param string|null $id Product id.
* @return \Cake\Http\Response|null|void Renders view
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null)
{
$product = $this->Products->get($id, [
'contain' => [],
]);

$this->set(compact('product'));
}

/**
* Add method
*
* @return \Cake\Http\Response|null|void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$product = $this->Products->newEmptyEntity();
if ($this->request->is('post')) {
$product = $this->Products->patchEntity($product, $this->request->getData());
if ($this->Products->save($product)) {
$this->Flash->success(__('The product has been saved.'));

return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The product could not be saved. Please, try again.'));
}
$this->set(compact('product'));
}

/**
* Edit method
*
* @param string|null $id Product id.
* @return \Cake\Http\Response|null|void Redirects on successful edit, renders view otherwise.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null)
{
$product = $this->Products->get($id, [
'contain' => [],
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$product = $this->Products->patchEntity($product, $this->request->getData());
if ($this->Products->save($product)) {
$this->Flash->success(__('The product has been saved.'));

return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The product could not be saved. Please, try again.'));
}
$this->set(compact('product'));
}

/**
* Delete method
*
* @param string|null $id Product id.
* @return \Cake\Http\Response|null|void Redirects to index.
* @throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$product = $this->Products->get($id);
if ($this->Products->delete($product)) {
$this->Flash->success(__('The product has been deleted.'));
} else {
$this->Flash->error(__('The product could not be deleted. Please, try again.'));
}

return $this->redirect(['action' => 'index']);
}

public function report()
{
$targetDateTime = FrozenTime::now()->modify('1 month ago');

$query = $this->Products->find();

$query->select([
'created',
'amount' => $query->func()->sum('Products.amount')
])
->where([
'Products.created >=' => $targetDateTime->startOfMonth(),
'Products.created >=' => $targetDateTime->endOfMonth(),
])
->group('created')
;

$this->set("products",$this->paginate($query));
}
}
36 changes: 36 additions & 0 deletions src/Model/Entity/Product.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
declare(strict_types=1);

namespace App\Model\Entity;

use Cake\ORM\Entity;

/**
* Product Entity
*
* @property int $id
* @property string $name
* @property int $amount
* @property string $description
* @property \Cake\I18n\FrozenTime $created
* @property \Cake\I18n\FrozenTime $modified
*/
class Product extends Entity
{
/**
* Fields that can be mass assigned using newEntity() or patchEntity().
*
* Note that when '*' is set to true, this allows all unspecified fields to
* be mass assigned. For security purposes, it is advised to set '*' to false
* (or remove it), and explicitly make individual fields accessible as needed.
*
* @var array<string, bool>
*/
protected $_accessible = [
'name' => true,
'amount' => true,
'description' => true,
'created' => true,
'modified' => true,
];
}
75 changes: 75 additions & 0 deletions src/Model/Table/ProductsTable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php
declare(strict_types=1);

namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;

/**
* Products Model
*
* @method \App\Model\Entity\Product newEmptyEntity()
* @method \App\Model\Entity\Product newEntity(array $data, array $options = [])
* @method \App\Model\Entity\Product[] newEntities(array $data, array $options = [])
* @method \App\Model\Entity\Product get($primaryKey, $options = [])
* @method \App\Model\Entity\Product findOrCreate($search, ?callable $callback = null, $options = [])
* @method \App\Model\Entity\Product patchEntity(\Cake\Datasource\EntityInterface $entity, array $data, array $options = [])
* @method \App\Model\Entity\Product[] patchEntities(iterable $entities, array $data, array $options = [])
* @method \App\Model\Entity\Product|false save(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Product saveOrFail(\Cake\Datasource\EntityInterface $entity, $options = [])
* @method \App\Model\Entity\Product[]|\Cake\Datasource\ResultSetInterface|false saveMany(iterable $entities, $options = [])
* @method \App\Model\Entity\Product[]|\Cake\Datasource\ResultSetInterface saveManyOrFail(iterable $entities, $options = [])
* @method \App\Model\Entity\Product[]|\Cake\Datasource\ResultSetInterface|false deleteMany(iterable $entities, $options = [])
* @method \App\Model\Entity\Product[]|\Cake\Datasource\ResultSetInterface deleteManyOrFail(iterable $entities, $options = [])
*
* @mixin \Cake\ORM\Behavior\TimestampBehavior
*/
class ProductsTable extends Table
{
/**
* Initialize method
*
* @param array $config The configuration for the Table.
* @return void
*/
public function initialize(array $config): void
{
parent::initialize($config);

$this->setTable('products');
$this->setDisplayField('name');
$this->setPrimaryKey('id');

$this->addBehavior('Timestamp');
}

/**
* Default validation rules.
*
* @param \Cake\Validation\Validator $validator Validator instance.
* @return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator): Validator
{
$validator
->scalar('name')
->maxLength('name', 255)
->requirePresence('name', 'create')
->notEmptyString('name');

$validator
->integer('amount')
->requirePresence('amount', 'create')
->notEmptyString('amount');

$validator
->scalar('description')
->requirePresence('description', 'create')
->notEmptyString('description');

return $validator;
}
}
29 changes: 29 additions & 0 deletions templates/Products/add.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Product $product
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading"><?= __('Actions') ?></h4>
<?= $this->Html->link(__('List Products'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column-responsive column-80">
<div class="products form content">
<?= $this->Form->create($product) ?>
<fieldset>
<legend><?= __('Add Product') ?></legend>
<?php
echo $this->Form->control('name');
echo $this->Form->control('amount');
echo $this->Form->control('description');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>
34 changes: 34 additions & 0 deletions templates/Products/edit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* @var \App\View\AppView $this
* @var \App\Model\Entity\Product $product
*/
?>
<div class="row">
<aside class="column">
<div class="side-nav">
<h4 class="heading"><?= __('Actions') ?></h4>
<?= $this->Form->postLink(
__('Delete'),
['action' => 'delete', $product->id],
['confirm' => __('Are you sure you want to delete # {0}?', $product->id), 'class' => 'side-nav-item']
) ?>
<?= $this->Html->link(__('List Products'), ['action' => 'index'], ['class' => 'side-nav-item']) ?>
</div>
</aside>
<div class="column-responsive column-80">
<div class="products form content">
<?= $this->Form->create($product) ?>
<fieldset>
<legend><?= __('Edit Product') ?></legend>
<?php
echo $this->Form->control('name');
echo $this->Form->control('amount');
echo $this->Form->control('description');
?>
</fieldset>
<?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>
</div>
</div>
50 changes: 50 additions & 0 deletions templates/Products/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* @var \App\View\AppView $this
* @var iterable<\App\Model\Entity\Product> $products
*/
?>
<div class="products index content">
<?= $this->Html->link(__('New Product'), ['action' => 'add'], ['class' => 'button float-right']) ?>
<h3><?= __('Products') ?></h3>
<div class="table-responsive">
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('id') ?></th>
<th><?= $this->Paginator->sort('name') ?></th>
<th><?= $this->Paginator->sort('amount') ?></th>
<th><?= $this->Paginator->sort('created') ?></th>
<th><?= $this->Paginator->sort('modified') ?></th>
<th class="actions"><?= __('Actions') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($products as $product): ?>
<tr>
<td><?= $this->Number->format($product->id) ?></td>
<td><?= h($product->name) ?></td>
<td><?= $this->Number->format($product->amount) ?></td>
<td><?= h($product->created) ?></td>
<td><?= h($product->modified) ?></td>
<td class="actions">
<?= $this->Html->link(__('View'), ['action' => 'view', $product->id]) ?>
<?= $this->Html->link(__('Edit'), ['action' => 'edit', $product->id]) ?>
<?= $this->Form->postLink(__('Delete'), ['action' => 'delete', $product->id], ['confirm' => __('Are you sure you want to delete # {0}?', $product->id)]) ?>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?></p>
</div>
</div>
38 changes: 38 additions & 0 deletions templates/Products/report.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
/**
* @var \App\View\AppView $this
* @var iterable<\App\Model\Entity\Product> $products
*/
?>
<div class="products index content">
<?= $this->Html->link(__('New Product'), ['action' => 'add'], ['class' => 'button float-right']) ?>
<h3><?= __('Products') ?></h3>
<div class="table-responsive">
<table>
<thead>
<tr>
<th><?= $this->Paginator->sort('created') ?></th>
<th><?= $this->Paginator->sort('amount') ?></th>
</tr>
</thead>
<tbody>
<?php foreach ($products as $product): ?>
<tr>
<td><?= h($product->created->format("Y-m-d")) ?></td>
<td><?= $this->Number->format($product->amount) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<div class="paginator">
<ul class="pagination">
<?= $this->Paginator->first('<< ' . __('first')) ?>
<?= $this->Paginator->prev('< ' . __('previous')) ?>
<?= $this->Paginator->numbers() ?>
<?= $this->Paginator->next(__('next') . ' >') ?>
<?= $this->Paginator->last(__('last') . ' >>') ?>
</ul>
<p><?= $this->Paginator->counter(__('Page {{page}} of {{pages}}, showing {{current}} record(s) out of {{count}} total')) ?></p>
</div>
</div>
Loading

0 comments on commit a8d9b7d

Please sign in to comment.