Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f4fb421
inventory usage - export feature
Nov 1, 2022
74e3e5d
fix([inventory-usage] send receipt): change from object to replyTo
Nov 2, 2022
14f8e33
fix([inventory-usage] edit): bug backdate on edit form
Nov 9, 2022
acb56c2
inventory-usage: wip unit test feature update
addincw Nov 16, 2022
bf2f69f
[inventory-usage]: wip test feature update
addincw Nov 22, 2022
3f1a32a
inventory-usage: completing unit test feature update
addincw Nov 23, 2022
a0bd1b0
Merge branch 'alpha1' of https://github.com/addincw/point into addin.…
addincw Nov 23, 2022
3749125
inventory-usage: add more unit test, asserting json on unit test
addincw Dec 4, 2022
6dc9fcf
Merge branch 'alpha1' of https://github.com/addincw/point into addin.…
addincw Dec 4, 2022
749513e
inventory-usage: wip unit test item dna
addincw Dec 4, 2022
4899507
[inventory-usage]: wip unit test feature update
addincw Dec 12, 2022
ee14a8f
[inventory-usage]: wip unit test feature update
addincw Dec 13, 2022
4583f99
[inventory-usage]: completing unit test feature update
addincw Dec 13, 2022
3c1cd73
[inventory-usage]: whitelist create inv audit from single unit test
addincw Dec 13, 2022
323953f
[invetory-usage]: fix assertion on unauthorized case
addincw Dec 13, 2022
bf7abb6
[inventory usage] tdd - change function name
addincw Dec 20, 2022
4241b13
[inventory-usage]: tdd feedbacks
addincw Dec 25, 2022
0098d1f
Merge branch 'alpha1' of https://github.com/addincw/point into addin.…
addincw Dec 25, 2022
5590314
fix([inventory-usage] edit): tdd feedbacks
addincw Jan 7, 2023
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
6 changes: 4 additions & 2 deletions app/Exceptions/InputBackDateForbiddenException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@

namespace App\Exceptions;

use App\Model\Inventory\InventoryAudit\InventoryAudit;
use Exception;

class InputBackDateForbiddenException extends Exception
{
public function __construct($audit, $item)
{
$form = $audit->form ?? InventoryAudit::find($audit->id)->form;
parent::__construct('Input error because'.
$item->label.' already audited in '.$audit->form->number.' on '.
date('d F Y H:i', strtotime($audit->form->date)), 422);
$item->label.' already audited in '.$form->number.' on '.
date('d F Y H:i', strtotime($form->date)), 422);
}
}
177 changes: 177 additions & 0 deletions app/Exports/Inventory/InventoryUsageExport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
<?php

namespace App\Exports\Inventory;

use Carbon\Carbon;
use App\Model\Form;
use App\Model\Inventory\InventoryUsage\InventoryUsage;
use App\Model\Inventory\InventoryUsage\InventoryUsageItem;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
use Maatwebsite\Excel\Concerns\WithColumnFormatting;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;

