refactor: update AnalysisService and index.tsx to streamline stock calculations and remove unused values

This commit is contained in:
Yoga Pangestu 2026-08-14 06:07:47 +07:00
parent 5fd0ab135d
commit b954e3cb84
2 changed files with 42 additions and 47 deletions

View File

@ -18,9 +18,9 @@
use App\Models\LeaveRequest; use App\Models\LeaveRequest;
use App\Models\Order; use App\Models\Order;
use App\Models\Payroll; use App\Models\Payroll;
use App\Models\ProductVariant;
use App\Models\Purchase; use App\Models\Purchase;
use App\Models\PurchaseItem; use App\Models\RawMaterialPrice;
use App\Models\RestockItem;
use App\Models\User; use App\Models\User;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
@ -82,13 +82,19 @@ public function getAttendanceStats(?string $startDate, ?string $endDate, ?User $
]; ];
} }
$employees = Employee::whereHas('user', fn ($q) => $q $employees = Employee::whereHas(
->where('is_active', true) 'user',
->whereHas('roles', fn ($r) => $r fn($q) => $q
->whereHas('permissions', fn ($p) => $p ->where('is_active', true)
->where('name', 'attendances.create') ->whereHas(
'roles',
fn($r) => $r
->whereHas(
'permissions',
fn($p) => $p
->where('name', 'attendances.create')
)
) )
)
) )
->where('join_date', '<=', $end) ->where('join_date', '<=', $end)
->where(function ($q) use ($start) { ->where(function ($q) use ($start) {
@ -199,49 +205,42 @@ public function getCashOverview(?string $startDate, ?string $endDate): array
public function getRawMaterialStock(): array public function getRawMaterialStock(): array
{ {
$query = PurchaseItem::query() $items = RawMaterialPrice::query()
->join('purchases', 'purchase_items.purchase_id', '=', 'purchases.id') ->join('raw_materials', 'raw_material_prices.raw_material_id', '=', 'raw_materials.id')
->leftJoin('raw_material_prices', 'purchase_items.raw_material_price_id', '=', 'raw_material_prices.id') ->select('raw_material_prices.stock', 'raw_materials.unit')
->leftJoin('raw_materials', 'raw_material_prices.raw_material_id', '=', 'raw_materials.id');
$items = $query->select('purchase_items.*', 'raw_materials.unit')
->get(); ->get();
$totalQty = $items->sum('quantity'); $totalQty = $items->sum('stock');
$totalValue = $items->sum('subtotal');
$byUnit = [ $byUnit = [
'yard' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::YARD)->sum('quantity'), 'yard' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::YARD->value)->sum('stock'),
'meter' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::METER)->sum('quantity'), 'meter' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::METER->value)->sum('stock'),
'kilogram' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::KG)->sum('quantity'), 'kilogram' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::KG->value)->sum('stock'),
]; ];
return [ return [
'total_stock' => $totalQty, 'total_stock' => $totalQty,
'total_value' => $totalValue,
'by_unit' => $byUnit, 'by_unit' => $byUnit,
]; ];
} }
public function getProductStock(): array public function getProductStock(): array
{ {
$query = RestockItem::query() $variants = ProductVariant::query()
->join('restocks', 'restock_items.restock_id', '=', 'restocks.id'); ->select('stock', 'reject_stock', 'retail_stock')
$items = $query->select('restock_items.*', 'restocks.stock_type')
->get(); ->get();
$totalQty = $items->sum('quantity'); $totalStock = $variants->sum('stock');
$totalValue = $items->sum('subtotal'); $totalRejectStock = $variants->sum('reject_stock');
$totalRetailStock = $variants->sum('retail_stock');
$byType = $items->groupBy(fn ($i) => $i->stock_type ?? 'unknown')
->map(fn ($group) => $group->sum('quantity'))
->toArray();
return [ return [
'total_stock' => $totalQty, 'total_stock' => $totalStock + $totalRejectStock + $totalRetailStock,
'total_value' => $totalValue, 'by_type' => [
'by_type' => $byType, 'stock' => $totalStock,
'reject_stock' => $totalRejectStock,
'retail_stock' => $totalRetailStock,
],
]; ];
} }
@ -382,7 +381,7 @@ public function getMonthlyRevenueByChannel(?string $startDate, ?string $endDate,
->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"), DB::raw("DATE_FORMAT(created_at, '%b %Y')")) ->groupBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"), DB::raw("DATE_FORMAT(created_at, '%b %Y')"))
->orderBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')")) ->orderBy(DB::raw("DATE_FORMAT(created_at, '%Y-%m')"))
->get() ->get()
->map(fn ($item) => [ ->map(fn($item) => [
'month' => $item->month, 'month' => $item->month,
'store' => (int) $item->store, 'store' => (int) $item->store,
'shopee' => (int) $item->shopee, 'shopee' => (int) $item->shopee,
@ -406,7 +405,7 @@ public function getRevenueByPaymentType(?string $startDate, ?string $endDate, ?U
->selectRaw('COALESCE(SUM(total_amount), 0) as total') ->selectRaw('COALESCE(SUM(total_amount), 0) as total')
->groupBy('payment_type') ->groupBy('payment_type')
->get() ->get()
->map(fn ($item) => [ ->map(fn($item) => [
'payment_type' => $item->payment_type, 'payment_type' => $item->payment_type,
'label' => $item->payment_type->label(), 'label' => $item->payment_type->label(),
'total' => (int) $item->total, 'total' => (int) $item->total,
@ -721,7 +720,7 @@ public function getRevenueTrend(?string $startDate, ?string $endDate, ?User $use
->groupBy(DB::raw('DATE(orders.created_at)')) ->groupBy(DB::raw('DATE(orders.created_at)'))
->orderBy(DB::raw('DATE(orders.created_at)')) ->orderBy(DB::raw('DATE(orders.created_at)'))
->get() ->get()
->map(fn ($item) => [ ->map(fn($item) => [
'date' => $item->date, 'date' => $item->date,
'qty' => (int) $item->qty, 'qty' => (int) $item->qty,
]) ])
@ -812,7 +811,7 @@ public function getOrderStats(?string $startDate, ?string $endDate, ?User $user
->groupBy('marketing_id') ->groupBy('marketing_id')
->with('marketing:id') ->with('marketing:id')
->get() ->get()
->map(fn ($item) => [ ->map(fn($item) => [
'name' => $item->marketing?->userProfile->full_name ?? '-', 'name' => $item->marketing?->userProfile->full_name ?? '-',
'count' => $item->count, 'count' => $item->count,
'total' => (int) $item->total, 'total' => (int) $item->total,

View File

@ -67,7 +67,6 @@ type AnalysisProps = {
}; };
rawMaterialStock: { rawMaterialStock: {
total_stock: number; total_stock: number;
total_value: number;
by_unit: { by_unit: {
yard: number; yard: number;
meter: number; meter: number;
@ -76,11 +75,10 @@ type AnalysisProps = {
}; };
productStock: { productStock: {
total_stock: number; total_stock: number;
total_value: number;
by_type: { by_type: {
good?: number; stock?: number;
reject?: number; reject_stock?: number;
retail?: number; retail_stock?: number;
}; };
}; };
revenueSummary: { revenueSummary: {
@ -591,7 +589,6 @@ export default function Analysis({
icon={Package} icon={Package}
mainLabel="Total Stok" mainLabel="Total Stok"
mainValue={rawMaterialStock.total_stock.toLocaleString('id-ID')} mainValue={rawMaterialStock.total_stock.toLocaleString('id-ID')}
subLabel={`Rp${formatRupiah(rawMaterialStock.total_value)}`}
description="Tidak terpengaruh filter tanggal" description="Tidak terpengaruh filter tanggal"
items={[ items={[
{ label: 'Yard', value: rawMaterialStock.by_unit?.yard?.toLocaleString('id-ID') ?? '0' }, { label: 'Yard', value: rawMaterialStock.by_unit?.yard?.toLocaleString('id-ID') ?? '0' },
@ -607,12 +604,11 @@ export default function Analysis({
icon={ShoppingCart} icon={ShoppingCart}
mainLabel="Total Stok" mainLabel="Total Stok"
mainValue={productStock.total_stock.toLocaleString('id-ID')} mainValue={productStock.total_stock.toLocaleString('id-ID')}
subLabel={`Rp${formatRupiah(productStock.total_value)}`}
description="Tidak terpengaruh filter tanggal" description="Tidak terpengaruh filter tanggal"
items={[ items={[
{ label: 'Bagus', value: (productStock.by_type?.good ?? 0).toLocaleString('id-ID') }, { label: 'Bagus', value: (productStock.by_type?.stock ?? 0).toLocaleString('id-ID') },
{ label: 'Reject', value: (productStock.by_type?.reject ?? 0).toLocaleString('id-ID') }, { label: 'Reject', value: (productStock.by_type?.reject_stock ?? 0).toLocaleString('id-ID') },
{ label: 'Ecer', value: (productStock.by_type?.retail ?? 0).toLocaleString('id-ID') }, { label: 'Ecer', value: (productStock.by_type?.retail_stock ?? 0).toLocaleString('id-ID') },
]} ]}
/> />
)} )}