210 lines
9.7 KiB
PHP
210 lines
9.7 KiB
PHP
<?php
|
|
|
|
use Illuminate\Support\Facades\Route;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Facades\DB;
|
|
use App\Models\Sale;
|
|
use App\Models\Product;
|
|
use App\Http\Controllers\AuthController;
|
|
use App\Http\Controllers\ProductController;
|
|
use App\Http\Controllers\StockController;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
/*
|
|
|--------------------------------------------------------------------------
|
|
| Web Routes
|
|
|--------------------------------------------------------------------------
|
|
*/
|
|
|
|
Route::get('/', function () {
|
|
$top = Sale::select('product_id', DB::raw('SUM(quantity) as total'))
|
|
->groupBy('product_id')
|
|
->orderByDesc('total')
|
|
->limit(3)
|
|
->get();
|
|
|
|
$productIds = $top->pluck('product_id')->toArray();
|
|
$products = Product::whereIn('id', $productIds)->get()->keyBy('id');
|
|
|
|
$topProducts = collect();
|
|
foreach ($productIds as $id) {
|
|
$product = $products->get($id);
|
|
if ($product) {
|
|
$product->total_sold = $top->firstWhere('product_id', $id)->total ?? 0;
|
|
$topProducts->push($product);
|
|
}
|
|
}
|
|
|
|
if ($topProducts->count() < 3) {
|
|
$needed = 3 - $topProducts->count();
|
|
$excluded = $topProducts->pluck('id')->toArray();
|
|
$extras = Product::whereNotIn('id', $excluded)->limit($needed)->get();
|
|
foreach ($extras as $e) {
|
|
$e->total_sold = 0;
|
|
$topProducts->push($e);
|
|
}
|
|
}
|
|
|
|
return view('landing', ['topProducts' => $topProducts]);
|
|
});
|
|
|
|
// TEST PENGIRIMAN EMAIL ROUTE
|
|
Route::get('/test-email', [\App\Http\Controllers\SendEmailController::class, 'showForm']);
|
|
Route::post('/test-email', [\App\Http\Controllers\SendEmailController::class, 'sendEmail']);
|
|
|
|
// AUTH ROUTES
|
|
Route::get('/login', [AuthController::class, 'showLoginForm'])->name('login');
|
|
Route::post('/authenticate', [AuthController::class, 'authenticate']);
|
|
Route::post('/logout', [AuthController::class, 'logout'])->name('logout');
|
|
|
|
// PASSWORD RESET ROUTES (Khusus Admin)
|
|
Route::get('/forgot-password', [App\Http\Controllers\PasswordResetController::class, 'showLinkRequestForm'])->name('password.request');
|
|
Route::post('/forgot-password', [App\Http\Controllers\PasswordResetController::class, 'sendResetLinkEmail'])->name('password.email');
|
|
Route::get('/reset-password/{token}', [App\Http\Controllers\PasswordResetController::class, 'showResetForm'])->name('password.reset');
|
|
Route::post('/reset-password', [App\Http\Controllers\PasswordResetController::class, 'reset'])->name('password.update');
|
|
|
|
// PROTECTED ROUTES
|
|
Route::middleware(['auth'])->group(function () {
|
|
|
|
// DASHBOARD REDIRECTION
|
|
Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index']);
|
|
Route::get('/admin/dashboard', [App\Http\Controllers\DashboardController::class, 'adminIndex']);
|
|
|
|
Route::get('/landing', function () {
|
|
$top = Sale::select('product_id', DB::raw('SUM(quantity) as total'))
|
|
->groupBy('product_id')
|
|
->orderByDesc('total')
|
|
->limit(3)
|
|
->get();
|
|
|
|
$productIds = $top->pluck('product_id')->toArray();
|
|
$products = Product::whereIn('id', $productIds)->get()->keyBy('id');
|
|
|
|
$topProducts = collect();
|
|
foreach ($productIds as $id) {
|
|
$product = $products->get($id);
|
|
if ($product) {
|
|
$product->total_sold = $top->firstWhere('product_id', $id)->total ?? 0;
|
|
$topProducts->push($product);
|
|
}
|
|
}
|
|
|
|
if ($topProducts->count() < 3) {
|
|
$needed = 3 - $topProducts->count();
|
|
$excluded = $topProducts->pluck('id')->toArray();
|
|
$extras = Product::whereNotIn('id', $excluded)->limit($needed)->get();
|
|
foreach ($extras as $e) {
|
|
$e->total_sold = 0;
|
|
$topProducts->push($e);
|
|
}
|
|
}
|
|
|
|
return view('landing', ['topProducts' => $topProducts]);
|
|
});
|
|
|
|
Route::get('/transaksi', function () {
|
|
return view('transaksi');
|
|
});
|
|
|
|
Route::get('/laporan', function () {
|
|
return view('laporan');
|
|
});
|
|
|
|
// PRODUCT - CRUD for karyawan (restricted to their branch)
|
|
Route::get('/produk', [ProductController::class, 'index']);
|
|
Route::post('/produk', [ProductController::class, 'store']);
|
|
Route::put('/produk/{id}', [ProductController::class, 'update']);
|
|
Route::delete('/produk/{id}', [ProductController::class, 'destroy']);
|
|
|
|
// BAHAN BAKU (RAW MATERIALS) - View only, all management via purchase
|
|
Route::get('/bahan-baku', [App\Http\Controllers\RawMaterialController::class, 'index']);
|
|
|
|
// ADMIN ONLY ROUTES
|
|
Route::middleware(['can:admin-access'])->group(function () {
|
|
// Manajemen akun
|
|
Route::get('/manajemen-akun', [App\Http\Controllers\AccountController::class, 'index']);
|
|
Route::post('/manajemen-akun', [App\Http\Controllers\AccountController::class, 'store']);
|
|
Route::put('/manajemen-akun/{id}', [App\Http\Controllers\AccountController::class, 'update']);
|
|
Route::delete('/manajemen-akun/{id}', [App\Http\Controllers\AccountController::class, 'destroy']);
|
|
|
|
// Manajemen cabang
|
|
Route::get('/branches', [App\Http\Controllers\BranchController::class, 'index']);
|
|
Route::post('/branches', [App\Http\Controllers\BranchController::class, 'store']);
|
|
Route::delete('/branches/{id}', [App\Http\Controllers\BranchController::class, 'destroy']);
|
|
|
|
// OPERATIONAL COSTS
|
|
Route::get('/biaya-operasional', [App\Http\Controllers\OperationalCostController::class, 'index']);
|
|
Route::post('/biaya-operasional', [App\Http\Controllers\OperationalCostController::class, 'store']);
|
|
Route::put('/biaya-operasional/{id}', [App\Http\Controllers\OperationalCostController::class, 'update']);
|
|
Route::delete('/biaya-operasional/{id}', [App\Http\Controllers\OperationalCostController::class, 'destroy']);
|
|
|
|
// BAHAN BAKU (RAW MATERIALS) - Admin view only
|
|
Route::get('/bahan-baku', [App\Http\Controllers\RawMaterialController::class, 'index']);
|
|
|
|
Route::get('/laporan/neraca-laba-rugi', [App\Http\Controllers\FinancialReportController::class, 'profitAndLoss']);
|
|
Route::get('/laporan/neraca-laba-rugi/export-pdf', [App\Http\Controllers\FinancialReportController::class, 'exportProfitAndLossPdf']);
|
|
Route::get('/laporan/buku-besar', [App\Http\Controllers\FinancialReportController::class, 'generalLedger']);
|
|
Route::get('/laporan/jurnal-umum', [App\Http\Controllers\FinancialReportController::class, 'generalJournal']);
|
|
Route::get('/laporan/perubahan-modal', [App\Http\Controllers\FinancialReportController::class, 'equityStatement']);
|
|
Route::get('/laporan/neraca-keuangan', [App\Http\Controllers\FinancialReportController::class, 'balanceSheet']);
|
|
Route::get('/laporan/arus-kas', [App\Http\Controllers\FinancialReportController::class, 'cashFlow']);
|
|
|
|
});
|
|
|
|
// SHARED / GENERAL REPORTS
|
|
|
|
Route::get('/laporan/pembelian', [App\Http\Controllers\PurchaseController::class, 'index']);
|
|
Route::get('/transaksi/pembelian/create', [App\Http\Controllers\PurchaseController::class, 'create']);
|
|
Route::get('/laporan/pembelian/export-pdf', [App\Http\Controllers\PurchaseController::class, 'exportPdf'])->middleware('can:admin-access');
|
|
Route::post('/laporan/pembelian', [App\Http\Controllers\PurchaseController::class, 'store']);
|
|
Route::put('/laporan/pembelian/{id}', [App\Http\Controllers\PurchaseController::class, 'update']);
|
|
Route::delete('/laporan/pembelian/{id}', [App\Http\Controllers\PurchaseController::class, 'destroy']);
|
|
|
|
Route::get('/laporan/penjualan', [App\Http\Controllers\SaleController::class, 'index']);
|
|
Route::get('/transaksi/penjualan/create', [App\Http\Controllers\SaleController::class, 'create']);
|
|
Route::get('/laporan/penjualan/export-pdf', [App\Http\Controllers\SaleController::class, 'exportPdf'])->middleware('can:admin-access');
|
|
Route::post('/laporan/penjualan', [App\Http\Controllers\SaleController::class, 'store']);
|
|
Route::put('/laporan/penjualan/{id}', [App\Http\Controllers\SaleController::class, 'update']);
|
|
Route::delete('/laporan/penjualan/{id}', [App\Http\Controllers\SaleController::class, 'destroy']);
|
|
|
|
// DEBUG ROUTE - hapus setelah selesai debug
|
|
Route::get('/debug-stok', function () {
|
|
$rawMaterials = \App\Models\RawMaterial::all()->map(fn($rm) => [
|
|
'id' => $rm->id,
|
|
'name' => $rm->name,
|
|
'unit' => $rm->unit,
|
|
'stock_quantity' => $rm->stock_quantity,
|
|
]);
|
|
|
|
$recipes = \App\Models\ProductRecipe::with(['product', 'rawMaterial'])->get()->map(fn($r) => [
|
|
'product' => $r->product?->name,
|
|
'raw_material' => $r->rawMaterial?->name,
|
|
'quantity_needed' => $r->quantity_needed,
|
|
]);
|
|
|
|
$purchases = \App\Models\Purchase::orderBy('id', 'desc')->limit(10)->get()->map(fn($p) => [
|
|
'id' => $p->id,
|
|
'item' => $p->item,
|
|
'quantity' => $p->quantity,
|
|
'type' => $p->type,
|
|
'raw_material_id'=> $p->raw_material_id,
|
|
'branch' => $p->branch,
|
|
'date' => $p->date,
|
|
]);
|
|
|
|
$stocks = \App\Models\Stock::with('product')->get()->map(fn($s) => [
|
|
'product' => $s->product?->name,
|
|
'branch' => $s->branch,
|
|
'quantity' => $s->quantity,
|
|
]);
|
|
|
|
return response()->json([
|
|
'raw_materials' => $rawMaterials,
|
|
'product_recipes' => $recipes,
|
|
'recent_purchases' => $purchases,
|
|
'stocks' => $stocks,
|
|
], 200, [], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
});
|
|
});
|
|
|