From 502e599eb3ec50fc7169370d879dba9590bf2e6d Mon Sep 17 00:00:00 2001 From: Fahim Date: Mon, 16 Aug 2021 23:03:51 +0600 Subject: [PATCH] Added: Quotation Module --- Modules/Quotation/Config/.gitkeep | 0 Modules/Quotation/Config/config.php | 5 + Modules/Quotation/Console/.gitkeep | 0 .../DataTables/QuotationsDataTable.php | 85 +++++++++ .../Quotation/Database/Migrations/.gitkeep | 0 ...1_08_16_015031_create_quotations_table.php | 44 +++++ ..._155013_create_quotation_details_table.php | 46 +++++ Modules/Quotation/Database/Seeders/.gitkeep | 0 .../Seeders/QuotationDatabaseSeeder.php | 21 +++ Modules/Quotation/Database/factories/.gitkeep | 0 Modules/Quotation/Emails/QuotationMail.php | 38 ++++ Modules/Quotation/Entities/.gitkeep | 0 Modules/Quotation/Entities/Quotation.php | 60 ++++++ .../Quotation/Entities/QuotationDetails.php | 43 +++++ Modules/Quotation/Http/Controllers/.gitkeep | 0 .../Http/Controllers/QuotationController.php | 174 ++++++++++++++++++ .../Controllers/QuotationSalesController.php | 48 +++++ .../SendQuotationEmailController.php | 32 ++++ Modules/Quotation/Http/Middleware/.gitkeep | 0 Modules/Quotation/Http/Requests/.gitkeep | 0 .../Http/Requests/StoreQuotationRequest.php | 38 ++++ .../Http/Requests/UpdateQuotationRequest.php | 38 ++++ Modules/Quotation/Providers/.gitkeep | 0 .../Providers/QuotationServiceProvider.php | 112 +++++++++++ .../Providers/RouteServiceProvider.php | 69 +++++++ Modules/Quotation/Resources/assets/.gitkeep | 0 Modules/Quotation/Resources/assets/js/app.js | 0 .../Quotation/Resources/assets/sass/app.scss | 0 Modules/Quotation/Resources/lang/.gitkeep | 0 Modules/Quotation/Resources/views/.gitkeep | 0 .../Resources/views/create.blade.php | 92 +++++++++ .../Quotation/Resources/views/edit.blade.php | 92 +++++++++ .../views/emails/quotation.blade.php | 120 ++++++++++++ .../Quotation/Resources/views/index.blade.php | 40 ++++ .../views/partials/actions.blade.php | 40 ++++ .../Resources/views/partials/status.blade.php | 9 + .../Quotation/Resources/views/print.blade.php | 133 +++++++++++++ .../views/quotation-sales/create.blade.php | 141 ++++++++++++++ .../Quotation/Resources/views/show.blade.php | 135 ++++++++++++++ Modules/Quotation/Routes/.gitkeep | 0 Modules/Quotation/Routes/api.php | 18 ++ Modules/Quotation/Routes/web.php | 36 ++++ Modules/Quotation/Tests/Feature/.gitkeep | 0 Modules/Quotation/Tests/Unit/.gitkeep | 0 Modules/Quotation/composer.json | 23 +++ Modules/Quotation/module.json | 13 ++ Modules/Quotation/package.json | 17 ++ Modules/Quotation/webpack.mix.js | 14 ++ Modules/Sale/Resources/views/show.blade.php | 2 +- .../Http/Controllers/UploadController.php | 8 + .../Seeders/PermissionsTableSeeder.php | 17 ++ .../User/Resources/views/roles/edit.blade.php | 130 +++++++++++++ app/Http/Controllers/HomeController.php | 18 +- app/Http/Livewire/ProductCart.php | 2 +- database/migrations/.gitkeep | 0 ...8_15_161053_create_notifications_table.php | 35 ---- modules_statuses.json | 3 +- resources/views/home.blade.php | 10 + resources/views/layouts/header.blade.php | 4 + resources/views/layouts/menu.blade.php | 22 +++ .../includes/product-cart-modal.blade.php | 2 +- 61 files changed, 1982 insertions(+), 47 deletions(-) create mode 100644 Modules/Quotation/Config/.gitkeep create mode 100644 Modules/Quotation/Config/config.php create mode 100644 Modules/Quotation/Console/.gitkeep create mode 100644 Modules/Quotation/DataTables/QuotationsDataTable.php create mode 100644 Modules/Quotation/Database/Migrations/.gitkeep create mode 100644 Modules/Quotation/Database/Migrations/2021_08_16_015031_create_quotations_table.php create mode 100644 Modules/Quotation/Database/Migrations/2021_08_16_155013_create_quotation_details_table.php create mode 100644 Modules/Quotation/Database/Seeders/.gitkeep create mode 100644 Modules/Quotation/Database/Seeders/QuotationDatabaseSeeder.php create mode 100644 Modules/Quotation/Database/factories/.gitkeep create mode 100644 Modules/Quotation/Emails/QuotationMail.php create mode 100644 Modules/Quotation/Entities/.gitkeep create mode 100644 Modules/Quotation/Entities/Quotation.php create mode 100644 Modules/Quotation/Entities/QuotationDetails.php create mode 100644 Modules/Quotation/Http/Controllers/.gitkeep create mode 100644 Modules/Quotation/Http/Controllers/QuotationController.php create mode 100644 Modules/Quotation/Http/Controllers/QuotationSalesController.php create mode 100644 Modules/Quotation/Http/Controllers/SendQuotationEmailController.php create mode 100644 Modules/Quotation/Http/Middleware/.gitkeep create mode 100644 Modules/Quotation/Http/Requests/.gitkeep create mode 100644 Modules/Quotation/Http/Requests/StoreQuotationRequest.php create mode 100644 Modules/Quotation/Http/Requests/UpdateQuotationRequest.php create mode 100644 Modules/Quotation/Providers/.gitkeep create mode 100644 Modules/Quotation/Providers/QuotationServiceProvider.php create mode 100644 Modules/Quotation/Providers/RouteServiceProvider.php create mode 100644 Modules/Quotation/Resources/assets/.gitkeep create mode 100644 Modules/Quotation/Resources/assets/js/app.js create mode 100644 Modules/Quotation/Resources/assets/sass/app.scss create mode 100644 Modules/Quotation/Resources/lang/.gitkeep create mode 100644 Modules/Quotation/Resources/views/.gitkeep create mode 100644 Modules/Quotation/Resources/views/create.blade.php create mode 100644 Modules/Quotation/Resources/views/edit.blade.php create mode 100644 Modules/Quotation/Resources/views/emails/quotation.blade.php create mode 100644 Modules/Quotation/Resources/views/index.blade.php create mode 100644 Modules/Quotation/Resources/views/partials/actions.blade.php create mode 100644 Modules/Quotation/Resources/views/partials/status.blade.php create mode 100644 Modules/Quotation/Resources/views/print.blade.php create mode 100644 Modules/Quotation/Resources/views/quotation-sales/create.blade.php create mode 100644 Modules/Quotation/Resources/views/show.blade.php create mode 100644 Modules/Quotation/Routes/.gitkeep create mode 100644 Modules/Quotation/Routes/api.php create mode 100644 Modules/Quotation/Routes/web.php create mode 100644 Modules/Quotation/Tests/Feature/.gitkeep create mode 100644 Modules/Quotation/Tests/Unit/.gitkeep create mode 100644 Modules/Quotation/composer.json create mode 100644 Modules/Quotation/module.json create mode 100644 Modules/Quotation/package.json create mode 100644 Modules/Quotation/webpack.mix.js create mode 100644 database/migrations/.gitkeep delete mode 100644 database/migrations/2021_08_15_161053_create_notifications_table.php diff --git a/Modules/Quotation/Config/.gitkeep b/Modules/Quotation/Config/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Config/config.php b/Modules/Quotation/Config/config.php new file mode 100644 index 00000000..9e6ed2e8 --- /dev/null +++ b/Modules/Quotation/Config/config.php @@ -0,0 +1,5 @@ + 'Quotation' +]; diff --git a/Modules/Quotation/Console/.gitkeep b/Modules/Quotation/Console/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/DataTables/QuotationsDataTable.php b/Modules/Quotation/DataTables/QuotationsDataTable.php new file mode 100644 index 00000000..75dfe510 --- /dev/null +++ b/Modules/Quotation/DataTables/QuotationsDataTable.php @@ -0,0 +1,85 @@ +eloquent($query) + ->addColumn('total_amount', function ($data) { + return format_currency($data->total_amount); + }) + ->addColumn('status', function ($data) { + return view('quotation::partials.status', compact('data')); + }) + ->addColumn('action', function ($data) { + return view('quotation::partials.actions', compact('data')); + }); + } + + public function query(Quotation $model) { + return $model->newQuery(); + } + + public function html() { + return $this->builder() + ->setTableId('sales-table') + ->columns($this->getColumns()) + ->minifiedAjax() + ->dom("<'row'<'col-md-3'l><'col-md-5 mb-2'B><'col-md-4'f>> . + 'tr' . + <'row'<'col-md-5'i><'col-md-7 mt-2'p>>") + ->orderBy(6) + ->buttons( + Button::make('excel') + ->text(' Excel'), + Button::make('print') + ->text(' Print'), + Button::make('reset') + ->text(' Reset'), + Button::make('reload') + ->text(' Reload') + ); + } + + protected function getColumns() { + return [ + Column::make('date') + ->className('text-center align-middle'), + + Column::make('reference') + ->className('text-center align-middle'), + + Column::make('customer_name') + ->title('Customer') + ->className('text-center align-middle'), + + Column::computed('status') + ->className('text-center align-middle'), + + Column::computed('total_amount') + ->className('text-center align-middle'), + + Column::computed('action') + ->exportable(false) + ->printable(false) + ->className('text-center align-middle'), + + Column::make('created_at') + ->visible(false) + ]; + } + + protected function filename() { + return 'Quotations_' . date('YmdHis'); + } +} diff --git a/Modules/Quotation/Database/Migrations/.gitkeep b/Modules/Quotation/Database/Migrations/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Database/Migrations/2021_08_16_015031_create_quotations_table.php b/Modules/Quotation/Database/Migrations/2021_08_16_015031_create_quotations_table.php new file mode 100644 index 00000000..3f36686f --- /dev/null +++ b/Modules/Quotation/Database/Migrations/2021_08_16_015031_create_quotations_table.php @@ -0,0 +1,44 @@ +id(); + $table->date('date'); + $table->string('reference'); + $table->unsignedBigInteger('customer_id')->nullable(); + $table->string('customer_name'); + $table->integer('tax_percentage')->default(0); + $table->integer('tax_amount')->default(0); + $table->integer('discount_percentage')->default(0); + $table->integer('discount_amount')->default(0); + $table->integer('shipping_amount')->default(0); + $table->integer('total_amount'); + $table->string('status'); + $table->text('note')->nullable(); + $table->foreign('customer_id')->references('id')->on('customers')->nullOnDelete(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('quotations'); + } +} diff --git a/Modules/Quotation/Database/Migrations/2021_08_16_155013_create_quotation_details_table.php b/Modules/Quotation/Database/Migrations/2021_08_16_155013_create_quotation_details_table.php new file mode 100644 index 00000000..6d1cbd75 --- /dev/null +++ b/Modules/Quotation/Database/Migrations/2021_08_16_155013_create_quotation_details_table.php @@ -0,0 +1,46 @@ +id(); + $table->unsignedBigInteger('quotation_id'); + $table->unsignedBigInteger('product_id')->nullable(); + $table->string('product_name'); + $table->string('product_code'); + $table->integer('quantity'); + $table->integer('price'); + $table->integer('unit_price'); + $table->integer('sub_total'); + $table->integer('product_discount_amount'); + $table->string('product_discount_type')->default('fixed'); + $table->integer('product_tax_amount'); + $table->foreign('quotation_id')->references('id') + ->on('quotations')->cascadeOnDelete(); + $table->foreign('product_id')->references('id') + ->on('products')->nullOnDelete(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('quotation_details'); + } +} diff --git a/Modules/Quotation/Database/Seeders/.gitkeep b/Modules/Quotation/Database/Seeders/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Database/Seeders/QuotationDatabaseSeeder.php b/Modules/Quotation/Database/Seeders/QuotationDatabaseSeeder.php new file mode 100644 index 00000000..c89516fc --- /dev/null +++ b/Modules/Quotation/Database/Seeders/QuotationDatabaseSeeder.php @@ -0,0 +1,21 @@ +call("OthersTableSeeder"); + } +} diff --git a/Modules/Quotation/Database/factories/.gitkeep b/Modules/Quotation/Database/factories/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Emails/QuotationMail.php b/Modules/Quotation/Emails/QuotationMail.php new file mode 100644 index 00000000..167fccbf --- /dev/null +++ b/Modules/Quotation/Emails/QuotationMail.php @@ -0,0 +1,38 @@ +quotation = $quotation; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this->subject('Quotation - ' . settings()->company_name) + ->view('quotation::emails.quotation', [ + 'settings' => settings(), + 'customer' => $this->quotation->customer + ]); + } +} diff --git a/Modules/Quotation/Entities/.gitkeep b/Modules/Quotation/Entities/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Entities/Quotation.php b/Modules/Quotation/Entities/Quotation.php new file mode 100644 index 00000000..c6074278 --- /dev/null +++ b/Modules/Quotation/Entities/Quotation.php @@ -0,0 +1,60 @@ +hasMany(QuotationDetails::class, 'quotation_id', 'id'); + } + + public function customer() { + return $this->belongsTo(Customer::class, 'customer_id', 'id'); + } + + public static function boot() { + parent::boot(); + + static::creating(function ($model) { + $number = Quotation::max('id') + 1; + $model->reference = make_reference_id('QT', $number); + }); + } + + public function getDateAttribute($value) { + return Carbon::parse($value)->format('d M, Y'); + } + + public function getShippingAmountAttribute($value) { + return $value / 100; + } + + public function getPaidAmountAttribute($value) { + return $value / 100; + } + + public function getTotalAmountAttribute($value) { + return $value / 100; + } + + public function getDueAmountAttribute($value) { + return $value / 100; + } + + public function getTaxAmountAttribute($value) { + return $value / 100; + } + + public function getDiscountAmountAttribute($value) { + return $value / 100; + } +} diff --git a/Modules/Quotation/Entities/QuotationDetails.php b/Modules/Quotation/Entities/QuotationDetails.php new file mode 100644 index 00000000..44f68cd3 --- /dev/null +++ b/Modules/Quotation/Entities/QuotationDetails.php @@ -0,0 +1,43 @@ +belongsTo(Product::class, 'product_id', 'id'); + } + + public function quotation() { + return $this->belongsTo(Quotation::class, 'quotation_id', 'id'); + } + + public function getPriceAttribute($value) { + return $value / 100; + } + + public function getUnitPriceAttribute($value) { + return $value / 100; + } + + public function getSubTotalAttribute($value) { + return $value / 100; + } + + public function getProductDiscountAmountAttribute($value) { + return $value / 100; + } + + public function getProductTaxAmountAttribute($value) { + return $value / 100; + }} diff --git a/Modules/Quotation/Http/Controllers/.gitkeep b/Modules/Quotation/Http/Controllers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Http/Controllers/QuotationController.php b/Modules/Quotation/Http/Controllers/QuotationController.php new file mode 100644 index 00000000..1afda851 --- /dev/null +++ b/Modules/Quotation/Http/Controllers/QuotationController.php @@ -0,0 +1,174 @@ +render('quotation::index'); + } + + + public function create() { + abort_if(Gate::denies('create_quotations'), 403); + + Cart::instance('quotation')->destroy(); + + return view('quotation::create'); + } + + + public function store(StoreQuotationRequest $request) { + DB::transaction(function () use ($request) { + $quotation = Quotation::create([ + 'date' => $request->date, + 'customer_id' => $request->customer_id, + 'customer_name' => Customer::findOrFail($request->customer_id)->customer_name, + 'tax_percentage' => $request->tax_percentage, + 'discount_percentage' => $request->discount_percentage, + 'shipping_amount' => $request->shipping_amount * 100, + 'total_amount' => $request->total_amount * 100, + 'status' => $request->status, + 'note' => $request->note, + 'tax_amount' => Cart::instance('quotation')->tax() * 100, + 'discount_amount' => Cart::instance('quotation')->discount() * 100, + ]); + + foreach (Cart::instance('quotation')->content() as $cart_item) { + QuotationDetails::create([ + 'quotation_id' => $quotation->id, + 'product_id' => $cart_item->id, + 'product_name' => $cart_item->name, + 'product_code' => $cart_item->options->code, + 'quantity' => $cart_item->qty, + 'price' => $cart_item->price * 100, + 'unit_price' => $cart_item->options->unit_price * 100, + 'sub_total' => $cart_item->options->sub_total * 100, + 'product_discount_amount' => $cart_item->options->product_discount * 100, + 'product_discount_type' => $cart_item->options->product_discount_type, + 'product_tax_amount' => $cart_item->options->product_tax * 100, + ]); + } + + Cart::instance('quotation')->destroy(); + }); + + toast('Quotation Created!', 'success'); + + return redirect()->route('quotations.index'); + } + + + public function show(Quotation $quotation) { + abort_if(Gate::denies('show_quotations'), 403); + + $customer = Customer::findOrFail($quotation->customer_id); + + return view('quotation::show', compact('quotation', 'customer')); + } + + + public function edit(Quotation $quotation) { + abort_if(Gate::denies('edit_quotations'), 403); + + $quotation_details = $quotation->quotationDetails; + + Cart::instance('quotation')->destroy(); + + $cart = Cart::instance('quotation'); + + foreach ($quotation_details as $quotation_detail) { + $cart->add([ + 'id' => $quotation_detail->product_id, + 'name' => $quotation_detail->product_name, + 'qty' => $quotation_detail->quantity, + 'price' => $quotation_detail->price, + 'weight' => 1, + 'options' => [ + 'product_discount' => $quotation_detail->product_discount_amount, + 'product_discount_type' => $quotation_detail->product_discount_type, + 'sub_total' => $quotation_detail->sub_total, + 'code' => $quotation_detail->product_code, + 'stock' => Product::findOrFail($quotation_detail->product_id)->product_quantity, + 'product_tax' => $quotation_detail->product_tax_amount, + 'unit_price' => $quotation_detail->unit_price + ] + ]); + } + + return view('quotation::edit', compact('quotation')); + } + + + public function update(UpdateQuotationRequest $request, Quotation $quotation) { + DB::transaction(function () use ($request, $quotation) { + foreach ($quotation->quotationDetails as $quotation_detail) { + $quotation_detail->delete(); + } + + $quotation->update([ + 'date' => $request->date, + 'reference' => $request->reference, + 'customer_id' => $request->customer_id, + 'customer_name' => Customer::findOrFail($request->customer_id)->customer_name, + 'tax_percentage' => $request->tax_percentage, + 'discount_percentage' => $request->discount_percentage, + 'shipping_amount' => $request->shipping_amount * 100, + 'total_amount' => $request->total_amount * 100, + 'status' => $request->status, + 'note' => $request->note, + 'tax_amount' => Cart::instance('quotation')->tax() * 100, + 'discount_amount' => Cart::instance('quotation')->discount() * 100, + ]); + + foreach (Cart::instance('quotation')->content() as $cart_item) { + QuotationDetails::create([ + 'quotation_id' => $quotation->id, + 'product_id' => $cart_item->id, + 'product_name' => $cart_item->name, + 'product_code' => $cart_item->options->code, + 'quantity' => $cart_item->qty, + 'price' => $cart_item->price * 100, + 'unit_price' => $cart_item->options->unit_price * 100, + 'sub_total' => $cart_item->options->sub_total * 100, + 'product_discount_amount' => $cart_item->options->product_discount * 100, + 'product_discount_type' => $cart_item->options->product_discount_type, + 'product_tax_amount' => $cart_item->options->product_tax * 100, + ]); + } + + Cart::instance('quotation')->destroy(); + }); + + toast('Quotation Updated!', 'info'); + + return redirect()->route('quotations.index'); + } + + + public function destroy(Quotation $quotation) { + abort_if(Gate::denies('delete_quotations'), 403); + + $quotation->delete(); + + toast('Quotation Deleted!', 'warning'); + + return redirect()->route('quotations.index'); + } +} diff --git a/Modules/Quotation/Http/Controllers/QuotationSalesController.php b/Modules/Quotation/Http/Controllers/QuotationSalesController.php new file mode 100644 index 00000000..a149b03e --- /dev/null +++ b/Modules/Quotation/Http/Controllers/QuotationSalesController.php @@ -0,0 +1,48 @@ +quotationDetails; + + Cart::instance('sale')->destroy(); + + $cart = Cart::instance('sale'); + + foreach ($quotation_details as $quotation_detail) { + $cart->add([ + 'id' => $quotation_detail->product_id, + 'name' => $quotation_detail->product_name, + 'qty' => $quotation_detail->quantity, + 'price' => $quotation_detail->price, + 'weight' => 1, + 'options' => [ + 'product_discount' => $quotation_detail->product_discount_amount, + 'product_discount_type' => $quotation_detail->product_discount_type, + 'sub_total' => $quotation_detail->sub_total, + 'code' => $quotation_detail->product_code, + 'stock' => Product::findOrFail($quotation_detail->product_id)->product_quantity, + 'product_tax' => $quotation_detail->product_tax_amount, + 'unit_price' => $quotation_detail->unit_price + ] + ]); + } + + return view('quotation::quotation-sales.create', [ + 'quotation_id' => $quotation->id, + 'sale' => $quotation + ]); + } +} diff --git a/Modules/Quotation/Http/Controllers/SendQuotationEmailController.php b/Modules/Quotation/Http/Controllers/SendQuotationEmailController.php new file mode 100644 index 00000000..1abe55e2 --- /dev/null +++ b/Modules/Quotation/Http/Controllers/SendQuotationEmailController.php @@ -0,0 +1,32 @@ +customer->customer_email)->send(new QuotationMail($quotation)); + + $quotation->update([ + 'status' => 'Sent' + ]); + + toast('Sent On "' . $quotation->customer->customer_email . '"!', 'success'); + + } catch (\Exception $exception) { + Log::error($exception); + toast('Something Went Wrong!', 'error'); + } + + return back(); + } +} diff --git a/Modules/Quotation/Http/Middleware/.gitkeep b/Modules/Quotation/Http/Middleware/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Http/Requests/.gitkeep b/Modules/Quotation/Http/Requests/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Http/Requests/StoreQuotationRequest.php b/Modules/Quotation/Http/Requests/StoreQuotationRequest.php new file mode 100644 index 00000000..0919f9a1 --- /dev/null +++ b/Modules/Quotation/Http/Requests/StoreQuotationRequest.php @@ -0,0 +1,38 @@ + 'required|numeric', + 'reference' => 'required|string|max:255', + 'tax_percentage' => 'required|integer|min:0|max:100', + 'discount_percentage' => 'required|integer|min:0|max:100', + 'shipping_amount' => 'required|numeric', + 'total_amount' => 'required|numeric', + 'status' => 'required|string|max:255', + 'note' => 'nullable|string|max:1000' + ]; + } + + /** + * Determine if the user is authorized to make this request. + * + * @return bool + */ + public function authorize() + { + return Gate::allows('create_quotations'); + } +} diff --git a/Modules/Quotation/Http/Requests/UpdateQuotationRequest.php b/Modules/Quotation/Http/Requests/UpdateQuotationRequest.php new file mode 100644 index 00000000..f6236188 --- /dev/null +++ b/Modules/Quotation/Http/Requests/UpdateQuotationRequest.php @@ -0,0 +1,38 @@ + 'required|numeric', + 'reference' => 'required|string|max:255', + 'tax_percentage' => 'required|integer|min:0|max:100', + 'discount_percentage' => 'required|integer|min:0|max:100', + 'shipping_amount' => 'required|numeric', + 'total_amount' => 'required|numeric', + 'status' => 'required|string|max:255', + 'note' => 'nullable|string|max:1000' + ]; + } + + /** + * Determine if the user is authorized to make this request. + * + * @return bool + */ + public function authorize() + { + return Gate::allows('edit_quotations'); + } +} diff --git a/Modules/Quotation/Providers/.gitkeep b/Modules/Quotation/Providers/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Providers/QuotationServiceProvider.php b/Modules/Quotation/Providers/QuotationServiceProvider.php new file mode 100644 index 00000000..9424cc5f --- /dev/null +++ b/Modules/Quotation/Providers/QuotationServiceProvider.php @@ -0,0 +1,112 @@ +registerTranslations(); + $this->registerConfig(); + $this->registerViews(); + $this->loadMigrationsFrom(module_path($this->moduleName, 'Database/Migrations')); + } + + /** + * Register the service provider. + * + * @return void + */ + public function register() + { + $this->app->register(RouteServiceProvider::class); + } + + /** + * Register config. + * + * @return void + */ + protected function registerConfig() + { + $this->publishes([ + module_path($this->moduleName, 'Config/config.php') => config_path($this->moduleNameLower . '.php'), + ], 'config'); + $this->mergeConfigFrom( + module_path($this->moduleName, 'Config/config.php'), $this->moduleNameLower + ); + } + + /** + * Register views. + * + * @return void + */ + public function registerViews() + { + $viewPath = resource_path('views/modules/' . $this->moduleNameLower); + + $sourcePath = module_path($this->moduleName, 'Resources/views'); + + $this->publishes([ + $sourcePath => $viewPath + ], ['views', $this->moduleNameLower . '-module-views']); + + $this->loadViewsFrom(array_merge($this->getPublishableViewPaths(), [$sourcePath]), $this->moduleNameLower); + } + + /** + * Register translations. + * + * @return void + */ + public function registerTranslations() + { + $langPath = resource_path('lang/modules/' . $this->moduleNameLower); + + if (is_dir($langPath)) { + $this->loadTranslationsFrom($langPath, $this->moduleNameLower); + } else { + $this->loadTranslationsFrom(module_path($this->moduleName, 'Resources/lang'), $this->moduleNameLower); + } + } + + /** + * Get the services provided by the provider. + * + * @return array + */ + public function provides() + { + return []; + } + + private function getPublishableViewPaths(): array + { + $paths = []; + foreach (\Config::get('view.paths') as $path) { + if (is_dir($path . '/modules/' . $this->moduleNameLower)) { + $paths[] = $path . '/modules/' . $this->moduleNameLower; + } + } + return $paths; + } +} diff --git a/Modules/Quotation/Providers/RouteServiceProvider.php b/Modules/Quotation/Providers/RouteServiceProvider.php new file mode 100644 index 00000000..077305c4 --- /dev/null +++ b/Modules/Quotation/Providers/RouteServiceProvider.php @@ -0,0 +1,69 @@ +mapApiRoutes(); + + $this->mapWebRoutes(); + } + + /** + * Define the "web" routes for the application. + * + * These routes all receive session state, CSRF protection, etc. + * + * @return void + */ + protected function mapWebRoutes() + { + Route::middleware('web') + ->namespace($this->moduleNamespace) + ->group(module_path('Quotation', '/Routes/web.php')); + } + + /** + * Define the "api" routes for the application. + * + * These routes are typically stateless. + * + * @return void + */ + protected function mapApiRoutes() + { + Route::prefix('api') + ->middleware('api') + ->namespace($this->moduleNamespace) + ->group(module_path('Quotation', '/Routes/api.php')); + } +} diff --git a/Modules/Quotation/Resources/assets/.gitkeep b/Modules/Quotation/Resources/assets/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Resources/assets/js/app.js b/Modules/Quotation/Resources/assets/js/app.js new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Resources/assets/sass/app.scss b/Modules/Quotation/Resources/assets/sass/app.scss new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Resources/lang/.gitkeep b/Modules/Quotation/Resources/lang/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Resources/views/.gitkeep b/Modules/Quotation/Resources/views/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Resources/views/create.blade.php b/Modules/Quotation/Resources/views/create.blade.php new file mode 100644 index 00000000..9d2c166e --- /dev/null +++ b/Modules/Quotation/Resources/views/create.blade.php @@ -0,0 +1,92 @@ +@extends('layouts.app') + +@section('title', 'Create Quotation') + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+ +
+
+ +
+
+
+
+ @include('utils.alerts') +
+ @csrf + +
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+
+ + +
+
+
+ +
+ + +
+ +
+ +
+ +
+
+
+
+
+@endsection + +@push('page_scripts') + +@endpush diff --git a/Modules/Quotation/Resources/views/edit.blade.php b/Modules/Quotation/Resources/views/edit.blade.php new file mode 100644 index 00000000..46557c4c --- /dev/null +++ b/Modules/Quotation/Resources/views/edit.blade.php @@ -0,0 +1,92 @@ +@extends('layouts.app') + +@section('title', 'Edit Quotation') + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+ +
+
+ +
+
+
+
+ @include('utils.alerts') +
+ @csrf + @method('patch') +
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+
+ + +
+
+
+ +
+ + +
+ +
+ +
+ +
+
+
+
+
+@endsection + +@push('page_scripts') + +@endpush diff --git a/Modules/Quotation/Resources/views/emails/quotation.blade.php b/Modules/Quotation/Resources/views/emails/quotation.blade.php new file mode 100644 index 00000000..a624c1b6 --- /dev/null +++ b/Modules/Quotation/Resources/views/emails/quotation.blade.php @@ -0,0 +1,120 @@ + + + + + + + Quotation Details + + + +
+
+
+
+ Logo +

