138 lines
3.3 KiB
Vue
138 lines
3.3 KiB
Vue
<script setup>
|
|
|
|
import { v4 as uuidv4 } from 'uuid';
|
|
|
|
const props = defineProps({
|
|
item: {
|
|
type: Object,
|
|
required: true
|
|
}
|
|
})
|
|
|
|
const products = ref([])
|
|
const units = ref([])
|
|
|
|
const setup = async () => {
|
|
products.value = await useEntities("products").select()
|
|
units.value = await useEntities("units").selectSpecial()
|
|
}
|
|
|
|
setup()
|
|
|
|
const addProductToMaterialComposition = () => {
|
|
|
|
if(!props.item.materialComposition) props.item.materialComposition = []
|
|
|
|
props.item.materialComposition.push({
|
|
id: uuidv4(),
|
|
unit: 1,
|
|
quantity: 1,
|
|
price: 0,
|
|
})
|
|
calculateTotalMaterialPrice()
|
|
}
|
|
|
|
const removeProductFromMaterialComposition = (id) => {
|
|
props.item.materialComposition = props.item.materialComposition.filter((item) => item.id !== id)
|
|
calculateTotalMaterialPrice()
|
|
}
|
|
|
|
const calculateTotalMaterialPrice = () => {
|
|
let total = 0
|
|
|
|
props.item.materialComposition.forEach((item) => {
|
|
let rowSum = item.quantity * item.price
|
|
total += rowSum
|
|
})
|
|
|
|
props.item.sellingPriceComposed.material = Number(total.toFixed(2))
|
|
props.item.sellingPriceComposed.total = Number((props.item.sellingPriceComposed.worker + props.item.sellingPriceComposed.material).toFixed(2))
|
|
}
|
|
|
|
const setRowData = (row) => {
|
|
let product = products.value.find(i => i.id === row.product)
|
|
|
|
row.unit = product.unit
|
|
row.price = product.selling_price
|
|
|
|
calculateTotalMaterialPrice()
|
|
}
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<UCard class="w-full">
|
|
<UButton
|
|
@click="addProductToMaterialComposition"
|
|
>
|
|
+ Artikel
|
|
</UButton>
|
|
|
|
<table class="w-full mt-3">
|
|
<tr>
|
|
<th>Artikel</th>
|
|
<th>Menge</th>
|
|
<th>Einheit</th>
|
|
<th>Verkaufspreis</th>
|
|
</tr>
|
|
<tr
|
|
v-for="product in props.item.materialComposition"
|
|
>
|
|
<td>
|
|
<USelectMenu
|
|
searchable
|
|
:search-attributes="['name']"
|
|
:options="products"
|
|
value-attribute="id"
|
|
option-attribute="name"
|
|
v-model="product.product"
|
|
:color="product.product ? 'primary' : 'rose'"
|
|
@change="setRowData(product)"
|
|
>
|
|
<template #label>
|
|
{{products.find(i => i.id === product.product) ? products.find(i => i.id === product.product).name : 'Kein Artikel ausgewählt'}}
|
|
</template>
|
|
</USelectMenu>
|
|
</td>
|
|
<td>
|
|
<UInput
|
|
type="number"
|
|
v-model="product.quantity"
|
|
:step="units.find(i => i.id === product.unit) ? units.find(i => i.id === product.unit).step : 1"
|
|
@change="calculateTotalMaterialPrice"
|
|
/>
|
|
</td>
|
|
<td>
|
|
<USelectMenu
|
|
:options="units"
|
|
value-attribute="id"
|
|
option-attribute="name"
|
|
v-model="product.unit"
|
|
></USelectMenu>
|
|
</td>
|
|
<td>
|
|
<UInput
|
|
type="number"
|
|
v-model="product.price"
|
|
step="0.01"
|
|
@change="calculateTotalMaterialPrice"
|
|
/>
|
|
</td>
|
|
<td>
|
|
<UButton
|
|
icon="i-heroicons-x-mark"
|
|
@click="removeProductFromMaterialComposition(product.id)"
|
|
variant="outline"
|
|
color="rose"
|
|
/>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</UCard>
|
|
</template>
|
|
|
|
<style scoped>
|
|
td {
|
|
margin-bottom: 0.5em;
|
|
}
|
|
</style> |