refactor: implement grouped material usage calculation across Cutting components for improved clarity and consistency in material representation

This commit is contained in:
Yoga Pangestu 2026-06-21 13:18:04 +07:00
parent de045a4588
commit 061edbc568
3 changed files with 75 additions and 39 deletions

View File

@ -12,18 +12,6 @@ import {
} from '@/components/ui/empty';
import type { CuttingListItem } from '@/types/cutting';
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
if (!totalUsage) {
return '0';
}
return String(parseFloat(totalUsage.toFixed(2)));
}
function getTotalMaterialUsageUnit(materials: any[]): string {
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
}
function formatMaterialUsage(mat: any): string {
return String(parseFloat(Number(mat.material_usage ?? 0).toFixed(2)));
}
@ -32,6 +20,28 @@ function getMaterialUnit(mat: any): string {
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
}
interface MaterialUsageGroup {
total: string;
unit: string;
}
function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
const groups: Record<string, number> = {};
materials.forEach((mat) => {
const unit = mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
const usage = Number(mat.material_usage ?? 0);
groups[unit] = (groups[unit] ?? 0) + usage;
});
return Object.entries(groups)
.filter(([, total]) => total > 0)
.map(([unit, total]) => ({
total: String(parseFloat(total.toFixed(2))),
unit,
}));
}
const props = defineProps<{
cuttings: CuttingListItem[];
}>();
@ -105,9 +115,13 @@ const totalCompleted = computed(() => props.cuttings.length);
<span class="text-muted-foreground">Total Hasil Cutting:</span>
<span class="font-semibold tabular-nums">{{ cutting.total_result_pieces ?? 0 }} pcs</span>
</div>
<div class="flex items-center justify-between text-[11px]">
<div v-if="cutting.materials.length" class="flex items-center justify-between text-[11px]">
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
<span class="font-semibold tabular-nums">{{ getGroupedMaterialUsage(cutting.materials).map(g => `${g.total} ${g.unit}`).join(', ') }}</span>
</div>
<div class="flex items-center justify-between text-[11px]">
<span class="text-muted-foreground">Biaya Bahan:</span>
<span class="font-semibold tabular-nums">{{ cutting.total_material_cost_formatted ?? 'Rp 0' }}</span>
</div>
</div>

View File

@ -137,16 +137,26 @@ function getMaterialUnit(materials: any[]): string | undefined {
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation;
}
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
if (!totalUsage) {
return '0';
}
return String(parseFloat(totalUsage.toFixed(2)));
interface MaterialUsageGroup {
total: string;
unit: string;
}
function getTotalMaterialUsageUnit(materials: any[]): string {
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
const groups: Record<string, number> = {};
materials.forEach((mat) => {
const unit = mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
const usage = Number(mat.material_usage ?? 0);
groups[unit] = (groups[unit] ?? 0) + usage;
});
return Object.entries(groups)
.filter(([, total]) => total > 0)
.map(([unit, total]) => ({
total: String(parseFloat(total.toFixed(2))),
unit,
}));
}
</script>
@ -185,9 +195,7 @@ function getTotalMaterialUsageUnit(materials: any[]): string {
<div class="flex flex-wrap gap-x-4 gap-y-1 text-sm">
<span>Total Hasil Cutting <strong class="text-primary">{{ cutting.total_result_pieces ??
0 }} pcs</strong></span>
<span>Total Pemakaian Bahan <strong class="text-primary">{{
formatTotalMaterialUsage(cutting.total_material_usage) }}
{{ getTotalMaterialUsageUnit(cutting.materials) }}</strong></span>
<span v-if="cutting.materials.length">Total Pemakaian Bahan <strong class="text-primary">{{ getGroupedMaterialUsage(cutting.materials).map(g => `${g.total} ${g.unit}`).join(', ') }}</strong></span>
<span>Biaya Bahan <strong class="text-primary">{{
cutting.total_material_cost_formatted ?? 'Rp 0' }}</strong></span>
</div>

View File

@ -3,18 +3,6 @@ import { Card } from '@/components/ui/card';
import type { CuttingListItem } from '@/types/cutting';
import DataTableActions from './data-table-actions.vue';
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
if (!totalUsage) {
return '0';
}
return String(parseFloat(totalUsage.toFixed(2)));
}
function getTotalMaterialUsageUnit(materials: any[]): string {
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
}
function formatMaterialUsage(mat: any): string {
return String(parseFloat(Number(mat.material_usage ?? 0).toFixed(2)));
}
@ -23,6 +11,28 @@ function getMaterialUnit(mat: any): string {
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
}
interface MaterialUsageGroup {
total: string;
unit: string;
}
function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
const groups: Record<string, number> = {};
materials.forEach((mat) => {
const unit = mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
const usage = Number(mat.material_usage ?? 0);
groups[unit] = (groups[unit] ?? 0) + usage;
});
return Object.entries(groups)
.filter(([, total]) => total > 0)
.map(([unit, total]) => ({
total: String(parseFloat(total.toFixed(2))),
unit,
}));
}
defineProps<{
cuttings: CuttingListItem[];
}>();
@ -80,9 +90,13 @@ defineProps<{
<span class="font-semibold tabular-nums">{{ cutting.total_result_pieces ?? 0 }}
pcs</span>
</div>
<div class="flex items-center justify-between text-[11px]">
<div v-if="cutting.materials.length" class="flex items-center justify-between text-[11px]">
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
<span class="font-semibold tabular-nums">{{ getGroupedMaterialUsage(cutting.materials).map(g => `${g.total} ${g.unit}`).join(', ') }}</span>
</div>
<div class="flex items-center justify-between text-[11px]">
<span class="text-muted-foreground">Biaya Bahan:</span>
<span class="font-semibold tabular-nums">{{ cutting.total_material_cost_formatted ?? 'Rp 0' }}</span>
</div>
</div>