Merge pull request #260 from gradido/dynamic-balance

bug: Dynamic Balance
This commit is contained in:
Moriz Wahl 2021-04-29 19:19:31 +02:00 committed by GitHub
commit bf0c6098bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 116 additions and 111 deletions

View File

@ -61,8 +61,8 @@ class AppRequestsController extends AppController
if(is_array($field)) {
$one_exist = false;
foreach($field as $oneField) {
if(isset($data[$oneField])) {
$param[$oneField] = $data[$oneField];
if(isset($data->$oneField)) {
$param[$oneField] = $data->$oneField;
$one_exist = true;
break;
}
@ -71,10 +71,10 @@ class AppRequestsController extends AppController
return ['state' => 'error', 'msg' => 'missing field of set', 'details' => $field];
}
} else {
if(!isset($data[$field])) {
if(!isset($data->$field)) {
return ['state' => 'error', 'msg' => 'missing field', 'details' => $field . ' not found'];
} else {
$param[$field] = $data[$field];
$param[$field] = $data->$field;
}
}
}
@ -85,9 +85,9 @@ class AppRequestsController extends AppController
{
foreach(array_keys($replaceKeys) as $key) {
$newKey = $replaceKeys[$key];
if(isset($data[$key])) {
$data[$newKey] = $data[$key];
unset($data[$key]);
if(isset($data->$key)) {
$data->$newKey = $data->$key;
unset($data->$key);
}
}
}
@ -98,8 +98,8 @@ class AppRequestsController extends AppController
$data = $this->request->input('json_decode');
}
$session_id = 0;
if(isset($data['session_id'])) {
$session_id = $data['session_id'];
if(isset($data->session_id)) {
$session_id = $data->session_id;
}
$login_request_result = $this->requestLogin($session_id, false);
if($login_request_result !== true) {
@ -119,12 +119,12 @@ class AppRequestsController extends AppController
return ['state' => 'error', 'msg' => 'amount is invalid', 'details' => $param['amount']];
}
if(isset($data['memo'])) {
$param['memo'] = $data['memo'];
if(isset($data->memo)) {
$param['memo'] = $data->memo;
}
if(isset($data['auto_sign'])) {
$param['auto_sign'] = boolval($data['auto_sign']);
if(isset($data->auto_sign)) {
$param['auto_sign'] = boolval($data->auto_sign);
}
return true;

View File

@ -199,7 +199,7 @@ class StateBalancesTable extends Table
$amount = 0;
if($transaction->transaction_type_id == 1) { // creation
$temp = $transaction->transaction_creations[0];
$temp = $transaction->transaction_creation;
/*$balance_temp = $this->newEntity();
$balance_temp->amount = $temp->amount;
@ -211,7 +211,7 @@ class StateBalancesTable extends Table
//$amount_date =
} else if($transaction->transaction_type_id == 2) { // transfer
$temp = $transaction->transaction_send_coins[0];
$temp = $transaction->transaction_send_coin;
$amount = intval($temp->amount);
// reverse if sender
if($stateUserId == $temp->state_user_id) {

View File

@ -49,12 +49,13 @@ const communityAPI = {
}
return apiPost(CONFIG.COMMUNITY_API__URL + 'createCoins/', payload)
},*/
send: async (session_id, email, amount, memo) => {
send: async (session_id, email, amount, memo, target_date) => {
const payload = {
session_id,
email,
amount,
memo,
target_date,
auto_sign: true,
}
return apiPost(CONFIG.COMMUNITY_API_URL + 'sendCoins/', payload)

View File

@ -10,7 +10,7 @@
<img :src="logo" class="navbar-brand-img" alt="..." />
</div>
<b-row class="text-center">
<b-col>{{ $n($store.state.user.balance) }} GDD</b-col>
<b-col>{{ $n(balance) }} GDD</b-col>
</b-row>
<slot name="mobile-right">
<ul class="nav align-items-center d-md-none">
@ -88,6 +88,10 @@ export default {
default: true,
description: 'Whether sidebar should autoclose on mobile when clicking an item',
},
balance: {
type: Number,
default: 0,
},
},
provide() {
return {

View File

@ -1,7 +1,6 @@
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import communityAPI from '../apis/communityAPI'
import createPersistedState from 'vuex-persistedstate'
export const store = new Vuex.Store({
@ -20,13 +19,6 @@ export const store = new Vuex.Store({
balance_gdt: 0,
},
modals: false,
optionAxios: {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': 'true',
},
},
},
getters: {},
// Syncronous mutation of the state
@ -65,13 +57,5 @@ export const store = new Vuex.Store({
commit('email', null)
sessionStorage.clear()
},
accountBalance: async ({ commit, dispatch, state }) => {
const result = await communityAPI.balance(state.session_id)
if (result.success) {
commit('user_balance', result.result.data.balance)
} else {
//dispatch('logout')
}
},
},
})

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-row v-show="row_form">
<b-row v-show="showTransactionList">
<b-col xl="12" md="12">
<b-alert show dismissible variant="warning" class="text-center">
<span class="alert-text" v-html="$t('form.attention')"></span>
@ -16,8 +16,8 @@
<div v-if="scan">
<!-- <b-row>
<qrcode-capture @detect="onDetect" capture="user" ></qrcode-capture>
</b-row> -->
<qrcode-capture @detect="onDetect" capture="user" ></qrcode-capture>
</b-row> -->
<qrcode-stream class="mt-3" @decode="onDecode" @detect="onDetect"></qrcode-stream>
@ -80,7 +80,7 @@
<br />
<div>
<b-col class="text-left p-3 p-sm-1">{{ $t('form.amount') }}</b-col>
<b-col v-if="$store.state.user.balance == form.amount" class="text-right">
<b-col v-if="balance == form.amount" class="text-right">
<b-badge variant="primary">{{ $t('form.max_gdd_info') }}</b-badge>
</b-col>
<b-input-group
@ -100,7 +100,7 @@
placeholder="0.01"
step="0.01"
min="0.01"
:max="$store.state.user.balance"
:max="balance"
style="font-size: xx-large; padding-left: 20px"
></b-form-input>
</b-input-group>
@ -204,9 +204,8 @@ export default {
BIcon,
},
props: {
row_form: { type: Boolean, default: true },
row_check: { type: Boolean, default: false },
row_thx: { type: Boolean, default: false },
balance: { type: Number, default: 0 },
showTransactionList: { type: Boolean, default: true },
},
data() {
return {
@ -226,6 +225,8 @@ export default {
auto_sign: true,
},
send: false,
row_check: false,
row_thx: false,
}
},
computed: {},
@ -234,7 +235,6 @@ export default {
this.scan = !this.scan
},
async onDecode(decodedString) {
//console.log('onDecode JSON.parse(decodedString)', JSON.parse(decodedString))
const arr = JSON.parse(decodedString)
this.form.email = arr[0].email
this.form.amount = arr[0].amount
@ -244,30 +244,31 @@ export default {
//event.preventDefault()
this.ajaxCreateData.email = this.form.email
this.ajaxCreateData.amount = this.form.amount
this.ajaxCreateData.target_date = Date.now()
const now = new Date(Date.now()).toISOString()
this.ajaxCreateData.target_date = now
this.ajaxCreateData.memo = this.form.memo
this.$emit('change-rows', { row_form: false, row_check: true, row_thx: false })
this.$emit('toggle-show-list', false)
this.row_check = true
this.row_thx = false
},
async sendTransaction() {
this.ajaxCreateData.amount = this.ajaxCreateData.amount * 10000
const result = await communityAPI.send(
this.$store.state.session_id,
this.ajaxCreateData.email,
this.ajaxCreateData.amount,
this.ajaxCreateData.amount * 10000,
this.ajaxCreateData.memo,
this.ajaxCreateData.target_date,
)
// console.log(result)
if (result.success) {
// console.log('send success')
this.$emit('change-rows', { row_form: false, row_check: false, row_thx: true })
this.$emit('toggle-show-list', false)
this.row_check = false
this.row_thx = true
this.$emit('update-balance', { ammount: this.ajaxCreateData.amount })
} else {
// console.log('send error')
alert('error')
this.$emit('change-rows', { row_form: true, row_check: false, row_thx: false })
this.$emit('toggle-show-list', true)
this.row_check = false
this.row_thx = false
}
},
onReset(event) {
@ -275,10 +276,12 @@ export default {
this.form.email = ''
this.form.amount = ''
this.show = false
this.$emit('toggle-show-list', true)
this.row_check = false
this.row_thx = false
this.$nextTick(() => {
this.show = true
})
this.$emit('change-rows', { row_form: true, row_check: false, row_thx: false })
},
},
}

View File

@ -9,7 +9,6 @@ describe('GddStatus', () => {
let state = {
user: {
balance: 1234,
balance_gdt: 9876,
},
}
@ -22,8 +21,12 @@ describe('GddStatus', () => {
$n: jest.fn((n) => n),
}
let propsData = {
balance: 1234,
}
const Wrapper = () => {
return mount(GddStatus, { localVue, store, mocks })
return mount(GddStatus, { localVue, store, mocks, propsData })
}
describe('mount', () => {

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-row v-show="this.row_form">
<b-row v-show="showTransactionList">
<b-col xl="6" md="6">
<stats-card
type="gradient-red"
@ -8,7 +8,7 @@
class="mb-4 h1"
style="background-color: #ebebeba3 !important"
>
{{ $n($store.state.user.balance) }} GDD
{{ $n(balance) }} GDD
</stats-card>
</b-col>
<b-col xl="6" md="6">
@ -29,7 +29,8 @@
export default {
name: 'GddStatus',
props: {
row_form: { type: Boolean, default: true },
showTransactionList: { type: Boolean, default: true },
balance: { type: Number, default: 0 },
},
}
</script>

View File

@ -1,6 +1,6 @@
<template>
<div>
<b-list-group v-show="this.row_form">
<b-list-group v-show="showTransactionList">
<b-list-group-item
v-for="item in filteredItems"
:key="item.id"
@ -93,7 +93,7 @@ import communityAPI from '../../apis/communityAPI'
export default {
name: 'GddTable',
props: {
row_form: { type: Boolean, default: true },
showTransactionList: { type: Boolean, default: true },
},
data() {
return {

View File

@ -1,7 +1,7 @@
<template>
<div class="wrapper">
<notifications></notifications>
<side-bar @logout="logout">
<side-bar @logout="logout" :balance="balance">
<template slot="links">
<b-nav-item href="#!" to="/overview">
<b-nav-text class="p-0 text-lg text-muted">{{ $t('send') }}</b-nav-text>
@ -26,7 +26,7 @@
<div @click="$sidebar.displaySidebar(false)">
<fade-transition :duration="200" origin="center top" mode="out-in">
<!-- your content here -->
<router-view></router-view>
<router-view :balance="balance" @update-balance="updateBalance"></router-view>
</fade-transition>
</div>
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
@ -57,6 +57,7 @@ import DashboardNavbar from './DashboardNavbar.vue'
import ContentFooter from './ContentFooter.vue'
// import DashboardContent from './Content.vue';
import { FadeTransition } from 'vue2-transitions'
import communityAPI from '../../apis/communityAPI'
export default {
components: {
@ -65,6 +66,11 @@ export default {
// DashboardContent,
FadeTransition,
},
data() {
return {
balance: 0,
}
},
methods: {
initScrollbar() {
let isWindows = navigator.platform.startsWith('Win')
@ -78,10 +84,24 @@ export default {
this.$store.dispatch('logout')
this.$router.push('/login')
},
async loadBalance() {
const result = await communityAPI.balance(this.$store.state.session_id)
if (result.success) {
this.balance = result.result.data.balance / 10000
} else {
// what to do when loading balance fails?
}
},
updateBalance(ammount) {
this.balance -= ammount
},
},
mounted() {
this.initScrollbar()
},
created() {
this.loadBalance()
},
}
</script>
<style lang="scss"></style>

View File

@ -1,26 +1,17 @@
import { shallowMount } from '@vue/test-utils'
import KontoOverview from './KontoOverview'
import Vuex from 'vuex'
const localVue = global.localVue
describe('KontoOverview', () => {
let wrapper
let actions = {
accountBalance: jest.fn(),
}
let store = new Vuex.Store({
actions,
})
let mocks = {
$t: jest.fn((t) => t),
}
const Wrapper = () => {
return shallowMount(KontoOverview, { localVue, store, mocks })
return shallowMount(KontoOverview, { localVue, mocks })
}
describe('shallow Mount', () => {
@ -44,37 +35,34 @@ describe('KontoOverview', () => {
expect(wrapper.find('gdd-table-stub').exists()).toBeTruthy()
})
it('calls "accountBalance" action from store on creation', () => {
const spy = jest.spyOn(actions, 'accountBalance')
expect(spy).toHaveBeenCalled()
})
it('updates transctions data when change-transactions is emitted', async () => {
wrapper.find('gdd-table-stub').vm.$emit('change-transactions', [0, 1])
await wrapper.vm.$nextTick()
expect(wrapper.vm.transactions).toEqual(expect.arrayContaining([0, 1]))
})
describe('setRows method', () => {
describe('updateBalance method', () => {
beforeEach(async () => {
wrapper.find('gdd-send-stub').vm.$emit('change-rows', {
row_form: false,
row_check: true,
row_thx: true,
wrapper.find('gdd-send-stub').vm.$emit('update-balance', {
ammount: 42,
})
await wrapper.vm.$nextTick()
})
it('updates row_form data when change-rows is emitted', () => {
expect(wrapper.vm.row_form).toBeFalsy()
it('emmits updateBalance with correct value', () => {
expect(wrapper.emitted('update-balance')).toEqual([[42]])
})
})
describe('toggleShowList method', () => {
beforeEach(async () => {
wrapper.setProps({ showTransactionList: false })
wrapper.find('gdd-send-stub').vm.$emit('toggle-show-list', true)
await wrapper.vm.$nextTick()
})
it('updates row_check data when change-rows is emitted', () => {
expect(wrapper.vm.row_check).toBeTruthy()
})
it('updates row_thx data when change-rows is emitted', () => {
expect(wrapper.vm.row_thx).toBeTruthy()
it('changes the value of property showTransactionList', () => {
expect(wrapper.vm.showTransactionList).toBeTruthy()
})
})
})

View File

@ -2,17 +2,17 @@
<div>
<base-header class="pb-6 pb-8 pt-5 pt-md-8 bg-transparent"></base-header>
<b-container fluid class="mt--7">
<gdd-status :row_form="row_form" />
<gdd-status :balance="balance" :show-transaction-list="showTransactionList" />
<br />
<gdd-send
:row_form="row_form"
:row_check="row_check"
:row_thx="row_thx"
@change-rows="setRows"
:balance="balance"
:show-transaction-list="showTransactionList"
@update-balance="updateBalance"
@toggle-show-list="toggleShowList"
/>
<hr />
<gdd-table
:row_form="row_form"
:show-transaction-list="showTransactionList"
:transactions="transactions"
@change-transactions="setTransactions"
/>
@ -28,25 +28,24 @@ export default {
name: 'Overview',
data() {
return {
row_form: true,
row_check: false,
row_thx: false,
transactions: [],
showTransactionList: true,
}
},
props: {
balance: { type: Number, default: 0 },
},
components: {
GddStatus,
GddSend,
GddTable,
},
created() {
this.$store.dispatch('accountBalance', this.$store.state.session_id)
},
methods: {
setRows(rows) {
this.row_form = rows.row_form
this.row_check = rows.row_check
this.row_thx = rows.row_thx
toggleShowList(bool) {
this.showTransactionList = bool
},
updateBalance(data) {
this.$emit('update-balance', data.ammount)
},
setTransactions(transactions) {
this.transactions = transactions

View File

@ -6,3 +6,5 @@ src/cpsp/*.cpp
src/cpp/proto/
build*/
/skeema/gradido_login/insert/crypto_key.sql
src/LOCALE/messages.pot

View File

@ -10,13 +10,13 @@ namespace model
namespace table
{
PendingTask::PendingTask()
: mUserId(0), mHederaId(0), mTaskTypeId(TASK_TYPE_NONE)
: mUserId(0), mHederaId(0), mTaskTypeId(TASK_TYPE_NONE), mChildPendingTaskId(0), mParentPendingTaskId(0)
{
}
PendingTask::PendingTask(int userId, std::string serializedProtoRequest, TaskType type)
: mUserId(userId), mHederaId(0), mRequest((const unsigned char*)serializedProtoRequest.data(), serializedProtoRequest.size()),
mTaskTypeId(TASK_TYPE_NONE)
mTaskTypeId(TASK_TYPE_NONE), mChildPendingTaskId(0), mParentPendingTaskId(0)
{
}