refactor: remove length unit handling from CuttingMaterial and related components for improved clarity and consistency in material usage representation
This commit is contained in:
parent
ec80f2145b
commit
fc234a6afd
@ -15,14 +15,9 @@
|
|||||||
#[Appends([
|
#[Appends([
|
||||||
'material_usage_formatted',
|
'material_usage_formatted',
|
||||||
'material_usage_input',
|
'material_usage_input',
|
||||||
'material_usage_cm_formatted',
|
|
||||||
'material_usage_cm_input',
|
|
||||||
'remaining_material_formatted',
|
'remaining_material_formatted',
|
||||||
'remaining_material_input',
|
'remaining_material_input',
|
||||||
'remaining_material_cm_formatted',
|
|
||||||
'remaining_material_cm_input',
|
|
||||||
'unit_abbreviation',
|
'unit_abbreviation',
|
||||||
'uses_length_unit',
|
|
||||||
])]
|
])]
|
||||||
class CuttingMaterial extends Model
|
class CuttingMaterial extends Model
|
||||||
{
|
{
|
||||||
@ -86,63 +81,6 @@ public function unitAbbreviation(): Attribute
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function usesLengthUnit(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn () => $this->rawMaterialPrice?->rawMaterial?->unit?->usesLengthUnit() ?? false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function materialUsageCmFormatted(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn () => $this->formatCmQuantity($this->material_usage),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function materialUsageCmInput(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn () => $this->formatCmQuantityInput($this->material_usage),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remainingMaterialCmFormatted(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn () => $this->formatCmQuantity($this->remaining_material),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remainingMaterialCmInput(): Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
get: fn () => $this->formatCmQuantityInput($this->remaining_material),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function materialUsageInCm(): ?float
|
|
||||||
{
|
|
||||||
$unit = $this->rawMaterialPrice?->rawMaterial?->unit;
|
|
||||||
|
|
||||||
if ($unit === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unit->toCm((float) $this->material_usage);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function remainingMaterialInCm(): ?float
|
|
||||||
{
|
|
||||||
$unit = $this->rawMaterialPrice?->rawMaterial?->unit;
|
|
||||||
|
|
||||||
if ($unit === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $unit->toCm((float) $this->remaining_material);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function materialCost(): int
|
public function materialCost(): int
|
||||||
{
|
{
|
||||||
$price = $this->rawMaterialPrice;
|
$price = $this->rawMaterialPrice;
|
||||||
@ -154,50 +92,6 @@ public function materialCost(): int
|
|||||||
return (int) round((float) $this->material_usage * (int) $price->price);
|
return (int) round((float) $this->material_usage * (int) $price->price);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function formatCmQuantity(float|string|null $value): ?string
|
|
||||||
{
|
|
||||||
$unit = $this->rawMaterialPrice?->rawMaterial?->unit;
|
|
||||||
|
|
||||||
if ($unit === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $unit->usesLengthUnit()) {
|
|
||||||
return $this->formatQuantity($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cm = $unit->toCm((float) $value);
|
|
||||||
|
|
||||||
if ($cm === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$formatted = rtrim(rtrim(number_format($cm, 4, ',', '.'), '0'), ',');
|
|
||||||
|
|
||||||
return "{$formatted} cm";
|
|
||||||
}
|
|
||||||
|
|
||||||
private function formatCmQuantityInput(float|string|null $value): ?string
|
|
||||||
{
|
|
||||||
$unit = $this->rawMaterialPrice?->rawMaterial?->unit;
|
|
||||||
|
|
||||||
if ($unit === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $unit->usesLengthUnit()) {
|
|
||||||
return $this->formatQuantityInput($value);
|
|
||||||
}
|
|
||||||
|
|
||||||
$cm = $unit->toCm((float) $value);
|
|
||||||
|
|
||||||
if ($cm === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rtrim(rtrim(number_format($cm, 4, '.', ''), '0'), '.');
|
|
||||||
}
|
|
||||||
|
|
||||||
private function formatQuantity(float|string|null $value): string
|
private function formatQuantity(float|string|null $value): string
|
||||||
{
|
{
|
||||||
$formatted = rtrim(rtrim(number_format((float) $value, 4, ',', '.'), '0'), ',');
|
$formatted = rtrim(rtrim(number_format((float) $value, 4, ',', '.'), '0'), ',');
|
||||||
|
|||||||
@ -281,17 +281,8 @@ public function syncDraftMaterial(array $validated, User $user): array
|
|||||||
->with('rawMaterial')
|
->with('rawMaterial')
|
||||||
->findOrFail($validated['raw_material_price_id']);
|
->findOrFail($validated['raw_material_price_id']);
|
||||||
|
|
||||||
$unit = $price->rawMaterial?->unit;
|
$materialUsage = round((float) $validated['material_usage'], 2);
|
||||||
$usageInput = round((float) $validated['material_usage'], 2);
|
$remainingMaterial = round((float) $validated['remaining_material'], 2);
|
||||||
$remainingInput = round((float) $validated['remaining_material'], 2);
|
|
||||||
|
|
||||||
if ($unit !== null && $unit->usesLengthUnit()) {
|
|
||||||
$materialUsage = round($unit->fromCm($usageInput), 2);
|
|
||||||
$remainingMaterial = round($unit->fromCm($remainingInput), 2);
|
|
||||||
} else {
|
|
||||||
$materialUsage = $usageInput;
|
|
||||||
$remainingMaterial = $remainingInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($materialUsage <= 0) {
|
if ($materialUsage <= 0) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
@ -652,17 +643,8 @@ private function buildMaterials(array $materials): array
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$unit = $price->rawMaterial?->unit;
|
$materialUsage = round((float) $itemData['material_usage'], 2);
|
||||||
$usageInput = round((float) $itemData['material_usage'], 2);
|
$remainingMaterial = round((float) $itemData['remaining_material'], 2);
|
||||||
$remainingInput = round((float) $itemData['remaining_material'], 2);
|
|
||||||
|
|
||||||
if ($unit !== null && $unit->usesLengthUnit()) {
|
|
||||||
$materialUsage = round($unit->fromCm($usageInput), 2);
|
|
||||||
$remainingMaterial = round($unit->fromCm($remainingInput), 2);
|
|
||||||
} else {
|
|
||||||
$materialUsage = $usageInput;
|
|
||||||
$remainingMaterial = $remainingInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($materialUsage <= 0) {
|
if ($materialUsage <= 0) {
|
||||||
throw ValidationException::withMessages([
|
throw ValidationException::withMessages([
|
||||||
@ -890,31 +872,16 @@ private function presentDraftMaterial(CuttingMaterial $item): array
|
|||||||
{
|
{
|
||||||
$price = $item->rawMaterialPrice;
|
$price = $item->rawMaterialPrice;
|
||||||
$rawMaterial = $price?->rawMaterial;
|
$rawMaterial = $price?->rawMaterial;
|
||||||
$unit = $rawMaterial?->unit;
|
|
||||||
|
|
||||||
$usesLengthUnit = $unit?->usesLengthUnit() ?? false;
|
|
||||||
|
|
||||||
// Convert stored native unit back to cm for display
|
|
||||||
if ($usesLengthUnit && $unit !== null) {
|
|
||||||
$materialUsageCm = round($unit->toCm((float) $item->material_usage), 2);
|
|
||||||
$remainingMaterialCm = round($unit->toCm((float) $item->remaining_material), 2);
|
|
||||||
$materialUsageDisplay = rtrim(rtrim(number_format($materialUsageCm, 2, '.', ''), '0'), '.');
|
|
||||||
$remainingMaterialDisplay = rtrim(rtrim(number_format($remainingMaterialCm, 2, '.', ''), '0'), '.');
|
|
||||||
} else {
|
|
||||||
$materialUsageDisplay = $this->formatQuantityInput((float) $item->material_usage);
|
|
||||||
$remainingMaterialDisplay = $this->formatQuantityInput((float) $item->remaining_material);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'raw_material_price_id' => $item->raw_material_price_id,
|
'raw_material_price_id' => $item->raw_material_price_id,
|
||||||
'raw_material_name' => $rawMaterial?->name ?? '',
|
'raw_material_name' => $rawMaterial?->name ?? '',
|
||||||
'variant' => $price?->variant ?? '',
|
'variant' => $price?->variant ?? '',
|
||||||
'unit' => $rawMaterial?->unit?->value ?? '',
|
'unit' => $rawMaterial?->unit?->value ?? '',
|
||||||
'uses_length_unit' => $usesLengthUnit,
|
|
||||||
'unit_abbreviation' => $rawMaterial?->unit?->abbreviation() ?? '',
|
'unit_abbreviation' => $rawMaterial?->unit?->abbreviation() ?? '',
|
||||||
'stock_input' => $price?->stock_input ?? '',
|
'stock_input' => $price?->stock_input ?? '',
|
||||||
'material_usage' => $materialUsageDisplay,
|
'material_usage' => $this->formatQuantityInput((float) $item->material_usage),
|
||||||
'remaining_material' => $remainingMaterialDisplay,
|
'remaining_material' => $this->formatQuantityInput((float) $item->remaining_material),
|
||||||
'images' => $price ? MediaPresenter::collection($price, 'images') : [],
|
'images' => $price ? MediaPresenter::collection($price, 'images') : [],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,35 +17,21 @@ const props = defineProps<{
|
|||||||
productCatalog: CuttingProductCatalogItem[];
|
productCatalog: CuttingProductCatalogItem[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
function usesLengthUnit(unit?: string): boolean {
|
|
||||||
return unit === 'yard' || unit === 'meter';
|
|
||||||
}
|
|
||||||
|
|
||||||
const initialData = computed(() => ({
|
const initialData = computed(() => ({
|
||||||
description: props.cutting.description ?? '',
|
description: props.cutting.description ?? '',
|
||||||
sewing_cost: String(props.cutting.sewing_cost ?? 0),
|
sewing_cost: String(props.cutting.sewing_cost ?? 0),
|
||||||
other_cost: String(props.cutting.other_cost ?? 0),
|
other_cost: String(props.cutting.other_cost ?? 0),
|
||||||
materials: props.cutting.materials.map((item) => {
|
materials: props.cutting.materials.map((item) => ({
|
||||||
const unit = item.raw_material_price?.raw_material?.unit ?? 'kilogram';
|
raw_material_price_id: item.raw_material_price_id,
|
||||||
const usesCm = usesLengthUnit(unit);
|
raw_material_name: item.raw_material_price?.raw_material?.name ?? '',
|
||||||
|
variant: item.raw_material_price?.variant ?? '',
|
||||||
return {
|
unit: item.raw_material_price?.raw_material?.unit ?? 'kilogram',
|
||||||
raw_material_price_id: item.raw_material_price_id,
|
unit_abbreviation: item.raw_material_price?.raw_material?.unit_abbreviation ?? '',
|
||||||
raw_material_name: item.raw_material_price?.raw_material?.name ?? '',
|
stock_input: item.raw_material_price?.stock_input ?? '',
|
||||||
variant: item.raw_material_price?.variant ?? '',
|
material_usage: item.material_usage_input,
|
||||||
unit,
|
remaining_material: item.remaining_material_input,
|
||||||
uses_length_unit: usesCm,
|
images: item.raw_material_price?.images ?? [],
|
||||||
unit_abbreviation: item.raw_material_price?.raw_material?.unit_abbreviation ?? '',
|
})),
|
||||||
stock_input: item.raw_material_price?.stock_input ?? '',
|
|
||||||
material_usage: usesCm
|
|
||||||
? (item.material_usage_cm_input ?? item.material_usage_input)
|
|
||||||
: item.material_usage_input,
|
|
||||||
remaining_material: usesCm
|
|
||||||
? (item.remaining_material_cm_input ?? item.remaining_material_input)
|
|
||||||
: item.remaining_material_input,
|
|
||||||
images: item.raw_material_price?.images ?? [],
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
results: props.cutting.results.map((item) => ({
|
results: props.cutting.results.map((item) => ({
|
||||||
product_variant_id: item.product_variant_id,
|
product_variant_id: item.product_variant_id,
|
||||||
product_name: item.product_variant?.product?.name ?? '',
|
product_name: item.product_variant?.product?.name ?? '',
|
||||||
|
|||||||
@ -45,10 +45,6 @@ import type {
|
|||||||
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
import PosCatalogCard from '../../shared/PosCatalogCard.vue';
|
||||||
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
import PosCatalogVariantThumb from '../../shared/PosCatalogVariantThumb.vue';
|
||||||
|
|
||||||
function usesLengthUnit(unit: string): boolean {
|
|
||||||
return unit === 'yard' || unit === 'meter';
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
rawMaterialCatalog: CuttingRawMaterialCatalogItem[];
|
||||||
productCatalog: CuttingProductCatalogItem[];
|
productCatalog: CuttingProductCatalogItem[];
|
||||||
@ -81,9 +77,6 @@ const form = useForm({
|
|||||||
other_cost: '0',
|
other_cost: '0',
|
||||||
});
|
});
|
||||||
|
|
||||||
const CM_PER_YARD = 91.44;
|
|
||||||
const CM_PER_METER = 100;
|
|
||||||
|
|
||||||
function findCatalogPrice(priceId: number) {
|
function findCatalogPrice(priceId: number) {
|
||||||
for (const rawMaterial of props.rawMaterialCatalog) {
|
for (const rawMaterial of props.rawMaterialCatalog) {
|
||||||
const price = rawMaterial.prices.find((item) => item.id === priceId);
|
const price = rawMaterial.prices.find((item) => item.id === priceId);
|
||||||
@ -99,18 +92,6 @@ function findCatalogPrice(priceId: number) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function usageInNativeUnit(usageInput: number, unit: string): number {
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return usageInput / CM_PER_YARD;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return usageInput / CM_PER_METER;
|
|
||||||
}
|
|
||||||
|
|
||||||
return usageInput;
|
|
||||||
}
|
|
||||||
|
|
||||||
const totalMaterialCost = computed(() =>
|
const totalMaterialCost = computed(() =>
|
||||||
materialCart.value.reduce((sum, item) => {
|
materialCart.value.reduce((sum, item) => {
|
||||||
const catalogPrice = findCatalogPrice(item.raw_material_price_id);
|
const catalogPrice = findCatalogPrice(item.raw_material_price_id);
|
||||||
@ -119,10 +100,7 @@ const totalMaterialCost = computed(() =>
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usage = usageInNativeUnit(
|
const usage = Number(item.material_usage) || 0;
|
||||||
Number(item.material_usage) || 0,
|
|
||||||
catalogPrice.unit,
|
|
||||||
);
|
|
||||||
|
|
||||||
return sum + Math.round(usage * catalogPrice.price);
|
return sum + Math.round(usage * catalogPrice.price);
|
||||||
}, 0),
|
}, 0),
|
||||||
@ -142,10 +120,7 @@ function materialLineCost(item: CuttingMaterialCartItem): number {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const usage = usageInNativeUnit(
|
const usage = Number(item.material_usage) || 0;
|
||||||
Number(item.material_usage) || 0,
|
|
||||||
catalogPrice.unit,
|
|
||||||
);
|
|
||||||
|
|
||||||
return Math.round(usage * catalogPrice.price);
|
return Math.round(usage * catalogPrice.price);
|
||||||
}
|
}
|
||||||
@ -382,7 +357,6 @@ async function addMaterial(
|
|||||||
raw_material_name: rawMaterial.name,
|
raw_material_name: rawMaterial.name,
|
||||||
variant: price.variant,
|
variant: price.variant,
|
||||||
unit: rawMaterial.unit,
|
unit: rawMaterial.unit,
|
||||||
uses_length_unit: usesLengthUnit(rawMaterial.unit),
|
|
||||||
unit_abbreviation: rawMaterial.unit_abbreviation,
|
unit_abbreviation: rawMaterial.unit_abbreviation,
|
||||||
stock_input: price.stock_input,
|
stock_input: price.stock_input,
|
||||||
material_usage: defaultUsage,
|
material_usage: defaultUsage,
|
||||||
@ -1006,7 +980,7 @@ function submit() {
|
|||||||
<div class="grid grid-cols-2 gap-2">
|
<div class="grid grid-cols-2 gap-2">
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel class="text-xs">
|
<FieldLabel class="text-xs">
|
||||||
Pemakaian ({{ item.uses_length_unit ? 'cm' : item.unit_abbreviation }})
|
Pemakaian ({{ item.unit_abbreviation }})
|
||||||
</FieldLabel>
|
</FieldLabel>
|
||||||
<DecimalInput
|
<DecimalInput
|
||||||
v-model="
|
v-model="
|
||||||
@ -1022,7 +996,7 @@ function submit() {
|
|||||||
</Field>
|
</Field>
|
||||||
<Field>
|
<Field>
|
||||||
<FieldLabel class="text-xs">
|
<FieldLabel class="text-xs">
|
||||||
Sisa ({{ item.uses_length_unit ? 'cm' : item.unit_abbreviation }})
|
Sisa ({{ item.unit_abbreviation }})
|
||||||
</FieldLabel>
|
</FieldLabel>
|
||||||
<DecimalInput
|
<DecimalInput
|
||||||
v-model="
|
v-model="
|
||||||
@ -1253,11 +1227,11 @@ function submit() {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<span class="shrink-0 text-xs font-medium tabular-nums">
|
<span class="shrink-0 text-xs font-medium tabular-nums">
|
||||||
{{ item.material_usage }} {{ item.uses_length_unit ? 'cm' : item.unit_abbreviation }}
|
{{ item.material_usage }} {{ item.unit_abbreviation }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1.5 flex items-center justify-between gap-2 text-xs text-muted-foreground">
|
<div class="mt-1.5 flex items-center justify-between gap-2 text-xs text-muted-foreground">
|
||||||
<span>Sisa: {{ item.remaining_material }} {{ item.uses_length_unit ? 'cm' : item.unit_abbreviation }}</span>
|
<span>Sisa: {{ item.remaining_material }} {{ item.unit_abbreviation }}</span>
|
||||||
<span class="font-medium text-foreground">{{ formatRupiah(materialLineCost(item)) }}</span>
|
<span class="font-medium text-foreground">{{ formatRupiah(materialLineCost(item)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -12,59 +12,23 @@ import {
|
|||||||
} from '@/components/ui/empty';
|
} from '@/components/ui/empty';
|
||||||
import type { CuttingListItem } from '@/types/cutting';
|
import type { CuttingListItem } from '@/types/cutting';
|
||||||
|
|
||||||
const CM_PER_YARD = 91.44;
|
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
|
||||||
const CM_PER_METER = 100;
|
if (!totalUsage) {
|
||||||
|
|
||||||
function formatTotalMaterialUsage(totalUsage: number | null | undefined, materials: any[]): string {
|
|
||||||
if (!totalUsage || !materials.length) {
|
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return (totalUsage * CM_PER_YARD).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return (totalUsage * CM_PER_METER).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalUsage.toFixed(2);
|
return totalUsage.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTotalMaterialUsageUnit(materials: any[]): string {
|
function getTotalMaterialUsageUnit(materials: any[]): string {
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard' || unit === 'meter') {
|
|
||||||
return 'cm';
|
|
||||||
}
|
|
||||||
|
|
||||||
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatMaterialUsage(mat: any): string {
|
function formatMaterialUsage(mat: any): string {
|
||||||
const usage = mat.material_usage ?? 0;
|
return (mat.material_usage ?? 0).toFixed(2);
|
||||||
const unit = mat.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return (usage * CM_PER_YARD).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return (usage * CM_PER_METER).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage.toFixed(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMaterialUnit(mat: any): string {
|
function getMaterialUnit(mat: any): string {
|
||||||
const unit = mat.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard' || unit === 'meter') {
|
|
||||||
return 'cm';
|
|
||||||
}
|
|
||||||
|
|
||||||
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +107,7 @@ const totalCompleted = computed(() => props.cuttings.length);
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between text-[11px]">
|
<div class="flex items-center justify-between text-[11px]">
|
||||||
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
|
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
|
||||||
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage, cutting.materials) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
|
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -137,34 +137,15 @@ function getMaterialUnit(materials: any[]): string | undefined {
|
|||||||
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation;
|
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CM_PER_YARD = 91.44;
|
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
|
||||||
const CM_PER_METER = 100;
|
if (!totalUsage) {
|
||||||
|
|
||||||
function formatTotalMaterialUsage(totalUsage: number | null | undefined, materials: any[]): string {
|
|
||||||
if (!totalUsage || !materials.length) {
|
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return (totalUsage * CM_PER_YARD).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return (totalUsage * CM_PER_METER).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalUsage.toFixed(2);
|
return totalUsage.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTotalMaterialUsageUnit(materials: any[]): string {
|
function getTotalMaterialUsageUnit(materials: any[]): string {
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard' || unit === 'meter') {
|
|
||||||
return 'cm';
|
|
||||||
}
|
|
||||||
|
|
||||||
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,7 +186,7 @@ function getTotalMaterialUsageUnit(materials: any[]): string {
|
|||||||
<span>Total Hasil Cutting <strong class="text-primary">{{ cutting.total_result_pieces ??
|
<span>Total Hasil Cutting <strong class="text-primary">{{ cutting.total_result_pieces ??
|
||||||
0 }} pcs</strong></span>
|
0 }} pcs</strong></span>
|
||||||
<span>Total Pemakaian Bahan <strong class="text-primary">{{
|
<span>Total Pemakaian Bahan <strong class="text-primary">{{
|
||||||
formatTotalMaterialUsage(cutting.total_material_usage, cutting.materials) }}
|
formatTotalMaterialUsage(cutting.total_material_usage) }}
|
||||||
{{ getTotalMaterialUsageUnit(cutting.materials) }}</strong></span>
|
{{ getTotalMaterialUsageUnit(cutting.materials) }}</strong></span>
|
||||||
<span>Biaya Bahan <strong class="text-primary">{{
|
<span>Biaya Bahan <strong class="text-primary">{{
|
||||||
cutting.total_material_cost_formatted ?? 'Rp 0' }}</strong></span>
|
cutting.total_material_cost_formatted ?? 'Rp 0' }}</strong></span>
|
||||||
@ -253,15 +234,9 @@ function getTotalMaterialUsageUnit(materials: any[]): string {
|
|||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell class="tabular-nums">
|
<TableCell class="tabular-nums">
|
||||||
{{ material.material_usage_formatted }}
|
{{ material.material_usage_formatted }}
|
||||||
<span v-if="material.uses_length_unit" class="text-muted-foreground">
|
|
||||||
({{ material.material_usage_cm_formatted }})
|
|
||||||
</span>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
<TableCell class="tabular-nums">
|
<TableCell class="tabular-nums">
|
||||||
{{ material.remaining_material_formatted }}
|
{{ material.remaining_material_formatted }}
|
||||||
<span v-if="material.uses_length_unit" class="text-muted-foreground">
|
|
||||||
({{ material.remaining_material_cm_formatted }})
|
|
||||||
</span>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -3,59 +3,23 @@ import { Card } from '@/components/ui/card';
|
|||||||
import type { CuttingListItem } from '@/types/cutting';
|
import type { CuttingListItem } from '@/types/cutting';
|
||||||
import DataTableActions from './data-table-actions.vue';
|
import DataTableActions from './data-table-actions.vue';
|
||||||
|
|
||||||
const CM_PER_YARD = 91.44;
|
function formatTotalMaterialUsage(totalUsage: number | null | undefined): string {
|
||||||
const CM_PER_METER = 100;
|
if (!totalUsage) {
|
||||||
|
|
||||||
function formatTotalMaterialUsage(totalUsage: number | null | undefined, materials: any[]): string {
|
|
||||||
if (!totalUsage || !materials.length) {
|
|
||||||
return '0';
|
return '0';
|
||||||
}
|
}
|
||||||
|
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return (totalUsage * CM_PER_YARD).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return (totalUsage * CM_PER_METER).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return totalUsage.toFixed(2);
|
return totalUsage.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTotalMaterialUsageUnit(materials: any[]): string {
|
function getTotalMaterialUsageUnit(materials: any[]): string {
|
||||||
const unit = materials[0]?.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard' || unit === 'meter') {
|
|
||||||
return 'cm';
|
|
||||||
}
|
|
||||||
|
|
||||||
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
return materials[0]?.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatMaterialUsage(mat: any): string {
|
function formatMaterialUsage(mat: any): string {
|
||||||
const usage = mat.material_usage ?? 0;
|
return (mat.material_usage ?? 0).toFixed(2);
|
||||||
const unit = mat.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard') {
|
|
||||||
return (usage * CM_PER_YARD).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (unit === 'meter') {
|
|
||||||
return (usage * CM_PER_METER).toFixed(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
return usage.toFixed(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getMaterialUnit(mat: any): string {
|
function getMaterialUnit(mat: any): string {
|
||||||
const unit = mat.raw_material_price?.raw_material?.unit;
|
|
||||||
|
|
||||||
if (unit === 'yard' || unit === 'meter') {
|
|
||||||
return 'cm';
|
|
||||||
}
|
|
||||||
|
|
||||||
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
return mat.raw_material_price?.raw_material?.unit_abbreviation ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -118,7 +82,7 @@ defineProps<{
|
|||||||
</div>
|
</div>
|
||||||
<div class="flex items-center justify-between text-[11px]">
|
<div class="flex items-center justify-between text-[11px]">
|
||||||
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
|
<span class="text-muted-foreground">Total Pemakaian Bahan:</span>
|
||||||
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage, cutting.materials) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
|
<span class="font-semibold tabular-nums">{{ formatTotalMaterialUsage(cutting.total_material_usage) }} {{ getTotalMaterialUsageUnit(cutting.materials) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@ -14,9 +14,6 @@ export type CuttingMaterialListItem = {
|
|||||||
id: number;
|
id: number;
|
||||||
material_usage_formatted: string;
|
material_usage_formatted: string;
|
||||||
remaining_material_formatted: string;
|
remaining_material_formatted: string;
|
||||||
uses_length_unit?: boolean;
|
|
||||||
material_usage_cm_formatted?: string;
|
|
||||||
remaining_material_cm_formatted?: string;
|
|
||||||
raw_material_price?: {
|
raw_material_price?: {
|
||||||
id: number;
|
id: number;
|
||||||
variant: string;
|
variant: string;
|
||||||
@ -88,7 +85,6 @@ export type CuttingMaterialCartItem = {
|
|||||||
raw_material_name: string;
|
raw_material_name: string;
|
||||||
variant: string;
|
variant: string;
|
||||||
unit: string;
|
unit: string;
|
||||||
uses_length_unit: boolean;
|
|
||||||
unit_abbreviation: string;
|
unit_abbreviation: string;
|
||||||
stock_input: string;
|
stock_input: string;
|
||||||
material_usage: string;
|
material_usage: string;
|
||||||
@ -117,8 +113,6 @@ export type CuttingEditItem = {
|
|||||||
raw_material_price_id: number;
|
raw_material_price_id: number;
|
||||||
material_usage_input: string;
|
material_usage_input: string;
|
||||||
remaining_material_input: string;
|
remaining_material_input: string;
|
||||||
material_usage_cm_input?: string | null;
|
|
||||||
remaining_material_cm_input?: string | null;
|
|
||||||
raw_material_price?: {
|
raw_material_price?: {
|
||||||
variant: string;
|
variant: string;
|
||||||
stock_input?: string;
|
stock_input?: string;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user