release v2.0.0 #4
|
@ -43,7 +43,7 @@ declare namespace FG {
|
||||||
cost_price_pro_volume?: number;
|
cost_price_pro_volume?: number;
|
||||||
cost_price_package_netto?: number;
|
cost_price_package_netto?: number;
|
||||||
tags: Array<Tag>;
|
tags: Array<Tag>;
|
||||||
type: DrinkType;
|
type?: DrinkType;
|
||||||
volumes: DrinkPriceVolume[];
|
volumes: DrinkPriceVolume[];
|
||||||
}
|
}
|
||||||
interface DrinkIngredient {
|
interface DrinkIngredient {
|
||||||
|
|
|
@ -1,13 +1,88 @@
|
||||||
<template>
|
<template>
|
||||||
<div>
|
|
||||||
<q-table
|
<q-table
|
||||||
title="Kalkulationstabelle"
|
title="Kalkulationstabelle"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
:data="drinks"
|
:data="drinks"
|
||||||
:visible-columns="visibleColumn"
|
:visible-columns="visibleColumn"
|
||||||
:dense="$q.screen.lt.md"
|
:dense="$q.screen.lt.md"
|
||||||
|
row-key="id"
|
||||||
|
virtual-scroll
|
||||||
|
:pagination.sync="pagination"
|
||||||
|
:rows-per-page-options="[0]"
|
||||||
>
|
>
|
||||||
|
<template v-slot: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 v-slot:top-right>
|
<template v-slot:top-right>
|
||||||
|
<div class="row justify-end q-gutter-sm">
|
||||||
|
<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
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Getränkname"
|
||||||
|
v-model="newDrink.name"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Artikelnummer"
|
||||||
|
v-model="newDrink.article_id"
|
||||||
|
/>
|
||||||
|
<q-select
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Kategorie"
|
||||||
|
:options="drinkTypes"
|
||||||
|
option-label="name"
|
||||||
|
v-model="newDrink.type"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Inhalt in L/Gebinde"
|
||||||
|
type="number"
|
||||||
|
v-model.number="newDrink.volume"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Gebindegröße"
|
||||||
|
type="number"
|
||||||
|
v-model.number="newDrink.package_size"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Preis Netto/Gebinde"
|
||||||
|
type="number"
|
||||||
|
v-model.number="newDrink.cost_price_package_netto"
|
||||||
|
/>
|
||||||
|
<q-input
|
||||||
|
class="col-sm-4 col-xs-6 q-pa-sm"
|
||||||
|
filled
|
||||||
|
label="Preis mit 19%/Liter"
|
||||||
|
v-model="cost_price_pro_volume"
|
||||||
|
:disable="calc_price_pro_volume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between">
|
||||||
|
<q-btn label="Abbrechen" v-close-popup @click="cancelAddDrink" />
|
||||||
|
<q-btn label="Speichern" v-close-popup color="primary" @click="addDrink" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-btn>
|
||||||
<q-select
|
<q-select
|
||||||
v-model="visibleColumn"
|
v-model="visibleColumn"
|
||||||
multiple
|
multiple
|
||||||
|
@ -21,6 +96,338 @@
|
||||||
option-value="name"
|
option-value="name"
|
||||||
options-cover
|
options-cover
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-slot:body="drinks_props">
|
||||||
|
<q-tr :props="drinks_props">
|
||||||
|
<q-td auto-width>
|
||||||
|
<q-btn
|
||||||
|
size="xs"
|
||||||
|
color="negative"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="mdi-delete"
|
||||||
|
class="q-mx-sm"
|
||||||
|
v-if="drinks_props.row.volumes.length === 0"
|
||||||
|
@click="deleteDrink(drinks_props.row)"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="name" :props="drinks_props">
|
||||||
|
{{ drinks_props.row.name }}
|
||||||
|
<q-popup-edit
|
||||||
|
v-model="drinks_props.row.name"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input v-model="drinks_props.row.name" filled dense autofocus clearable />
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="drink_type" :props="drinks_props">
|
||||||
|
{{ drinks_props.row.type.name }}
|
||||||
|
<q-popup-edit
|
||||||
|
v-model="drinks_props.row.type"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-select
|
||||||
|
v-model="drinks_props.row.type"
|
||||||
|
:options="drinkTypes"
|
||||||
|
option-label="name"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="article_id" :props="drinks_props">
|
||||||
|
{{ drinks_props.row.article_id || 'o.A.' }}
|
||||||
|
<q-popup-edit
|
||||||
|
v-model="drinks_props.row.article_id"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input v-model="drinks_props.row.article_id" filled dense autofocus clearable />
|
||||||
|
</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)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model.number="drinks_props.row.volume"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
v-model.number="drinks_props.row.volume"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
type="number"
|
||||||
|
clearable
|
||||||
|
step="0.01"
|
||||||
|
min="0"
|
||||||
|
suffix="L"
|
||||||
|
/>
|
||||||
|
</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)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="drinks_props.row.package_size"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
v-model.number="drinks_props.row.package_size"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
/>
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="cost_price_package_netto" :props="drinks_props">
|
||||||
|
{{
|
||||||
|
drinks_props.row.cost_price_package_netto
|
||||||
|
? `${drinks_props.row.cost_price_package_netto}€`
|
||||||
|
: 'o.A.'
|
||||||
|
}}
|
||||||
|
<q-popup-edit
|
||||||
|
v-if="
|
||||||
|
!drinks_props.row.volumes.some(volume =>
|
||||||
|
volume.ingredients.some(ingredient => ingredient.drink_ingredient)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="drinks_props.row.cost_price_package_netto"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
v-model.number="drinks_props.row.cost_price_package_netto"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
min="0"
|
||||||
|
suffix="€"
|
||||||
|
@change="console.log(drinks_props.row)"
|
||||||
|
/>
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="cost_price_pro_volume" :props="drinks_props">
|
||||||
|
{{
|
||||||
|
drinks_props.row.cost_price_pro_volume.value
|
||||||
|
? `${drinks_props.row.cost_price_pro_volume.value.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)
|
||||||
|
)
|
||||||
|
"
|
||||||
|
v-model="drinks_props.row.cost_price_pro_volume.value"
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
@save="updateDrink(drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
v-model.number="drinks_props.row.cost_price_pro_volume.value"
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
autofocus
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
|
suffix="€"
|
||||||
|
/>
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="volumes" :props="drinks_props">
|
||||||
|
<q-table
|
||||||
|
:columns="column_calc"
|
||||||
|
:data="drinks_props.row.volumes"
|
||||||
|
dense
|
||||||
|
:visible-columns="visibleColumn"
|
||||||
|
row-key="id"
|
||||||
|
flat
|
||||||
|
>
|
||||||
|
<template v-slot: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 v-slot:body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td auto-width>
|
||||||
|
<q-btn
|
||||||
|
size="sm"
|
||||||
|
color="accent"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
@click="props.expand = !props.expand"
|
||||||
|
:icon="props.expand ? 'mdi-chevron-up' : 'mdi-chevron-down'"
|
||||||
|
v-if="!drinks_props.row.cost_price_pro_volume.value"
|
||||||
|
/>
|
||||||
|
<q-btn
|
||||||
|
size="xs"
|
||||||
|
color="negative"
|
||||||
|
round
|
||||||
|
dense
|
||||||
|
icon="mdi-delete"
|
||||||
|
class="q-mx-sm"
|
||||||
|
v-if="props.row.ingredients.length === 0 && props.row.prices.length === 0"
|
||||||
|
@click="deleteVolume(props.row, drinks_props.row)"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="volume" :props="props">
|
||||||
|
{{ parseFloat(props.row.volume.value).toFixed(3) }}L
|
||||||
|
<q-popup-edit
|
||||||
|
buttons
|
||||||
|
label-cancel="Abbrechen"
|
||||||
|
label-set="Speichern"
|
||||||
|
v-model="props.row.volume.value"
|
||||||
|
v-if="drinks_props.row.cost_price_pro_volume"
|
||||||
|
@save="updateVolume(props.row, drinks_props.row)"
|
||||||
|
>
|
||||||
|
<q-input
|
||||||
|
dense
|
||||||
|
filled
|
||||||
|
v-model.number="props.row.volume.value"
|
||||||
|
type="number"
|
||||||
|
suffix="L"
|
||||||
|
/>
|
||||||
|
</q-popup-edit>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="min_prices" :props="props">
|
||||||
|
<div
|
||||||
|
v-for="(min_price, index) in props.row.min_prices"
|
||||||
|
:key="`min_prices` + index"
|
||||||
|
class="row justify-between"
|
||||||
|
>
|
||||||
|
<div class="col">
|
||||||
|
<q-badge color="primary">{{ min_price.percentage }}%</q-badge>
|
||||||
|
</div>
|
||||||
|
<div class="col" style="text-align: end">
|
||||||
|
{{ min_price.price.value.toFixed(3) }}€
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="prices" :props="props">
|
||||||
|
<price-table
|
||||||
|
:columns="column_prices"
|
||||||
|
:data="props.row.prices"
|
||||||
|
:row="props.row"
|
||||||
|
:visible-columns="visibleColumn"
|
||||||
|
/>
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
|
<q-tr v-show="props.expand" :props="props">
|
||||||
|
<q-td colspan="100%">
|
||||||
|
<ingredients :ingredients="props.row.ingredients" :volume="props.row" />
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
<template v-slot:bottom>
|
||||||
|
<div class="full-width row justify-end">
|
||||||
|
<q-btn
|
||||||
|
color="positive"
|
||||||
|
icon-right="add"
|
||||||
|
label="Abgabe hinzufügen"
|
||||||
|
size="xs"
|
||||||
|
v-if="drinks_props.row.cost_price_pro_volume"
|
||||||
|
>
|
||||||
|
<q-menu anchor="center middle" self="center middle">
|
||||||
|
<div class="row justify-around q-pa-sm">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
label="Liter"
|
||||||
|
type="number"
|
||||||
|
v-model.number="newVolume.volume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between q-pa-sm">
|
||||||
|
<q-btn label="Abbrechen" @click="cancelAddVolume" v-close-popup />
|
||||||
|
<q-btn
|
||||||
|
label="Speichern"
|
||||||
|
color="primary"
|
||||||
|
@click="addVolume(drinks_props.row)"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-slot:no-data>
|
||||||
|
<div class="full-width row justify-end">
|
||||||
|
<q-btn
|
||||||
|
color="positive"
|
||||||
|
icon-right="add"
|
||||||
|
label="Abgabe hinzufügen"
|
||||||
|
size="xs"
|
||||||
|
v-if="drinks_props.row.cost_price_pro_volume"
|
||||||
|
>
|
||||||
|
<q-menu anchor="center middle" self="center middle">
|
||||||
|
<div class="row justify-around q-pa-sm">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
label="Liter"
|
||||||
|
type="number"
|
||||||
|
v-model.number="newVolume.volume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between q-pa-sm">
|
||||||
|
<q-btn label="Abbrechen" @click="cancelAddVolume" v-close-popup />
|
||||||
|
<q-btn
|
||||||
|
label="Speichern"
|
||||||
|
color="primary"
|
||||||
|
@click="addVolume(drinks_props.row)"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
|
</q-td>
|
||||||
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
<template v-slot:body-cell-volumes="volumes">
|
<template v-slot:body-cell-volumes="volumes">
|
||||||
<q-table
|
<q-table
|
||||||
|
@ -132,6 +539,44 @@
|
||||||
dense
|
dense
|
||||||
label="Liter"
|
label="Liter"
|
||||||
type="number"
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="0.01"
|
||||||
|
suffix="L"
|
||||||
|
v-model.number="newVolume.volume"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-between q-pa-sm">
|
||||||
|
<q-btn label="Abbrechen" @click="cancelAddVolume" v-close-popup />
|
||||||
|
<q-btn
|
||||||
|
label="Speichern"
|
||||||
|
color="primary"
|
||||||
|
@click="addVolume(volumes.row)"
|
||||||
|
v-close-popup
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</q-menu>
|
||||||
|
</q-btn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-slot:no-data>
|
||||||
|
<div class="full-width row justify-end">
|
||||||
|
<q-btn
|
||||||
|
color="positive"
|
||||||
|
icon-right="add"
|
||||||
|
label="Abgabe hinzufügen"
|
||||||
|
size="xs"
|
||||||
|
v-if="volumes.row.cost_price_pro_volume"
|
||||||
|
>
|
||||||
|
<q-menu anchor="center middle" self="center middle">
|
||||||
|
<div class="row justify-around q-pa-sm">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
label="Liter"
|
||||||
|
type="number"
|
||||||
|
min="0"
|
||||||
|
step="0.01"
|
||||||
|
suffix="L"
|
||||||
v-model.number="newVolume.volume"
|
v-model.number="newVolume.volume"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
@ -151,28 +596,21 @@
|
||||||
</q-table>
|
</q-table>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import { defineComponent, onBeforeMount, ref, computed } from '@vue/composition-api';
|
||||||
defineComponent,
|
import store, { DrinkPriceVolume, Drink } from '../store/altStore';
|
||||||
onBeforeMount,
|
|
||||||
ref,
|
|
||||||
computed,
|
|
||||||
WritableComputedRef
|
|
||||||
} from '@vue/composition-api';
|
|
||||||
import { v4 } from 'uuid';
|
|
||||||
import store, { create_volume, DrinkPriceVolume, Drink } from '../store/altStore';
|
|
||||||
import PriceTable from 'src/plugins/pricelist/components/CalculationTable/PriceTable.vue';
|
import PriceTable from 'src/plugins/pricelist/components/CalculationTable/PriceTable.vue';
|
||||||
import Ingredients from 'src/plugins/pricelist/components/CalculationTable/Ingredients.vue';
|
import Ingredients from 'src/plugins/pricelist/components/CalculationTable/Ingredients.vue';
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'CalculationTable',
|
name: 'CalculationTable',
|
||||||
components: { PriceTable, Ingredients },
|
components: { PriceTable, Ingredients },
|
||||||
setup(_, { root }) {
|
setup() {
|
||||||
onBeforeMount(() => {
|
onBeforeMount(() => {
|
||||||
store.actions.getDrinks();
|
store.actions.getDrinks();
|
||||||
store.actions.getExtraIngredients();
|
store.actions.getExtraIngredients();
|
||||||
|
store.actions.getDrinkTypes();
|
||||||
});
|
});
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
|
@ -258,8 +696,11 @@ export default defineComponent({
|
||||||
];
|
];
|
||||||
const visibleColumn = ref([
|
const visibleColumn = ref([
|
||||||
'name',
|
'name',
|
||||||
'drink_kind',
|
'drink_type',
|
||||||
'cost_price_pro_volumne',
|
'volume_package',
|
||||||
|
'cost_price_package_netto',
|
||||||
|
'package_size',
|
||||||
|
'cost_price_pro_volume',
|
||||||
'volumes',
|
'volumes',
|
||||||
'volume',
|
'volume',
|
||||||
'min_prices',
|
'min_prices',
|
||||||
|
@ -300,12 +741,65 @@ export default defineComponent({
|
||||||
store.actions.deleteVolume(volume, drink);
|
store.actions.deleteVolume(volume, drink);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addIngredient(ingredients: FG.Ingredient[]) {
|
const pagination = computed(() => {
|
||||||
ingredients.push({ id: -1, drink_ingredient: null, extra_ingredient: null });
|
rowsPerPage: store.state.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;
|
||||||
|
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.state.drinkTypes);
|
||||||
|
|
||||||
|
function addDrink() {
|
||||||
|
store.actions.setDrink(newDrink.value);
|
||||||
|
cancelAddDrink();
|
||||||
|
}
|
||||||
|
function cancelAddDrink() {
|
||||||
|
setTimeout(() => (newDrink.value = emptyDrink), 200);
|
||||||
|
}
|
||||||
|
function updateDrink(drink: Drink) {
|
||||||
|
store.actions.updateDrink(drink);
|
||||||
|
}
|
||||||
|
function deleteDrink(drink: Drink) {
|
||||||
|
store.actions.deleteDrink(drink);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
drinks: computed(() => store.state.drinks),
|
drinks: computed(() => store.state.drinks),
|
||||||
|
pagination,
|
||||||
columns,
|
columns,
|
||||||
column_calc,
|
column_calc,
|
||||||
column_prices,
|
column_prices,
|
||||||
|
@ -315,7 +809,14 @@ export default defineComponent({
|
||||||
newVolume,
|
newVolume,
|
||||||
updateVolume,
|
updateVolume,
|
||||||
deleteVolume,
|
deleteVolume,
|
||||||
addIngredient,
|
newDrink,
|
||||||
|
cost_price_pro_volume,
|
||||||
|
calc_price_pro_volume,
|
||||||
|
drinkTypes,
|
||||||
|
addDrink,
|
||||||
|
cancelAddDrink,
|
||||||
|
updateDrink,
|
||||||
|
deleteDrink,
|
||||||
console
|
console
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,9 @@
|
||||||
dense
|
dense
|
||||||
label="Volume"
|
label="Volume"
|
||||||
type="number"
|
type="number"
|
||||||
steps="0.1"
|
steps="0.01"
|
||||||
|
min="0"
|
||||||
|
suffix="L"
|
||||||
v-model.number="newIngredientVolume"
|
v-model.number="newIngredientVolume"
|
||||||
v-if="newIngredient && newIngredient.volume"
|
v-if="newIngredient && newIngredient.volume"
|
||||||
/>
|
/>
|
||||||
|
@ -117,6 +119,8 @@
|
||||||
dense
|
dense
|
||||||
label="Preis"
|
label="Preis"
|
||||||
disable
|
disable
|
||||||
|
min="0"
|
||||||
|
steps="0.1"
|
||||||
:value="newIngredient.price.toFixed(3)"
|
:value="newIngredient.price.toFixed(3)"
|
||||||
suffix="€"
|
suffix="€"
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
dense
|
dense
|
||||||
filled
|
filled
|
||||||
autofocus
|
autofocus
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
suffix="€"
|
suffix="€"
|
||||||
/> </q-popup-edit
|
/> </q-popup-edit
|
||||||
></q-td>
|
></q-td>
|
||||||
|
@ -42,7 +44,7 @@
|
||||||
label-set="Speichern"
|
label-set="Speichern"
|
||||||
@save="updatePrice(prices_props.row, row)"
|
@save="updatePrice(prices_props.row, row)"
|
||||||
>
|
>
|
||||||
<q-input v-model="prices_props.row.description" dense autofocus filled />
|
<q-input v-model="prices_props.row.description" dense autofocus filled clearable />
|
||||||
</q-popup-edit>
|
</q-popup-edit>
|
||||||
</q-td>
|
</q-td>
|
||||||
<q-td key="public" :props="prices_props">
|
<q-td key="public" :props="prices_props">
|
||||||
|
@ -78,6 +80,8 @@
|
||||||
type="number"
|
type="number"
|
||||||
label="Preis"
|
label="Preis"
|
||||||
suffix="€"
|
suffix="€"
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="newPrice.description"
|
v-model="newPrice.description"
|
||||||
|
@ -85,6 +89,7 @@
|
||||||
filled
|
filled
|
||||||
class="q-px-sm"
|
class="q-px-sm"
|
||||||
label="Beschreibung"
|
label="Beschreibung"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
|
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,6 +114,8 @@
|
||||||
type="number"
|
type="number"
|
||||||
label="Preis"
|
label="Preis"
|
||||||
suffix="€"
|
suffix="€"
|
||||||
|
min="0"
|
||||||
|
step="0.1"
|
||||||
/>
|
/>
|
||||||
<q-input
|
<q-input
|
||||||
v-model="newPrice.description"
|
v-model="newPrice.description"
|
||||||
|
@ -116,6 +123,7 @@
|
||||||
filled
|
filled
|
||||||
class="q-px-sm"
|
class="q-px-sm"
|
||||||
label="Beschreibung"
|
label="Beschreibung"
|
||||||
|
clearable
|
||||||
/>
|
/>
|
||||||
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
|
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -179,8 +187,8 @@ export default defineComponent({
|
||||||
store.actions.deletePrice(price, volume);
|
store.actions.deletePrice(price, volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
const pagination = computed(() => {
|
const pagination = ref({
|
||||||
rowsPerPage: props.data.length;
|
rowsPerPage: props.row.prices.length
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -22,8 +22,93 @@ interface DrinkPriceVolume extends Omit<Omit<FG.DrinkPriceVolume, 'volume'>, 'mi
|
||||||
volume: WritableComputedRef<number> | null;
|
volume: WritableComputedRef<number> | null;
|
||||||
min_prices: MinPrice[];
|
min_prices: MinPrice[];
|
||||||
}
|
}
|
||||||
interface Drink extends Omit<FG.Drink, 'volumes'> {
|
interface Drink extends Omit<Omit<FG.Drink, 'cost_price_pro_volume'>, 'volumes'> {
|
||||||
volumes: DrinkPriceVolume[];
|
volumes: DrinkPriceVolume[];
|
||||||
|
cost_price_pro_volume: WritableComputedRef<number | undefined>;
|
||||||
|
_cost_price_pro_volume?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class DrinkPriceVolume {
|
||||||
|
constructor({ id, volume, min_prices, prices, ingredients }: FG.DrinkPriceVolume, drink: Drink) {
|
||||||
|
this.id = id;
|
||||||
|
this._volume = volume;
|
||||||
|
this.prices = prices;
|
||||||
|
this.ingredients = ingredients;
|
||||||
|
this.min_prices = [
|
||||||
|
{
|
||||||
|
percentage: 100,
|
||||||
|
price: create_min_prices(drink, this, 100)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
percentage: 250,
|
||||||
|
price: create_min_prices(drink, this, 250)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
percentage: 300,
|
||||||
|
price: create_min_prices(drink, this, 300)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
this.volume = computed<number>({
|
||||||
|
get: () => {
|
||||||
|
if (this.ingredients.some(ingredient => !!ingredient.drink_ingredient)) {
|
||||||
|
let retVal = 0;
|
||||||
|
this.ingredients.forEach(ingredient => {
|
||||||
|
if (ingredient.drink_ingredient?.volume) {
|
||||||
|
retVal += ingredient.drink_ingredient.volume;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this._volume = retVal;
|
||||||
|
return retVal;
|
||||||
|
} else {
|
||||||
|
return this._volume;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set: val => (this._volume = val)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Drink {
|
||||||
|
constructor({
|
||||||
|
id,
|
||||||
|
article_id,
|
||||||
|
package_size,
|
||||||
|
name,
|
||||||
|
volume,
|
||||||
|
cost_price_pro_volume,
|
||||||
|
cost_price_package_netto,
|
||||||
|
tags,
|
||||||
|
type,
|
||||||
|
volumes
|
||||||
|
}: FG.Drink) {
|
||||||
|
this.id = id;
|
||||||
|
this.article_id = article_id;
|
||||||
|
this.package_size = package_size;
|
||||||
|
this.name = name;
|
||||||
|
this.volume = volume;
|
||||||
|
this.cost_price_package_netto = cost_price_package_netto;
|
||||||
|
this._cost_price_pro_volume = cost_price_pro_volume;
|
||||||
|
this.cost_price_pro_volume = computed({
|
||||||
|
get: () => {
|
||||||
|
if (!!this.volume && !!this.package_size && !!this.cost_price_package_netto) {
|
||||||
|
const retVal =
|
||||||
|
((this.cost_price_package_netto || 0) /
|
||||||
|
((this.volume || 0) * (this.package_size || 0))) *
|
||||||
|
1.19;
|
||||||
|
this._cost_price_pro_volume = Math.round(retVal * 1000) / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._cost_price_pro_volume;
|
||||||
|
},
|
||||||
|
set: val => (this._cost_price_pro_volume = val)
|
||||||
|
});
|
||||||
|
this.tags = tags;
|
||||||
|
this.type = type;
|
||||||
|
this.volumes = [];
|
||||||
|
/*volumes.forEach(volume => {
|
||||||
|
this.volumes.push(new DrinkPriceVolume(volume, this));
|
||||||
|
});*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const actions = {
|
const actions = {
|
||||||
|
@ -31,58 +116,15 @@ const actions = {
|
||||||
axios
|
axios
|
||||||
.get('pricelist/drinks')
|
.get('pricelist/drinks')
|
||||||
.then((response: AxiosResponse<FG.Drink[]>) => {
|
.then((response: AxiosResponse<FG.Drink[]>) => {
|
||||||
//state.drinks = [...response.data];
|
state.drinks = [];
|
||||||
/*state.drinks.forEach((drink: Drink) => {
|
|
||||||
drink.volumes.forEach((volume: DrinkPriceVolume) => {
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
||||||
// @ts-ignore
|
|
||||||
volume._volume = volume.volume;
|
|
||||||
volume.volume = create_volume(drink, volume);
|
|
||||||
volume.min_prices = [
|
|
||||||
{
|
|
||||||
percentage: 100,
|
|
||||||
price: create_min_prices(drink, volume, 100)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 250,
|
|
||||||
price: create_min_prices(drink, volume, 250)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 300,
|
|
||||||
price: create_min_prices(drink, volume, 300)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
this.sortPrices(volume);
|
|
||||||
});
|
|
||||||
});*/
|
|
||||||
response.data.forEach(drink => {
|
response.data.forEach(drink => {
|
||||||
const newDrink: Drink = { ...drink, volumes: [] };
|
state.drinks.push(new Drink(drink));
|
||||||
drink.volumes.forEach(volume => {
|
});
|
||||||
const newVolume: DrinkPriceVolume = {
|
state.drinks.forEach(drink => {
|
||||||
...volume,
|
const _drink = response.data.find(a => a.id === drink.id);
|
||||||
_volume: volume.volume,
|
_drink?.volumes.forEach(volume => {
|
||||||
min_prices: [],
|
drink.volumes.push(new DrinkPriceVolume(volume, drink));
|
||||||
volume: null
|
|
||||||
};
|
|
||||||
newVolume.volume = create_volume(newDrink, newVolume);
|
|
||||||
newVolume.min_prices = [
|
|
||||||
{
|
|
||||||
percentage: 100,
|
|
||||||
price: create_min_prices(newDrink, newVolume, 100)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 250,
|
|
||||||
price: create_min_prices(newDrink, newVolume, 250)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 300,
|
|
||||||
price: create_min_prices(newDrink, newVolume, 300)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
console.log(newVolume);
|
|
||||||
newDrink.volumes.push(newVolume);
|
|
||||||
});
|
});
|
||||||
state.drinks.push(newDrink);
|
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(err => console.warn(err));
|
.catch(err => console.warn(err));
|
||||||
|
@ -130,29 +172,7 @@ const actions = {
|
||||||
axios
|
axios
|
||||||
.post(`pricelist/drinks/${drink.id}/volumes`, { ...volume, volume: volume.volume })
|
.post(`pricelist/drinks/${drink.id}/volumes`, { ...volume, volume: volume.volume })
|
||||||
.then((response: AxiosResponse<FG.DrinkPriceVolume>) => {
|
.then((response: AxiosResponse<FG.DrinkPriceVolume>) => {
|
||||||
const a: DrinkPriceVolume = {
|
drink.volumes.push(new DrinkPriceVolume(response.data, drink));
|
||||||
...response.data,
|
|
||||||
min_prices: [],
|
|
||||||
_volume: response.data.volume,
|
|
||||||
volume: null
|
|
||||||
};
|
|
||||||
a.volume = create_volume(drink, a);
|
|
||||||
a.min_prices = [
|
|
||||||
{
|
|
||||||
percentage: 100,
|
|
||||||
price: create_min_prices(drink, a, 100)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 250,
|
|
||||||
price: create_min_prices(drink, a, 250)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
percentage: 300,
|
|
||||||
price: create_min_prices(drink, a, 300)
|
|
||||||
}
|
|
||||||
];
|
|
||||||
console.log(a);
|
|
||||||
drink.volumes.push(a);
|
|
||||||
})
|
})
|
||||||
.catch(err => console.warn(err));
|
.catch(err => console.warn(err));
|
||||||
},
|
},
|
||||||
|
@ -209,36 +229,55 @@ const actions = {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(err => console.warn(err));
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
getDrinkTypes() {
|
||||||
|
axios
|
||||||
|
.get('pricelist/drink-types')
|
||||||
|
.then((response: AxiosResponse<FG.DrinkType[]>) => {
|
||||||
|
state.drinkTypes = response.data;
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
setDrink(drink: FG.Drink) {
|
||||||
|
axios
|
||||||
|
.post('pricelist/drinks', drink)
|
||||||
|
.then((response: AxiosResponse<FG.Drink>) => {
|
||||||
|
state.drinks.push(new Drink(response.data));
|
||||||
|
const drink = state.drinks.find(a => a.id === response.data.id);
|
||||||
|
response.data.volumes.forEach(volume => {
|
||||||
|
drink?.volumes.push(new DrinkPriceVolume(volume, drink));
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
updateDrink(drink: Drink) {
|
||||||
|
axios
|
||||||
|
.put(`pricelist/drinks/${drink.id}`, {
|
||||||
|
...drink,
|
||||||
|
cost_price_pro_volume: drink.cost_price_pro_volume?.value
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
|
},
|
||||||
|
deleteDrink(drink: Drink) {
|
||||||
|
axios
|
||||||
|
.delete(`pricelist/drinks/${drink.id}`)
|
||||||
|
.then(() => {
|
||||||
|
const index = state.drinks.findIndex(a => a.id === drink.id);
|
||||||
|
if (index > -1) {
|
||||||
|
state.drinks.splice(index, 1);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(err => console.warn(err));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getters = {};
|
const getters = {};
|
||||||
|
|
||||||
function create_volume(drink: Drink, volume: DrinkPriceVolume) {
|
|
||||||
return computed<number>({
|
|
||||||
get: () => {
|
|
||||||
if (volume.ingredients.some(ingredient => !!ingredient.drink_ingredient)) {
|
|
||||||
let retVal = 0;
|
|
||||||
volume.ingredients.forEach(ingredient => {
|
|
||||||
if (ingredient.drink_ingredient?.volume) {
|
|
||||||
retVal += ingredient.drink_ingredient.volume;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
volume._volume = retVal;
|
|
||||||
return retVal;
|
|
||||||
} else {
|
|
||||||
return volume._volume;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
set: val => (volume._volume = val)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: number) {
|
function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: number) {
|
||||||
if (drink.cost_price_pro_volume) {
|
if (drink.cost_price_pro_volume?.value) {
|
||||||
if (volume.ingredients.every(ingredient => !!ingredient.drink_ingredient)) {
|
if (volume.ingredients.every(ingredient => !!ingredient.drink_ingredient)) {
|
||||||
return computed<number>(() => {
|
return computed<number>(() => {
|
||||||
let retVal = (drink.cost_price_pro_volume || 0) * (volume.volume?.value || 0);
|
let retVal = (drink.cost_price_pro_volume?.value || 0) * (volume.volume?.value || 0);
|
||||||
volume.ingredients.forEach(ingredient => {
|
volume.ingredients.forEach(ingredient => {
|
||||||
if (ingredient.extra_ingredient) {
|
if (ingredient.extra_ingredient) {
|
||||||
retVal += ingredient.extra_ingredient.price;
|
retVal += ingredient.extra_ingredient.price;
|
||||||
|
@ -249,7 +288,9 @@ function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: n
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return computed<number>(
|
return computed<number>(
|
||||||
() => ((drink.cost_price_pro_volume || 0) * (volume.volume?.value || 0) * percentage) / 100
|
() =>
|
||||||
|
((drink.cost_price_pro_volume?.value || 0) * (volume.volume?.value || 0) * percentage) /
|
||||||
|
100
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -270,7 +311,7 @@ function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: n
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export { create_min_prices, create_volume, DrinkPriceVolume, MinPrice, Drink };
|
export { create_min_prices, DrinkPriceVolume, MinPrice, Drink };
|
||||||
export default {
|
export default {
|
||||||
state,
|
state,
|
||||||
actions,
|
actions,
|
||||||
|
|
Loading…
Reference in New Issue