feat: add total price calculations for raw materials and products in analysis components
This commit is contained in:
parent
25a316ccf0
commit
ef136bd1e7
@ -8,6 +8,7 @@
|
||||
use App\Enums\OrderStatus;
|
||||
use App\Enums\PaymentType;
|
||||
use App\Enums\PayrollStatus;
|
||||
use App\Enums\PriceType;
|
||||
use App\Enums\RawMaterialUnit;
|
||||
use App\Enums\Role;
|
||||
use App\Models\Attendance;
|
||||
@ -18,6 +19,7 @@
|
||||
use App\Models\LeaveRequest;
|
||||
use App\Models\Order;
|
||||
use App\Models\Payroll;
|
||||
use App\Models\ProductPrice;
|
||||
use App\Models\ProductVariant;
|
||||
use App\Models\Purchase;
|
||||
use App\Models\RawMaterialPrice;
|
||||
@ -207,10 +209,11 @@ public function getRawMaterialStock(): array
|
||||
{
|
||||
$items = RawMaterialPrice::query()
|
||||
->join('raw_materials', 'raw_material_prices.raw_material_id', '=', 'raw_materials.id')
|
||||
->select('raw_material_prices.stock', 'raw_materials.unit')
|
||||
->select('raw_material_prices.stock', 'raw_material_prices.price', 'raw_materials.unit')
|
||||
->get();
|
||||
|
||||
$totalQty = $items->sum('stock');
|
||||
$totalPrice = $items->sum(fn ($i) => $i->stock * $i->price);
|
||||
|
||||
$byUnit = [
|
||||
'yard' => $items->filter(fn ($i) => $i->unit === RawMaterialUnit::YARD->value)->sum('stock'),
|
||||
@ -220,6 +223,7 @@ public function getRawMaterialStock(): array
|
||||
|
||||
return [
|
||||
'total_stock' => $totalQty,
|
||||
'total_price' => $totalPrice,
|
||||
'by_unit' => $byUnit,
|
||||
];
|
||||
}
|
||||
@ -227,15 +231,21 @@ public function getRawMaterialStock(): array
|
||||
public function getProductStock(): array
|
||||
{
|
||||
$variants = ProductVariant::query()
|
||||
->select('stock', 'reject_stock', 'retail_stock')
|
||||
->leftJoin('product_prices', function ($join) {
|
||||
$join->on('product_variants.id', '=', 'product_prices.variant_id')
|
||||
->where('product_prices.type', '=', PriceType::RETAIL->value);
|
||||
})
|
||||
->select('product_variants.stock', 'product_variants.reject_stock', 'product_variants.retail_stock', 'product_prices.price')
|
||||
->get();
|
||||
|
||||
$totalStock = $variants->sum('stock');
|
||||
$totalRejectStock = $variants->sum('reject_stock');
|
||||
$totalRetailStock = $variants->sum('retail_stock');
|
||||
$totalPrice = $variants->sum(fn ($v) => ($v->stock + $v->reject_stock + $v->retail_stock) * ($v->price ?? 0));
|
||||
|
||||
return [
|
||||
'total_stock' => $totalStock + $totalRejectStock + $totalRetailStock,
|
||||
'total_price' => $totalPrice,
|
||||
'by_type' => [
|
||||
'stock' => $totalStock,
|
||||
'reject_stock' => $totalRejectStock,
|
||||
|
||||
@ -31,7 +31,7 @@ export function StatCard({ title, icon: Icon, mainLabel, mainValue, subLabel, de
|
||||
{subLabel && <p className="text-xs text-muted-foreground">{subLabel}</p>}
|
||||
{description && <p className="mt-1 text-[10px] text-muted-foreground italic">{description}</p>}
|
||||
{items.length > 0 && (
|
||||
<div className={cn('mt-3 grid gap-2', cols === 2 && 'grid-cols-2', cols === 3 && 'grid-cols-3', cols === 4 && 'grid-cols-4')}>
|
||||
<div className={cn('mt-3 grid gap-2', cols === 2 && 'grid-cols-2', cols === 3 && 'grid-cols-2 sm:grid-cols-3', cols === 4 && 'grid-cols-2 sm:grid-cols-4')}>
|
||||
{items.map((item, index) => (
|
||||
<div key={index}>
|
||||
<p className="text-xs text-muted-foreground">{item.label}</p>
|
||||
|
||||
@ -67,6 +67,7 @@ type AnalysisProps = {
|
||||
};
|
||||
rawMaterialStock: {
|
||||
total_stock: number;
|
||||
total_price: number;
|
||||
by_unit: {
|
||||
yard: number;
|
||||
meter: number;
|
||||
@ -75,6 +76,7 @@ type AnalysisProps = {
|
||||
};
|
||||
productStock: {
|
||||
total_stock: number;
|
||||
total_price: number;
|
||||
by_type: {
|
||||
stock?: number;
|
||||
reject_stock?: number;
|
||||
@ -622,7 +624,9 @@ export default function Analysis({
|
||||
{ label: 'Yard', value: rawMaterialStock.by_unit?.yard?.toLocaleString('id-ID') ?? '0' },
|
||||
{ label: 'Meter', value: rawMaterialStock.by_unit?.meter?.toLocaleString('id-ID') ?? '0' },
|
||||
{ label: 'Kg', value: rawMaterialStock.by_unit?.kilogram?.toLocaleString('id-ID') ?? '0' },
|
||||
{ label: 'Total Harga', value: `Rp${formatRupiah(rawMaterialStock.total_price)}` },
|
||||
]}
|
||||
cols={4}
|
||||
/>
|
||||
)}
|
||||
|
||||
@ -637,7 +641,9 @@ export default function Analysis({
|
||||
{ label: 'Bagus', value: (productStock.by_type?.stock ?? 0).toLocaleString('id-ID') },
|
||||
{ label: 'Reject', value: (productStock.by_type?.reject_stock ?? 0).toLocaleString('id-ID') },
|
||||
{ label: 'Ecer', value: (productStock.by_type?.retail_stock ?? 0).toLocaleString('id-ID') },
|
||||
{ label: 'Total Harga', value: `Rp${formatRupiah(productStock.total_price)}` },
|
||||
]}
|
||||
cols={4}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user