diff --git a/src/plugins/balance/components/BalanceHeader.vue b/src/plugins/balance/components/BalanceHeader.vue new file mode 100644 index 0000000..7d78b8b --- /dev/null +++ b/src/plugins/balance/components/BalanceHeader.vue @@ -0,0 +1,44 @@ + + + diff --git a/src/plugins/balance/components/Transaction.vue b/src/plugins/balance/components/Transaction.vue new file mode 100644 index 0000000..5e51920 --- /dev/null +++ b/src/plugins/balance/components/Transaction.vue @@ -0,0 +1,76 @@ + + + diff --git a/src/plugins/balance/pages/Add.vue b/src/plugins/balance/pages/Add.vue index 65862e4..37b529e 100644 --- a/src/plugins/balance/pages/Add.vue +++ b/src/plugins/balance/pages/Add.vue @@ -1,95 +1,123 @@ diff --git a/src/plugins/balance/pages/Admin.vue b/src/plugins/balance/pages/Admin.vue new file mode 100644 index 0000000..a0c0eb1 --- /dev/null +++ b/src/plugins/balance/pages/Admin.vue @@ -0,0 +1,54 @@ + + + diff --git a/src/plugins/balance/pages/Transfer.vue b/src/plugins/balance/pages/Transfer.vue new file mode 100644 index 0000000..83a7f0e --- /dev/null +++ b/src/plugins/balance/pages/Transfer.vue @@ -0,0 +1,111 @@ + + + diff --git a/src/plugins/balance/permissions.ts b/src/plugins/balance/permissions.ts new file mode 100644 index 0000000..0543207 --- /dev/null +++ b/src/plugins/balance/permissions.ts @@ -0,0 +1,21 @@ +const PERMISSIONS = { + // Show own and others balance + SHOW: 'balance_show', + SHOW_OTHER: 'balance_show_others', + // Credit balance (give) + CREDIT: 'balance_credit', + // Debit balance (take) + DEBIT: 'balance_debit', + // Debit own balance only + DEBIT_OWN: 'balance_debit_own', + // Send from to other + SEND: 'balance_send', + // Send from other to another + SEND_OTHER: 'balance_send_others', + // Can set limit for users + SET_LIMIT: 'balance_set_limit', + //Allow sending / sub while exceeding the set limit + EXCEED_LIMIT: 'balance_exceed_limit' +}; + +export default PERMISSIONS; diff --git a/src/plugins/balance/plugin.ts b/src/plugins/balance/plugin.ts index b411f8c..f84d72c 100644 --- a/src/plugins/balance/plugin.ts +++ b/src/plugins/balance/plugin.ts @@ -1,12 +1,12 @@ import { Module } from 'vuex'; import { StateInterface } from 'src/store'; -import mainRoutes from './routes'; +import routes from './routes'; import { FG_Plugin } from 'src/plugins'; import balance, { BalanceInterface } from './store/balance'; const plugin: FG_Plugin.Plugin = { name: 'Balance', - mainRoutes, + mainRoutes: routes, requiredModules: ['User'], requiredBackendModules: ['balance'], version: '0.0.1', diff --git a/src/plugins/balance/routes/index.ts b/src/plugins/balance/routes/index.ts index 1b4a1f0..e84aa82 100644 --- a/src/plugins/balance/routes/index.ts +++ b/src/plugins/balance/routes/index.ts @@ -1,24 +1,5 @@ import { FG_Plugin } from 'src/plugins'; - -const permissions = { - // Show own and others balance - SHOW: 'balance_show', - SHOW_OTHER: 'balance_show_others', - // Credit balance (give) - CREDIT: 'balance_credit', - // Debit balance (take) - DEBIT: 'balance_debit', - // Debit own balance only - DEBIT_OWN: 'balance_debit_own', - // Send from to other - SEND: 'balance_send', - // Send from other to another - SEND_OTHER: 'balance_send_others', - // Can set limit for users - SET_LIMIT: 'balance_set_limit', - //Allow sending / sub while exceeding the set limit - EXCEED_LIMIT: 'balance_exceed_limit' -}; +import permissions from '../permissions'; const mainRoutes: FG_Plugin.PluginRouteConfig[] = [ { @@ -26,17 +7,33 @@ const mainRoutes: FG_Plugin.PluginRouteConfig[] = [ icon: 'mdi-cash-100', path: 'balance', name: 'balance', - component: () => import('../pages/MainPage.vue'), + redirect: { name: 'balance-add' }, meta: { permissions: ['user'] }, children: [ { title: 'Anschreiben', - icon: 'mdi-cash-100', - path: 'balance-add', + icon: 'mdi-cash-plus', + path: 'add', name: 'balance-add', shortcut: true, meta: { permissions: [permissions.DEBIT_OWN, permissions.SHOW] }, component: () => import('../pages/Add.vue') + }, + { + title: 'Übertragen', + icon: 'mdi-cash-refund', + path: 'transfer', + name: 'balance-transfer', + meta: { permissions: [permissions.SEND] }, + component: () => import('../pages/Transfer.vue') + }, + { + title: 'Verwaltung', + icon: 'mdi-account-cash', + path: 'admin', + name: 'balance-admin', + meta: { permissions: [permissions.DEBIT_OWN, permissions.SHOW] }, + component: () => import('../pages/Admin.vue') } ] } diff --git a/src/plugins/balance/store/balance.ts b/src/plugins/balance/store/balance.ts index f86939f..505111b 100644 --- a/src/plugins/balance/store/balance.ts +++ b/src/plugins/balance/store/balance.ts @@ -9,51 +9,75 @@ interface BalanceResponse { debit: number; } -export interface BalanceInterface extends BalanceResponse { - limit: number; +export interface UserBalance extends BalanceResponse { + limit: number | null; +} + +export interface BalanceInterface { + balances: Map; + shortcuts: Array; loading: number; } +export interface StateInterfaceBalance extends StateInterface { + balance: BalanceInterface; +} + const state: BalanceInterface = { - balance: 0, - credit: 0, - debit: 0, - limit: 0, + balances: new Map(), + shortcuts: [], loading: 0 }; const mutations: MutationTree = { - setBalance(state, data: number) { - state.balance = data; + setBalance(state, data: { userid: string; balance: BalanceResponse }) { + state.balances.set( + data.userid, + Object.assign({ limit: state.balances.get(data.userid)?.limit || null }, data.balance) + ); }, - setCredit(state, data: number) { - state.credit = data; + changeBalance(state, data: { userid: string; amount: number }) { + const user = state.balances.get(data.userid); + if (data.amount < 0) user.debit += data.amount; + else user.credit += data.amount; + user.balance += data.amount; }, - setDebit(state, data: number) { - state.debit = data; - }, - setLimit(state, data: number) { - state.limit = data; + setLimit(state, data: { userid: string; limit: number | null }) { + if (state.balances.has(data.userid)) + (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) { + state.shortcuts = data.sort().reverse(); } }; const actions: ActionTree = { - getBalance({ commit, rootState }) { + getShortcuts({ commit, state, rootState }, force = false) { + if (force || state.shortcuts.length == 0) { + commit('setLoading'); + const user = rootState.user.currentUser; + return axios + .get(`/users/${user.userid}/balance/shortcuts`) + .then(({ data }: AxiosResponse) => { + commit('setShortcuts', data); + return data; + }) + .finally(() => commit('setLoading', false)); + } + }, + getBalance({ commit, rootState }, user: FG.User | undefined = undefined) { commit('setLoading'); - axios - /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */ - .get(`/users/${rootState.user.currentUser?.userid}/balance`) + if (!user) user = rootState.user.currentUser; + return axios + .get(`/users/${user.userid}/balance`) .then(({ data }: AxiosResponse) => { - commit('setBalance', data.balance); - commit('setCredit', data.credit); - commit('setDebit', data.debit); - }) - .catch(err => { - console.warn(err); + commit('setBalance', { userid: user?.userid, balance: data }); + return data; }) .finally(() => commit('setLoading', false)); }, @@ -70,19 +94,32 @@ const actions: ActionTree = { }) .finally(() => commit('setLoading', false)); }, - changeBalance({ rootState, dispatch, commit }, amount: number) { + revert({ dispatch }, transaction: FG.Transaction) { + return axios.delete(`/balance/${transaction.id}`).then(() => { + dispatch('getBalance').catch(err => console.warn(err)); + }); + }, + changeBalance({ dispatch, commit }, data: { amount: number; user: string; sender?: string }) { commit('setLoading'); - axios - /* eslint-disable-next-line @typescript-eslint/restrict-template-expressions */ - .put(`/users/${rootState.user.currentUser?.userid}/balance`, < - { amount: number } - >{ - amount: amount + return axios + .put(`/users/${data.user}/balance`, data) + .then((response: AxiosResponse) => { + 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 response.data; }) - .then(() => { + .catch(err => { + // Maybe Balance changed dispatch('getBalance').catch(err => console.warn(err)); + console.warn(err); }) - .catch(err => console.warn(err)) .finally(() => commit('setLoading', false)); } };