+ Reference:: {{ $quotation->reference }} +

+
+
+
+
+
+

Company Info:

+
{{ settings()->company_name }}
+
{{ settings()->company_address }}
+
Email: {{ settings()->company_email }}
+
Phone: {{ settings()->company_phone }}
+
+ +
+

Customer Info:

+
{{ $customer->customer_name }}
+
{{ $customer->address }}
+
Email: {{ $customer->customer_email }}
+
Phone: {{ $customer->customer_phone }}
+
+
+ +
+ + + + + + + + + + + + + @foreach($quotation->quotationDetails as $item) + + + + + + + + + + + + + + @endforeach + +
ProductNet Unit PriceQuantityDiscountTaxSub Total
+ {{ $item->product_name }}
+ + {{ $item->product_code }} + +
{{ format_currency($item->unit_price) }} + {{ $item->quantity }} + + {{ format_currency($item->product_discount_amount) }} + + {{ format_currency($item->product_tax_amount) }} + + {{ format_currency($item->sub_total) }} +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
Discount ({{ $quotation->discount_percentage }}%){{ format_currency($quotation->discount_amount) }}
Tax ({{ $quotation->tax_percentage }}%){{ format_currency($quotation->tax_amount) }}
Shipping){{ format_currency($quotation->shipping_amount) }}
Grand Total{{ format_currency($quotation->total_amount) }}
+
+
+
+
+

