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

485 lines
14 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">
2021-03-21 22:02:25 +00:00
<q-menu v-model="showNewDrink" anchor="center middle" self="center middle">
<new-drink @close="showNewDrink = false" />
</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>
2021-03-22 22:18:22 +00:00
<q-td key="picture" :props="drinks_props" style="width: 128px">
<q-img
:src="`http://localhost/api/pricelist/drinks/${drinks_props.row.id}/picture?size=128`"
/>
<q-popup-edit
v-slot="scope"
v-model="drinkPic"
buttons
label-set="Speichern"
label-cancel="Abbrechen"
@update:modelValue="savePicture(drinks_props.row)"
>
2021-03-24 16:28:41 +00:00
<q-file v-model="scope.value" filled>
<template #prepend>
2021-03-22 22:18:22 +00:00
<q-icon name="attach_file" />
</template>
</q-file>
</q-popup-edit>
</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">
2021-03-22 22:18:22 +00:00
import {
defineComponent,
onBeforeMount,
ComputedRef,
computed,
ref,
getCurrentInstance,
} 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-21 22:02:25 +00:00
import NewDrink from 'src/plugins/pricelist/components/CalculationTable/NewDrink.vue';
2021-03-22 22:18:22 +00:00
import { Notify } from 'quasar';
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 22:02:25 +00:00
components: { MinPriceSetting, DrinkPriceVolumesTable, NewDrink },
setup() {
const mainStore = useMainStore();
const store = usePricelistStore();
2021-03-22 22:18:22 +00:00
const root = getCurrentInstance()?.proxy;
onBeforeMount(() => {
store.getPriceCalcColumn(user);
});
const user = mainStore.currentUser.userid;
2021-03-14 19:37:41 +00:00
const columns = [
2021-03-22 22:18:22 +00:00
{
name: 'picture',
label: 'Bild',
},
2021-03-14 19:37:41 +00:00
{
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 drinkTypes = computed(() => store.drinkTypes);
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
}
2021-03-21 22:02:25 +00:00
const showNewDrink = ref(false);
2021-03-22 22:18:22 +00:00
const drinkPic = ref<File>();
function onPictureRejected() {
Notify.create({
group: false,
type: 'negative',
message: 'Datei zu groß oder keine gültige Bilddatei.',
timeout: 10000,
progress: true,
actions: [{ icon: 'mdi-close', color: 'white' }],
});
drinkPic.value = undefined;
}
function savePicture(drink: Drink) {
console.log('hier bin ich!!!', drinkPic.value);
if (drinkPic.value && drinkPic.value instanceof File)
store
.upload_drink_picture(drink, drinkPic.value)
.then(() => {
root?.$forceUpdate();
})
.catch((response: Response) => {
if (response && response.status == 400) {
onPictureRejected();
}
});
}
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,
drinkTypes,
updateDrink,
deleteDrink,
2021-03-21 22:02:25 +00:00
showNewDrink,
2021-03-22 22:18:22 +00:00
drinkPic,
savePicture,
console,
};
},
2021-03-14 19:37:41 +00:00
});
</script>
<style scoped></style>