332 lines
11 KiB
TypeScript
332 lines
11 KiB
TypeScript
import { api } from 'src/boot/axios';
|
|
import { defineStore } from 'pinia';
|
|
import { AxiosResponse } from 'axios';
|
|
import { computed, WritableComputedRef } from 'vue';
|
|
|
|
interface MinPrice extends Omit<FG.MinPrices, 'price'> {
|
|
price?: WritableComputedRef<number>;
|
|
}
|
|
interface DrinkPriceVolume extends Omit<Omit<FG.DrinkPriceVolume, 'volume'>, 'min_prices'> {
|
|
_volume: number;
|
|
volume?: WritableComputedRef<number>;
|
|
min_prices: MinPrice[];
|
|
}
|
|
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 implements 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));
|
|
//});
|
|
}
|
|
}
|
|
|
|
function create_min_prices(drink: Drink, volume: DrinkPriceVolume, percentage: number) {
|
|
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?.value || 0) * (volume.volume?.value || 0);
|
|
volume.ingredients.forEach((ingredient) => {
|
|
if (ingredient.extra_ingredient) {
|
|
retVal += ingredient.extra_ingredient.price;
|
|
}
|
|
});
|
|
retVal = (retVal * percentage) / 100;
|
|
return retVal;
|
|
});
|
|
} else {
|
|
return computed<number>(
|
|
() =>
|
|
((drink.cost_price_pro_volume?.value || 0) * (volume.volume?.value || 0) * percentage) /
|
|
100
|
|
);
|
|
}
|
|
} else {
|
|
return computed<number>(() => {
|
|
let retVal = 0;
|
|
volume.ingredients.forEach((ingredient) => {
|
|
if (ingredient.drink_ingredient) {
|
|
const _drink = usePricelistStore().drinks.find(
|
|
(a) => a.id === ingredient.drink_ingredient?.drink_ingredient_id
|
|
);
|
|
retVal +=
|
|
ingredient.drink_ingredient.volume * (_drink?.cost_price_pro_volume?.value || 0);
|
|
}
|
|
if (ingredient.extra_ingredient) {
|
|
retVal += ingredient.extra_ingredient.price;
|
|
}
|
|
});
|
|
console.log(volume);
|
|
return (retVal * percentage) / 100;
|
|
});
|
|
}
|
|
}
|
|
|
|
export const usePricelistStore = defineStore({
|
|
id: 'pricelist',
|
|
|
|
state: () => ({
|
|
drinkTypes: [] as Array<FG.DrinkType>,
|
|
drinks: [] as Array<Drink>,
|
|
extraIngredients: [] as Array<FG.ExtraIngredient>,
|
|
pricecalc_columns: [] as Array<string>,
|
|
}),
|
|
|
|
actions: {
|
|
async getDrinkTypes(force = false) {
|
|
if (force || this.drinks.length == 0) {
|
|
const { data } = await api.get<Array<FG.DrinkType>>('/pricelist/drink-types');
|
|
this.drinkTypes = data;
|
|
}
|
|
return this.drinkTypes;
|
|
},
|
|
async addDrinkType(name: string) {
|
|
const { data } = await api.post<FG.DrinkType>('/pricelist/drink-types', { name: name });
|
|
this.drinkTypes.push(data);
|
|
},
|
|
async removeDrinkType(id: number) {
|
|
await api.delete(`/pricelist/drink-types/${id}`);
|
|
const idx = this.drinkTypes.findIndex((val) => val.id == id);
|
|
if (idx >= 0) this.drinkTypes.splice(idx, 1);
|
|
},
|
|
async changeDrinkTypeName(drinkType: FG.DrinkType) {
|
|
await api.put(`/pricelist/drink-types/${drinkType.id}`, drinkType);
|
|
const itm = this.drinkTypes.filter((val) => val.id == drinkType.id);
|
|
if (itm.length > 0) itm[0].name = drinkType.name;
|
|
},
|
|
async getExtraIngredients() {
|
|
const { data } = await api.get<Array<FG.ExtraIngredient>>(
|
|
'pricelist/ingredients/extraIngredients'
|
|
);
|
|
this.extraIngredients = data;
|
|
},
|
|
async setExtraIngredient(ingredient: FG.ExtraIngredient) {
|
|
const { data } = await api.post<FG.ExtraIngredient>(
|
|
'pricelist/ingredients/extraIngredients',
|
|
ingredient
|
|
);
|
|
this.extraIngredients.push(data);
|
|
},
|
|
async updateExtraIngredient(ingredient: FG.ExtraIngredient) {
|
|
const { data } = await api.put<FG.ExtraIngredient>(
|
|
`pricelist/ingredients/extraIngredients/${ingredient.id}`,
|
|
ingredient
|
|
);
|
|
const index = this.extraIngredients.findIndex((a) => a.id === ingredient.id);
|
|
if (index > -1) {
|
|
this.extraIngredients[index] = data;
|
|
} else {
|
|
this.extraIngredients.push(data);
|
|
}
|
|
},
|
|
async deleteExtraIngredient(ingredient: FG.ExtraIngredient) {
|
|
await api.delete(`pricelist/ingredients/extraIngredients/${ingredient.id}`);
|
|
const index = this.extraIngredients.findIndex((a) => a.id === ingredient.id);
|
|
if (index > -1) {
|
|
this.extraIngredients.splice(index, 1);
|
|
}
|
|
},
|
|
getDrinks() {
|
|
api
|
|
.get('pricelist/drinks')
|
|
.then((response: AxiosResponse<FG.Drink[]>) => {
|
|
this.drinks = [];
|
|
response.data.forEach((drink) => {
|
|
this.drinks.push(new Drink(drink));
|
|
});
|
|
this.drinks.forEach((drink) => {
|
|
const _drink = response.data.find((a) => a.id === drink.id);
|
|
_drink?.volumes.forEach((volume) => {
|
|
drink.volumes.push(new DrinkPriceVolume(volume, drink));
|
|
});
|
|
});
|
|
console.log(this.drinks);
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
sortPrices(volume: DrinkPriceVolume) {
|
|
volume.prices.sort((a, b) => {
|
|
if (a.price > b.price) return 1;
|
|
if (b.price > a.price) return -1;
|
|
return 0;
|
|
});
|
|
},
|
|
deletePrice(price: FG.DrinkPrice, volume: FG.DrinkPriceVolume) {
|
|
api
|
|
.delete(`pricelist/prices/${price.id}`)
|
|
.then(() => {
|
|
const index = volume.prices.findIndex((a) => a.id == price.id);
|
|
if (index > -1) {
|
|
volume.prices.splice(index, 1);
|
|
}
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
deleteVolume(volume: FG.DrinkPriceVolume, drink: FG.Drink) {
|
|
api
|
|
.delete(`pricelist/volumes/${volume.id}`)
|
|
.then(() => {
|
|
const index = drink.volumes.findIndex((a) => a.id === volume.id);
|
|
if (index > -1) {
|
|
drink.volumes.splice(index, 1);
|
|
}
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
deleteIngredient(ingredient: FG.Ingredient, volume: DrinkPriceVolume) {
|
|
api
|
|
.delete(`pricelist/ingredients/${ingredient.id}`)
|
|
.then(() => {
|
|
const index = volume.ingredients.findIndex((a) => a.id === ingredient.id);
|
|
if (index > -1) {
|
|
volume.ingredients.splice(index, 1);
|
|
}
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
setDrink(drink: FG.Drink) {
|
|
api
|
|
.post('pricelist/drinks', drink)
|
|
.then((response: AxiosResponse<FG.Drink>) => {
|
|
this.drinks.push(new Drink(response.data));
|
|
const drink = this.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) {
|
|
api
|
|
.put(`pricelist/drinks/${drink.id}`, {
|
|
...drink,
|
|
cost_price_pro_volume: drink.cost_price_pro_volume?.value,
|
|
})
|
|
.then(({ data }: AxiosResponse<FG.Drink>) => {
|
|
const index = this.drinks.findIndex((a) => a.id === data.id);
|
|
if (index > -1) {
|
|
this.drinks[index] = new Drink(data);
|
|
const drink = this.drinks.find((a) => a.id === data.id);
|
|
data.volumes.forEach((volume) => {
|
|
drink?.volumes.push(new DrinkPriceVolume(volume, drink));
|
|
});
|
|
}
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
deleteDrink(drink: Drink) {
|
|
api
|
|
.delete(`pricelist/drinks/${drink.id}`)
|
|
.then(() => {
|
|
const index = this.drinks.findIndex((a) => a.id === drink.id);
|
|
if (index > -1) {
|
|
this.drinks.splice(index, 1);
|
|
}
|
|
})
|
|
.catch((err) => console.warn(err));
|
|
},
|
|
getPriceCalcColumn(userid: string) {
|
|
api
|
|
.get(`pricelist/users/${userid}/pricecalc_columns`)
|
|
.then(({ data }: AxiosResponse<Array<string>>) => {
|
|
if (data.length > 0) {
|
|
this.pricecalc_columns = data;
|
|
}
|
|
})
|
|
.catch((err) => console.log(err));
|
|
},
|
|
updatePriceCalcColumn(userid: string, data: Array<string>) {
|
|
api
|
|
.put(`pricelist/users/${userid}/pricecalc_columns`, data)
|
|
.then(() => {
|
|
this.pricecalc_columns = data;
|
|
})
|
|
.catch((err) => console.log(err));
|
|
},
|
|
},
|
|
});
|
|
|
|
export { create_min_prices, DrinkPriceVolume, MinPrice, Drink };
|