flaschengeist-frontend/src/plugins/pricelist/components/CalculationTable.vue

523 lines
15 KiB
Vue
Raw Normal View History

2021-03-14 19:37:41 +00:00
<template>
<q-table
v-model:pagination="pagination"
title="Kalkulationstabelle"
:columns="columns"
:rows="drinks"
:visible-columns="visibleColumn"
:dense="$q.screen.lt.md"
row-key="id"
virtual-scroll
:rows-per-page-options="[0]"
>
<template #header="props">
<q-tr :props="props">
<q-th auto-width />
<q-th v-for="col in props.cols" :key="col.name" :props="props">
{{ col.label }}
</q-th>
</q-tr>
</template>
<template #top-right>
<div class="row justify-end q-gutter-sm">
2021-03-21 21:07:12 +00:00
<q-btn label="Aufpreise">
<q-menu anchor="center middle" self="center middle">
<min-price-setting />
</q-menu>
</q-btn>
<q-btn label="neues Getränk" color="positive" icon-right="add">
<q-menu anchor="center middle" self="center middle">
<div class="q-pa-sm">
<div class="q-table__title q-pa-sm">Neues Getränk</div>
<div class="row">
<q-input
v-model="newDrink.name"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Getränkname"
/>
<q-input
v-model="newDrink.article_id"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Artikelnummer"
/>
<q-select
v-model="newDrink.type"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Kategorie"
:options="drinkTypes"
option-label="name"
/>
<q-input
v-model.number="newDrink.volume"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Inhalt in L/Gebinde"
type="number"
/>
<q-input
v-model.number="newDrink.package_size"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Gebindegröße"
type="number"
/>
<q-input
v-model.number="newDrink.cost_price_package_netto"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Preis Netto/Gebinde"
type="number"
/>
<q-input
v-model="cost_price_pro_volume"
class="col-sm-4 col-xs-6 q-pa-sm"
filled
label="Preis mit 19%/Liter"
:disable="calc_price_pro_volume"
/>
</div>
<div class="row justify-between">
<q-btn v-close-popup label="Abbrechen" @click="cancelAddDrink" />
<q-btn v-close-popup label="Speichern" color="primary" @click="addDrink" />
</div>
</div>
</q-menu>
</q-btn>
2021-03-14 19:37:41 +00:00
<q-select
v-model="visibleColumn"
multiple
filled
dense
options-dense
display-value="Sichtbarkeit"
emit-value
map-options
:options="[...columns, ...column_calc, ...column_prices]"
option-value="name"
options-cover
/>
</div>
</template>
<template #body="drinks_props">
<q-tr :props="drinks_props">
<q-td auto-width>
<q-btn
v-if="drinks_props.row.volumes.length === 0"
size="xs"
color="negative"
round
dense
icon="mdi-delete"
class="q-mx-sm"
@click="deleteDrink(drinks_props.row)"
/>
</q-td>
<q-td key="name" :props="drinks_props">
{{ drinks_props.row.name }}
<q-popup-edit
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.name"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
2021-03-21 21:07:12 +00:00
<q-input
v-model="scope.value"
filled
dense
autofocus
clearable
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="drink_type" :props="drinks_props">
{{ drinks_props.row.type.name }}
<q-popup-edit
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.type"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
<q-select
2021-03-21 21:07:12 +00:00
v-model="scope.value"
:options="drinkTypes"
option-label="name"
filled
dense
autofocus
2021-03-21 21:07:12 +00:00
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="article_id" :props="drinks_props">
{{ drinks_props.row.article_id || 'o.A.' }}
<q-popup-edit
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.article_id"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
2021-03-21 21:07:12 +00:00
<q-input
v-model="scope.value"
filled
dense
autofocus
clearable
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="volume_package" :props="drinks_props">
{{ drinks_props.row.volume ? `${drinks_props.row.volume} L` : 'o.A.' }}
<q-popup-edit
v-if="
!drinks_props.row.volumes.some((volume) =>
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
)
"
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model.number="drinks_props.row.volume"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
<q-input
2021-03-21 21:07:12 +00:00
v-model.number="scope.value"
filled
dense
autofocus
type="number"
clearable
step="0.01"
min="0"
suffix="L"
2021-03-21 21:07:12 +00:00
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="package_size" :props="drinks_props">
{{ drinks_props.row.package_size || 'o.A.' }}
<q-popup-edit
v-if="
!drinks_props.row.volumes.some((volume) =>
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
)
"
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.package_size"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
<q-input
2021-03-21 21:07:12 +00:00
v-model.number="scope.value"
filled
dense
autofocus
type="number"
min="0"
2021-03-21 21:07:12 +00:00
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="cost_price_package_netto" :props="drinks_props">
{{
drinks_props.row.cost_price_package_netto
2021-03-21 21:07:12 +00:00
? `${drinks_props.row.cost_price_package_netto.toFixed(2)}`
: 'o.A.'
}}
<q-popup-edit
v-if="
!drinks_props.row.volumes.some((volume) =>
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
)
"
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.cost_price_package_netto"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
<q-input
2021-03-21 21:07:12 +00:00
v-model.number="scope.value"
filled
dense
autofocus
type="number"
step="0.01"
min="0"
suffix="€"
2021-03-21 21:07:12 +00:00
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="cost_price_pro_volume" :props="drinks_props">
{{
drinks_props.row.cost_price_pro_volume
? `${drinks_props.row.cost_price_pro_volume.toFixed(3)}`
: 'o.A.'
}}
<q-popup-edit
v-if="
!(
!!drinks_props.row.cost_price_package_netto &&
!!drinks_props.row.volume &&
!!drinks_props.row.package_size
) &&
!drinks_props.row.volumes.some((volume) =>
volume.ingredients.some((ingredient) => ingredient.drink_ingredient)
)
"
2021-03-21 21:07:12 +00:00
v-slot="scope"
v-model="drinks_props.row.cost_price_pro_volume"
buttons
label-cancel="Abbrechen"
label-set="Speichern"
2021-03-21 21:07:12 +00:00
@update:modelValue="updateDrink(drinks_props.row)"
>
<q-input
2021-03-21 21:07:12 +00:00
v-model.number="scope.value"
filled
dense
autofocus
type="number"
min="0"
step="0.1"
suffix="€"
2021-03-21 21:07:12 +00:00
@keyup.enter="scope.set"
/>
</q-popup-edit>
</q-td>
<q-td key="volumes" :props="drinks_props">
2021-03-21 21:07:12 +00:00
<drink-price-volumes-table
:rows="drinks_props.row.volumes"
:visible-columns="visibleColumn"
:columns="column_calc"
:drink="drinks_props.row"
@updateDrink="updateDrink(drinks_props.row)"
/>
</q-td>
</q-tr>
</template>
</q-table>
2021-03-14 19:37:41 +00:00
</template>
<script lang="ts">
import { defineComponent, onBeforeMount, ref, ComputedRef, computed } from 'vue';
import DrinkPriceVolumesTable from 'src/plugins/pricelist/components/CalculationTable/DrinkPriceVolumesTable.vue';
2021-03-21 21:07:12 +00:00
import { useMainStore } from 'src/store';
import { Drink, usePricelistStore } from 'src/plugins/pricelist/store';
2021-03-21 21:07:12 +00:00
import MinPriceSetting from 'src/plugins/pricelist/components/MinPriceSetting.vue';
2021-03-18 20:10:54 +00:00
function sort(a: string | number, b: string | number) {
if (a > b) return 1;
if (b > a) return -1;
return 0;
}
2021-03-14 19:37:41 +00:00
export default defineComponent({
name: 'CalculationTable',
2021-03-21 21:07:12 +00:00
components: { MinPriceSetting, DrinkPriceVolumesTable },
setup() {
const mainStore = useMainStore();
const store = usePricelistStore();
onBeforeMount(() => {
store.getPriceCalcColumn(user);
});
const user = mainStore.currentUser.userid;
2021-03-14 19:37:41 +00:00
const columns = [
{
name: 'name',
label: 'Getränkename',
field: 'name',
2021-03-18 20:10:54 +00:00
sortable: true,
sort,
2021-03-14 19:37:41 +00:00
},
{
name: 'article_id',
label: 'Artikelnummer',
field: 'article_id',
2021-03-18 20:10:54 +00:00
sortable: true,
sort,
2021-03-14 19:37:41 +00:00
},
{
name: 'drink_type',
2021-03-14 19:37:41 +00:00
label: 'Kategorie',
field: 'type',
format: (val: FG.DrinkType) => `${val.name}`,
2021-03-18 20:10:54 +00:00
sortable: true,
sort: (a: FG.DrinkType, b: FG.DrinkType) => sort(a.name, b.name),
2021-03-14 19:37:41 +00:00
},
{
name: 'volume_package',
label: 'Inhalt in l des Gebinde',
field: 'volume',
2021-03-18 20:10:54 +00:00
sortable: true,
sort,
2021-03-14 19:37:41 +00:00
},
{
name: 'package_size',
label: 'Gebindegröße',
field: 'package_size',
2021-03-18 20:10:54 +00:00
sortable: true,
sort,
2021-03-14 19:37:41 +00:00
},
{
name: 'cost_price_package_netto',
label: 'Preis Netto/Gebinde',
field: 'cost_price_package_netto',
format: (val: number | null) => (val ? `${val.toFixed(3)}` : ''),
2021-03-18 20:10:54 +00:00
sortable: true,
sort,
2021-03-14 19:37:41 +00:00
},
{
name: 'cost_price_pro_volume',
label: 'Preis mit 19%/Liter',
field: 'cost_price_pro_volume',
format: (val: number | null) => (val ? `${val.toFixed(3)}` : ''),
2021-03-18 20:10:54 +00:00
sortable: true,
sort: (a: ComputedRef, b: ComputedRef) => sort(a.value, b.value),
2021-03-14 19:37:41 +00:00
},
{
name: 'volumes',
2021-03-14 19:37:41 +00:00
label: 'Preiskalkulation',
field: 'volumes',
},
2021-03-14 19:37:41 +00:00
];
const column_calc = [
{
name: 'volume',
label: 'Abgabe in l',
field: 'volume',
},
{
name: 'min_prices',
label: 'Minimal Preise',
field: 'min_prices',
2021-03-14 19:37:41 +00:00
},
{
name: 'prices',
label: 'Preise',
field: 'prices',
},
2021-03-14 19:37:41 +00:00
];
const column_prices = [
{
name: 'price',
label: 'Preis',
field: 'price',
format: (val: number) => `${val.toFixed(2)}`,
2021-03-14 19:37:41 +00:00
},
{
name: 'description',
label: 'Beschreibung',
field: 'description',
2021-03-14 19:37:41 +00:00
},
{
name: 'public',
label: 'Öffentlich',
field: 'public',
},
];
const visibleColumn = computed({
get: () => store.pricecalc_columns,
set: (val) => {
store.updatePriceCalcColumn(user, val);
},
});
2021-03-14 19:37:41 +00:00
// eslint-disable-next-line vue/return-in-computed-property
const pagination = computed(() => {
rowsPerPage: store.drinks.length;
});
const emptyDrink: FG.Drink = {
id: -1,
article_id: undefined,
package_size: undefined,
name: '',
volume: undefined,
cost_price_pro_volume: undefined,
cost_price_package_netto: undefined,
tags: [],
type: undefined,
volumes: [],
};
const newDrink = ref<FG.Drink>(emptyDrink);
const calc_price_pro_volume = computed(
() =>
!!newDrink.value.cost_price_package_netto &&
!!newDrink.value.volume &&
!!newDrink.value.package_size
);
const cost_price_pro_volume = computed({
get: () => {
if (calc_price_pro_volume.value) {
const retVal =
((newDrink.value.cost_price_package_netto || 0) /
((newDrink.value.volume || 0) * (newDrink.value.package_size || 0))) *
1.19;
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
newDrink.value.cost_price_pro_volume = Math.round(retVal * 1000) / 1000;
}
return newDrink.value.cost_price_pro_volume;
},
set: (val) => {
newDrink.value.cost_price_pro_volume = val;
},
});
const drinkTypes = computed(() => store.drinkTypes);
function addDrink() {
2021-03-21 21:07:12 +00:00
void store.setDrink(newDrink.value);
cancelAddDrink();
}
function cancelAddDrink() {
setTimeout(() => (newDrink.value = emptyDrink), 200);
}
function updateDrink(drink: Drink) {
2021-03-21 21:07:12 +00:00
void store.updateDrink(drink);
}
function deleteDrink(drink: Drink) {
store.deleteDrink(drink);
2021-03-14 19:37:41 +00:00
}
return {
drinks: computed(() => store.drinks),
pagination,
2021-03-14 19:37:41 +00:00
columns,
column_calc,
column_prices,
visibleColumn,
newDrink,
cost_price_pro_volume,
calc_price_pro_volume,
drinkTypes,
addDrink,
cancelAddDrink,
updateDrink,
deleteDrink,
console,
};
},
2021-03-14 19:37:41 +00:00
});
</script>
<style scoped></style>