{{ settings()->company_name }} © {{ date('Y') }}

+
+
+
+
+
+
+
+ + diff --git a/Modules/Quotation/Resources/views/index.blade.php b/Modules/Quotation/Resources/views/index.blade.php new file mode 100644 index 00000000..3521373b --- /dev/null +++ b/Modules/Quotation/Resources/views/index.blade.php @@ -0,0 +1,40 @@ +@extends('layouts.app') + +@section('title', 'Quotations') + +@section('third_party_stylesheets') + +@endsection + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+
+
+ + Add Quotation + + +
+ +
+ {!! $dataTable->table() !!} +
+
+
+
+
+
+@endsection + +@push('page_scripts') + {!! $dataTable->scripts() !!} +@endpush diff --git a/Modules/Quotation/Resources/views/partials/actions.blade.php b/Modules/Quotation/Resources/views/partials/actions.blade.php new file mode 100644 index 00000000..ec5e6107 --- /dev/null +++ b/Modules/Quotation/Resources/views/partials/actions.blade.php @@ -0,0 +1,40 @@ +
+ + +
diff --git a/Modules/Quotation/Resources/views/partials/status.blade.php b/Modules/Quotation/Resources/views/partials/status.blade.php new file mode 100644 index 00000000..0d2e02be --- /dev/null +++ b/Modules/Quotation/Resources/views/partials/status.blade.php @@ -0,0 +1,9 @@ +@if ($data->status == 'Pending') + + {{ $data->status }} + +@else + + {{ $data->status }} + +@endif diff --git a/Modules/Quotation/Resources/views/print.blade.php b/Modules/Quotation/Resources/views/print.blade.php new file mode 100644 index 00000000..6a97c559 --- /dev/null +++ b/Modules/Quotation/Resources/views/print.blade.php @@ -0,0 +1,133 @@ + + + + + + + Quotation Details + + + +
+
+
+
+ Logo +

