feat: enhance cutting and purchase services by adding raw material attributes and updating related UI components for improved material management

This commit is contained in:
Yoga Pangestu 2026-06-29 00:02:35 +07:00
parent 8da733ec08
commit 944c0bc14a
8 changed files with 33 additions and 17 deletions

View File

@ -811,10 +811,15 @@ private function breakMaterialCircularReference(CuttingMaterial $material): void
if ($price) { if ($price) {
$rawMaterial = $price->rawMaterial; $rawMaterial = $price->rawMaterial;
$material->setAttribute('variant', $price->variant);
if ($rawMaterial) { if ($rawMaterial) {
$unitAbbreviation = $rawMaterial->unit->abbreviation(); $unitAbbreviation = $rawMaterial->unit->abbreviation();
$price->setAttribute('unit_abbreviation', $unitAbbreviation); $price->setAttribute('unit_abbreviation', $unitAbbreviation);
$material->setAttribute('unit_abbreviation', $unitAbbreviation); $material->setAttribute('unit_abbreviation', $unitAbbreviation);
$material->setAttribute('raw_material_id', $rawMaterial->id);
$material->setAttribute('raw_material_name', $rawMaterial->name);
$material->setAttribute('raw_material_unit_label', $rawMaterial->unit->label());
} }
$price->unsetRelation('rawMaterial'); $price->unsetRelation('rawMaterial');

View File

@ -795,10 +795,15 @@ private function breakItemCircularReference(PurchaseItem $item): void
if ($price) { if ($price) {
$rawMaterial = $price->rawMaterial; $rawMaterial = $price->rawMaterial;
$item->setAttribute('variant', $price->variant);
if ($rawMaterial) { if ($rawMaterial) {
$unitAbbreviation = $rawMaterial->unit->abbreviation(); $unitAbbreviation = $rawMaterial->unit->abbreviation();
$price->setAttribute('unit_abbreviation', $unitAbbreviation); $price->setAttribute('unit_abbreviation', $unitAbbreviation);
$item->setAttribute('unit_abbreviation', $unitAbbreviation); $item->setAttribute('unit_abbreviation', $unitAbbreviation);
$item->setAttribute('raw_material_id', $rawMaterial->id);
$item->setAttribute('raw_material_name', $rawMaterial->name);
$item->setAttribute('raw_material_unit_label', $rawMaterial->unit->label());
} }
$price->unsetRelation('rawMaterial'); $price->unsetRelation('rawMaterial');

View File

@ -17,7 +17,7 @@ function formatMaterialUsage(mat: any): string {
} }
function getMaterialUnit(mat: any): string { function getMaterialUnit(mat: any): string {
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? ''; return mat.unit_abbreviation ?? '';
} }
interface MaterialUsageGroup { interface MaterialUsageGroup {
@ -29,7 +29,7 @@ function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
const groups: Record<string, number> = {}; const groups: Record<string, number> = {};
materials.forEach((mat) => { materials.forEach((mat) => {
const unit = mat.raw_material_price?.raw_material?.unit_abbreviation ?? ''; const unit = mat.unit_abbreviation ?? '';
const usage = Number(mat.material_usage ?? 0); const usage = Number(mat.material_usage ?? 0);
groups[unit] = (groups[unit] ?? 0) + usage; groups[unit] = (groups[unit] ?? 0) + usage;
}); });
@ -94,7 +94,7 @@ const totalCompleted = computed(() => props.cuttings.length);
<span class="font-medium text-foreground">Bahan Baku:</span> <span class="font-medium text-foreground">Bahan Baku:</span>
<ul class="list-disc pl-4 space-y-0.5 text-muted-foreground"> <ul class="list-disc pl-4 space-y-0.5 text-muted-foreground">
<li v-for="mat in cutting.materials" :key="mat.id"> <li v-for="mat in cutting.materials" :key="mat.id">
{{ mat.raw_material_price?.raw_material?.name }} ({{ mat.raw_material_price?.variant }}) - {{ formatMaterialUsage(mat) }} {{ getMaterialUnit(mat) }} {{ mat.raw_material_name }} ({{ mat.variant }}) - {{ formatMaterialUsage(mat) }} {{ getMaterialUnit(mat) }}
</li> </li>
<li v-if="!cutting.materials.length">Belum ada bahan baku</li> <li v-if="!cutting.materials.length">Belum ada bahan baku</li>
</ul> </ul>

View File

@ -59,10 +59,9 @@ function getGroupedMaterials(materials: any[]): GroupedCuttingMaterials[] {
const groups: Record<number, GroupedCuttingMaterials> = {}; const groups: Record<number, GroupedCuttingMaterials> = {};
materials.forEach((item) => { materials.forEach((item) => {
const rawMaterial = item.raw_material_price?.raw_material; const rawMaterialId = item.raw_material_id ?? 0;
const rawMaterialId = rawMaterial?.id ?? 0; const rawMaterialName = item.raw_material_name || 'Bahan Baku Tidak Diketahui';
const rawMaterialName = rawMaterial?.name ?? 'Bahan Baku Tidak Diketahui'; const unitLabel = item.raw_material_unit_label;
const unitLabel = rawMaterial?.unit_label;
if (!groups[rawMaterialId]) { if (!groups[rawMaterialId]) {
groups[rawMaterialId] = { groups[rawMaterialId] = {
@ -176,7 +175,7 @@ function getGroupedResults(results: any[]): GroupedCuttingResults[] {
</TableRow> </TableRow>
<TableRow v-for="material in group.items" :key="material.id"> <TableRow v-for="material in group.items" :key="material.id">
<TableCell class="pl-6 font-medium"> <TableCell class="pl-6 font-medium">
{{ material.raw_material_price?.variant }} {{ material.variant }}
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ material.material_usage_formatted }} {{ material.material_usage_formatted }}

View File

@ -8,7 +8,7 @@ function formatMaterialUsage(mat: any): string {
} }
function getMaterialUnit(mat: any): string { function getMaterialUnit(mat: any): string {
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? ''; return mat.unit_abbreviation ?? '';
} }
interface MaterialUsageGroup { interface MaterialUsageGroup {
@ -20,7 +20,7 @@ function getGroupedMaterialUsage(materials: any[]): MaterialUsageGroup[] {
const groups: Record<string, number> = {}; const groups: Record<string, number> = {};
materials.forEach((mat) => { materials.forEach((mat) => {
const unit = mat.raw_material_price?.raw_material?.unit_abbreviation ?? ''; const unit = mat.unit_abbreviation ?? '';
const usage = Number(mat.material_usage ?? 0); const usage = Number(mat.material_usage ?? 0);
groups[unit] = (groups[unit] ?? 0) + usage; groups[unit] = (groups[unit] ?? 0) + usage;
}); });
@ -66,8 +66,8 @@ defineProps<{
<span class="font-medium text-foreground">Bahan Baku:</span> <span class="font-medium text-foreground">Bahan Baku:</span>
<ul class="list-disc pl-4 space-y-0.5 text-muted-foreground"> <ul class="list-disc pl-4 space-y-0.5 text-muted-foreground">
<li v-for="mat in cutting.materials" :key="mat.id"> <li v-for="mat in cutting.materials" :key="mat.id">
{{ mat.raw_material_price?.raw_material?.name }} ({{ {{ mat.raw_material_name }} ({{
mat.raw_material_price?.variant }}) - {{ formatMaterialUsage(mat) }} {{ getMaterialUnit(mat) }} mat.variant }}) - {{ formatMaterialUsage(mat) }} {{ getMaterialUnit(mat) }}
</li> </li>
<li v-if="!cutting.materials.length">Belum ada bahan baku</li> <li v-if="!cutting.materials.length">Belum ada bahan baku</li>
</ul> </ul>

View File

@ -58,10 +58,9 @@ function getGroupedItems(items: PurchaseItemDetail[]): GroupedPurchaseItems[] {
const groups: Record<number, GroupedPurchaseItems> = {}; const groups: Record<number, GroupedPurchaseItems> = {};
items.forEach((item) => { items.forEach((item) => {
const rawMaterial = item.raw_material_price?.raw_material; const rawMaterialId = item.raw_material_id ?? 0;
const rawMaterialId = rawMaterial?.id ?? 0; const rawMaterialName = item.raw_material_name || 'Bahan Baku Tidak Diketahui';
const rawMaterialName = rawMaterial?.name ?? 'Bahan Baku Tidak Diketahui'; const unitLabel = item.raw_material_unit_label;
const unitLabel = rawMaterial?.unit_label;
if (!groups[rawMaterialId]) { if (!groups[rawMaterialId]) {
groups[rawMaterialId] = { groups[rawMaterialId] = {
@ -150,7 +149,7 @@ function getGroupedItems(items: PurchaseItemDetail[]): GroupedPurchaseItems[] {
</TableRow> </TableRow>
<TableRow v-for="item in group.items" :key="item.id"> <TableRow v-for="item in group.items" :key="item.id">
<TableCell class="pl-6 font-medium"> <TableCell class="pl-6 font-medium">
{{ item.raw_material_price?.variant }} {{ item.variant }}
</TableCell> </TableCell>
<TableCell class="tabular-nums"> <TableCell class="tabular-nums">
{{ item.quantity_formatted }} {{ item.quantity_formatted }}

View File

@ -14,6 +14,10 @@ export type CuttingStatusAction = {
export type CuttingMaterialListItem = { export type CuttingMaterialListItem = {
id: number; id: number;
material_usage_formatted: string; material_usage_formatted: string;
variant?: string;
raw_material_id?: number;
raw_material_name?: string;
raw_material_unit_label?: string;
raw_material_price?: { raw_material_price?: {
id: number; id: number;
variant: string; variant: string;

View File

@ -8,12 +8,16 @@ export type PurchaseItemListItem = {
id: number; id: number;
raw_material_name: string; raw_material_name: string;
variant_name: string; variant_name: string;
variant?: string;
quantity_formatted: string; quantity_formatted: string;
unit_price_formatted: string; unit_price_formatted: string;
subtotal_formatted: string; subtotal_formatted: string;
}; };
export type PurchaseItemDetail = PurchaseItemListItem & { export type PurchaseItemDetail = PurchaseItemListItem & {
raw_material_id?: number;
raw_material_name?: string;
raw_material_unit_label?: string;
raw_material_price?: { raw_material_price?: {
id: number; id: number;
variant: string; variant: string;