flaschengeist-frontend/src/plugins/balance/store/balance.ts

172 lines
5.7 KiB
TypeScript

import { Module, MutationTree, ActionTree, GetterTree } from 'vuex';
import { StateInterface } from 'src/store';
import { axios } from 'src/boot/axios';
import { AxiosResponse } from 'axios';
interface BalanceResponse {
balance: number;
credit: number;
debit: number;
}
export interface UserBalance extends BalanceResponse {
limit: number | null;
}
export interface BalanceInterface {
balances: Map<string, UserBalance>;
shortcuts: Array<number>;
transactions: Array<FG.Transaction>;
loading: number;
}
export interface StateInterfaceBalance extends StateInterface {
balance: BalanceInterface;
}
const state: BalanceInterface = {
balances: new Map<string, UserBalance>(),
shortcuts: [],
transactions: [],
loading: 0
};
const mutations: MutationTree<BalanceInterface> = {
setBalance(state, data: { userid: string; balance: BalanceResponse }) {
state.balances.set(
data.userid,
Object.assign({ limit: state.balances.get(data.userid)?.limit || null }, data.balance)
);
},
changeBalance(state, data: { userid: string; amount: number }) {
const user = <UserBalance>state.balances.get(data.userid);
if (data.amount < 0) user.debit += data.amount;
else user.credit += data.amount;
user.balance += data.amount;
},
setLimit(state, data: { userid: string; limit: number | null }) {
if (state.balances.has(data.userid))
(<UserBalance>state.balances.get(data.userid)).limit = data.limit;
else state.balances.set(data.userid, { balance: 0, debit: 0, credit: 0, limit: data.limit });
},
setLoading(state, data = true) {
if (data) state.loading += 1;
else state.loading -= 1;
},
setShortcuts(state, data: Array<number>) {
state.shortcuts.splice(0, state.shortcuts.length, ...data);
},
addTransaction(state, data: FG.Transaction) {
state.transactions.push(data);
},
reverseTransaction(state, data: { transaction: FG.Transaction; reversal: FG.Transaction }) {
const idx = state.transactions.findIndex(value => value.id === data.transaction.id);
data.transaction.reversal = data.reversal;
if (idx > -1) state.transactions[idx] = data.transaction;
else state.transactions.push(data.transaction);
}
};
const actions: ActionTree<BalanceInterface, StateInterface> = {
addShortcut({ commit, state, rootState }, shortcut) {
const sc = [...state.shortcuts, shortcut];
sc.sort().reverse();
const user = <FG.User>rootState.user.currentUser;
return axios.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => {
commit('setShortcuts', sc);
});
},
removeShortcut({ commit, state, rootState }, shortcut) {
const sc = state.shortcuts.filter((value: number) => value != shortcut);
const user = <FG.User>rootState.user.currentUser;
return axios.put(`/users/${user.userid}/balance/shortcuts`, sc).then(() => {
commit('setShortcuts', sc);
});
},
getShortcuts({ commit, state, rootState }, force = false) {
if (force || state.shortcuts.length == 0) {
commit('setLoading');
const user = <FG.User>rootState.user.currentUser;
return axios
.get(`/users/${user.userid}/balance/shortcuts`)
.then(({ data }: AxiosResponse<BalanceResponse>) => {
commit('setShortcuts', data);
return data;
})
.finally(() => commit('setLoading', false));
}
},
getBalance({ commit, rootState }, user: FG.User | undefined = undefined) {
commit('setLoading');
if (!user) user = <FG.User>rootState.user.currentUser;
return axios
.get(`/users/${user.userid}/balance`)
.then(({ data }: AxiosResponse<BalanceResponse>) => {
commit('setBalance', { userid: user?.userid, balance: data });
return data;
})
.finally(() => commit('setLoading', false));
},
getLimit({ rootState, commit }) {
commit('setLoading');
axios
/* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */
.get(`/users/${rootState.user.currentUser?.userid}/balance/limit`)
.then(({ data }) => {
console.log(data);
})
.catch(err => {
console.warn(err);
})
.finally(() => commit('setLoading', false));
},
revert({ dispatch, commit }, transaction: FG.Transaction) {
return axios
.delete(`/balance/${transaction.id}`)
.then((response: AxiosResponse<FG.Transaction>) => {
commit('reverseTransaction', { transaction: transaction, reversal: response.data });
dispatch('getBalance').catch(err => console.warn(err));
});
},
changeBalance({ dispatch, commit }, data: { amount: number; user: string; sender?: string }) {
commit('setLoading');
return axios
.put(`/users/${data.user}/balance`, data)
.then((response: AxiosResponse<FG.Transaction>) => {
const transaction = response.data;
transaction.time = new Date(transaction.time);
commit('addTransaction', transaction);
commit(state.balances.has(data.user) ? 'changeBalance' : 'setBalance', {
userid: data.user,
amount: data.amount
});
if (data.sender)
commit(state.balances.has(data.sender) ? 'changeBalance' : 'setBalance', {
userid: data.sender,
amount: -1 * data.amount
});
return transaction;
})
.catch(err => {
console.debug(err);
// Maybe Balance changed
return dispatch('getBalance', data.sender ? data.sender : data.user);
})
.finally(() => commit('setLoading', false));
}
};
const getters: GetterTree<BalanceInterface, StateInterface> = {};
const balance: Module<BalanceInterface, StateInterface> = {
namespaced: true,
state,
mutations,
actions,
getters
};
export default balance;