feat: introduce LogHelper for centralized exception handling and implement consistent error logging across admin controllers
This commit is contained in:
parent
635dcf712b
commit
53a7b23cbe
@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
use App\Models\Payroll;
|
use App\Models\Payroll;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Throwable;
|
use Throwable;
|
||||||
|
|
||||||
class GeneratePayrollCommand extends Command
|
class GeneratePayrollCommand extends Command
|
||||||
@ -60,8 +60,8 @@ public function handle()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::error('Payroll generate failed', [
|
LogHelper::logException($e, 'Payroll generate failed', [
|
||||||
'error' => $e->getMessage(),
|
'period' => $periodMonth,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$this->info('Gagal generate data penggajian, silakan hubungi pengembang.');
|
$this->info('Gagal generate data penggajian, silakan hubungi pengembang.');
|
||||||
|
|||||||
@ -5,12 +5,12 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Admin\Finance\SalaryAdjustmentRequest;
|
use App\Http\Requests\Admin\Finance\SalaryAdjustmentRequest;
|
||||||
use App\Models\Payroll;
|
use App\Models\Payroll;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Artisan;
|
use Illuminate\Support\Facades\Artisan;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
use Inertia\Response;
|
use Inertia\Response;
|
||||||
use Throwable;
|
use Throwable;
|
||||||
@ -75,9 +75,8 @@ public function update(SalaryAdjustmentRequest $request, Payroll $payroll): Redi
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::error('Payroll update failed', [
|
LogHelper::logException($e, 'Payroll update failed', [
|
||||||
'payroll_id' => $payroll->id,
|
'payroll_id' => $payroll->id,
|
||||||
'error' => $e->getMessage(),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
return back()->withInput()->with('error', 'Gagal memperbarui data. Silakan coba lagi.');
|
return back()->withInput()->with('error', 'Gagal memperbarui data. Silakan coba lagi.');
|
||||||
|
|||||||
@ -11,6 +11,7 @@
|
|||||||
use App\Models\Order;
|
use App\Models\Order;
|
||||||
use App\Models\OrderItem;
|
use App\Models\OrderItem;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -46,48 +47,60 @@ public function store(OrderRequest $request): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($validated) {
|
try {
|
||||||
$totalItemsPrice = collect($validated['items'])->sum('total');
|
DB::transaction(function () use ($validated) {
|
||||||
$hpp = collect($validated['items'])->sum(function ($item) {
|
$totalItemsPrice = collect($validated['items'])->sum('total');
|
||||||
$product = Product::find($item['product_id']);
|
$hpp = collect($validated['items'])->sum(function ($item) {
|
||||||
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
$product = Product::find($item['product_id']);
|
||||||
|
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
||||||
|
|
||||||
return $purchasePrice * $item['qty'];
|
return $purchasePrice * $item['qty'];
|
||||||
});
|
});
|
||||||
|
|
||||||
$order = Order::create([
|
$order = Order::create([
|
||||||
'user_id' => auth()->id(),
|
|
||||||
'invoice_number' => $validated['invoice_number'] ?? 'INV-'.now()->format('YmdHis').'-'.strtoupper(fake()->bothify('??##')),
|
|
||||||
'customer_name' => $validated['customer_name'],
|
|
||||||
'hpp' => $hpp,
|
|
||||||
'discount' => $validated['discount'],
|
|
||||||
'payment' => $validated['payment'],
|
|
||||||
'total' => $totalItemsPrice - $validated['discount'],
|
|
||||||
'payment_method' => $validated['payment_method'],
|
|
||||||
'order_status' => $validated['order_status'],
|
|
||||||
'order_channel' => $validated['order_channel'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
foreach ($validated['items'] as $item) {
|
|
||||||
OrderItem::create([
|
|
||||||
'user_id' => auth()->id(),
|
'user_id' => auth()->id(),
|
||||||
'order_id' => $order->id,
|
'invoice_number' => $validated['invoice_number'] ?? 'INV-'.now()->format('YmdHis').'-'.strtoupper(fake()->bothify('??##')),
|
||||||
'product_id' => $item['product_id'],
|
'customer_name' => $validated['customer_name'],
|
||||||
'price' => $item['price'],
|
'hpp' => $hpp,
|
||||||
'qty' => $item['qty'],
|
'discount' => $validated['discount'],
|
||||||
'total' => $item['total'],
|
'payment' => $validated['payment'],
|
||||||
'price_type' => $item['price_type'],
|
'total' => $totalItemsPrice - $validated['discount'],
|
||||||
|
'payment_method' => $validated['payment_method'],
|
||||||
|
'order_status' => $validated['order_status'],
|
||||||
|
'order_channel' => $validated['order_channel'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Product::find($item['product_id'])->decrement('stock', $item['qty']);
|
foreach ($validated['items'] as $item) {
|
||||||
}
|
OrderItem::create([
|
||||||
|
'user_id' => auth()->id(),
|
||||||
|
'order_id' => $order->id,
|
||||||
|
'product_id' => $item['product_id'],
|
||||||
|
'price' => $item['price'],
|
||||||
|
'qty' => $item['qty'],
|
||||||
|
'total' => $item['total'],
|
||||||
|
'price_type' => $item['price_type'],
|
||||||
|
]);
|
||||||
|
|
||||||
OrderItem::where('user_id', auth()->id())
|
Product::find($item['product_id'])->decrement('stock', $item['qty']);
|
||||||
->whereNull('order_id')
|
}
|
||||||
->delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('order.index')->with('success', 'Pesanan berhasil disimpan');
|
OrderItem::where('user_id', auth()->id())
|
||||||
|
->whereNull('order_id')
|
||||||
|
->delete();
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('order.index')->with('success', 'Pesanan berhasil disimpan');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to store order', [
|
||||||
|
'customer_name' => $validated['customer_name'],
|
||||||
|
'items_count' => count($validated['items'] ?? []),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Terjadi kesalahan saat menyimpan pesanan');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Order $order): Response
|
public function edit(Order $order): Response
|
||||||
@ -108,76 +121,104 @@ public function update(OrderRequest $request, Order $order): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($validated, $order) {
|
try {
|
||||||
$totalItemsPrice = collect($validated['items'])->sum(fn ($item) => $item['qty'] * $item['price']);
|
DB::transaction(function () use ($validated, $order) {
|
||||||
$hpp = collect($validated['items'])->sum(function ($item) {
|
$totalItemsPrice = collect($validated['items'])->sum(fn ($item) => $item['qty'] * $item['price']);
|
||||||
$product = Product::find($item['product_id']);
|
$hpp = collect($validated['items'])->sum(function ($item) {
|
||||||
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
$product = Product::find($item['product_id']);
|
||||||
|
$purchasePrice = $product->prices()->where('price_type', PriceType::PURCHASE)->first()?->price ?? 0;
|
||||||
|
|
||||||
return $purchasePrice * $item['qty'];
|
return $purchasePrice * $item['qty'];
|
||||||
});
|
});
|
||||||
|
|
||||||
// Restore stock for old items
|
// Restore stock for old items
|
||||||
foreach ($order->items as $item) {
|
foreach ($order->items as $item) {
|
||||||
$item->product->increment('stock', $item->qty);
|
$item->product->increment('stock', $item->qty);
|
||||||
}
|
}
|
||||||
|
|
||||||
$order->items()->delete();
|
$order->items()->delete();
|
||||||
|
|
||||||
$order->update([
|
$order->update([
|
||||||
'customer_name' => $validated['customer_name'],
|
'customer_name' => $validated['customer_name'],
|
||||||
'hpp' => $hpp,
|
'hpp' => $hpp,
|
||||||
'discount' => $validated['discount'],
|
'discount' => $validated['discount'],
|
||||||
'payment' => $validated['payment'],
|
'payment' => $validated['payment'],
|
||||||
'total' => $totalItemsPrice - $validated['discount'],
|
'total' => $totalItemsPrice - $validated['discount'],
|
||||||
'payment_method' => $validated['payment_method'],
|
'payment_method' => $validated['payment_method'],
|
||||||
'order_status' => $validated['order_status'],
|
'order_status' => $validated['order_status'],
|
||||||
'order_channel' => $validated['order_channel'],
|
'order_channel' => $validated['order_channel'],
|
||||||
]);
|
|
||||||
|
|
||||||
foreach ($validated['items'] as $item) {
|
|
||||||
$order->items()->create([
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
'product_id' => $item['product_id'],
|
|
||||||
'price' => $item['price'],
|
|
||||||
'qty' => $item['qty'],
|
|
||||||
'total' => $item['total'],
|
|
||||||
'price_type' => $item['price_type'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Product::find($item['product_id'])->decrement('stock', $item['qty']);
|
foreach ($validated['items'] as $item) {
|
||||||
}
|
$order->items()->create([
|
||||||
});
|
'user_id' => auth()->id(),
|
||||||
|
'product_id' => $item['product_id'],
|
||||||
|
'price' => $item['price'],
|
||||||
|
'qty' => $item['qty'],
|
||||||
|
'total' => $item['total'],
|
||||||
|
'price_type' => $item['price_type'],
|
||||||
|
]);
|
||||||
|
|
||||||
return redirect()->route('order.index')->with('success', 'Pesanan berhasil diperbarui');
|
Product::find($item['product_id'])->decrement('stock', $item['qty']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('order.index')->with('success', 'Pesanan berhasil diperbarui');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to update order', [
|
||||||
|
'order_id' => $order->id,
|
||||||
|
'customer_name' => $validated['customer_name'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Terjadi kesalahan saat memperbarui pesanan');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Order $order): RedirectResponse
|
public function destroy(Order $order): RedirectResponse
|
||||||
{
|
{
|
||||||
DB::transaction(function () use ($order) {
|
try {
|
||||||
foreach ($order->items as $item) {
|
DB::transaction(function () use ($order) {
|
||||||
$item->product->increment('stock', $item->qty);
|
foreach ($order->items as $item) {
|
||||||
}
|
$item->product->increment('stock', $item->qty);
|
||||||
$order->delete();
|
}
|
||||||
});
|
$order->delete();
|
||||||
|
});
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Pesanan berhasil dihapus');
|
return redirect()->back()->with('success', 'Pesanan berhasil dihapus');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to delete order', [
|
||||||
|
'order_id' => $order->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus pesanan');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bulkDestroy(Request $request): RedirectResponse
|
public function bulkDestroy(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$ids = $request->input('ids');
|
$ids = $request->input('ids');
|
||||||
|
|
||||||
DB::transaction(function () use ($ids) {
|
try {
|
||||||
$orders = Order::with('items')->whereIn('id', $ids)->get();
|
DB::transaction(function () use ($ids) {
|
||||||
foreach ($orders as $order) {
|
$orders = Order::with('items')->whereIn('id', $ids)->get();
|
||||||
foreach ($order->items as $item) {
|
foreach ($orders as $order) {
|
||||||
$item->product->increment('stock', $item->qty);
|
foreach ($order->items as $item) {
|
||||||
|
$item->product->increment('stock', $item->qty);
|
||||||
|
}
|
||||||
|
$order->delete();
|
||||||
}
|
}
|
||||||
$order->delete();
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Pesanan terpilih berhasil dihapus');
|
return redirect()->back()->with('success', 'Pesanan terpilih berhasil dihapus');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to bulk delete orders', [
|
||||||
|
'ids' => $ids,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus beberapa pesanan');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
use App\Models\Purchase;
|
use App\Models\Purchase;
|
||||||
use App\Models\PurchaseItem;
|
use App\Models\PurchaseItem;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -38,34 +39,46 @@ public function store(PurchaseRequest $request): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($validated) {
|
try {
|
||||||
$total = collect($validated['items'])->sum(fn ($item) => $item['quantity'] * $item['unit_price']);
|
DB::transaction(function () use ($validated) {
|
||||||
|
$total = collect($validated['items'])->sum(fn ($item) => $item['quantity'] * $item['unit_price']);
|
||||||
|
|
||||||
$purchase = Purchase::create([
|
$purchase = Purchase::create([
|
||||||
'purchase_date' => $validated['purchase_date'],
|
'purchase_date' => $validated['purchase_date'],
|
||||||
'note' => $validated['note'],
|
'note' => $validated['note'],
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
]);
|
|
||||||
|
|
||||||
foreach ($validated['items'] as $item) {
|
|
||||||
PurchaseItem::create([
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
'purchase_id' => $purchase->id,
|
|
||||||
'product_id' => $item['product_id'],
|
|
||||||
'quantity' => $item['quantity'],
|
|
||||||
'unit_price' => $item['unit_price'],
|
|
||||||
'total_price' => $item['quantity'] * $item['unit_price'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Product::find($item['product_id'])->increment('stock', $item['quantity']);
|
foreach ($validated['items'] as $item) {
|
||||||
}
|
PurchaseItem::create([
|
||||||
|
'user_id' => auth()->id(),
|
||||||
|
'purchase_id' => $purchase->id,
|
||||||
|
'product_id' => $item['product_id'],
|
||||||
|
'quantity' => $item['quantity'],
|
||||||
|
'unit_price' => $item['unit_price'],
|
||||||
|
'total_price' => $item['quantity'] * $item['unit_price'],
|
||||||
|
]);
|
||||||
|
|
||||||
PurchaseItem::where('user_id', auth()->id())
|
Product::find($item['product_id'])->increment('stock', $item['quantity']);
|
||||||
->whereNull('purchase_id')
|
}
|
||||||
->delete();
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('purchase.index')->with('success', 'Data berhasil disimpan');
|
PurchaseItem::where('user_id', auth()->id())
|
||||||
|
->whereNull('purchase_id')
|
||||||
|
->delete();
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('purchase.index')->with('success', 'Data berhasil disimpan');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to store purchase', [
|
||||||
|
'purchase_date' => $validated['purchase_date'] ?? null,
|
||||||
|
'items_count' => count($validated['items'] ?? []),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Terjadi kesalahan saat menyimpan pembelian');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Purchase $purchase): Response
|
public function edit(Purchase $purchase): Response
|
||||||
@ -82,63 +95,91 @@ public function update(PurchaseRequest $request, Purchase $purchase): RedirectRe
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($validated, $purchase) {
|
try {
|
||||||
$total = collect($validated['items'])->sum(fn ($item) => $item['quantity'] * $item['unit_price']);
|
DB::transaction(function () use ($validated, $purchase) {
|
||||||
|
$total = collect($validated['items'])->sum(fn ($item) => $item['quantity'] * $item['unit_price']);
|
||||||
|
|
||||||
$purchase->update([
|
$purchase->update([
|
||||||
'purchase_date' => $validated['purchase_date'],
|
'purchase_date' => $validated['purchase_date'],
|
||||||
'note' => $validated['note'],
|
'note' => $validated['note'],
|
||||||
'total' => $total,
|
'total' => $total,
|
||||||
]);
|
|
||||||
|
|
||||||
foreach ($purchase->items as $item) {
|
|
||||||
$item->product->decrement('stock', $item->quantity);
|
|
||||||
}
|
|
||||||
|
|
||||||
$purchase->items()->delete();
|
|
||||||
|
|
||||||
foreach ($validated['items'] as $item) {
|
|
||||||
$purchase->items()->create([
|
|
||||||
'user_id' => auth()->id(),
|
|
||||||
'product_id' => $item['product_id'],
|
|
||||||
'quantity' => $item['quantity'],
|
|
||||||
'unit_price' => $item['unit_price'],
|
|
||||||
'total_price' => $item['quantity'] * $item['unit_price'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Product::find($item['product_id'])->increment('stock', $item['quantity']);
|
foreach ($purchase->items as $item) {
|
||||||
}
|
$item->product->decrement('stock', $item->quantity);
|
||||||
});
|
}
|
||||||
|
|
||||||
return redirect()->route('purchase.index')->with('success', 'Data berhasil diperbarui');
|
$purchase->items()->delete();
|
||||||
|
|
||||||
|
foreach ($validated['items'] as $item) {
|
||||||
|
$purchase->items()->create([
|
||||||
|
'user_id' => auth()->id(),
|
||||||
|
'product_id' => $item['product_id'],
|
||||||
|
'quantity' => $item['quantity'],
|
||||||
|
'unit_price' => $item['unit_price'],
|
||||||
|
'total_price' => $item['quantity'] * $item['unit_price'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
Product::find($item['product_id'])->increment('stock', $item['quantity']);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('purchase.index')->with('success', 'Data berhasil diperbarui');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to update purchase', [
|
||||||
|
'purchase_id' => $purchase->id,
|
||||||
|
'items_count' => count($validated['items'] ?? []),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->withInput()
|
||||||
|
->with('error', 'Terjadi kesalahan saat memperbarui pembelian');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Purchase $purchase): RedirectResponse
|
public function destroy(Purchase $purchase): RedirectResponse
|
||||||
{
|
{
|
||||||
DB::transaction(function () use ($purchase) {
|
try {
|
||||||
foreach ($purchase->items as $item) {
|
DB::transaction(function () use ($purchase) {
|
||||||
$item->product->decrement('stock', $item->quantity);
|
foreach ($purchase->items as $item) {
|
||||||
}
|
$item->product->decrement('stock', $item->quantity);
|
||||||
$purchase->delete();
|
}
|
||||||
});
|
$purchase->delete();
|
||||||
|
});
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Data berhasil dihapus');
|
return redirect()->back()->with('success', 'Data berhasil dihapus');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to delete purchase', [
|
||||||
|
'purchase_id' => $purchase->id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus pembelian');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function bulkDestroy(Request $request): RedirectResponse
|
public function bulkDestroy(Request $request): RedirectResponse
|
||||||
{
|
{
|
||||||
$ids = $request->input('ids');
|
$ids = $request->input('ids');
|
||||||
|
|
||||||
DB::transaction(function () use ($ids) {
|
try {
|
||||||
$purchases = Purchase::with('items')->whereIn('id', $ids)->get();
|
DB::transaction(function () use ($ids) {
|
||||||
foreach ($purchases as $purchase) {
|
$purchases = Purchase::with('items')->whereIn('id', $ids)->get();
|
||||||
foreach ($purchase->items as $item) {
|
foreach ($purchases as $purchase) {
|
||||||
$item->product->decrement('stock', $item->quantity);
|
foreach ($purchase->items as $item) {
|
||||||
|
$item->product->decrement('stock', $item->quantity);
|
||||||
|
}
|
||||||
|
$purchase->delete();
|
||||||
}
|
}
|
||||||
$purchase->delete();
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->back()->with('success', 'Data terpilih berhasil dihapus');
|
return redirect()->back()->with('success', 'Data terpilih berhasil dihapus');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to bulk delete purchases', [
|
||||||
|
'ids' => $ids,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return redirect()->back()->with('error', 'Terjadi kesalahan saat menghapus beberapa pembelian');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
use App\Http\Requests\Admin\Master\ProductRequest;
|
use App\Http\Requests\Admin\Master\ProductRequest;
|
||||||
use App\Models\Category;
|
use App\Models\Category;
|
||||||
use App\Models\Product;
|
use App\Models\Product;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -35,38 +36,57 @@ public function store(ProductRequest $request): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($request, $validated) {
|
try {
|
||||||
$product = Product::create([
|
DB::transaction(function () use ($request, $validated) {
|
||||||
'name' => $validated['name'],
|
$product = Product::create([
|
||||||
'description' => $validated['description'],
|
'name' => $validated['name'],
|
||||||
|
'description' => $validated['description'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$product->categories()->sync($validated['category_ids'] ?? []);
|
||||||
|
|
||||||
|
foreach ($validated['prices'] as $type => $price) {
|
||||||
|
$enumType = PriceType::tryFrom($type);
|
||||||
|
if ($enumType) {
|
||||||
|
$product->prices()->create([
|
||||||
|
'price_type' => $enumType,
|
||||||
|
'price' => $price,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('thumbnail')) {
|
||||||
|
$product->addMediaFromRequest('thumbnail')
|
||||||
|
->toMediaCollection('thumbnail');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('images')) {
|
||||||
|
foreach ($request->file('images') as $image) {
|
||||||
|
$product->addMedia($image)
|
||||||
|
->toMediaCollection('images');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('product.index')->with('success', 'Data berhasil disimpan');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to store product', [
|
||||||
|
'input_summary' => [
|
||||||
|
'name' => $request->input('name'),
|
||||||
|
'categories_count' => count($request->input('category_ids', [])),
|
||||||
|
'prices_keys' => array_keys($request->input('prices', [])),
|
||||||
|
'has_thumbnail' => $request->hasFile('thumbnail'),
|
||||||
|
'images_count' => $request->hasFile('images')
|
||||||
|
? count($request->file('images'))
|
||||||
|
: 0,
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$product->categories()->sync($validated['category_ids'] ?? []);
|
return redirect()
|
||||||
|
->back()
|
||||||
foreach ($validated['prices'] as $type => $price) {
|
->withInput()
|
||||||
$enumType = PriceType::tryFrom($type);
|
->with('error', 'Terjadi kesalahan saat menyimpan data');
|
||||||
if ($enumType) {
|
}
|
||||||
$product->prices()->create([
|
|
||||||
'price_type' => $enumType,
|
|
||||||
'price' => $price,
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasFile('thumbnail')) {
|
|
||||||
$product->addMediaFromRequest('thumbnail')
|
|
||||||
->toMediaCollection('thumbnail');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasFile('images')) {
|
|
||||||
foreach ($request->file('images') as $image) {
|
|
||||||
$product->addMedia($image)
|
|
||||||
->toMediaCollection('images');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('product.index')->with('success', 'Data berhasil disimpan');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(Product $product): Response
|
public function edit(Product $product): Response
|
||||||
@ -83,46 +103,63 @@ public function update(ProductRequest $request, Product $product): RedirectRespo
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($request, $product, $validated) {
|
try {
|
||||||
$product->update([
|
DB::transaction(function () use ($request, $product, $validated) {
|
||||||
'name' => $validated['name'],
|
$product->update([
|
||||||
'description' => $validated['description'],
|
'name' => $validated['name'],
|
||||||
'stock' => $validated['stock'] ?? 0,
|
'description' => $validated['description'],
|
||||||
|
'stock' => $validated['stock'] ?? 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$product->categories()->sync($validated['category_ids'] ?? []);
|
||||||
|
|
||||||
|
foreach ($validated['prices'] as $type => $price) {
|
||||||
|
$enumType = PriceType::tryFrom($type);
|
||||||
|
if ($enumType) {
|
||||||
|
$product->prices()->updateOrCreate(
|
||||||
|
['price_type' => $enumType],
|
||||||
|
['price' => $price]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (! empty($validated['delete_image_ids'])) {
|
||||||
|
Media::whereIn('id', $validated['delete_image_ids'])
|
||||||
|
->where('model_type', Product::class)
|
||||||
|
->where('model_id', $product->id)
|
||||||
|
->each(fn ($media) => $media->delete());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('thumbnail')) {
|
||||||
|
$product->addMediaFromRequest('thumbnail')
|
||||||
|
->toMediaCollection('thumbnail');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->hasFile('images')) {
|
||||||
|
foreach ($request->file('images') as $image) {
|
||||||
|
$product->addMedia($image)
|
||||||
|
->toMediaCollection('images');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('product.index')->with('success', 'Data berhasil diperbarui');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to update product', [
|
||||||
|
'product_id' => $product->id,
|
||||||
|
'input_summary' => [
|
||||||
|
'name' => $request->input('name'),
|
||||||
|
'categories_count' => count($request->input('category_ids', [])),
|
||||||
|
'prices_keys' => array_keys($request->input('prices', [])),
|
||||||
|
'has_thumbnail' => $request->hasFile('thumbnail'),
|
||||||
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$product->categories()->sync($validated['category_ids'] ?? []);
|
return redirect()
|
||||||
|
->back()
|
||||||
foreach ($validated['prices'] as $type => $price) {
|
->withInput()
|
||||||
$enumType = PriceType::tryFrom($type);
|
->with('error', 'Terjadi kesalahan saat memperbarui data');
|
||||||
if ($enumType) {
|
}
|
||||||
$product->prices()->updateOrCreate(
|
|
||||||
['price_type' => $enumType],
|
|
||||||
['price' => $price]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! empty($validated['delete_image_ids'])) {
|
|
||||||
Media::whereIn('id', $validated['delete_image_ids'])
|
|
||||||
->where('model_type', Product::class)
|
|
||||||
->where('model_id', $product->id)
|
|
||||||
->each(fn ($media) => $media->delete());
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasFile('thumbnail')) {
|
|
||||||
$product->addMediaFromRequest('thumbnail')
|
|
||||||
->toMediaCollection('thumbnail');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($request->hasFile('images')) {
|
|
||||||
foreach ($request->file('images') as $image) {
|
|
||||||
$product->addMedia($image)
|
|
||||||
->toMediaCollection('images');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('product.index')->with('success', 'Data berhasil diperbarui');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroy(Product $product): RedirectResponse
|
public function destroy(Product $product): RedirectResponse
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Admin\Master\UserRequest;
|
use App\Http\Requests\Admin\Master\UserRequest;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Support\LogHelper;
|
||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@ -31,25 +32,37 @@ public function store(UserRequest $request): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($validated) {
|
try {
|
||||||
$user = User::create([
|
DB::transaction(function () use ($validated) {
|
||||||
|
$user = User::create([
|
||||||
|
'username' => $validated['username'],
|
||||||
|
'email' => $validated['email'],
|
||||||
|
'password' => Hash::make(config('auth.password_default')),
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user->profile()->create([
|
||||||
|
'nik' => $validated['nik'],
|
||||||
|
'full_name' => $validated['full_name'],
|
||||||
|
'phone_number' => $validated['phone_number'],
|
||||||
|
'address' => $validated['address'],
|
||||||
|
'birth_place' => $validated['birth_place'],
|
||||||
|
'birth_date' => $validated['birth_date'],
|
||||||
|
'base_salary' => $validated['base_salary'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('user.index')->with('success', 'Data berhasil disimpan');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to store user', [
|
||||||
'username' => $validated['username'],
|
'username' => $validated['username'],
|
||||||
'email' => $validated['email'],
|
'email' => $validated['email'],
|
||||||
'password' => Hash::make(config('auth.password_default')),
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user->profile()->create([
|
return redirect()
|
||||||
'nik' => $validated['nik'],
|
->back()
|
||||||
'full_name' => $validated['full_name'],
|
->withInput()
|
||||||
'phone_number' => $validated['phone_number'],
|
->with('error', 'Terjadi kesalahan saat menyimpan data');
|
||||||
'address' => $validated['address'],
|
}
|
||||||
'birth_place' => $validated['birth_place'],
|
|
||||||
'birth_date' => $validated['birth_date'],
|
|
||||||
'base_salary' => $validated['base_salary'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('user.index')->with('success', 'Data berhasil disimpan');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function edit(User $user): Response
|
public function edit(User $user): Response
|
||||||
@ -65,24 +78,36 @@ public function update(UserRequest $request, User $user): RedirectResponse
|
|||||||
{
|
{
|
||||||
$validated = $request->validated();
|
$validated = $request->validated();
|
||||||
|
|
||||||
DB::transaction(function () use ($user, $validated) {
|
try {
|
||||||
$user->update([
|
DB::transaction(function () use ($user, $validated) {
|
||||||
|
$user->update([
|
||||||
|
'username' => $validated['username'],
|
||||||
|
'email' => $validated['email'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$user->profile()->update([
|
||||||
|
'nik' => $validated['nik'],
|
||||||
|
'full_name' => $validated['full_name'],
|
||||||
|
'phone_number' => $validated['phone_number'],
|
||||||
|
'address' => $validated['address'],
|
||||||
|
'birth_place' => $validated['birth_place'],
|
||||||
|
'birth_date' => $validated['birth_date'],
|
||||||
|
'base_salary' => $validated['base_salary'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
return redirect()->route('user.index')->with('success', 'Data berhasil diperbarui');
|
||||||
|
} catch (\Throwable $e) {
|
||||||
|
LogHelper::logException($e, 'Failed to update user', [
|
||||||
|
'user_id' => $user->id,
|
||||||
'username' => $validated['username'],
|
'username' => $validated['username'],
|
||||||
'email' => $validated['email'],
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$user->profile()->update([
|
return redirect()
|
||||||
'nik' => $validated['nik'],
|
->back()
|
||||||
'full_name' => $validated['full_name'],
|
->withInput()
|
||||||
'phone_number' => $validated['phone_number'],
|
->with('error', 'Terjadi kesalahan saat memperbarui data');
|
||||||
'address' => $validated['address'],
|
}
|
||||||
'birth_place' => $validated['birth_place'],
|
|
||||||
'birth_date' => $validated['birth_date'],
|
|
||||||
'base_salary' => $validated['base_salary'],
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
return redirect()->route('user.index')->with('success', 'Data berhasil diperbarui');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resetPassword(User $user): RedirectResponse
|
public function resetPassword(User $user): RedirectResponse
|
||||||
|
|||||||
@ -39,8 +39,8 @@ private function getLogFiles(): array
|
|||||||
$files = File::files($path);
|
$files = File::files($path);
|
||||||
|
|
||||||
return collect($files)
|
return collect($files)
|
||||||
->map(fn($file) => $file->getFilename())
|
->map(fn ($file) => $file->getFilename())
|
||||||
->filter(fn($filename) => str_ends_with($filename, '.log'))
|
->filter(fn ($filename) => str_ends_with($filename, '.log'))
|
||||||
->sortDesc()
|
->sortDesc()
|
||||||
->take(10)
|
->take(10)
|
||||||
->values()
|
->values()
|
||||||
|
|||||||
47
app/Support/LogHelper.php
Normal file
47
app/Support/LogHelper.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Support;
|
||||||
|
|
||||||
|
use Illuminate\Support\Arr;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
class LogHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Log an exception with full request and context details.
|
||||||
|
*
|
||||||
|
* @param Throwable $e The exception to log
|
||||||
|
* @param string $message Custom log message
|
||||||
|
* @param array $extraContext Additional context data
|
||||||
|
*/
|
||||||
|
public static function logException(Throwable $e, string $message, array $extraContext = []): void
|
||||||
|
{
|
||||||
|
$request = request();
|
||||||
|
|
||||||
|
Log::error($message, [
|
||||||
|
'message' => $e->getMessage(),
|
||||||
|
'exception' => get_class($e),
|
||||||
|
'file' => $e->getFile(),
|
||||||
|
'line' => $e->getLine(),
|
||||||
|
|
||||||
|
// stack trace (take top 10)
|
||||||
|
'trace' => collect($e->getTrace())->take(10)->toArray(),
|
||||||
|
|
||||||
|
// request context
|
||||||
|
'request' => [
|
||||||
|
'url' => $request->fullUrl(),
|
||||||
|
'method' => $request->method(),
|
||||||
|
'ip' => $request->ip(),
|
||||||
|
'user_agent' => $request->userAgent(),
|
||||||
|
'payload' => Arr::except($request->all(), ['password', 'token', 'password_confirmation']),
|
||||||
|
],
|
||||||
|
|
||||||
|
// auth context
|
||||||
|
'user' => optional(auth()->user())->only(['id', 'email']),
|
||||||
|
|
||||||
|
// custom context
|
||||||
|
'extra' => $extraContext,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user