+ Reference:: {{ $quotation->reference }} +

+
+
+
+
+
+

Company Info:

+
{{ settings()->company_name }}
+
{{ settings()->company_address }}
+
Email: {{ settings()->company_email }}
+
Phone: {{ settings()->company_phone }}
+
+ +
+

Customer Info:

+
{{ $customer->customer_name }}
+
{{ $customer->address }}
+
Email: {{ $customer->customer_email }}
+
Phone: {{ $customer->customer_phone }}
+
+ +
+

Invoice Info:

+
Invoice: INV/{{ $quotation->reference }}
+
Date: {{ \Carbon\Carbon::parse($quotation->date)->format('d M, Y') }}
+
+ Status: {{ $quotation->status }} +
+
+ Payment Status: {{ $quotation->payment_status }} +
+
+ +
+ +
+ + + + + + + + + + + + + @foreach($quotation->quotationDetails as $item) + + + + + + + + + + + + + + @endforeach + +
ProductNet Unit PriceQuantityDiscountTaxSub Total
+ {{ $item->product_name }}
+ + {{ $item->product_code }} + +
{{ format_currency($item->unit_price) }} + {{ $item->quantity }} + + {{ format_currency($item->product_discount_amount) }} + + {{ format_currency($item->product_tax_amount) }} + + {{ format_currency($item->sub_total) }} +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
Discount ({{ $quotation->discount_percentage }}%){{ format_currency($quotation->discount_amount) }}
Tax ({{ $quotation->tax_percentage }}%){{ format_currency($quotation->tax_amount) }}
Shipping){{ format_currency($quotation->shipping_amount) }}
Grand Total{{ format_currency($quotation->total_amount) }}
+
+
+
+
+

