release v2.0.0 #4
|
@ -371,8 +371,13 @@
|
|||
props.row.uuid ? `/api/pricelist/picture/${props.row.uuid}?size=256` : 'no-image.svg'
|
||||
"
|
||||
>
|
||||
<div class='absolute-top-right justify-end' style='background-color: transparent;'>
|
||||
<q-btn @click="console.log('hallo')" round icon='mdi-pencil' style='background-color: rgba(0,0,0,0.5)'/>
|
||||
<div class="absolute-top-right justify-end" style="background-color: transparent">
|
||||
<q-btn
|
||||
round
|
||||
icon="mdi-pencil"
|
||||
style="background-color: rgba(0, 0, 0, 0.5)"
|
||||
@click="editDrink = props.row"
|
||||
/>
|
||||
</div>
|
||||
<div class="absolute-bottom-right justify-end">
|
||||
<div class="text-subtitle1 text-right">
|
||||
|
@ -447,14 +452,20 @@
|
|||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
|
||||
<q-card-section v-if="props.row.volumes.length > 0">
|
||||
<drink-price-volumes :props="props.row" />
|
||||
<drink-price-volumes v-model="props.row.volumes" />
|
||||
</q-card-section>
|
||||
</q-card>
|
||||
</div>
|
||||
</template>
|
||||
</q-table>
|
||||
<q-dialog :model-value="editDrink !== undefined" persistent>
|
||||
<drink-modify
|
||||
:drink="editDrink"
|
||||
@save="editDrink = undefined"
|
||||
@cancel="editDrink = undefined"
|
||||
/>
|
||||
</q-dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -467,6 +478,7 @@ import NewDrink from 'src/plugins/pricelist/components/CalculationTable/NewDrink
|
|||
import BuildManual from 'src/plugins/pricelist/components/CalculationTable/BuildManual.vue';
|
||||
import SearchInput from './SearchInput.vue';
|
||||
import DrinkPriceVolumes from 'src/plugins/pricelist/components/CalculationTable/DrinkPriceVolumes.vue';
|
||||
import DrinkModify from './DrinkModify.vue';
|
||||
import { filter, Search } from '../utils/filter';
|
||||
import { Notify } from 'quasar';
|
||||
import { sort } from '../utils/sort';
|
||||
|
@ -480,6 +492,7 @@ export default defineComponent({
|
|||
BuildManual,
|
||||
DrinkPriceVolumesTable,
|
||||
DrinkPriceVolumes,
|
||||
DrinkModify,
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
@ -715,6 +728,7 @@ export default defineComponent({
|
|||
label: '',
|
||||
});
|
||||
const grid = ref(true);
|
||||
const editDrink = ref();
|
||||
return {
|
||||
drinks: computed(() => store.drinks),
|
||||
pagination,
|
||||
|
@ -737,6 +751,7 @@ export default defineComponent({
|
|||
search_keys,
|
||||
grid,
|
||||
tags: computed(() => store.tags),
|
||||
editDrink,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -37,7 +37,7 @@ export default defineComponent({
|
|||
const emptyVolume: DrinkPriceVolume = {
|
||||
id: -1,
|
||||
_volume: 0,
|
||||
min_prices: [{ percentage: 100 }, { percentage: 250 }, { percentage: 300 }],
|
||||
min_prices: [],
|
||||
prices: [],
|
||||
ingredients: [],
|
||||
};
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
navigation
|
||||
arrows
|
||||
>
|
||||
<q-carousel-slide v-for="volume in props.volumes" :key="volume.id" :name="volume.id">
|
||||
<q-carousel-slide v-for="volume in volumes" :key="volume.id" :name="volume.id">
|
||||
<q-input
|
||||
v-model.number="volume.volume"
|
||||
class="q-pa-sm"
|
||||
:model-value="volume.volume"
|
||||
outlined
|
||||
readonly
|
||||
:outlined="!editable"
|
||||
:filled="editable"
|
||||
:readonly="!editable"
|
||||
dense
|
||||
label="Inhalt"
|
||||
mask="#.###"
|
||||
fill-mask="0"
|
||||
suffix="L"
|
||||
min="0"
|
||||
step="0.001"
|
||||
/>
|
||||
<div class="full-width row q-gutter-sm q-pa-sm justify-around">
|
||||
<div v-for="(min_price, index) in volume.min_prices" :key="index">
|
||||
|
@ -30,58 +33,104 @@
|
|||
<div class="q-pa-sm">
|
||||
<div v-for="(price, index) in volume.prices" :key="price.id">
|
||||
<div class="fit row justify-around q-py-sm">
|
||||
<div class="text-body1 col-xs-12 col-md-4">{{ price.price.toFixed(2) }}€</div>
|
||||
<div class="text-body1 col-xs-12 col-md-4">
|
||||
<div v-if="!editable" class="text-body1 col-xs-12 col-md-3">
|
||||
{{ price.price.toFixed(2) }}€
|
||||
</div>
|
||||
<q-input
|
||||
v-else
|
||||
v-model.number="price.price"
|
||||
class="col-xs-12 col-md-3"
|
||||
type="number"
|
||||
min="0"
|
||||
step="0.01"
|
||||
suffix="€"
|
||||
filled
|
||||
dense
|
||||
label="Preis"
|
||||
/>
|
||||
<div class="text-body1 col-xs-12 col-md-2">
|
||||
<q-toggle
|
||||
:model-value="price.public"
|
||||
disable
|
||||
v-model="price.public"
|
||||
:disable="!editable"
|
||||
checked-icon="mdi-earth"
|
||||
unchecked-icon="mdi-earth-off"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-body1 col-xs-12 col-md-4">
|
||||
<div v-if="!editable" class="text-body1 col-xs-12 col-md-5">
|
||||
{{ price.description }}
|
||||
</div>
|
||||
<q-input
|
||||
v-else
|
||||
v-model="price.description"
|
||||
class="col-xs-12 col-md-5"
|
||||
filled
|
||||
dense
|
||||
label="Beschreibung"
|
||||
/>
|
||||
</div>
|
||||
<q-separator v-if="index < volume.prices.length - 1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="q-pa-sm">
|
||||
<ingredients :ingredients="volume.ingredients" :volume="volume" />
|
||||
<ingredients v-model="volume.ingredients" :editable="editable" />
|
||||
</div>
|
||||
</q-carousel-slide>
|
||||
</q-carousel>
|
||||
<q-btn-toggle v-model="volume" :options="options" />
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType, ref } from 'vue';
|
||||
import { Drink } from 'src/plugins/pricelist/store';
|
||||
import { computed, defineComponent, PropType, ref, onBeforeMount } from 'vue';
|
||||
import { DrinkPriceVolume } from 'src/plugins/pricelist/store';
|
||||
import Ingredients from 'src/plugins/pricelist/components/CalculationTable/Ingredients.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'DrinkPriceVolume',
|
||||
components: { Ingredients },
|
||||
props: {
|
||||
props: {
|
||||
type: Object as PropType<Drink>,
|
||||
modelValue: {
|
||||
type: Array as PropType<Array<DrinkPriceVolume>>,
|
||||
required: true,
|
||||
},
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
setup(props) {
|
||||
},
|
||||
emits: {
|
||||
'update:modelValue': (val: Array<DrinkPriceVolume>) => val,
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
onBeforeMount(() => {
|
||||
volumes.value = <Array<DrinkPriceVolume>>[...props.modelValue];
|
||||
});
|
||||
const volumes = ref<Array<DrinkPriceVolume>>([]);
|
||||
const _volume = ref<number | undefined>();
|
||||
const volume = computed<number | undefined>({
|
||||
get: () => {
|
||||
if (_volume.value !== undefined) {
|
||||
return _volume.value;
|
||||
}
|
||||
if (props.props.volumes.length > 0) {
|
||||
return props.props.volumes[0].id;
|
||||
if (volumes.value.length > 0) {
|
||||
return volumes.value[0].id;
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
set: (val: number | undefined) => (_volume.value = val),
|
||||
});
|
||||
return { volume };
|
||||
const options = computed<Array<{ label: string; value: number }>>(() => {
|
||||
const retVal: Array<{ label: string; value: number }> = [];
|
||||
volumes.value.forEach((volume: DrinkPriceVolume) => {
|
||||
retVal.push({ label: `${<number>volume.volume}L`, value: volume.id });
|
||||
});
|
||||
return retVal;
|
||||
});
|
||||
|
||||
function updateVolume() {
|
||||
emit('update:modelValue', volumes.value);
|
||||
}
|
||||
|
||||
return { volumes, volume, options, updateVolume };
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<template>
|
||||
<div class="full-width">
|
||||
<div
|
||||
v-for="ingredient in ingredients"
|
||||
:key="`volume:${volume.id},ingredient:${ingredient.id}`"
|
||||
v-for="ingredient in edit_ingredients"
|
||||
:key="`ingredient:${ingredient.id}`"
|
||||
class="full-width row justify-evenly q-py-xs"
|
||||
>
|
||||
<div class="full-width row justify-evenly">
|
||||
|
@ -11,14 +11,16 @@
|
|||
<div class="col">
|
||||
{{ get_drink_ingredient_name(ingredient.drink_ingredient.ingredient_id) }}
|
||||
<q-popup-edit
|
||||
v-if="editable"
|
||||
v-slot="scope"
|
||||
v-model="ingredient.drink_ingredient.ingredient_id"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@save="updateDrink"
|
||||
@save="updateValue"
|
||||
>
|
||||
<q-select
|
||||
v-model="ingredient.drink_ingredient.ingredient_id"
|
||||
v-model="scope.ingredient_id"
|
||||
class="col q-px-sm"
|
||||
label="Getränk"
|
||||
filled
|
||||
|
@ -34,14 +36,16 @@
|
|||
<div class="col">
|
||||
{{ ingredient.drink_ingredient.volume.toFixed(3) }}L
|
||||
<q-popup-edit
|
||||
v-if="editable"
|
||||
v-slot="scope"
|
||||
v-model="ingredient.drink_ingredient.volume"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@save="updateDrink"
|
||||
@save="updateValue"
|
||||
>
|
||||
<q-input
|
||||
v-model.number="ingredient.drink_ingredient.volume"
|
||||
v-model.number="scope.value"
|
||||
class="col q-px-sm"
|
||||
label="Volume"
|
||||
type="number"
|
||||
|
@ -63,11 +67,12 @@
|
|||
<div class="col">{{ ingredient.extra_ingredient.price.toFixed(3) }}€</div>
|
||||
</div>
|
||||
<q-popup-edit
|
||||
v-if="editable"
|
||||
v-model="ingredient.extra_ingredient"
|
||||
buttons
|
||||
label-cancel="Abbrechen"
|
||||
label-set="Speichern"
|
||||
@save="updateDrink"
|
||||
@save="updateValue"
|
||||
>
|
||||
<q-select
|
||||
v-model="ingredient.extra_ingredient"
|
||||
|
@ -78,19 +83,19 @@
|
|||
/>
|
||||
</q-popup-edit>
|
||||
</div>
|
||||
<div class="col-1 row justify-end q-pa-xs">
|
||||
<div v-if="editable" class="col-1 row justify-end q-pa-xs">
|
||||
<q-btn
|
||||
icon="mdi-delete"
|
||||
round
|
||||
size="xs"
|
||||
color="negative"
|
||||
@click="deleteIngredient(ingredient, volume)"
|
||||
@click="deleteIngredient(ingredient)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<q-separator />
|
||||
</div>
|
||||
<div class="full-width row justify-end q-py-xs">
|
||||
<div v-if="editable" class="full-width row justify-end q-py-xs">
|
||||
<q-btn size="sm" icon-right="mdi-plus" color="positive" label="Zutat hinzufügen">
|
||||
<q-menu anchor="center middle" self="center middle">
|
||||
<div class="full-width row justify-around q-gutter-sm q-pa-sm">
|
||||
|
@ -133,12 +138,7 @@
|
|||
</div>
|
||||
<div class="full-width row jusitfy-between q-gutter-sm q-pa-sm">
|
||||
<q-btn v-close-popup label="Abbrechen" @click="cancelAddIngredient" />
|
||||
<q-btn
|
||||
v-close-popup
|
||||
label="Speichern"
|
||||
color="positive"
|
||||
@click="addIngredient(volume)"
|
||||
/>
|
||||
<q-btn v-close-popup label="Speichern" color="positive" @click="addIngredient" />
|
||||
</div>
|
||||
</q-menu>
|
||||
</q-btn>
|
||||
|
@ -147,34 +147,39 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, PropType, ref } from 'vue';
|
||||
import { DrinkPriceVolume, usePricelistStore } from '../../store';
|
||||
import { computed, defineComponent, PropType, ref, onBeforeMount } from 'vue';
|
||||
import { usePricelistStore } from '../../store';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Ingredients',
|
||||
props: {
|
||||
ingredients: {
|
||||
type: Array as PropType<FG.Ingredient[]>,
|
||||
modelValue: {
|
||||
type: Object as PropType<Array<FG.Ingredient>>,
|
||||
required: true,
|
||||
},
|
||||
volume: {
|
||||
type: Object /*as PropType<DrinkPriceVolume>*/,
|
||||
required: true,
|
||||
editable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
emits: {
|
||||
updateDrink: () => true,
|
||||
addIngredient: (val: FG.Ingredient, volume: DrinkPriceVolume) =>
|
||||
(val.drink_ingredient || val.extra_ingredient) && volume,
|
||||
deleteIngredient: (ingredient: FG.Ingredient, volume: DrinkPriceVolume) =>
|
||||
(ingredient.drink_ingredient || ingredient.extra_ingredient) && volume,
|
||||
'update:modelValue': (val: Array<FG.Ingredient>) => val,
|
||||
},
|
||||
setup(_, { emit }) {
|
||||
setup(props, { emit }) {
|
||||
onBeforeMount(() => {
|
||||
edit_ingredients.value = [];
|
||||
props.modelValue.forEach((a) => {
|
||||
edit_ingredients.value.push(Object.assign({}, a));
|
||||
});
|
||||
console.log(edit_ingredients);
|
||||
});
|
||||
|
||||
const store = usePricelistStore();
|
||||
|
||||
const edit_ingredients = ref<Array<FG.Ingredient>>([]);
|
||||
const newIngredient = ref<FG.Drink | FG.ExtraIngredient>();
|
||||
const newIngredientVolume = ref<number>(0);
|
||||
function addIngredient(volume: DrinkPriceVolume) {
|
||||
function addIngredient() {
|
||||
let _ingredient: FG.Ingredient;
|
||||
if ((<FG.Drink>newIngredient.value)?.volume && newIngredient.value) {
|
||||
_ingredient = {
|
||||
|
@ -193,20 +198,27 @@ export default defineComponent({
|
|||
extra_ingredient: <FG.ExtraIngredient>newIngredient.value,
|
||||
};
|
||||
}
|
||||
emit('addIngredient', _ingredient, volume);
|
||||
edit_ingredients.value.push(_ingredient);
|
||||
emit('update:modelValue', edit_ingredients.value);
|
||||
cancelAddIngredient();
|
||||
}
|
||||
function updateDrink() {
|
||||
console.log('updateDrink from Ingredients');
|
||||
emit('updateDrink');
|
||||
|
||||
function updateValue(value: number, initValue: number) {
|
||||
console.log('updateValue', value, initValue);
|
||||
emit('update:modelValue', edit_ingredients.value);
|
||||
}
|
||||
|
||||
function cancelAddIngredient() {
|
||||
setTimeout(() => {
|
||||
(newIngredient.value = undefined), (newIngredientVolume.value = 0);
|
||||
}, 200);
|
||||
}
|
||||
function deleteIngredient(ingredient: FG.Ingredient, volume: DrinkPriceVolume) {
|
||||
emit('deleteIngredient', ingredient, volume);
|
||||
function deleteIngredient(ingredient: FG.Ingredient) {
|
||||
const index = edit_ingredients.value.findIndex((a) => a.id === ingredient.id);
|
||||
if (index > -1) {
|
||||
edit_ingredients.value.splice(index, 1);
|
||||
}
|
||||
emit('update:modelValue', edit_ingredients.value);
|
||||
}
|
||||
const drinks = computed(() =>
|
||||
store.drinks.filter((drink) => {
|
||||
|
@ -227,9 +239,10 @@ export default defineComponent({
|
|||
newIngredient,
|
||||
newIngredientVolume,
|
||||
cancelAddIngredient,
|
||||
updateDrink,
|
||||
updateValue,
|
||||
deleteIngredient,
|
||||
get_drink_ingredient_name,
|
||||
edit_ingredients,
|
||||
};
|
||||
},
|
||||
});
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
<template>
|
||||
<q-card>
|
||||
<q-card-section>
|
||||
<div class="text-h6">Getränk Bearbeiten</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<div class="fit row">
|
||||
<q-input
|
||||
v-model="edit_drink.article_id"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
filled
|
||||
label="Artikelnummer"
|
||||
dense
|
||||
/>
|
||||
<q-input
|
||||
v-model="edit_drink.volume"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
filled
|
||||
label="Inhalt"
|
||||
dense
|
||||
suffix="L"
|
||||
/>
|
||||
<q-input
|
||||
v-model="edit_drink.package_size"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
filled
|
||||
label="Gebindegröße"
|
||||
dense
|
||||
/>
|
||||
<q-input
|
||||
v-model="edit_drink.cost_per_package"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm"
|
||||
filled
|
||||
label="Preis Gebinde"
|
||||
suffix="€"
|
||||
dense
|
||||
/>
|
||||
<q-input
|
||||
v-model="edit_drink.cost_per_volume"
|
||||
class="col-xs-12 col-sm-6 q-pa-sm q-pb-lg"
|
||||
filled
|
||||
label="Preis pro L"
|
||||
hint="Inkl. 19% Mehrwertsteuer"
|
||||
suffix="€"
|
||||
dense
|
||||
/>
|
||||
</div>
|
||||
</q-card-section>
|
||||
<q-card-section>
|
||||
<drink-price-volumes v-model="edit_drink.volumes" editable />
|
||||
</q-card-section>
|
||||
<q-card-actions class="justify-around">
|
||||
<q-btn label="Abbrechen" @click="cancel" />
|
||||
<q-btn label="Speichern" color="primary" @click="save" />
|
||||
</q-card-actions>
|
||||
</q-card>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent, PropType, ref, onBeforeMount } from 'vue';
|
||||
import { Drink, DrinkPriceVolume } from '../store';
|
||||
import DrinkPriceVolumes from './CalculationTable/DrinkPriceVolumes.vue';
|
||||
import { calc_volume } from 'src/plugins/pricelist/utils/utils';
|
||||
export default defineComponent({
|
||||
name: 'DrinkModify',
|
||||
components: { DrinkPriceVolumes },
|
||||
props: {
|
||||
drink: {
|
||||
type: Object as PropType<Drink>,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
emits: { save: () => true, cancel: () => true },
|
||||
setup(props, { emit }) {
|
||||
onBeforeMount(() => {
|
||||
edit_drink.value = Object.assign({}, props.drink);
|
||||
});
|
||||
|
||||
const edit_drink = ref<Drink>();
|
||||
function save() {
|
||||
emit('save');
|
||||
}
|
||||
function cancel() {
|
||||
emit('cancel');
|
||||
}
|
||||
function updateVolume(volume: DrinkPriceVolume) {
|
||||
if (volume) {
|
||||
console.log('edit_volume', volume);
|
||||
volume.volume = calc_volume(volume);
|
||||
}
|
||||
}
|
||||
return { edit_drink, save, cancel, updateVolume };
|
||||
},
|
||||
});
|
||||
</script>
|
|
@ -27,7 +27,7 @@
|
|||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed, defineComponent, onBeforeMount, ref } from 'vue';
|
||||
import { defineComponent, onBeforeMount, ref } from 'vue';
|
||||
import Ingredients from 'src/plugins/pricelist/components/CalculationTable/Ingredients.vue';
|
||||
import { DrinkPriceVolume, usePricelistStore } from 'src/plugins/pricelist/store';
|
||||
export default defineComponent({
|
||||
|
@ -39,7 +39,7 @@ export default defineComponent({
|
|||
store.min_prices.forEach((min_price) => {
|
||||
(<DrinkPriceVolume>volume.value).min_prices.push({
|
||||
percentage: min_price,
|
||||
price: computed<number>(() => {
|
||||
price: /*computed<number>(() => {
|
||||
let retVal = 0;
|
||||
let extraIngredientPrice = 0;
|
||||
volume.value.ingredients.forEach((ingredient) => {
|
||||
|
@ -55,7 +55,7 @@ export default defineComponent({
|
|||
}
|
||||
});
|
||||
return (retVal * min_price) / 100 + extraIngredientPrice;
|
||||
}),
|
||||
}) */ 0,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
import { api } from 'src/boot/axios';
|
||||
import { defineStore } from 'pinia';
|
||||
import { AxiosResponse } from 'axios';
|
||||
import { computed, ComputedRef, WritableComputedRef } from 'vue';
|
||||
import {
|
||||
calc_volume,
|
||||
calc_cost_per_volume,
|
||||
calc_all_min_prices,
|
||||
} from 'src/plugins/pricelist/utils/utils';
|
||||
|
||||
interface MinPrice extends Omit<FG.MinPrices, 'price'> {
|
||||
price?: WritableComputedRef<number>;
|
||||
}
|
||||
|
||||
interface DrinkPriceVolume extends Omit<Omit<FG.DrinkPriceVolume, 'volume'>, 'min_prices'> {
|
||||
interface DrinkPriceVolume extends Omit<FG.DrinkPriceVolume, 'volume'> {
|
||||
_volume: number;
|
||||
volume?: WritableComputedRef<number>;
|
||||
min_prices: MinPrice[];
|
||||
volume?: number;
|
||||
}
|
||||
|
||||
interface Drink extends Omit<Omit<FG.Drink, 'cost_per_volume'>, 'volumes'> {
|
||||
volumes: DrinkPriceVolume[];
|
||||
cost_per_volume: WritableComputedRef<number | undefined>;
|
||||
cost_per_volume?: number;
|
||||
_cost_per_volume?: number;
|
||||
}
|
||||
|
||||
|
@ -26,23 +25,7 @@ class DrinkPriceVolume implements DrinkPriceVolume {
|
|||
this.prices = prices;
|
||||
this.ingredients = ingredients;
|
||||
this.min_prices = [];
|
||||
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),
|
||||
});
|
||||
this.volume = calc_volume(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,18 +50,7 @@ class Drink {
|
|||
this.volume = volume;
|
||||
this.cost_per_package = cost_per_package;
|
||||
this._cost_per_volume = cost_per_volume;
|
||||
this.cost_per_volume = computed({
|
||||
get: () => {
|
||||
if (!!this.volume && !!this.package_size && !!this.cost_per_package) {
|
||||
const retVal =
|
||||
((this.cost_per_package || 0) / ((this.volume || 0) * (this.package_size || 0))) * 1.19;
|
||||
this._cost_per_volume = Math.round(retVal * 1000) / 1000;
|
||||
}
|
||||
|
||||
return this._cost_per_volume;
|
||||
},
|
||||
set: (val) => (this._cost_per_volume = val),
|
||||
});
|
||||
this.cost_per_volume = calc_cost_per_volume(this);
|
||||
this.tags = tags;
|
||||
this.type = type;
|
||||
this.volumes = [];
|
||||
|
@ -164,7 +136,7 @@ export const usePricelistStore = defineStore({
|
|||
});
|
||||
this.drinks.push(_drink);
|
||||
});
|
||||
this.create_min_prices();
|
||||
calc_all_min_prices(this.drinks, this.min_prices);
|
||||
console.log(this.drinks);
|
||||
},
|
||||
sortPrices(volume: DrinkPriceVolume) {
|
||||
|
@ -217,7 +189,7 @@ export const usePricelistStore = defineStore({
|
|||
_drink.volumes.push(_volume);
|
||||
});
|
||||
this.drinks.push(_drink);
|
||||
this.create_min_prices();
|
||||
calc_all_min_prices(this.drinks, this.min_prices);
|
||||
},
|
||||
async updateDrink(drink: Drink) {
|
||||
console.log(drink);
|
||||
|
@ -234,7 +206,7 @@ export const usePricelistStore = defineStore({
|
|||
});
|
||||
this.drinks[index] = _drink;
|
||||
}
|
||||
this.create_min_prices();
|
||||
calc_all_min_prices(this.drinks, this.min_prices);
|
||||
},
|
||||
deleteDrink(drink: Drink) {
|
||||
api
|
||||
|
@ -271,46 +243,7 @@ export const usePricelistStore = defineStore({
|
|||
},
|
||||
async set_min_prices() {
|
||||
await api.post<Array<number>>('pricelist/settings/min_prices', this.min_prices);
|
||||
this.create_min_prices();
|
||||
},
|
||||
create_min_prices() {
|
||||
this.drinks.forEach((drink) => {
|
||||
drink.volumes.forEach((volume) => {
|
||||
volume.min_prices = [];
|
||||
this.min_prices.forEach((min_price) => {
|
||||
let computedMinPrice: ComputedRef;
|
||||
if (drink.cost_per_volume) {
|
||||
computedMinPrice = computed<number>(
|
||||
() =>
|
||||
(<number>(<unknown>drink.cost_per_volume) *
|
||||
<number>(<unknown>volume.volume) *
|
||||
min_price) /
|
||||
100
|
||||
);
|
||||
} else {
|
||||
computedMinPrice = computed<number>(() => {
|
||||
let retVal = 0;
|
||||
let extraIngredientPrice = 0;
|
||||
volume.ingredients.forEach((ingredient) => {
|
||||
if (ingredient.drink_ingredient) {
|
||||
const _drink = usePricelistStore().drinks.find(
|
||||
(a) => a.id === ingredient.drink_ingredient?.ingredient_id
|
||||
);
|
||||
retVal +=
|
||||
ingredient.drink_ingredient.volume *
|
||||
<number>(<unknown>_drink?.cost_per_volume);
|
||||
}
|
||||
if (ingredient.extra_ingredient) {
|
||||
extraIngredientPrice += ingredient.extra_ingredient.price;
|
||||
}
|
||||
});
|
||||
return (retVal * min_price) / 100 + extraIngredientPrice;
|
||||
});
|
||||
}
|
||||
volume.min_prices.push({ percentage: min_price, price: computedMinPrice });
|
||||
});
|
||||
});
|
||||
});
|
||||
calc_all_min_prices(this.drinks, this.min_prices);
|
||||
},
|
||||
async upload_drink_picture(drink: Drink, file: File) {
|
||||
const formData = new FormData();
|
||||
|
@ -351,4 +284,4 @@ export const usePricelistStore = defineStore({
|
|||
},
|
||||
});
|
||||
|
||||
export { DrinkPriceVolume, MinPrice, Drink };
|
||||
export { DrinkPriceVolume, Drink };
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
import { Drink, DrinkPriceVolume, usePricelistStore } from 'src/plugins/pricelist/store';
|
||||
|
||||
function calc_volume(volume: DrinkPriceVolume) {
|
||||
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;
|
||||
}
|
||||
});
|
||||
return retVal;
|
||||
} else {
|
||||
return volume._volume;
|
||||
}
|
||||
}
|
||||
|
||||
function calc_cost_per_volume(drink: Drink) {
|
||||
let retVal = drink._cost_per_volume;
|
||||
if (!!drink.volume && !!drink.package_size && !!drink.cost_per_package) {
|
||||
retVal =
|
||||
((drink.cost_per_package || 0) / ((drink.volume || 0) * (drink.package_size || 0))) * 1.19;
|
||||
}
|
||||
|
||||
return retVal ? Math.round(retVal * 1000) / 1000 : retVal;
|
||||
}
|
||||
|
||||
function calc_all_min_prices(drinks: Array<Drink>, min_prices: Array<number>) {
|
||||
drinks.forEach((drink) => {
|
||||
drink.volumes.forEach((volume) => {
|
||||
volume.min_prices = calc_min_prices(volume, drink.cost_per_volume, min_prices);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function helper(volume: DrinkPriceVolume, min_price: number) {
|
||||
let retVal = 0;
|
||||
let extraIngredientPrice = 0;
|
||||
volume.ingredients.forEach((ingredient) => {
|
||||
if (ingredient.drink_ingredient) {
|
||||
const _drink = usePricelistStore().drinks.find(
|
||||
(a) => a.id === ingredient.drink_ingredient?.ingredient_id
|
||||
);
|
||||
retVal += ingredient.drink_ingredient.volume * <number>(<unknown>_drink?.cost_per_volume);
|
||||
}
|
||||
if (ingredient.extra_ingredient) {
|
||||
extraIngredientPrice += ingredient.extra_ingredient.price;
|
||||
}
|
||||
});
|
||||
return (retVal * min_price) / 100 + extraIngredientPrice;
|
||||
}
|
||||
|
||||
function calc_min_prices(
|
||||
volume: DrinkPriceVolume,
|
||||
cost_per_volume: number | undefined,
|
||||
min_prices: Array<number>
|
||||
) {
|
||||
const retVal: Array<FG.MinPrices> = [];
|
||||
volume.min_prices = [];
|
||||
min_prices.forEach((min_price) => {
|
||||
let computedMinPrice: number;
|
||||
if (cost_per_volume) {
|
||||
computedMinPrice = (cost_per_volume * <number>volume.volume * min_price) / 100;
|
||||
} else {
|
||||
computedMinPrice = helper(volume, min_price);
|
||||
}
|
||||
retVal.push({ percentage: min_price, price: computedMinPrice });
|
||||
});
|
||||
return retVal;
|
||||
}
|
||||
|
||||
export { calc_volume, calc_cost_per_volume, calc_all_min_prices, calc_min_prices };
|
Loading…
Reference in New Issue