flaschengeist-pricelist/src/store.ts

401 lines
13 KiB
TypeScript

import { api } from '@flaschengeist/api';
import { defineStore } from 'pinia';
import { calc_volume, calc_cost_per_volume, calc_all_min_prices } from './utils/utils';
import Ingredient = FG.Ingredient;
interface DrinkPriceVolume extends Omit<FG.DrinkPriceVolume, 'volume'> {
_volume: number;
volume?: number;
}
interface Drink extends Omit<Omit<FG.Drink, 'cost_per_volume'>, 'volumes'> {
volumes: DrinkPriceVolume[];
cost_per_volume?: number;
_cost_per_volume?: number;
}
interface Pricelist {
name: string;
type: FG.DrinkType;
tags: Array<FG.Tag>;
volume: number;
price: number;
public: boolean;
description: string;
}
class DrinkPriceVolume implements DrinkPriceVolume {
constructor({ id, volume, prices, ingredients }: FG.DrinkPriceVolume) {
this.id = id;
this._volume = volume;
this.prices = prices;
this.ingredients = ingredients;
this.min_prices = [];
this.volume = calc_volume(this);
}
}
class Drink {
constructor({
id,
article_id,
package_size,
name,
volume,
cost_per_volume,
cost_per_package,
tags,
type,
has_image,
receipt,
}: FG.Drink) {
this.id = id;
this.article_id = article_id;
this.package_size = package_size;
this.name = name;
this.volume = volume;
this.cost_per_package = cost_per_package;
this._cost_per_volume = cost_per_volume;
this.cost_per_volume = calc_cost_per_volume(this);
this.tags = tags;
this.type = type;
this.volumes = [];
this.has_image = has_image;
this.receipt = receipt || [];
}
}
interface Order {
label: string;
name: string;
}
export const usePricelistStore = defineStore({
id: 'pricelist',
state: () => ({
drinkTypes: [] as Array<FG.DrinkType>,
drinks: [] as Array<Drink>,
pricelist: [] as Array<FG.DrinkPrice>,
extraIngredients: [] as Array<FG.ExtraIngredient>,
min_prices: [] as Array<number>,
tags: [] as Array<FG.Tag>,
pricecalc_columns: [] as Array<string>,
pricelist_view: false as boolean,
pricelist_columns_order: [] as Array<Order>,
}),
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);
}
},
async getDrinks(filter: {
limit?: number;
offset?: number;
descending?: boolean;
search_name?: string;
search_key?: string;
receipt?: boolean;
}) {
if (!filter) filter = { limit: 10 };
console.log('filter_api', filter);
const { data } = await api.get<Array<FG.Drink>>('pricelist/drinks', {
params: filter,
});
this.drinks = [];
data.drinks.forEach((drink) => {
const _drink = new Drink(drink);
drink.volumes.forEach((volume) => {
const _volume = new DrinkPriceVolume(volume);
_drink.volumes.push(_volume);
});
this.drinks.push(_drink);
});
calc_all_min_prices(this.drinks, this.min_prices);
return data;
},
sortPrices(volume: DrinkPriceVolume) {
volume.prices.sort((a, b) => {
if (a.price > b.price) return 1;
if (b.price > a.price) return -1;
return 0;
});
},
async getDrinks_no_store(filter: {
limit?: number;
offset?: number;
descending?: boolean;
search_name?: string;
search_key?: string;
ingredient?: boolean;
}) {
if (!filter) filter = { limit: 10 };
console.log('filter_api', filter);
const { data } = await api.get<{ drinks: Array<FG.Drink>; count: number }>(
'pricelist/drinks',
{
params: filter,
}
);
const drinks = [];
data.drinks.forEach((drink) => {
const _drink = new Drink(drink);
drink.volumes.forEach((volume) => {
const _volume = new DrinkPriceVolume(volume);
_drink.volumes.push(_volume);
});
drinks.push(_drink);
});
calc_all_min_prices(drinks, this.min_prices);
return drinks;
},
async getPricelist(filter: {
limit?: number;
offset?: number;
descending?: boolean;
search_name?: string;
search_key?: string;
sortBy?: string;
}) {
const { data } = await api.get<{ pricelist: Array<FG.DrinkPrice>; count: number }>(
'pricelist/list',
{
params: filter,
}
);
this.pricelist = [];
console.log(data);
this.pricelist = data.pricelist;
console.log(this.pricelist);
return data.count;
},
async deletePrice(price: FG.DrinkPrice) {
await api.delete(`pricelist/prices/${price.id}`);
},
async deleteVolume(volume: DrinkPriceVolume, drink: Drink) {
await api.delete(`pricelist/volumes/${volume.id}`);
const index = drink.volumes.findIndex((a) => a.id === volume.id);
if (index > -1) {
drink.volumes.splice(index, 1);
}
},
async deleteIngredient(ingredient: FG.Ingredient) {
await api.delete(`pricelist/ingredients/${ingredient.id}`);
},
async setDrink(drink: Drink) {
const { data } = await api.post<FG.Drink>('pricelist/drinks', {
...drink,
});
const _drink = new Drink(data);
data.volumes.forEach((volume) => {
const _volume = new DrinkPriceVolume(volume);
_drink.volumes.push(_volume);
});
this.drinks.push(_drink);
calc_all_min_prices(this.drinks, this.min_prices);
return _drink;
},
async updateDrink(drink: Drink) {
const { data } = await api.put<FG.Drink>(`pricelist/drinks/${drink.id}`, {
...drink,
});
const index = this.drinks.findIndex((a) => a.id === data.id);
if (index > -1) {
const _drink = new Drink(data);
data.volumes.forEach((volume) => {
const _volume = new DrinkPriceVolume(volume);
_drink.volumes.push(_volume);
});
this.drinks[index] = _drink;
}
if (!!drink.cost_per_volume) {
this.drinks.forEach((_drink: Drink) => {
_drink.volumes.forEach((_volume: DrinkPriceVolume) => {
_volume.ingredients.forEach((_ingredient: Ingredient) => {
if (
_ingredient.drink_ingredient &&
_ingredient.drink_ingredient.ingredient_id === drink.id
) {
_ingredient.drink_ingredient.cost_per_volume = drink.cost_per_volume;
_ingredient.drink_ingredient.name = drink.name;
}
});
});
});
}
calc_all_min_prices(this.drinks, this.min_prices);
},
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));
},
async get_min_prices() {
const { data } = await api.get<Array<number>>('pricelist/settings/min_prices');
this.min_prices = data;
},
async set_min_prices() {
await api.post<Array<number>>('pricelist/settings/min_prices', this.min_prices);
calc_all_min_prices(this.drinks, this.min_prices);
},
async upload_drink_picture(drink: Drink, file: File) {
const formData = new FormData();
formData.append('file', file);
const { data } = await api.post<FG.Drink>(`pricelist/drinks/${drink.id}/picture`, formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
const _drink = this.drinks.find((a) => a.id === drink.id);
if (_drink) {
_drink.has_image = data.has_image;
}
},
async delete_drink_picture(drink: Drink) {
await api.delete(`pricelist/drinks/${drink.id}/picture`);
drink.has_image = false;
},
async getTags() {
const { data } = await api.get<Array<FG.Tag>>('/pricelist/tags');
this.tags = data;
},
async setTag(tag: FG.Tag) {
const { data } = await api.post<FG.Tag>('/pricelist/tags', tag);
this.tags.push(data);
},
async updateTag(tag: FG.Tag) {
const { data } = await api.put<FG.Tag>(`/pricelist/tags/${tag.id}`, tag);
const index = this.tags.findIndex((a) => a.id === data.id);
if (index > -1) {
this.tags[index] = data;
}
},
async deleteTag(tag: FG.Tag) {
await api.delete(`/pricelist/tags/${tag.id}`);
const index = this.tags.findIndex((a) => a.id === tag.id);
if (index > -1) {
this.tags.splice(index, 1);
}
},
async getPriceCalcColumn(userid: string) {
const { data } = await api.get<Array<string>>(`pricelist/users/${userid}/pricecalc_columns`);
this.pricecalc_columns = data;
},
async updatePriceCalcColumn(userid: string, data: Array<string>) {
await api.put<Array<string>>(`pricelist/users/${userid}/pricecalc_columns`, data);
this.pricecalc_columns = data;
},
async getPriceListView(userid: string) {
const { data } = await api.get<{ value: boolean }>(`pricelist/users/${userid}/pricelist`);
this.pricelist_view = data.value;
},
async updatePriceListView(userid: string, data: boolean) {
await api.put<Array<string>>(`pricelist/users/${userid}/pricelist`, { value: data });
this.pricelist_view = data;
},
async getPriceListColumnOrder(userid: string) {
const { data } = await api.get<Array<Order>>(
`pricelist/users/${userid}/pricecalc_columns_order`
);
this.pricelist_columns_order = data;
},
async updatePriceListColumnOrder(userid: string, data: Array<Order>) {
await api.put<Array<string>>(`pricelist/users/${userid}/pricecalc_columns_order`, data);
this.pricelist_columns_order = data;
},
},
getters: {
/*pricelist() {
const retVal: Array<Pricelist> = [];
this.drinks.forEach((drink) => {
drink.volumes.forEach((volume) => {
volume.prices.forEach((price) => {
retVal.push({
name: drink.name,
type: <FG.DrinkType>drink.type,
tags: <Array<FG.Tag>>drink.tags,
volume: <number>volume.volume,
price: price.price,
public: price.public,
description: <string>price.description,
});
});
});
});
return retVal;
},*/
computed_pricelist() {
const retVal: Array<Pricelist> = [];
this.pricelist.forEach((price) => {
retVal.push({
name: price.volume.drink.name,
type: <FG.DrinkType>price.volume.drink.type,
tags: <Array<FG.Tag>>price.volume.drink.tags,
volume: <number>price.volume.volume,
public: price.public,
price: price.price,
description: <string>price.description,
});
});
},
},
});
export { DrinkPriceVolume, Drink, Order };