{{ settings()->company_name }} © {{ date('Y') }}

+
+
+
+
+
+
+
+ + diff --git a/Modules/Quotation/Resources/views/quotation-sales/create.blade.php b/Modules/Quotation/Resources/views/quotation-sales/create.blade.php new file mode 100644 index 00000000..9609b848 --- /dev/null +++ b/Modules/Quotation/Resources/views/quotation-sales/create.blade.php @@ -0,0 +1,141 @@ +@extends('layouts.app') + +@section('title', 'Create Sale From Quotation') + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+ +
+
+ +
+
+
+
+ @include('utils.alerts') +
+ @csrf + +
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+ + + +
+
+
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +
+ +
+ +
+
+
+
+
+ +
+ + +
+ + + +
+ +
+ +
+
+
+
+
+@endsection + +@push('page_scripts') + + +@endpush diff --git a/Modules/Quotation/Resources/views/show.blade.php b/Modules/Quotation/Resources/views/show.blade.php new file mode 100644 index 00000000..119b05a0 --- /dev/null +++ b/Modules/Quotation/Resources/views/show.blade.php @@ -0,0 +1,135 @@ +@extends('layouts.app') + +@section('title', 'Quotation Details') + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+
+
+
+ Reference: {{ $quotation->reference }} +
+ + Print + + + Save + +
+
+
+
+
Company Info:
+
{{ settings()->company_name }}
+
{{ settings()->company_address }}
+
Email: {{ settings()->company_email }}
+
Phone: {{ settings()->company_phone }}
+
+ +
+
Customer Info:
+
{{ $customer->customer_name }}
+
{{ $customer->address }}
+
Email: {{ $customer->customer_email }}
+
Phone: {{ $customer->customer_phone }}
+
+ +
+
Invoice Info:
+
Invoice: INV/{{ $quotation->reference }}
+
Date: {{ \Carbon\Carbon::parse($quotation->date)->format('d M, Y') }}
+
+ Status: {{ $quotation->status }} +
+
+ Payment Status: {{ $quotation->payment_status }} +
+
+ +
+ +
+ + + + + + + + + + + + + @foreach($quotation->quotationDetails as $item) + + + + + + + + + + + + + + @endforeach + +
ProductNet Unit PriceQuantityDiscountTaxSub Total
+ {{ $item->product_name }}
+ + {{ $item->product_code }} + +
{{ format_currency($item->unit_price) }} + {{ $item->quantity }} + + {{ format_currency($item->product_discount_amount) }} + + {{ format_currency($item->product_tax_amount) }} + + {{ format_currency($item->sub_total) }} +
+
+
+
+ + + + + + + + + + + + + + + + + + + +
Discount ({{ $quotation->discount_percentage }}%){{ format_currency($quotation->discount_amount) }}
Tax ({{ $quotation->tax_percentage }}%){{ format_currency($quotation->tax_amount) }}
Shipping{{ format_currency($quotation->shipping_amount) }}
Grand Total{{ format_currency($quotation->total_amount) }}
+
+
+
+
+
+
+
+@endsection + diff --git a/Modules/Quotation/Routes/.gitkeep b/Modules/Quotation/Routes/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Routes/api.php b/Modules/Quotation/Routes/api.php new file mode 100644 index 00000000..62d2a31f --- /dev/null +++ b/Modules/Quotation/Routes/api.php @@ -0,0 +1,18 @@ +get('/quotation', function (Request $request) { + return $request->user(); +}); \ No newline at end of file diff --git a/Modules/Quotation/Routes/web.php b/Modules/Quotation/Routes/web.php new file mode 100644 index 00000000..f86fe6ca --- /dev/null +++ b/Modules/Quotation/Routes/web.php @@ -0,0 +1,36 @@ + 'auth'], function () { + //Generate PDF + Route::get('/quotations/pdf/{id}', function ($id) { + $quotation = \Modules\Quotation\Entities\Quotation::findOrFail($id); + $customer = \Modules\People\Entities\Customer::findOrFail($quotation->customer_id); + + $pdf = \PDF::loadView('quotation::print', [ + 'quotation' => $quotation, + 'customer' => $customer, + ])->setPaper('a4'); + + return $pdf->stream('quotation-'. $quotation->reference .'.pdf'); + })->name('quotations.pdf'); + + //Send Quotation Mail + Route::get('/quotation/mail/{quotation}', 'SendQuotationEmailController')->name('quotation.email'); + + //Sales Form Quotation + Route::get('/quotation-sales/{quotation}', 'QuotationSalesController')->name('quotation-sales.create'); + + //quotations + Route::resource('quotations', 'QuotationController'); +}); diff --git a/Modules/Quotation/Tests/Feature/.gitkeep b/Modules/Quotation/Tests/Feature/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/Tests/Unit/.gitkeep b/Modules/Quotation/Tests/Unit/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/Modules/Quotation/composer.json b/Modules/Quotation/composer.json new file mode 100644 index 00000000..6e76966e --- /dev/null +++ b/Modules/Quotation/composer.json @@ -0,0 +1,23 @@ +{ + "name": "nwidart/quotation", + "description": "", + "authors": [ + { + "name": "Nicolas Widart", + "email": "n.widart@gmail.com" + } + ], + "extra": { + "laravel": { + "providers": [], + "aliases": { + + } + } + }, + "autoload": { + "psr-4": { + "Modules\\Quotation\\": "" + } + } +} diff --git a/Modules/Quotation/module.json b/Modules/Quotation/module.json new file mode 100644 index 00000000..6a8a96e4 --- /dev/null +++ b/Modules/Quotation/module.json @@ -0,0 +1,13 @@ +{ + "name": "Quotation", + "alias": "quotation", + "description": "", + "keywords": [], + "priority": 0, + "providers": [ + "Modules\\Quotation\\Providers\\QuotationServiceProvider" + ], + "aliases": {}, + "files": [], + "requires": [] +} diff --git a/Modules/Quotation/package.json b/Modules/Quotation/package.json new file mode 100644 index 00000000..4599509f --- /dev/null +++ b/Modules/Quotation/package.json @@ -0,0 +1,17 @@ +{ + "private": true, + "scripts": { + "dev": "npm run development", + "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", + "watch": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --watch --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js", + "watch-poll": "npm run watch -- --watch-poll", + "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js", + "prod": "npm run production", + "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js" + }, + "devDependencies": { + "cross-env": "^7.0", + "laravel-mix": "^5.0.1", + "laravel-mix-merge-manifest": "^0.1.2" + } +} diff --git a/Modules/Quotation/webpack.mix.js b/Modules/Quotation/webpack.mix.js new file mode 100644 index 00000000..ef59991a --- /dev/null +++ b/Modules/Quotation/webpack.mix.js @@ -0,0 +1,14 @@ +const dotenvExpand = require('dotenv-expand'); +dotenvExpand(require('dotenv').config({ path: '../../.env'/*, debug: true*/})); + +const mix = require('laravel-mix'); +require('laravel-mix-merge-manifest'); + +mix.setPublicPath('../../public').mergeManifest(); + +mix.js(__dirname + '/Resources/assets/js/app.js', 'js/quotation.js') + .sass( __dirname + '/Resources/assets/sass/app.scss', 'css/quotation.css'); + +if (mix.inProduction()) { + mix.version(); +} diff --git a/Modules/Sale/Resources/views/show.blade.php b/Modules/Sale/Resources/views/show.blade.php index 680f8730..767c2f16 100644 --- a/Modules/Sale/Resources/views/show.blade.php +++ b/Modules/Sale/Resources/views/show.blade.php @@ -115,7 +115,7 @@ {{ format_currency($sale->tax_amount) }} - Shipping) + Shipping {{ format_currency($sale->shipping_amount) }} diff --git a/Modules/Upload/Http/Controllers/UploadController.php b/Modules/Upload/Http/Controllers/UploadController.php index e27ac986..53c80310 100644 --- a/Modules/Upload/Http/Controllers/UploadController.php +++ b/Modules/Upload/Http/Controllers/UploadController.php @@ -13,6 +13,8 @@ class UploadController extends Controller { public function filepondUpload(Request $request) { + abort_if(!request()->ajax(), 404); + $request->validate([ 'image' => 'required|image|mimes:png,jpeg,jpg' ]); @@ -39,6 +41,8 @@ class UploadController extends Controller public function filepondDelete(Request $request) { + abort_if(!request()->ajax(), 404); + $upload = Upload::where('folder', $request->getContent())->first(); Storage::deleteDirectory('temp/' . $upload->folder); @@ -49,6 +53,8 @@ class UploadController extends Controller public function dropzoneUpload(Request $request) { + abort_if(!request()->ajax(), 404); + $file = $request->file('file'); $filename = now()->timestamp . '.' . trim($file->getClientOriginalExtension()); @@ -62,6 +68,8 @@ class UploadController extends Controller } public function dropzoneDelete(Request $request) { + abort_if(!request()->ajax(), 404); + Storage::delete('temp/dropzone/' . $request->file_name); return response()->json($request->file_name, 200); diff --git a/Modules/User/Database/Seeders/PermissionsTableSeeder.php b/Modules/User/Database/Seeders/PermissionsTableSeeder.php index 92ee294e..e39584f5 100644 --- a/Modules/User/Database/Seeders/PermissionsTableSeeder.php +++ b/Modules/User/Database/Seeders/PermissionsTableSeeder.php @@ -18,7 +18,14 @@ class PermissionsTableSeeder extends Seeder { $permissions = [ //User Mangement + 'edit_own_profile', 'access_user_management', + //Dashboard + 'show_total_stats', + 'show_month_overview', + 'show_weekly_sales_purchases', + 'show_monthly_cashflow', + 'show_notifications', //Products 'access_products', 'create_products', @@ -35,6 +42,16 @@ class PermissionsTableSeeder extends Seeder 'show_adjustments', 'edit_adjustments', 'delete_adjustments', + //Quotaions + 'access_quotations', + 'create_quotations', + 'show_quotations', + 'edit_quotations', + 'delete_quotations', + //Create Sale From Quotation + 'create_quotation_sales', + //Send Quotation On Email + 'send_quotation_mails', //Expenses 'access_expenses', 'create_expenses', diff --git a/Modules/User/Resources/views/roles/edit.blade.php b/Modules/User/Resources/views/roles/edit.blade.php index 33f33ce9..4d1d23a4 100644 --- a/Modules/User/Resources/views/roles/edit.blade.php +++ b/Modules/User/Resources/views/roles/edit.blade.php @@ -53,6 +53,59 @@
+ +
+
+
+ Dashboard +
+
+
+
+
+ hasPermissionTo('show_total_stats') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('show_notifications') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('show_month_overview') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('show_weekly_sales_purchases') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('show_monthly_cashflow') ? 'checked' : '' }}> + +
+
+
+
+
+
+
@@ -69,6 +122,14 @@
+
+
+ hasPermissionTo('edit_own_profile') ? 'checked' : '' }}> + +
+
@@ -196,6 +257,75 @@ + +
+
+
+ Quotaions +
+
+
+
+
+ hasPermissionTo('access_quotations') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('create_quotations') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('show_quotations') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('edit_quotations') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('delete_quotations') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('send_quotation_mails') ? 'checked' : '' }}> + +
+
+
+
+ hasPermissionTo('create_quotation_sales') ? 'checked' : '' }}> + +
+
+
+
+
+
+
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 17d00e97..0ee895e0 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -20,12 +20,12 @@ class HomeController extends Controller { public function index() { - $sales = Sale::sum('total_amount'); - $sale_returns = SaleReturn::sum('total_amount'); - $purchase_returns = PurchaseReturn::sum('total_amount'); + $sales = Sale::where('status', 'Completed')->sum('total_amount'); + $sale_returns = SaleReturn::where('status', 'Completed')->sum('total_amount'); + $purchase_returns = PurchaseReturn::where('status', 'Completed')->sum('total_amount'); $product_costs = 0; - foreach (Sale::with('saleDetails')->get() as $sale) { + foreach (Sale::where('status', 'Completed')->with('saleDetails')->get() as $sale) { foreach ($sale->saleDetails as $saleDetail) { $product_costs += $saleDetail->product->product_cost; } @@ -46,10 +46,10 @@ class HomeController extends Controller public function currentMonthChart() { abort_if(!request()->ajax(), 404); - $currentMonthSales = Sale::whereMonth('date', date('m')) + $currentMonthSales = Sale::where('status', 'Completed')->whereMonth('date', date('m')) ->whereYear('date', date('Y')) ->sum('total_amount') / 100; - $currentMonthPurchases = Purchase::whereMonth('date', date('m')) + $currentMonthPurchases = Purchase::where('status', 'Completed')->whereMonth('date', date('m')) ->whereYear('date', date('Y')) ->sum('total_amount') / 100; $currentMonthExpenses = Expense::whereMonth('date', date('m')) @@ -160,7 +160,8 @@ class HomeController extends Controller $date_range = Carbon::today()->subDays(6); - $sales = Sale::where('date', '>=', $date_range) + $sales = Sale::where('status', 'Completed') + ->where('date', '>=', $date_range) ->groupBy(DB::raw("DATE_FORMAT(date,'%d-%m-%y')")) ->orderBy('date') ->get([ @@ -191,7 +192,8 @@ class HomeController extends Controller $date_range = Carbon::today()->subDays(6); - $purchases = Purchase::where('date', '>=', $date_range) + $purchases = Purchase::where('status', 'Completed') + ->where('date', '>=', $date_range) ->groupBy(DB::raw("DATE_FORMAT(date,'%d-%m-%y')")) ->orderBy('date') ->get([ diff --git a/app/Http/Livewire/ProductCart.php b/app/Http/Livewire/ProductCart.php index f040a71e..ed17d451 100644 --- a/app/Http/Livewire/ProductCart.php +++ b/app/Http/Livewire/ProductCart.php @@ -43,7 +43,7 @@ class ProductCart extends Component if ($cart_item->options->product_discount_type == 'fixed') { $this->item_discount[$cart_item->id] = $cart_item->options->product_discount; } elseif ($cart_item->options->product_discount_type == 'percentage') { - $this->item_discount[$cart_item->id] = 100 * ($cart_item->options->product_discount / $cart_item->price); + $this->item_discount[$cart_item->id] = round(100 * ($cart_item->options->product_discount / $cart_item->price)); } } } else { diff --git a/database/migrations/.gitkeep b/database/migrations/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/database/migrations/2021_08_15_161053_create_notifications_table.php b/database/migrations/2021_08_15_161053_create_notifications_table.php deleted file mode 100644 index 9797596d..00000000 --- a/database/migrations/2021_08_15_161053_create_notifications_table.php +++ /dev/null @@ -1,35 +0,0 @@ -uuid('id')->primary(); - $table->string('type'); - $table->morphs('notifiable'); - $table->text('data'); - $table->timestamp('read_at')->nullable(); - $table->timestamps(); - }); - } - - /** - * Reverse the migrations. - * - * @return void - */ - public function down() - { - Schema::dropIfExists('notifications'); - } -} diff --git a/modules_statuses.json b/modules_statuses.json index 24448aa9..517dd1e3 100644 --- a/modules_statuses.json +++ b/modules_statuses.json @@ -11,5 +11,6 @@ "Purchase": true, "SaleReturn": true, "SalesReturn": true, - "PurchasesReturn": true + "PurchasesReturn": true, + "Quotation": true } \ No newline at end of file diff --git a/resources/views/home.blade.php b/resources/views/home.blade.php index 39061c33..8bfa3d34 100644 --- a/resources/views/home.blade.php +++ b/resources/views/home.blade.php @@ -10,6 +10,7 @@ @section('content')
+ @can('show_total_stats')
@@ -67,8 +68,11 @@
+ @endcan + @can('show_weekly_sales_purchases|show_month_overview')
+ @can('show_weekly_sales_purchases')
@@ -79,6 +83,8 @@
+ @endcan + @can('show_month_overview')
@@ -91,8 +97,11 @@
+ @endcan
+ @endcan + @can('show_monthly_cashflow')
@@ -105,6 +114,7 @@
+ @endcan
@endsection diff --git a/resources/views/layouts/header.blade.php b/resources/views/layouts/header.blade.php index 05def684..468e6b42 100644 --- a/resources/views/layouts/header.blade.php +++ b/resources/views/layouts/header.blade.php @@ -10,12 +10,15 @@
  • + + Quotations + + +
  • +@endcan + @can('access_purchases')
  • diff --git a/resources/views/livewire/includes/product-cart-modal.blade.php b/resources/views/livewire/includes/product-cart-modal.blade.php index d91d3a4a..5b05f768 100644 --- a/resources/views/livewire/includes/product-cart-modal.blade.php +++ b/resources/views/livewire/includes/product-cart-modal.blade.php @@ -43,7 +43,7 @@ @elseif($discount_type[$cart_item->id] == 'fixed') - + @endif