order module (code needs cleaning up)

This commit is contained in:
omair saleh
2020-09-14 16:05:34 +08:00
parent 26c9654894
commit 7f0993d968
23 changed files with 488 additions and 195 deletions
@@ -115,6 +115,21 @@ class AddressObject implements DataTransferObject
return $this->country;
}
/**
* @return int
*/
public function getDefault(): int
{
return $this->default;
}
/**
* @return int
*/
public function getBilling(): int
{
return $this->billing;
}
}
@@ -0,0 +1,27 @@
<?php
namespace App\Classes\Modules\Orders\Services;
use App\Models\Order;
class ChecksIfOrderNumberExists
{
/** @var Order */
private $repository;
/**
* ChecksIfOrderNumberExists constructor.
* @param Order $repository
*/
public function __construct(Order $repository)
{
$this->repository = $repository;
}
public function execute(int $accountNumber): bool {
return $this->repository->where('order_number', $accountNumber)->exists();
}
}
@@ -0,0 +1,32 @@
<?php
namespace App\Classes\Modules\Orders\Services;
class GeneratesUniqueOrderNumber
{
/** @var ChecksIfOrderNumberExists */
private $checksIfOrderNumberExists;
/**
* GeneratesUniqueOrderNumber constructor.
* @param ChecksIfOrderNumberExists $checksIfOrderNumberExists
*/
public function __construct(ChecksIfOrderNumberExists $checksIfOrderNumberExists)
{
$this->checksIfOrderNumberExists = $checksIfOrderNumberExists;
}
/**
* @return int
*/
public function execute(): int {
$number = mt_rand(100000001, 999999999);
return !$this->checksIfOrderNumberExists->execute($number) ? $number : self::execute();
}
}
@@ -10,4 +10,6 @@ final class ModuleTypes
public const FORWARDER = 1;
public const WAREHOUSE= 2;
}
@@ -0,0 +1,13 @@
<?php
namespace App\Classes\ValueObjects\Constants;
final class OrderWarehouseType
{
public const ORIGIN = 0;
public const DESTINATION = 1;
}
@@ -3,15 +3,80 @@
namespace App\Http\Controllers\Orders;
use App\Classes\Modules\Orders\Services\GeneratesUniqueOrderNumber;
use App\Classes\ValueObjects\Constants\HttpStatus;
use App\Classes\ValueObjects\Response\ApiResponseObject;
use App\Http\Resources\OrderResource;
use App\Models\Company;
use App\Models\Order;
use Illuminate\Http\Request;
class OrderController
{
public function create(Request $request){
$order = new Order();
$order->company_id = $request->company_id;
public function create(Request $request, GeneratesUniqueOrderNumber $generatesUniqueOrderNumber){
try {
/** @var Company $company */
$company = Company::findOrFail($request->company_id);
$order = new Order();
$order->company_id = $company->id;
$order->order_number = $generatesUniqueOrderNumber->execute();
$order->forwarder_id = 1;
$order->address_id = $company->addresses()->first()->id;
$order->contact_id = $company->contacts()->first()->id;
$order->current_step = 'MS_WAREHOUSE_RECEIVING';
$order->multiple_batch = false;
$order->complete = false;
$order->save();
$order->warehouses()->attach($request->warehouse_id === 1 ? 3 : 2);
return (new ApiResponseObject('New Order',
'Order has been placed successfully',
HttpStatus::OK_WITH_MESSAGE, []))->handler();
} catch (\Exception $exception){
return (new ApiResponseObject('New Order',
$exception->getMessage(),
$exception->getCode(), []))->handler();
}
}
public function list(String $companyId){
$orders = Order::where('company_id', $companyId)->orderBy('created_at', 'DESC')
->paginate(10);
return (new ApiResponseObject('',
'',
HttpStatus::OK_WITH_MESSAGE, json_decode(OrderResource::collection($orders)->response()->getContent(), true)))->handler();
}
public function download(String $orderId){
/** @var Order $order */
$order = order::findOrFail($orderId);
/** @var Company $warehouse */
$warehouse = $order->warehouses()->first();
$warehouseAddress = $warehouse->addresses()->first();
$warehouseContact = $warehouse->contacts()->get();
$data = [
'order' => $order,
'company' => $order->importer(),
'delivery_address' => $order->address(),
'warehouse_address' => $warehouseAddress,
'warehouse_contact' => $warehouseContact
];
// return view('pages.pdf.qr', $data);
return $this->pdf->loadView('pages.pdf.qr', $data)->stream();
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Http\Resources;
use App\Models\Address;
use App\Models\Company;
use Illuminate\Http\Resources\Json\JsonResource;
class OrderResource extends JsonResource
{
/**
* Transform the resource into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'id' => $this->id,
'marking' => $this->order_number,
'company' => Company::where('id', $this->company_id)->first(),
'warehouse_id' => $this->warehouse_id,
'address' => new AddressResource(Address::where('id', $this->address_id)->first()),
'complete' => (int)$this->complete,
'date' => $this->created_at->format('d/m/Y')
];
}
}
+8
View File
@@ -35,6 +35,14 @@ class Company extends AbstractModel
return $this->hasMany(Address::class, 'company_id', 'id');
}
/**
* @return HasMany
*/
public function contacts(): hasMany
{
return $this->hasMany(Contact::class, 'company_id', 'id');
}
/**
* @return HasOne
*/
+2 -2
View File
@@ -11,7 +11,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @package App\Models
* @version August 5, 2020, 10:46 pm
*
* @property \App\Models\Company company
* @property \App\Models\Contact contact
* @property string name
* @property string designation
* @property string email
@@ -36,7 +36,7 @@ class Contact extends AbstractModel
*/
public function company(): HasOne
{
return $this->hasOne(\App\Models\Company::class, 'company_id', 'id');
return $this->hasOne(Company::class, 'company_id', 'id');
}
}
+30
View File
@@ -2,6 +2,9 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -27,4 +30,31 @@ class Order extends AbstractModel
protected $dates = ['deleted_at'];
/**
* @return belongsToMany
*/
public function warehouses(): belongsToMany
{
return $this->belongsToMany(Company::class, (new OrderWarehouse())->getTable(), 'warehouse_id','order_id');
}
/**
* @return belongsTo
*/
public function importer(): belongsTo
{
return $this->belongsTo(Company::class, 'company_id','id');
}
/**
* @return belongsTo
*/
public function address(): belongsTo
{
return $this->belongsTo(Address::class, 'address_id','id');
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Class Address
* @package App\Models
* @version August 4, 2020, 4:36 am
*
* @property \App\Models\Company company
* @property string street_one
* @property string street_two
* @property string city
* @property string state
* @property string post_code
* @property string country
*/
class OrderWarehouse extends AbstractModel
{
use SoftDeletes;
protected $table = 'order_warehouses';
protected $dates = ['deleted_at'];
}
@@ -19,6 +19,7 @@ class CreateCompanyConnectionsTable extends Migration
$table->id();
$table->foreignId('module_one');
$table->foreignId('module_two');
$table->text('marking');
$table->integer('status')->default(RelationStatus::PENDING);
$table->foreignId('instigator')->comment('entity that is responsible for current status');
$table->timestamps();
@@ -1,5 +1,6 @@
<?php
use App\Classes\ValueObjects\Constants\OrderWarehouseType;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
@@ -17,6 +18,7 @@ class CreateOrderWarehousesTable extends Migration
$table->id();
$table->foreignId('order_id');
$table->foreignId('warehouse_id');
$table->integer('type')->default(OrderWarehouseType::ORIGIN);
$table->timestamps();
$table->foreign('order_id')->references('id')->on('orders');
+48 -2
View File
@@ -25,8 +25,54 @@ class CompaniesTableSeeder extends Seeder
$company->modules()->create(['module_type' => ModuleTypes::FORWARDER]);
$company = new Company();
$company->reference_no = 1000000001;
$company->name = 'YW-V01 浙江义乌仓库';
$company->type = CompanyTypes::COMPANY_BUSINESS;
$company->status = AccountStatus::ACTIVE;
$company->save();
// if (app()->environment('local'))
// factory(App\Models\Company::class, 30)->create();
$company->addresses()->create([
'street_one' => '浙江省义乌市诚信大道义乌港A区2楼194号',
'post_code' => 322000,
'city' => '',
'state' => '',
'country' => 'China',
'default' => 1,
'billing' => 1
]);
$company->contacts()->create([
'name' => '小叶(叶兴)',
'phone' => '13757951501',
]);
$company->modules()->create(['module_type' => ModuleTypes::WAREHOUSE]);
$company = new Company();
$company->reference_no = 1000000002;
$company->name = 'GZ-BY-V02 广州白云江高仓库';
$company->type = CompanyTypes::COMPANY_BUSINESS;
$company->status = AccountStatus::ACTIVE;
$company->save();
$company->addresses()->create([
'street_one' => '广东省,广州市,白云区,大朗南路 白云湖大道自编13号 7号仓库',
'street_two' => ' 高德地图导航:广州市世通行',
'post_code' => 510450,
'city' => '',
'state' => '',
'country' => 'China',
'default' => 1,
'billing' => 1
]);
$company->contacts()->create([
'name' => '杨维民',
'phone' => '13600055019',
]);
$company->modules()->create(['module_type' => ModuleTypes::WAREHOUSE]);
}
}
@@ -85,7 +85,9 @@
city: '',
state: '',
post_code: '',
country: ''
country: '',
default: 1,
billing: 1
}
}
File diff suppressed because one or more lines are too long
@@ -7,10 +7,10 @@
<div class="col-auto no-padding all-caps">
<div class="row">
<div class="col fs-10">
<span class="bold">#47586979</span>
<span class="bold">#{{order.marking}}</span>
</div>
</div>
<div class="row">
<div class="row d-none">
<div class="col">
<div class="fs-9 muted all-caps">Importer:
@@ -28,7 +28,7 @@
<!---->
</div>
</div>
<div class="row fs-9">
<div class="row fs-9 ">
<div class="col muted">
<span class="inline v-align-middle">Waiting for supplier to deliver order to warehouse</span>
<!---->
@@ -37,139 +37,6 @@
</div>
</div>
</div>
<div class="col-auto">
<div class="row">
<div class="hide">
<div class="row">
<div class="col no-padding">
<div class="row">
<div class="col all-caps fs-13 bold"></div>
</div>
<div class="row fs-12 m-t-5">
<div class="col"></div>
</div>
</div>
</div>
</div>
<div class="col">
<div class="row align-items-center justify-content-center">
<div class="col-auto p-l-0">
<div class="inline">
<div data-type="receiveNote" class="modal fade modalContainer stick-up">
<div class="modal-dialog">
<div class="modal-content-wrapper">
<div class="modal-content">
<div class="modal-body">
<div class="hide">
<div class="row">
<div class="col no-padding">
<div class="row">
<div class="col all-caps fs-13 bold"></div>
</div>
<div class="row fs-12 m-t-5">
<div class="col"></div>
</div>
</div>
</div>
</div>
<div class="absolute w-100 h-100" style="z-index: 1051; left: 0px; display: none;">
<div class="absolute w-100 h-100 bg-white" style="opacity: 0.6;"></div>
<div class="row h-100 align-items-center justify-content-center">
<div class="col">
<div data-v-7c827517="" class="breeding-rhombus-spinner m-auto" style="height: 60px; width: 60px;">
<div data-v-7c827517="" class="rhombus child-1" style="animation-delay: 100ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-2" style="animation-delay: 150ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-3" style="animation-delay: 200ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-4" style="animation-delay: 250ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-5" style="animation-delay: 300ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-6" style="animation-delay: 350ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-7" style="animation-delay: 400ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus child-8" style="animation-delay: 450ms; height: 8px; width: 8px; animation-duration: 1000ms; top: 25.9999px; left: 25.9999px; background-color: rgb(255, 29, 94);"></div>
<div data-v-7c827517="" class="rhombus big" style="height: 20px; width: 20px; top: 20px; left: 20px; background-color: rgb(255, 29, 94);"></div>
</div>
</div>
</div>
</div>
<div class="card card-default no-border">
<div class="card-block no-padding">
<div class="row p-t-30">
<div class="col no-padding">
<div class="b-l b-success p-l-15 m-b-15" style="border-left-width: 3px;">
<h6 class="bold all-caps no-margin text-success">Warehouse Received</h6>
<div class="muted all-caps fs-12">Order Receive Note</div>
</div>
</div>
</div>
<form method="post" class="receiveForm" novalidate="novalidate">
<div class="row">
<div class="col no-padding">
<div class="form-group form-group-default input-group">
<div class="row w-100">
<div class="col no-padding">
<label class="muted block">Tracking Number</label>
<input name="tracking_number" class="form-control block">
</div>
</div>
</div>
<div class="form-group form-group-default input-group" style="overflow: visible;">
<div class="form-input-group">
<label>Date Received</label>
<input type="text" class="form-control" name="complete_date">
</div>
</div>
<div class="row">
<div class="col text-right no-padding">
<div class="row">
<div class="col no-padding">
<button data-dismiss="modal" class="btn b-rad-none btn-default">Cancel</button>
<button type="button" data-dismiss="modal" class="btn b-rad-none btn-success">Confirm</button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="dropdown inline">
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm btn-default b-rad-none p-t-10 p-b-10">
<i class="fa fa-angle-down"></i>
</button>
<div aria-labelledby="dropdownMenuLink" class="dropdown-menu dropdown-menu-right b-rad-none no-padding pointer" style="box-shadow: none; min-width: 150px;">
<a href="https://www.izyim.com/order/3573/profile">
<div class="row no-margin align-items-center justify-content-center text-black" style="border-bottom: 1px solid rgb(225, 225, 225);">
<div class="col-3 p-t-15 p-b-15 bg-master-lighter muted">
<i class="fa fa-chevron-right fs-10"></i>
</div>
<div class="col" style="white-space: nowrap;">
<span class="fs-10 all-caps bold">View Details</span>
</div>
</div>
</a>
<div class="text-danger all-caps gb-master-lightest" style="white-space: nowrap;">
<div class="row no-margin align-items-center justify-content-center">
<div class="col-3 p-t-15 p-b-15 bg-master-lighter">
<i class="fa fa-times fs-10"></i>
</div>
<div class="col" style="white-space: nowrap;">
<span class="fs-10 bold">Cancel Order</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col">
@@ -179,7 +46,7 @@
</div>
</div>
<div class="row fs-12 p-t-15 p-b-15 m-l-0 m-r-0 ">
<div class="col">
<div class="col-3 d-none d-md-block">
<div class="row no-margin">
<div class="col no-padding relative b-a b-grey b-dashed qr-container">
<a href="https://www.izyim.com/3573/qr/pdf/download" target="_blank">
@@ -219,41 +86,16 @@
</div>
</div>
</div>
<div class="col-9 p-l-0">
<div class="row m-l-0 m-r-0 m-b-10">
<div class="col p-l-0">
<small class="muted all-caps">Order History</small>
</div>
</div>
<div class="row">
<div class="col p-l-0">
<div class="row m-l-0 m-r-0 relative order-history p-b-15">
<div class="absolute bullet-connector hint-text"></div>
<div class="col">
<div class="row no-margin">
<div class="col">
<div class="row m-b-10">
<div class="col">
<div class="row align-items-center justify-content-center fs-10">
<div class="col-auto p-r-10">
<div class="bg-master-light btn-rounded hint-text" style="width: 8px; height: 8px;"></div>
</div>
<div class="col-auto hint-text p-l-0">
30-07-2020
</div>
<div class="col p-l-0 lh-20">Guangzhou confirmed as your order's warehouse</div>
</div>
<small class="text-danger bold">Important: Click on the button below download order reference and send it to your supplier to print and place on all of your order packages</small>
</div>
</div>
<div class="row m-l-0 m-r-0 relative order-history p-b-15">
<div class="absolute bullet-connector hint-text"></div>
<div class="col">
<div class="row align-items-center justify-content-center fs-10">
<div class="col-auto p-r-10">
<div class="bg-master-light btn-rounded hint-text" style="width: 8px; height: 8px;"></div>
</div>
<div class="col-auto hint-text p-l-0">
30-07-2020
</div>
<div class="col p-l-0 lh-20">Order number has been created</div>
</div>
</div>
<div class="row">
<div class="btn btn-block btn-sm b-rad-none btn-success" :href="route('order.qr.download', data.id)" target="_blank">Download Qr Reference PDF</div>
</div>
</div>
</div>
@@ -263,4 +105,25 @@
</div>
</div>
</div>
</template>
</template>
<script>
export default {
props: {
'data': {
type: Object,
required: true
}
},
data() {
return {
order: this.data
}
},
watch: {
'data': function() {
this.oder = this.data;
}
},
}
</script>
@@ -42,7 +42,7 @@
</div>
<div class="row">
<div class="col">
<div class="row" v-if="parameters.warehouse_id">
<div class="row" @click="submit((route('api.order.create')), 'post', 'order.form', true, true)" v-if="parameters.warehouse_id">
<div class="col text-right">
<div class="btn btn-lg btn-block btn-primary b-rad-none p-t-10 p-b-10">
<div class="row align-items-center justify-content-center">
@@ -55,7 +55,7 @@
</div>
</div>
<div class="col all-caps">
<small class="fs-11 bold" style="letter-spacing: 2px;" @click="closeModal">Place order</small>
<small class="fs-11 bold" style="letter-spacing: 2px;">Place order</small>
</div>
<div class="col-auto p-l-0 p-r-10">
<i class="fa fa-long-arrow-right"></i>
@@ -86,7 +86,7 @@
data() {
return {
parameters : {
company_id: '',
company_id: this.id,
warehouse_id: ''
}
@@ -4,7 +4,7 @@
@include('partials.header')
<div class="page-container">
<div class="page-content-wrapper p-b-50">
<div class="content ">
<div class="content pt-md-auto pt-4">
<div class="container container-fixed-lg">
@yield('inner_content')
</div>
+73
View File
@@ -0,0 +1,73 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>order-qr-{{$order->marking}}</title>
</head>
<style>
@font-face {
font-family: 'HanWangYenHeavy';
font-style: normal;
font-weight: 400;
src: url(http://eclecticgeek.com/dompdf/fonts/cjk/fireflysung.ttf) format('truetype');
}
@page { margin: 0px; }
body { margin: 0px; }
body {
font-family: Firefly Sung, DejaVu Sans, sans-serif;
text-transform: uppercase;
}
.page-break {
page-break-after: always;
}
</style>
<body>
<table style="width: 100%; border: 2px solid #000000;">
<tbody>
@for ($i = 0; $i < 4; $i++)
<tr>
<td align="center" width="30%" style="border: 2px solid #000000;">
<table width="100%">
<tbody>
<tr align="center">
<td>
<img src="{{ url('https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl={"hash":"{1*23456}","id":'.$order->id.'}') }}" />
</td>
</tr>
<tr align="center">
<td>
<h5 style="margin: 0 !important;"><strong>#{{$order->marking}}</strong></h5>
</td>
</tr>
</tbody>
</table>
</td>
<td width="70%" style="border: 2px solid #000000; padding: 15px !important;">
<table>
<tbody>
<tr>
<td style="border-bottom: solid 2px #000000;">
<h3 style="margin-top: 0px !important; margin-bottom: 10px !important;">@if(strtolower($delivery_address->state) === 'sabah') SB/ @elseif(strtolower($delivery_address->state) === 'sarawak') SRW/ @endif{{$company->marking}}/{{$order->marking}}</h3>
</td>
</tr>
{{--<tr>--}}
{{--<td style="border-bottom: solid 1px #000000;">--}}
{{--<h5 style="margin-top: 10px !important; margin-bottom: 10px !important; word-wrap: break-word">{{$delivery_address->street_one.' '.$delivery_address->street_two.' '.$delivery_address->city.' '.$delivery_address->post_code.' '.$delivery_address->state}}</h5>--}}
{{--</td>--}}
{{--</tr>--}}
<tr>
<td>
<p style="font-size: 12px; margin-bottom: 0 !important; margin-top: 10px !important;">仓库地址:</p>
<p style="margin-top: 5px !important; margin-bottom: 5px !important; word-wrap: break-word; font-size: 16px;">{{$warehouse_address->street_one.' '.$warehouse_address->street_two.' '.$warehouse_address->city.' '.$warehouse_address->state.' 邮编:'.$warehouse_address->post_code}}</p>
<p style="margin-top: 5px !important; margin-bottom: 0px !important; font-size: 12px;">联系:{{$warehouse_contact[0]->contact.' '.$warehouse_contact[0]->name}} @if(array_key_exists(1, $warehouse_contact)) / {{$warehouse_contact[1]->contact.' '.$warehouse_contact[1]->name}} @endif</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
@endfor
</tbody>
</table>
</body>
</html>
+2 -2
View File
@@ -1,8 +1,8 @@
<div class="header p-r-0 bg-primary" id="header">
<div class="header p-r-0 p-l-0 bg-primary" id="header">
<div class="row m-l-0 header-inner header-md-height">
<div class="col h-100">
<div class="row h-100 align-items-center justify-content-center">
<div class="col-auto d-md-none d-lg-none">
<div class="col-auto d-none">
<a href="#" class="btn-link toggle-sidebar fa fa-bars text-white" data-toggle="horizontal-menu"></a>
</div>
<div class="col-auto d-xs-none">
+2
View File
@@ -19,5 +19,7 @@ Route::group(['middleware' => 'api', 'prefix' => 'v1', 'as' => 'api.'], function
Route::group(['middleware' => 'valid.token'], function () {
require __DIR__ . '/crud.php';
Route::post('order/create', 'Orders\OrderController@create')->name('order.create');
Route::get('orders/{company_id}/list', 'Orders\OrderController@list')->name('order.list');
});
});
+2
View File
@@ -32,3 +32,5 @@ Route::get('/company/{id}/importer/dashboard', function ($id) {
Route::get('/company/forwarder/dashboard', function () {
return view('pages.dashboards.forwarder_profile');
})->name('dashboard.forwarder');
Route::get('orders/{order_id}/download', 'Orders\OrderController@download')->name('order.qr.download');