class InventoryUsageExport implements WithColumnFormatting, FromQuery, WithHeadings, WithMapping, ShouldAutoSize, WithEvents
{
/**
* InventoryUsageExport constructor.
*
* @param string $tenantName
* @param object $filters
*/
public function __construct(string $tenantName, object $filters)
{
$this->tenantName = $tenantName;
$this->filters = $filters;
}

/**
* @return \Illuminate\Database\Eloquent\Builder
*/
public function query()
{
$inventoryUsages = InventoryUsage::from(InventoryUsage::getTableName().' as '.InventoryUsage::$alias)
->eloquentFilter($this->filters);

$inventoryUsages = InventoryUsage::joins($inventoryUsages, $this->filters->get('join'));

return $inventoryUsages;
}

public function columnFormats(): array
{
return [
'I' => NumberFormat::FORMAT_NUMBER,
];
}

/**
* @return array
*/
public function headings(): array
{
$dateExport = Carbon::now()->timezone(config()->get('project.timezone'));
$periodExport = $this->_getPeriodExport();

return [
['Date Export', ': ' . $dateExport->format('d M Y H:i')],
['Period Export', ': ' . $periodExport],
[$this->tenantName],
['Inventory Usage'],
[
'Date Form',
'Form Number',
'Warehouse',
'Employee',
'Account',
'Item',
'Production Number',
'Expiry Date',
'Quantity Usage',
'Notes',
'Allocation',
'Notes',
'Created By',
'Approved By',
'Approval Status',
'Form Status',
'Created At',
'Updated At',
'Deleted At'
]
];
}

/**
* @param mixed $row
* @return array
*/
public function map($row): array
{
$form = Form::where('formable_id', $row->inventory_usage_id)
->with(['createdBy', 'approvalBy'])
->where('formable_type', InventoryUsage::$morphName)
->first();

$usageItem = InventoryUsageItem::where('id', $row->id)
->with(['item', 'account', 'allocation'])
->first();

return [
date('d F Y', strtotime($form->date)),
$form->number,
$row->warehouse->name,
$row->employee->name,
$usageItem->account->name,
$usageItem->item->name,
$row->production_number,
$row->expiry_date,
round($row->quantity, 2) . ' ' . $row->unit,
$row->notes,
$usageItem->allocation->name,
$form->notes,
$form->createdBy->getFullNameAttribute(),
optional($form->approvalBy)->getFullNameAttribute(),
$form->approval_status,
$form->done,
date('d F Y', strtotime($form->created_at)),
date('d F Y', strtotime($form->updated_at)),
date('d F Y', strtotime($form->updated_at)),
];
}

public function registerEvents(): array
{
return [
AfterSheet::class => function(AfterSheet $event) {
$event->sheet->getDelegate()->getStyle('F6:F100')
->getAlignment()
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_LEFT);
$event->sheet->getColumnDimension('B')
->setAutoSize(false)
->setWidth(18);
$tenanNameColl = 'A3:M3'; // All headers
$event->sheet->mergeCells($tenanNameColl);
$event->sheet->getDelegate()->getStyle($tenanNameColl)->getFont()->setBold(true);
$event->sheet->getDelegate()->getStyle($tenanNameColl)
->getAlignment()
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
$titleColl = 'A4:M4'; // All headers
$event->sheet->mergeCells($titleColl);
$event->sheet->getDelegate()->getStyle($titleColl)->getFont()->setBold(true);
$event->sheet->getDelegate()->getStyle($titleColl)
->getAlignment()
->setHorizontal(\PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER);
},

];
}

private function _getPeriodExport()
{
$dateMin = $this->filters->filter_date_min;
$dateMin = !is_null($dateMin) && !is_array($dateMin)
? json_decode($dateMin, true)
: [];

$dateMax = $this->filters->filter_date_max;
$dateMax = !is_null($dateMax) && !is_array($dateMax)
? json_decode($dateMax, true)
: [];

$periodExport = '';
if (isset($dateMin['form.date'])) {
$periodExport .= Carbon::createFromFormat('Y-m-d H:i:s', $dateMin['form.date'])->format('d M Y');
}
if (isset($dateMax['form.date'])) {
if($periodExport !== '') $periodExport .= ' - ';
$periodExport .= Carbon::createFromFormat('Y-m-d H:i:s', $dateMax['form.date'])->format('d M Y');
}

return $periodExport;
}
}
2 changes: 1 addition & 1 deletion app/Helpers/Inventory/InventoryHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ public static function auditExists($item, $date, $warehouse, $options)
$inventoryExist = InventoryAuditItem::join(InventoryAudit::getTableName(), InventoryAudit::getTableName('id'), '=', InventoryAuditItem::getTableName('inventory_audit_id'))
->join(Form::getTableName(), function ($query) {
$query->on(Form::getTableName('formable_id'), '=', InventoryAudit::getTableName('id'))
->where(Form::getTableName('formable_type'), '=', InventoryAudit::class);
->where(Form::getTableName('formable_type'), '=', InventoryAudit::$morphName);
})
->where(Form::getTableName('date'), '>=', $date)
// check if form is not canceled
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

namespace App\Http\Controllers\Api\Inventory\InventoryUsage;

use App\Exports\Inventory\InventoryUsageExport;
use App\Http\Controllers\Controller;
use App\Http\Requests\Inventory\Usage\StoreRequest;
use App\Http\Requests\Inventory\Usage\UpdateRequest;
use App\Http\Resources\ApiCollection;
use App\Http\Resources\ApiResource;
use App\Model\CloudStorage;
use App\Model\Inventory\InventoryUsage\InventoryUsage;
use App\Model\Project\Project;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\DB;
use Maatwebsite\Excel\Facades\Excel;

class InventoryUsageController extends Controller
{
Expand Down Expand Up @@ -126,4 +132,36 @@ public function destroy(Request $request, $id)

return response()->json([], 204);
}

