[pricelist] cleanup some code
This commit is contained in:
		
							parent
							
								
									1c64dbbaf6
								
							
						
					
					
						commit
						7a3a151688
					
				| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
    const _volume = ref<number|undefined>();
 | 
			
		||||
    const volume = computed<number|undefined>({
 | 
			
		||||
  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),
 | 
			
		||||
      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