Added: Sales Report
This commit is contained in:
parent
13f64c9a2b
commit
f9d4295656
|
@ -2,7 +2,7 @@ APP_NAME="Triangle POS"
|
|||
APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_URL=http://127.0.0.1:8000
|
||||
|
||||
DEBUGBAR_ENABLED=false
|
||||
|
||||
|
@ -12,8 +12,8 @@ LOG_LEVEL=debug
|
|||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=laravel
|
||||
DB_USERNAME=root
|
||||
DB_DATABASE=triangle_pos
|
||||
DB_USERNAME=
|
||||
DB_PASSWORD=
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'name' => 'Reports'
|
||||
];
|
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\Reports\Database\Seeders;
|
||||
|
||||
use Illuminate\Database\Seeder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class ReportsDatabaseSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* Run the database seeds.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
Model::unguard();
|
||||
|
||||
// $this->call("OthersTableSeeder");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\Reports\Http\Controllers;
|
||||
|
||||
use Illuminate\Contracts\Support\Renderable;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Routing\Controller;
|
||||
|
||||
class ReportsController extends Controller
|
||||
{
|
||||
public function salesReport() {
|
||||
return view('reports::sales.index');
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\Reports\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Database\Eloquent\Factory;
|
||||
|
||||
class ReportsServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* @var string $moduleName
|
||||
*/
|
||||
protected $moduleName = 'Reports';
|
||||
|
||||
/**
|
||||
* @var string $moduleNameLower
|
||||
*/
|
||||
protected $moduleNameLower = 'reports';
|
||||
|
||||
/**
|
||||
* Boot the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
$this->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;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
<?php
|
||||
|
||||
namespace Modules\Reports\Providers;
|
||||
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
|
||||
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The module namespace to assume when generating URLs to actions.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $moduleNamespace = 'Modules\Reports\Http\Controllers';
|
||||
|
||||
/**
|
||||
* Called before routes are registered.
|
||||
*
|
||||
* Register any model bindings or pattern based filters.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
parent::boot();
|
||||
}
|
||||
|
||||
/**
|
||||
* Define the routes for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function map()
|
||||
{
|
||||
$this->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('Reports', '/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('Reports', '/Routes/api.php'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
@extends('layouts.app')
|
||||
|
||||
@section('title', 'Sales Report')
|
||||
|
||||
@section('breadcrumb')
|
||||
<ol class="breadcrumb border-0 m-0">
|
||||
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
|
||||
<li class="breadcrumb-item active">Sales Report</li>
|
||||
</ol>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="container-fluid">
|
||||
<livewire:reports.sales-report :customers="\Modules\People\Entities\Customer::all()"/>
|
||||
</div>
|
||||
@endsection
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| API Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register API routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| is assigned the "api" middleware group. Enjoy building your API!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::middleware('auth:api')->get('/reports', function (Request $request) {
|
||||
return $request->user();
|
||||
});
|
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Web Routes
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here is where you can register web routes for your application. These
|
||||
| routes are loaded by the RouteServiceProvider within a group which
|
||||
| contains the "web" middleware group. Now create something great!
|
||||
|
|
||||
*/
|
||||
|
||||
Route::group(['middleware' => 'auth'], function () {
|
||||
//Sales Report
|
||||
Route::get('/sales-report', 'ReportsController@salesReport')
|
||||
->name('sales-report.index');
|
||||
});
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "nwidart/reports",
|
||||
"description": "",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Widart",
|
||||
"email": "n.widart@gmail.com"
|
||||
}
|
||||
],
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"providers": [],
|
||||
"aliases": {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Modules\\Reports\\": ""
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"name": "Reports",
|
||||
"alias": "reports",
|
||||
"description": "",
|
||||
"keywords": [],
|
||||
"priority": 0,
|
||||
"providers": [
|
||||
"Modules\\Reports\\Providers\\ReportsServiceProvider"
|
||||
],
|
||||
"aliases": {},
|
||||
"files": [],
|
||||
"requires": []
|
||||
}
|
|
@ -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"
|
||||
}
|
||||
}
|
|
@ -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/reports.js')
|
||||
.sass( __dirname + '/Resources/assets/sass/app.scss', 'css/reports.css');
|
||||
|
||||
if (mix.inProduction()) {
|
||||
mix.version();
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Livewire\Reports;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
use Modules\Sale\Entities\Sale;
|
||||
|
||||
class SalesReport extends Component
|
||||
{
|
||||
|
||||
use WithPagination;
|
||||
|
||||
protected $paginationTheme = 'bootstrap';
|
||||
|
||||
public $customers;
|
||||
public $start_date;
|
||||
public $end_date;
|
||||
public $customer_id;
|
||||
public $sale_status;
|
||||
public $payment_status;
|
||||
|
||||
protected $rules = [
|
||||
'start_date' => 'required|date|before:end_date',
|
||||
'end_date' => 'required|date|after:start_date',
|
||||
];
|
||||
|
||||
public function mount($customers) {
|
||||
$this->customers = $customers;
|
||||
$this->start_date = today()->subDays(30)->format('Y-m-d');
|
||||
$this->end_date = today()->format('Y-m-d');
|
||||
$this->customer_id = '';
|
||||
$this->sale_status = '';
|
||||
$this->payment_status = '';
|
||||
}
|
||||
|
||||
public function render() {
|
||||
$sales = Sale::whereDate('date', '>=', $this->start_date)
|
||||
->whereDate('date', '<=', $this->end_date)
|
||||
->when($this->customer_id, function ($query) {
|
||||
return $query->where('customer_id', $this->customer_id);
|
||||
})
|
||||
->when($this->sale_status, function ($query) {
|
||||
return $query->where('status', $this->sale_status);
|
||||
})
|
||||
->when($this->payment_status, function ($query) {
|
||||
return $query->where('payment_status', $this->payment_status);
|
||||
})
|
||||
->orderBy('date', 'desc')->paginate(10);
|
||||
|
||||
return view('livewire.reports.sales-report', [
|
||||
'sales' => $sales
|
||||
]);
|
||||
}
|
||||
|
||||
public function generateReport() {
|
||||
$this->validate();
|
||||
$this->render();
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -12,5 +12,6 @@
|
|||
"SaleReturn": true,
|
||||
"SalesReturn": true,
|
||||
"PurchasesReturn": true,
|
||||
"Quotation": true
|
||||
"Quotation": true,
|
||||
"Reports": true
|
||||
}
|
|
@ -133,7 +133,7 @@
|
|||
@endcan
|
||||
|
||||
@can('access_sales')
|
||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('sales*') || request()->routeIs('sale-payments*') ? 'c-show' : '' }}">
|
||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('sales.*') || request()->routeIs('sale-payments*') ? 'c-show' : '' }}">
|
||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||
<i class="c-sidebar-nav-icon bi bi-receipt" style="line-height: 1;"></i> Sales
|
||||
</a>
|
||||
|
@ -233,6 +233,23 @@
|
|||
</li>
|
||||
@endcan
|
||||
|
||||
@can('access_sales_report')
|
||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('sales-report.index') ? 'c-show' : '' }}">
|
||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||
<i class="c-sidebar-nav-icon bi bi-graph-up" style="line-height: 1;"></i> Reports
|
||||
</a>
|
||||
<ul class="c-sidebar-nav-dropdown-items">
|
||||
@can('access_sales_report')
|
||||
<li class="c-sidebar-nav-item">
|
||||
<a class="c-sidebar-nav-link {{ request()->routeIs('sales-report.index') ? 'c-active' : '' }}" href="{{ route('sales-report.index') }}">
|
||||
<i class="c-sidebar-nav-icon bi bi-clipboard-data" style="line-height: 1;"></i> Sales Report
|
||||
</a>
|
||||
</li>
|
||||
@endcan
|
||||
</ul>
|
||||
</li>
|
||||
@endcan
|
||||
|
||||
@can('access_user_management')
|
||||
<li class="c-sidebar-nav-item c-sidebar-nav-dropdown {{ request()->routeIs('roles*') ? 'c-show' : '' }}">
|
||||
<a class="c-sidebar-nav-link c-sidebar-nav-dropdown-toggle" href="#">
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
<div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<form wire:submit.prevent="generateReport">
|
||||
<div class="form-row">
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<label>Start Date <span class="text-danger">*</span></label>
|
||||
<input wire:model.defer="start_date" type="date" class="form-control" name="start_date">
|
||||
@error('start_date')
|
||||
<span class="text-danger mb-1">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<label>End Date <span class="text-danger">*</span></label>
|
||||
<input wire:model.defer="end_date" type="date" class="form-control" name="end_date">
|
||||
@error('end_date')
|
||||
<span class="text-danger mb-1">{{ $message }}</span>
|
||||
@enderror
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
<div class="form-group">
|
||||
<label>Customer</label>
|
||||
<select wire:model.defer="customer_id" class="form-control" name="customer_id">
|
||||
<option value="" disabled>Select Customer</option>
|
||||
@foreach($customers as $customer)
|
||||
<option value="{{ $customer->id }}">{{ $customer->customer_name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label>Status</label>
|
||||
<select wire:model.defer="sale_status" class="form-control" name="sale_status">
|
||||
<option value="" disabled>Select Status</option>
|
||||
<option value="Pending">Pending</option>
|
||||
<option value="Shipped">Shipped</option>
|
||||
<option value="Completed">Completed</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label>Payment Status</label>
|
||||
<select wire:model.defer="sale_status" class="form-control" name="payment_status">
|
||||
<option value="" disabled>Select Payment Status</option>
|
||||
<option value="Paid">Paid</option>
|
||||
<option value="Unpaid">Unpaid</option>
|
||||
<option value="Partial">Partial</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mb-0">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
<span wire:target="generateReport" wire:loading class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
|
||||
<i wire:target="generateReport" wire:loading.remove class="bi bi-shuffle"></i>
|
||||
Filter Report
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<table class="table table-bordered table-striped text-center mb-0">
|
||||
<div wire:loading.flex class="col-12 position-absolute justify-content-center align-items-center" style="top:0;right:0;left:0;bottom:0;background-color: rgba(255,255,255,0.5);z-index: 99;">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Reference</th>
|
||||
<th>Customer</th>
|
||||
<th>Status</th>
|
||||
<th>Total</th>
|
||||
<th>Paid</th>
|
||||
<th>Due</th>
|
||||
<th>Payment Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@forelse($sales as $sale)
|
||||
<tr>
|
||||
<td>{{ \Carbon\Carbon::parse($sale->date)->format('d M, Y') }}</td>
|
||||
<td>{{ $sale->reference }}</td>
|
||||
<td>{{ $sale->customer_name }}</td>
|
||||
<td>
|
||||
@if ($sale->status == 'Pending')
|
||||
<span class="badge badge-info">
|
||||
{{ $sale->status }}
|
||||
</span>
|
||||
@elseif ($sale->status == 'Shipped')
|
||||
<span class="badge badge-primary">
|
||||
{{ $sale->status }}
|
||||
</span>
|
||||
@else
|
||||
<span class="badge badge-success">
|
||||
{{ $sale->status }}
|
||||
</span>
|
||||
@endif
|
||||
</td>
|
||||
<td>{{ format_currency($sale->total_amount) }}</td>
|
||||
<td>{{ format_currency($sale->paid_amount) }}</td>
|
||||
<td>{{ format_currency($sale->due_amount) }}</td>
|
||||
<td>
|
||||
@if ($sale->payment_status == 'Partial')
|
||||
<span class="badge badge-warning">
|
||||
{{ $sale->payment_status }}
|
||||
</span>
|
||||
@elseif ($sale->payment_status == 'Paid')
|
||||
<span class="badge badge-success">
|
||||
{{ $sale->payment_status }}
|
||||
</span>
|
||||
@else
|
||||
<span class="badge badge-danger">
|
||||
{{ $sale->payment_status }}
|
||||
</span>
|
||||
@endif
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8">
|
||||
<span class="text-danger">No Sales Data Available!</span>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
@if($sales->links())
|
||||
<div class="mt-3">
|
||||
{{ $sales->links() }}
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
Reference in New Issue