public function export(Request $request)
{
try {
$tenant = strtolower($request->header('Tenant'));
$key = Str::random(16);
$fileName = strtoupper($tenant).' - Inventory Usage';
$fileExt = 'xlsx';
$path = 'tmp/'.$tenant.'/'.$key.'.'.$fileExt;

Excel::store(new InventoryUsageExport($tenant, $request), $path, env('STORAGE_DISK'));

$cloudStorage = new CloudStorage();
$cloudStorage->file_name = $fileName;
$cloudStorage->file_ext = $fileExt;
$cloudStorage->feature = 'Inventory Usage Export';
$cloudStorage->key = $key;
$cloudStorage->path = $path;
$cloudStorage->disk = env('STORAGE_DISK');
$cloudStorage->project_id = Project::where('code', strtolower($tenant))->first()->id;
$cloudStorage->owner_id = auth()->user()->id;
$cloudStorage->expired_at = Carbon::now()->addDay(1);
$cloudStorage->download_url = env('API_URL').'/download?key='.$key;
$cloudStorage->save();

return response()->json([
'data' => [ 'url' => $cloudStorage->download_url ],
], 200);
} catch (\Throwable $th) {
return response_error($th);
}
}
}
18 changes: 14 additions & 4 deletions app/Http/Requests/Inventory/Usage/UpdateRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace App\Http\Requests\Inventory\Usage;

use App\Http\Requests\ValidationRule;
use App\Model\Inventory\InventoryUsage\InventoryUsage;
use Illuminate\Foundation\Http\FormRequest;

class UpdateRequest extends FormRequest
Expand All @@ -24,15 +25,24 @@ public function authorize()
*/
public function rules()
{
return [
'warehouse_id' => 'required',
'request_approval_to' => 'required',
$inventoryUsage = InventoryUsage::find($this->id);

$rulesForm = ValidationRule::form();
$rulesForm['date'] = 'required|date|after_or_equal:'.optional($inventoryUsage->form)->date;

$rulesUpdate = [
'warehouse_id' => ValidationRule::foreignKey('warehouses'),
'employee_id' => ValidationRule::foreignKey('employees'),
'request_approval_to' => 'required',
'notes' => 'nullable|string|max:255',
'items.*.item_id' => ValidationRule::foreignKey('items'),
'items.*.quantity' => ValidationRule::quantity(),
'items.*.unit' => ValidationRule::unit(),
'items.*.converter' => ValidationRule::converter(),
'items.*.chart_of_account_id' => 'required',
'items.*.chart_of_account_id' => ValidationRule::foreignKey('chart_of_accounts'),
'items.*.allocation_id' => ValidationRule::foreignKey('allocations'),
];

return array_merge($rulesForm, $rulesUpdate);
}
}
5 changes: 1 addition & 4 deletions app/Mail/CustomEmail.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public function build()
$user = $this->user;
$request = $this->request;

$this->from($user->email, $user->getFullNameAttribute());
$this->replyTo($user->email, $user->getFullNameAttribute());
$this->to($request->to);

if (optional($request)->cc) {
Expand All @@ -47,9 +47,6 @@ public function build()
if (optional($request)->bcc) {
$this->bcc($request->bcc);
}
if (optional($request)->reply_to) {
$this->replyTo($request->reply_to, $request->reply_to_name);
}

$this->subject($request->subject);
$this->view('emails.custom-email', ['body' => $request->body]);
Expand Down
10 changes: 10 additions & 0 deletions app/Model/Inventory/InventoryUsage/InventoryUsage.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Exception;
use App\Exceptions\StockNotEnoughException;
use App\Exceptions\ExpiryDateNotFoundException;
use App\Exceptions\ProductionNumberNotFoundException;
use App\Helpers\Inventory\InventoryHelper;
use App\Mail\Inventory\InventoryUsageApprovalMail;
use App\Model\TransactionModel;
Expand Down Expand Up @@ -174,6 +176,14 @@ private static function mapItems($items, $inventoryUsage)
if ($itemModel->require_production_number || $itemModel->require_expiry_date) {
if ($item['dna']) {
foreach ($item['dna'] as $dna) {
if ($itemModel->require_production_number && !isset($dna['production_number'])) {
throw new ProductionNumberNotFoundException($itemModel);
}

if ($itemModel->require_expiry_date && !isset($dna['expiry_date'])) {
throw new ExpiryDateNotFoundException($itemModel);
}

if ($dna['quantity'] > 0) {
$options = [
'expiry_date' => $dna['expiry_date'],
Expand Down
1 change: 1 addition & 0 deletions routes/api/inventory.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

Route::get('usages/{id}/histories', 'InventoryUsageHistoryController@index');

Route::get('usages/export', 'InventoryUsageController@export');
Route::apiResource('usages', 'InventoryUsageController');
});
});
Expand Down
Loading