release v2.0.0 #4

Merged
crimsen merged 481 commits from develop into master 2024-01-18 15:15:08 +00:00
5 changed files with 804 additions and 250 deletions
Showing only changes of commit 57f21936c0 - Show all commits

View File

@ -43,7 +43,7 @@ declare namespace FG {
cost_price_pro_volume?: number;
cost_price_package_netto?: number;
tags: Array<Tag>;
type: DrinkType;
type?: DrinkType;
volumes: DrinkPriceVolume[];
}
interface DrinkIngredient {

View File

@ -1,13 +1,88 @@
<template>
<div>
<q-table
title="Kalkulationstabelle"
:columns="columns"
:data="drinks"
:visible-columns="visibleColumn"
:dense="$q.screen.lt.md"
>
<template v-slot:top-right>
<q-table
title="Kalkulationstabelle"
:columns="columns"
:data="drinks"
:visible-columns="visibleColumn"
: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>
<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
v-model="visibleColumn"
multiple
@ -21,158 +96,521 @@
option-value="name"
options-cover
/>
</template>
<template v-slot:body-cell-volumes="volumes">
<q-table
:columns="column_calc"
:data="volumes.value"
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>
</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;
console.log(volumes);
"
:icon="props.expand ? 'mdi-chevron-up' : 'mdi-chevron-down'"
v-if="volumes.row.cost_price_pro_volume == null"
/>
<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, volumes.row)"
/>
</q-td>
<q-td key="volume" :props="props">
{{ parseFloat(props.row.volume.value).toFixed(3) }}L
<!--{{ props.row.volume }}-->
<q-popup-edit
buttons
label-cancel="Abbrechen"
label-set="Speichern"
v-model="props.row.volume.value"
v-if="volumes.row.cost_price_pro_volume"
@save="updateVolume(props.row, volumes.row)"
>
<q-input
<template v-slot:body="props">
<q-tr :props="props">
<q-td auto-width>
<q-btn
size="sm"
color="accent"
round
dense
filled
v-model.number="props.row.volume.value"
type="number"
suffix="L"
@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-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">
<!--{{ parseFloat(min_price.price).toFixed(3) }}-->
{{ 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="volumes.row.cost_price_pro_volume"
>
<q-menu anchor="center middle" self="center middle">
<div class="row justify-around q-pa-sm">
<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
filled
dense
label="Liter"
filled
v-model.number="props.row.volume.value"
type="number"
v-model.number="newVolume.volume"
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>
<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>
</q-table>
</template>
</q-table>
</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 v-slot:body-cell-volumes="volumes">
<q-table
:columns="column_calc"
:data="volumes.value"
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;
console.log(volumes);
"
:icon="props.expand ? 'mdi-chevron-up' : 'mdi-chevron-down'"
v-if="volumes.row.cost_price_pro_volume == null"
/>
<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, volumes.row)"
/>
</q-td>
<q-td key="volume" :props="props">
{{ parseFloat(props.row.volume.value).toFixed(3) }}L
<!--{{ props.row.volume }}-->
<q-popup-edit
buttons
label-cancel="Abbrechen"
label-set="Speichern"
v-model="props.row.volume.value"
v-if="volumes.row.cost_price_pro_volume"
@save="updateVolume(props.row, volumes.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">
<!--{{ parseFloat(min_price.price).toFixed(3) }}-->
{{ 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="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"
/>
</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"
/>
</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>
</q-table>
</template>
</q-table>
</template>
<script lang="ts">
import {
defineComponent,
onBeforeMount,
ref,
computed,
WritableComputedRef
} from '@vue/composition-api';
import { v4 } from 'uuid';
import store, { create_volume, DrinkPriceVolume, Drink } from '../store/altStore';
import { defineComponent, onBeforeMount, ref, computed } from '@vue/composition-api';
import store, { DrinkPriceVolume, Drink } from '../store/altStore';
import PriceTable from 'src/plugins/pricelist/components/CalculationTable/PriceTable.vue';
import Ingredients from 'src/plugins/pricelist/components/CalculationTable/Ingredients.vue';
export default defineComponent({
name: 'CalculationTable',
components: { PriceTable, Ingredients },
setup(_, { root }) {
setup() {
onBeforeMount(() => {
store.actions.getDrinks();
store.actions.getExtraIngredients();
store.actions.getDrinkTypes();
});
const columns = [
@ -258,8 +696,11 @@ export default defineComponent({
];
const visibleColumn = ref([
'name',
'drink_kind',
'cost_price_pro_volumne',
'drink_type',
'volume_package',
'cost_price_package_netto',
'package_size',
'cost_price_pro_volume',
'volumes',
'volume',
'min_prices',
@ -300,12 +741,65 @@ export default defineComponent({
store.actions.deleteVolume(volume, drink);
}
function addIngredient(ingredients: FG.Ingredient[]) {
ingredients.push({ id: -1, drink_ingredient: null, extra_ingredient: null });
const pagination = computed(() => {
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 {
drinks: computed(() => store.state.drinks),
pagination,
columns,
column_calc,
column_prices,
@ -315,7 +809,14 @@ export default defineComponent({
newVolume,
updateVolume,
deleteVolume,
addIngredient,
newDrink,
cost_price_pro_volume,
calc_price_pro_volume,
drinkTypes,
addDrink,
cancelAddDrink,
updateDrink,
deleteDrink,
console
};
}

View File

@ -107,7 +107,9 @@
dense
label="Volume"
type="number"
steps="0.1"
steps="0.01"
min="0"
suffix="L"
v-model.number="newIngredientVolume"
v-if="newIngredient && newIngredient.volume"
/>
@ -117,6 +119,8 @@
dense
label="Preis"
disable
min="0"
steps="0.1"
:value="newIngredient.price.toFixed(3)"
suffix="€"
/>

View File

@ -29,6 +29,8 @@
dense
filled
autofocus
min="0"
step="0.1"
suffix="€"
/> </q-popup-edit
></q-td>
@ -42,7 +44,7 @@
label-set="Speichern"
@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-td>
<q-td key="public" :props="prices_props">
@ -78,6 +80,8 @@
type="number"
label="Preis"
suffix="€"
min="0"
step="0.1"
/>
<q-input
v-model="newPrice.description"
@ -85,6 +89,7 @@
filled
class="q-px-sm"
label="Beschreibung"
clearable
/>
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
</div>
@ -109,6 +114,8 @@
type="number"
label="Preis"
suffix="€"
min="0"
step="0.1"
/>
<q-input
v-model="newPrice.description"
@ -116,6 +123,7 @@
filled
class="q-px-sm"
label="Beschreibung"
clearable
/>
<q-toggle v-model="newPrice.public" dense class="q-px-sm" label="Öffentlich" />
</div>
@ -179,8 +187,8 @@ export default defineComponent({
store.actions.deletePrice(price, volume);
}
const pagination = computed(() => {
rowsPerPage: props.data.length;
const pagination = ref({
rowsPerPage: props.row.prices.length
});
return {

View File

@ -22,8 +22,93 @@ interface DrinkPriceVolume extends Omit<Omit<FG.DrinkPriceVolume, 'volume'>, 'mi
volume: WritableComputedRef<number> | null;
min_prices: MinPrice[];
}
interface Drink extends Omit<FG.Drink, 'volumes'> {
interface Drink extends Omit<Omit<FG.Drink, 'cost_price_pro_volume'>, 'volumes'> {
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 = {
@ -31,58 +116,15 @@ const actions = {
axios
.get('pricelist/drinks')
.then((response: AxiosResponse<FG.Drink[]>) => {
//state.drinks = [...response.data];
/*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);
});
});*/
state.drinks = [];
response.data.forEach(drink => {
const newDrink: Drink = { ...drink, volumes: [] };
drink.volumes.forEach(volume => {
const newVolume: DrinkPriceVolume = {
...volume,
_volume: volume.volume,
min_prices: [],
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(new Drink(drink));
});
state.drinks.forEach(drink => {
const _drink = response.data.find(a => a.id === drink.id);
_drink?.volumes.forEach(volume => {
drink.volumes.push(new DrinkPriceVolume(volume, drink));
});
state.drinks.push(newDrink);
});
})
.catch(err => console.warn(err));
@ -130,29 +172,7 @@ const actions = {
axios
.post(`pricelist/drinks/${drink.id}/volumes`, { ...volume, volume: volume.volume })
.then((response: AxiosResponse<FG.DrinkPriceVolume>) => {
const a: DrinkPriceVolume = {
...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);
drink.volumes.push(new DrinkPriceVolume(response.data, drink));
})
.catch(err => console.warn(err));
},
@ -209,36 +229,55 @@ const actions = {
}
})
.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 = {};
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) {
if (drink.cost_price_pro_volume) {
if (drink.cost_price_pro_volume?.value) {
if (volume.ingredients.every(ingredient => !!ingredient.drink_ingredient)) {
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 => {
if (ingredient.extra_ingredient) {
retVal += ingredient.extra_ingredient.price;
@ -249,7 +288,9 @@ function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: n
});
} else {
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 {
@ -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 {
state,
actions,