mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Merge branch 'master' into last-community_server
This commit is contained in:
commit
19f6e1fc63
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -448,7 +448,7 @@ jobs:
|
|||||||
report_name: Coverage Admin Interface
|
report_name: Coverage Admin Interface
|
||||||
type: lcov
|
type: lcov
|
||||||
result_path: ./coverage/lcov.info
|
result_path: ./coverage/lcov.info
|
||||||
min_coverage: 78
|
min_coverage: 81
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|||||||
@ -12,7 +12,7 @@
|
|||||||
"dev": "yarn run serve",
|
"dev": "yarn run serve",
|
||||||
"build": "vue-cli-service build",
|
"build": "vue-cli-service build",
|
||||||
"lint": "eslint --ext .js,.vue .",
|
"lint": "eslint --ext .js,.vue .",
|
||||||
"test": "jest --coverage",
|
"test": "TZ=UTC jest --coverage",
|
||||||
"locales": "scripts/missing-keys.sh && scripts/sort.sh"
|
"locales": "scripts/missing-keys.sh && scripts/sort.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -36,14 +36,12 @@
|
|||||||
"graphql": "^15.6.1",
|
"graphql": "^15.6.1",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "26.6.3",
|
"jest": "26.6.3",
|
||||||
"moment": "^2.29.1",
|
|
||||||
"regenerator-runtime": "^0.13.9",
|
"regenerator-runtime": "^0.13.9",
|
||||||
"stats-webpack-plugin": "^0.7.0",
|
"stats-webpack-plugin": "^0.7.0",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
"vue-apollo": "^3.0.8",
|
"vue-apollo": "^3.0.8",
|
||||||
"vue-i18n": "^8.26.5",
|
"vue-i18n": "^8.26.5",
|
||||||
"vue-jest": "^3.0.7",
|
"vue-jest": "^3.0.7",
|
||||||
"vue-moment": "^4.1.0",
|
|
||||||
"vue-router": "^3.5.3",
|
"vue-router": "^3.5.3",
|
||||||
"vue-toasted": "^1.1.28",
|
"vue-toasted": "^1.1.28",
|
||||||
"vuex": "^3.6.2",
|
"vuex": "^3.6.2",
|
||||||
|
|||||||
@ -5,14 +5,6 @@ import { createPendingCreations } from '../graphql/createPendingCreations'
|
|||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
const apolloMock = jest.fn().mockResolvedValue({
|
|
||||||
data: {
|
|
||||||
verifyLogin: {
|
|
||||||
name: 'success',
|
|
||||||
id: 0,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
const apolloMutateMock = jest.fn().mockResolvedValue({
|
const apolloMutateMock = jest.fn().mockResolvedValue({
|
||||||
data: {
|
data: {
|
||||||
createPendingCreation: [0, 0, 0],
|
createPendingCreation: [0, 0, 0],
|
||||||
@ -23,19 +15,12 @@ const toastedErrorMock = jest.fn()
|
|||||||
const toastedSuccessMock = jest.fn()
|
const toastedSuccessMock = jest.fn()
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t, options) => (options ? [t, options] : t)),
|
||||||
$moment: jest.fn(() => {
|
$d: jest.fn((d) => {
|
||||||
return {
|
const date = new Date(d)
|
||||||
format: jest.fn((m) => m),
|
return date.toISOString().split('T')[0]
|
||||||
subtract: jest.fn(() => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloMock,
|
|
||||||
mutate: apolloMutateMock,
|
mutate: apolloMutateMock,
|
||||||
},
|
},
|
||||||
$store: {
|
$store: {
|
||||||
@ -56,7 +41,12 @@ const mocks = {
|
|||||||
const propsData = {
|
const propsData = {
|
||||||
type: '',
|
type: '',
|
||||||
creation: [],
|
creation: [],
|
||||||
itemsMassCreation: {},
|
}
|
||||||
|
|
||||||
|
const now = new Date(Date.now())
|
||||||
|
const getCreationDate = (sub) => {
|
||||||
|
const date = sub === 0 ? now : new Date(now.getFullYear(), now.getMonth() - sub, 1, 0)
|
||||||
|
return date.toISOString().split('T')[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('CreationFormular', () => {
|
describe('CreationFormular', () => {
|
||||||
@ -75,21 +65,24 @@ describe('CreationFormular', () => {
|
|||||||
expect(wrapper.find('.component-creation-formular').exists()).toBeTruthy()
|
expect(wrapper.find('.component-creation-formular').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('server sends back moderator data', () => {
|
describe('text and value form props', () => {
|
||||||
it('called store commit with mocked data', () => {
|
beforeEach(async () => {
|
||||||
expect(stateCommitMock).toBeCalledWith('moderator', { name: 'success', id: 0 })
|
wrapper = mount(CreationFormular, {
|
||||||
|
localVue,
|
||||||
|
mocks,
|
||||||
|
propsData: {
|
||||||
|
creationUserData: { memo: 'Memo from property', amount: 42 },
|
||||||
|
...propsData,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('server throws error for moderator data call', () => {
|
it('has text taken from props', () => {
|
||||||
beforeEach(() => {
|
expect(wrapper.vm.text).toBe('Memo from property')
|
||||||
jest.clearAllMocks()
|
|
||||||
apolloMock.mockRejectedValueOnce({ message: 'Ouch!' })
|
|
||||||
wrapper = Wrapper()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('has called store commit with fake data', () => {
|
it('has value taken from props', () => {
|
||||||
expect(stateCommitMock).toBeCalledWith('moderator', { id: 0, name: 'Test Moderator' })
|
expect(wrapper.vm.value).toBe(42)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -98,52 +91,6 @@ describe('CreationFormular', () => {
|
|||||||
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with mass creation', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
await wrapper.setProps({ type: 'massCreation', creation: [200, 400, 600] })
|
|
||||||
await wrapper.setData({ rangeMin: 180 })
|
|
||||||
await wrapper.setData({ text: 'Test create coins' })
|
|
||||||
await wrapper.setData({ value: 90 })
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('first radio button', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(0).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('emits update-radio-selected with index 0', () => {
|
|
||||||
expect(wrapper.emitted()['update-radio-selected']).toEqual([
|
|
||||||
[expect.arrayContaining([0])],
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('second radio button', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('emits update-radio-selected with index 1', () => {
|
|
||||||
expect(wrapper.emitted()['update-radio-selected']).toEqual([
|
|
||||||
[expect.arrayContaining([1])],
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('third radio button', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(2).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('emits update-radio-selected with index 2', () => {
|
|
||||||
expect(wrapper.emitted()['update-radio-selected']).toEqual([
|
|
||||||
[expect.arrayContaining([2])],
|
|
||||||
])
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('with single creation', () => {
|
describe('with single creation', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
@ -153,17 +100,17 @@ describe('CreationFormular', () => {
|
|||||||
item: { email: 'benjamin@bluemchen.de' },
|
item: { email: 'benjamin@bluemchen.de' },
|
||||||
})
|
})
|
||||||
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
||||||
await wrapper.find('textarea').setValue('Test create coins')
|
|
||||||
await wrapper.find('input[type="number"]').setValue(90)
|
await wrapper.find('input[type="number"]').setValue(90)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('first radio button', () => {
|
describe('first radio button', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await wrapper.findAll('input[type="radio"]').at(0).setChecked()
|
await wrapper.findAll('input[type="radio"]').at(0).setChecked()
|
||||||
|
await wrapper.find('textarea').setValue('Test create coins')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sets rangeMax to 200', () => {
|
it('sets rangeMax to 200', () => {
|
||||||
expect(wrapper.vm.rangeMax).toBe(400)
|
expect(wrapper.vm.rangeMax).toBe(200)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('sendForm', () => {
|
describe('sendForm', () => {
|
||||||
@ -177,7 +124,7 @@ describe('CreationFormular', () => {
|
|||||||
mutation: createPendingCreation,
|
mutation: createPendingCreation,
|
||||||
variables: {
|
variables: {
|
||||||
email: 'benjamin@bluemchen.de',
|
email: 'benjamin@bluemchen.de',
|
||||||
creationDate: 'YYYY-MM-01',
|
creationDate: getCreationDate(2),
|
||||||
amount: 90,
|
amount: 90,
|
||||||
memo: 'Test create coins',
|
memo: 'Test create coins',
|
||||||
moderator: 0,
|
moderator: 0,
|
||||||
@ -185,9 +132,30 @@ describe('CreationFormular', () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('emits update-user-data', () => {
|
||||||
|
expect(wrapper.emitted('update-user-data')).toEqual([
|
||||||
|
[{ email: 'benjamin@bluemchen.de' }, [0, 0, 0]],
|
||||||
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('sendForm', () => {
|
it('toasts a success message', () => {
|
||||||
|
expect(toastedSuccessMock).toBeCalledWith([
|
||||||
|
'creation_form.toasted',
|
||||||
|
{ email: 'benjamin@bluemchen.de', value: '90' },
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updates open creations in store', () => {
|
||||||
|
expect(stateCommitMock).toBeCalledWith('openCreationsPlus', 1)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('resets the form data', () => {
|
||||||
|
expect(wrapper.vm.value).toBe(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('sendForm with server error', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
apolloMutateMock.mockRejectedValueOnce({ message: 'Ouch!' })
|
apolloMutateMock.mockRejectedValueOnce({ message: 'Ouch!' })
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
await wrapper.find('.test-submit').trigger('click')
|
||||||
@ -373,9 +341,18 @@ describe('CreationFormular', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with mass creation', () => {
|
describe('mass creation with success', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
jest.clearAllMocks()
|
jest.clearAllMocks()
|
||||||
|
apolloMutateMock.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
createPendingCreations: {
|
||||||
|
success: true,
|
||||||
|
successfulCreation: ['bob@baumeister.de', 'bibi@bloxberg.de'],
|
||||||
|
failedCreation: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
await wrapper.setProps({
|
await wrapper.setProps({
|
||||||
type: 'massCreation',
|
type: 'massCreation',
|
||||||
creation: [200, 400, 600],
|
creation: [200, 400, 600],
|
||||||
@ -395,14 +372,14 @@ describe('CreationFormular', () => {
|
|||||||
pendingCreations: [
|
pendingCreations: [
|
||||||
{
|
{
|
||||||
email: 'bob@baumeister.de',
|
email: 'bob@baumeister.de',
|
||||||
creationDate: 'YYYY-MM-01',
|
creationDate: getCreationDate(1),
|
||||||
amount: 200,
|
amount: 200,
|
||||||
memo: 'Test mass create coins',
|
memo: 'Test mass create coins',
|
||||||
moderator: 0,
|
moderator: 0,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
email: 'bibi@bloxberg.de',
|
email: 'bibi@bloxberg.de',
|
||||||
creationDate: 'YYYY-MM-01',
|
creationDate: getCreationDate(1),
|
||||||
amount: 200,
|
amount: 200,
|
||||||
memo: 'Test mass create coins',
|
memo: 'Test mass create coins',
|
||||||
moderator: 0,
|
moderator: 0,
|
||||||
@ -412,6 +389,73 @@ describe('CreationFormular', () => {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('updates open creations in store', () => {
|
||||||
|
expect(stateCommitMock).toBeCalledWith('openCreationsPlus', 2)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('emits remove-all-bookmark', () => {
|
||||||
|
expect(wrapper.emitted('remove-all-bookmark')).toBeTruthy()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mass creation with success but all failed', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
apolloMutateMock.mockResolvedValue({
|
||||||
|
data: {
|
||||||
|
createPendingCreations: {
|
||||||
|
success: true,
|
||||||
|
successfulCreation: [],
|
||||||
|
failedCreation: ['bob@baumeister.de', 'bibi@bloxberg.de'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
await wrapper.setProps({
|
||||||
|
type: 'massCreation',
|
||||||
|
creation: [200, 400, 600],
|
||||||
|
items: [{ email: 'bob@baumeister.de' }, { email: 'bibi@bloxberg.de' }],
|
||||||
|
})
|
||||||
|
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
||||||
|
await wrapper.find('textarea').setValue('Test mass create coins')
|
||||||
|
await wrapper.find('input[type="number"]').setValue(200)
|
||||||
|
await wrapper.find('.test-submit').trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('updates open creations in store', () => {
|
||||||
|
expect(stateCommitMock).toBeCalledWith('openCreationsPlus', 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toasts two errors', () => {
|
||||||
|
expect(toastedErrorMock).toBeCalledWith(
|
||||||
|
'Could not created PendingCreation for bob@baumeister.de',
|
||||||
|
)
|
||||||
|
expect(toastedErrorMock).toBeCalledWith(
|
||||||
|
'Could not created PendingCreation for bibi@bloxberg.de',
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('mass creation with error', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
jest.clearAllMocks()
|
||||||
|
apolloMutateMock.mockRejectedValue({
|
||||||
|
message: 'Oh no!',
|
||||||
|
})
|
||||||
|
await wrapper.setProps({
|
||||||
|
type: 'massCreation',
|
||||||
|
creation: [200, 400, 600],
|
||||||
|
items: [{ email: 'bob@baumeister.de' }, { email: 'bibi@bloxberg.de' }],
|
||||||
|
})
|
||||||
|
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
||||||
|
await wrapper.find('textarea').setValue('Test mass create coins')
|
||||||
|
await wrapper.find('input[type="number"]').setValue(200)
|
||||||
|
await wrapper.find('.test-submit').trigger('click')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toasts an error message', () => {
|
||||||
|
expect(toastedErrorMock).toBeCalledWith('Oh no!')
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,51 +7,15 @@
|
|||||||
<label>{{ $t('creation_form.select_month') }}</label>
|
<label>{{ $t('creation_form.select_month') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<b-row class="ml-4">
|
<b-row class="ml-4">
|
||||||
<b-col>
|
<b-form-radio-group
|
||||||
<b-form-radio
|
v-model="selected"
|
||||||
id="beforeLastMonth"
|
:options="radioOptions"
|
||||||
v-model="radioSelected"
|
value-field="item"
|
||||||
:value="beforeLastMonth"
|
text-field="name"
|
||||||
:disabled="creation[0] === 0"
|
name="month-selection"
|
||||||
size="lg"
|
></b-form-radio-group>
|
||||||
@change="updateRadioSelected(beforeLastMonth, 0, creation[0])"
|
|
||||||
>
|
|
||||||
<label for="beforeLastMonth">
|
|
||||||
{{ beforeLastMonth.short }} {{ creation[0] != null ? creation[0] + ' GDD' : '' }}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
<b-col>
|
|
||||||
<b-form-radio
|
|
||||||
id="lastMonth"
|
|
||||||
v-model="radioSelected"
|
|
||||||
:value="lastMonth"
|
|
||||||
:disabled="creation[1] === 0"
|
|
||||||
size="lg"
|
|
||||||
@change="updateRadioSelected(lastMonth, 1, creation[1])"
|
|
||||||
>
|
|
||||||
<label for="lastMonth">
|
|
||||||
{{ lastMonth.short }} {{ creation[1] != null ? creation[1] + ' GDD' : '' }}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
<b-col>
|
|
||||||
<b-form-radio
|
|
||||||
id="currentMonth"
|
|
||||||
v-model="radioSelected"
|
|
||||||
:value="currentMonth"
|
|
||||||
:disabled="creation[2] === 0"
|
|
||||||
size="lg"
|
|
||||||
@change="updateRadioSelected(currentMonth, 2, creation[2])"
|
|
||||||
>
|
|
||||||
<label for="currentMonth">
|
|
||||||
{{ currentMonth.short }} {{ creation[2] != null ? creation[2] + ' GDD' : '' }}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
</b-row>
|
</b-row>
|
||||||
|
<b-row class="m-4" v-show="selected !== ''">
|
||||||
<div class="m-4" v-show="createdIndex != null">
|
|
||||||
<label>{{ $t('creation_form.select_value') }}</label>
|
<label>{{ $t('creation_form.select_value') }}</label>
|
||||||
<div>
|
<div>
|
||||||
<b-input-group prepend="GDD" append=".00">
|
<b-input-group prepend="GDD" append=".00">
|
||||||
@ -62,7 +26,6 @@
|
|||||||
:max="rangeMax"
|
:max="rangeMax"
|
||||||
></b-form-input>
|
></b-form-input>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
|
|
||||||
<b-input-group prepend="0" :append="String(rangeMax)" class="mt-3">
|
<b-input-group prepend="0" :append="String(rangeMax)" class="mt-3">
|
||||||
<b-form-input
|
<b-form-input
|
||||||
type="range"
|
type="range"
|
||||||
@ -73,7 +36,7 @@
|
|||||||
></b-form-input>
|
></b-form-input>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</b-row>
|
||||||
<div class="m-4">
|
<div class="m-4">
|
||||||
<label>{{ $t('creation_form.enter_text') }}</label>
|
<label>{{ $t('creation_form.enter_text') }}</label>
|
||||||
<div>
|
<div>
|
||||||
@ -100,18 +63,17 @@
|
|||||||
variant="success"
|
variant="success"
|
||||||
class="test-submit"
|
class="test-submit"
|
||||||
@click="submitCreation"
|
@click="submitCreation"
|
||||||
:disabled="radioSelected === '' || value <= 0 || text.length < 10"
|
:disabled="selected === '' || value <= 0 || text.length < 10"
|
||||||
>
|
>
|
||||||
{{ $t('creation_form.update_creation') }}
|
{{ $t('creation_form.update_creation') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
|
|
||||||
<b-button
|
<b-button
|
||||||
v-else
|
v-else
|
||||||
type="button"
|
type="button"
|
||||||
variant="success"
|
variant="success"
|
||||||
class="test-submit"
|
class="test-submit"
|
||||||
@click="submitCreation"
|
@click="submitCreation"
|
||||||
:disabled="radioSelected === '' || value <= 0 || text.length < 10"
|
:disabled="selected === '' || value <= 0 || text.length < 10"
|
||||||
>
|
>
|
||||||
{{ $t('creation_form.submit_creation') }}
|
{{ $t('creation_form.submit_creation') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
@ -123,11 +85,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { verifyLogin } from '../graphql/verifyLogin'
|
|
||||||
import { createPendingCreation } from '../graphql/createPendingCreation'
|
import { createPendingCreation } from '../graphql/createPendingCreation'
|
||||||
import { createPendingCreations } from '../graphql/createPendingCreations'
|
import { createPendingCreations } from '../graphql/createPendingCreations'
|
||||||
|
import { creationMonths } from '../mixins/creationMonths'
|
||||||
export default {
|
export default {
|
||||||
name: 'CreationFormular',
|
name: 'CreationFormular',
|
||||||
|
mixins: [creationMonths],
|
||||||
props: {
|
props: {
|
||||||
type: {
|
type: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -166,71 +129,39 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
radioSelected: '',
|
|
||||||
text: !this.creationUserData.memo ? '' : this.creationUserData.memo,
|
text: !this.creationUserData.memo ? '' : this.creationUserData.memo,
|
||||||
value: !this.creationUserData.amount ? 0 : this.creationUserData.amount,
|
value: !this.creationUserData.amount ? 0 : this.creationUserData.amount,
|
||||||
rangeMin: 0,
|
rangeMin: 0,
|
||||||
rangeMax: 1000,
|
rangeMax: 1000,
|
||||||
currentMonth: {
|
selected: '',
|
||||||
short: this.$moment().format('MMMM'),
|
|
||||||
long: this.$moment().format('YYYY-MM-DD'),
|
|
||||||
year: this.$moment().format('YYYY'),
|
|
||||||
},
|
|
||||||
lastMonth: {
|
|
||||||
short: this.$moment().subtract(1, 'month').format('MMMM'),
|
|
||||||
long: this.$moment().subtract(1, 'month').format('YYYY-MM') + '-01',
|
|
||||||
year: this.$moment().subtract(1, 'month').format('YYYY'),
|
|
||||||
},
|
|
||||||
beforeLastMonth: {
|
|
||||||
short: this.$moment().subtract(2, 'month').format('MMMM'),
|
|
||||||
long: this.$moment().subtract(2, 'month').format('YYYY-MM') + '-01',
|
|
||||||
year: this.$moment().subtract(2, 'month').format('YYYY'),
|
|
||||||
},
|
|
||||||
submitObj: null,
|
|
||||||
isdisabled: true,
|
|
||||||
createdIndex: null,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
// Auswählen eines Zeitraumes
|
updateRadioSelected(name) {
|
||||||
updateRadioSelected(name, index, openCreation) {
|
// do we want to reset the memo everytime the month changes?
|
||||||
this.createdIndex = index
|
|
||||||
this.text = this.$t('creation_form.creation_for') + ' ' + name.short + ' ' + name.year
|
this.text = this.$t('creation_form.creation_for') + ' ' + name.short + ' ' + name.year
|
||||||
// Wenn Mehrfachschöpfung
|
if (this.type === 'singleCreation') {
|
||||||
if (this.type === 'massCreation') {
|
|
||||||
// An Creation.vue emitten und radioSelectedMass aktualisieren
|
|
||||||
this.$emit('update-radio-selected', [name, index])
|
|
||||||
} else if (this.type === 'singleCreation') {
|
|
||||||
this.rangeMin = 0
|
this.rangeMin = 0
|
||||||
// Der maximale offene Betrag an GDD die für ein User noch geschöpft werden kann
|
this.rangeMax = name.creation
|
||||||
this.rangeMax = openCreation
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
submitCreation() {
|
submitCreation() {
|
||||||
|
let submitObj = []
|
||||||
if (this.type === 'massCreation') {
|
if (this.type === 'massCreation') {
|
||||||
// Die anzahl der Mitglieder aus der Mehrfachschöpfung
|
|
||||||
const i = Object.keys(this.items).length
|
|
||||||
// hinweis das eine Mehrfachschöpfung ausgeführt wird an (Anzahl der MItgleider an die geschöpft wird)
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('SUBMIT CREATION => ' + this.type + ' >> für VIELE ' + i + ' Mitglieder')
|
|
||||||
this.submitObj = []
|
|
||||||
this.items.forEach((item) => {
|
this.items.forEach((item) => {
|
||||||
this.submitObj.push({
|
submitObj.push({
|
||||||
email: item.email,
|
email: item.email,
|
||||||
creationDate: this.radioSelected.long,
|
creationDate: this.selected.date,
|
||||||
amount: Number(this.value),
|
amount: Number(this.value),
|
||||||
memo: this.text,
|
memo: this.text,
|
||||||
moderator: Number(this.$store.state.moderator.id),
|
moderator: Number(this.$store.state.moderator.id),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.log('MehrfachSCHÖPFUNG ABSENDEN FÜR >> ' + i + ' Mitglieder')
|
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: createPendingCreations,
|
mutation: createPendingCreations,
|
||||||
variables: {
|
variables: {
|
||||||
pendingCreations: this.submitObj,
|
pendingCreations: submitObj,
|
||||||
},
|
},
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
})
|
})
|
||||||
@ -241,6 +172,7 @@ export default {
|
|||||||
)
|
)
|
||||||
if (result.data.createPendingCreations.failedCreation.length > 0) {
|
if (result.data.createPendingCreations.failedCreation.length > 0) {
|
||||||
result.data.createPendingCreations.failedCreation.forEach((failed) => {
|
result.data.createPendingCreations.failedCreation.forEach((failed) => {
|
||||||
|
// TODO: Please localize this error message
|
||||||
this.$toasted.error('Could not created PendingCreation for ' + failed)
|
this.$toasted.error('Could not created PendingCreation for ' + failed)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -250,18 +182,17 @@ export default {
|
|||||||
this.$toasted.error(error.message)
|
this.$toasted.error(error.message)
|
||||||
})
|
})
|
||||||
} else if (this.type === 'singleCreation') {
|
} else if (this.type === 'singleCreation') {
|
||||||
this.submitObj = {
|
submitObj = {
|
||||||
email: this.item.email,
|
email: this.item.email,
|
||||||
creationDate: this.radioSelected.long,
|
creationDate: this.selected.date,
|
||||||
amount: Number(this.value),
|
amount: Number(this.value),
|
||||||
memo: this.text,
|
memo: this.text,
|
||||||
moderator: Number(this.$store.state.moderator.id),
|
moderator: Number(this.$store.state.moderator.id),
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: createPendingCreation,
|
mutation: createPendingCreation,
|
||||||
variables: this.submitObj,
|
variables: submitObj,
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
this.$emit('update-user-data', this.item, result.data.createPendingCreation)
|
this.$emit('update-user-data', this.item, result.data.createPendingCreation)
|
||||||
@ -272,36 +203,22 @@ export default {
|
|||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
this.$store.commit('openCreationsPlus', 1)
|
this.$store.commit('openCreationsPlus', 1)
|
||||||
this.submitObj = null
|
// what is this? Tests says that this.text is not reseted
|
||||||
this.createdIndex = null
|
|
||||||
// das creation Formular reseten
|
|
||||||
this.$refs.creationForm.reset()
|
this.$refs.creationForm.reset()
|
||||||
// Den geschöpften Wert auf o setzen
|
|
||||||
this.value = 0
|
this.value = 0
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.error(error.message)
|
||||||
this.submitObj = null
|
|
||||||
// das creation Formular reseten
|
|
||||||
this.$refs.creationForm.reset()
|
this.$refs.creationForm.reset()
|
||||||
// Den geschöpften Wert auf o setzen
|
|
||||||
this.value = 0
|
this.value = 0
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
searchModeratorData() {
|
|
||||||
this.$apollo
|
|
||||||
.query({ query: verifyLogin })
|
|
||||||
.then((result) => {
|
|
||||||
this.$store.commit('moderator', result.data.verifyLogin)
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.$store.commit('moderator', { id: 0, name: 'Test Moderator' })
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
selected() {
|
||||||
|
this.updateRadioSelected(this.selected)
|
||||||
},
|
},
|
||||||
created() {
|
|
||||||
this.searchModeratorData()
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -7,8 +7,9 @@ const apolloMutateMock = jest.fn().mockResolvedValue({
|
|||||||
data: {
|
data: {
|
||||||
updatePendingCreation: {
|
updatePendingCreation: {
|
||||||
creation: [0, 0, 0],
|
creation: [0, 0, 0],
|
||||||
|
amount: 500,
|
||||||
date: new Date(),
|
date: new Date(),
|
||||||
memo: 'qwertzuiopasdfghjkl',
|
memo: 'Test Schöpfung 2',
|
||||||
moderator: 0,
|
moderator: 0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -20,15 +21,9 @@ const toastedSuccessMock = jest.fn()
|
|||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
$moment: jest.fn(() => {
|
$d: jest.fn((d) => {
|
||||||
return {
|
const date = new Date(d)
|
||||||
format: jest.fn((m) => m),
|
return date.toISOString().split('T')[0]
|
||||||
subtract: jest.fn(() => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}),
|
}),
|
||||||
$apollo: {
|
$apollo: {
|
||||||
mutate: apolloMutateMock,
|
mutate: apolloMutateMock,
|
||||||
@ -48,12 +43,18 @@ const mocks = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const now = new Date(Date.now())
|
||||||
|
const getCreationDate = (sub) => {
|
||||||
|
const date = sub === 0 ? now : new Date(now.getFullYear(), now.getMonth() - sub, 1, 0)
|
||||||
|
return date.toISOString().split('T')[0]
|
||||||
|
}
|
||||||
|
|
||||||
const propsData = {
|
const propsData = {
|
||||||
creation: [200, 400, 600],
|
creation: [200, 400, 600],
|
||||||
creationUserData: {
|
creationUserData: {
|
||||||
memo: 'Test schöpfung 1',
|
memo: 'Test schöpfung 1',
|
||||||
amount: 100,
|
amount: 100,
|
||||||
date: '2021-12-01',
|
date: getCreationDate(0),
|
||||||
},
|
},
|
||||||
item: {
|
item: {
|
||||||
id: 0,
|
id: 0,
|
||||||
@ -82,42 +83,32 @@ describe('EditCreationFormular', () => {
|
|||||||
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
expect(wrapper.findAll('input[type="radio"]').length).toBe(3)
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('with single creation', () => {
|
it('has the third radio button checked', () => {
|
||||||
beforeEach(async () => {
|
expect(wrapper.findAll('input[type="radio"]').at(0).element.checked).toBeFalsy()
|
||||||
jest.clearAllMocks()
|
expect(wrapper.findAll('input[type="radio"]').at(1).element.checked).toBeFalsy()
|
||||||
await wrapper.setProps({ creation: [200, 400, 600] })
|
expect(wrapper.findAll('input[type="radio"]').at(2).element.checked).toBeTruthy()
|
||||||
await wrapper.setData({ rangeMin: 180 })
|
})
|
||||||
await wrapper.setData({ text: 'Test create coins' })
|
|
||||||
await wrapper.setData({ value: 90 })
|
it('has rangeMax of 700', () => {
|
||||||
})
|
expect(wrapper.find('input[type="number"]').attributes('max')).toBe('700')
|
||||||
|
})
|
||||||
describe('first radio button', () => {
|
|
||||||
beforeEach(async () => {
|
describe('change and save memo and value with success', () => {
|
||||||
await wrapper.findAll('input[type="radio"]').at(0).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMin to 0', () => {
|
|
||||||
expect(wrapper.vm.rangeMin).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMax to 200', () => {
|
|
||||||
expect(wrapper.vm.rangeMax).toBe(200)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sendForm', () => {
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
await wrapper.find('input[type="number"]').setValue(500)
|
||||||
|
await wrapper.find('textarea').setValue('Test Schöpfung 2')
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
await wrapper.find('.test-submit').trigger('click')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sends ... to apollo', () => {
|
it('calls the API', () => {
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
expect(apolloMutateMock).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
variables: {
|
variables: {
|
||||||
amount: 90,
|
|
||||||
creationDate: 'YYYY-MM-01',
|
|
||||||
email: 'bob@baumeister.de',
|
|
||||||
id: 0,
|
id: 0,
|
||||||
memo: 'Test create coins',
|
email: 'bob@baumeister.de',
|
||||||
|
creationDate: getCreationDate(0),
|
||||||
|
amount: 500,
|
||||||
|
memo: 'Test Schöpfung 2',
|
||||||
moderator: 0,
|
moderator: 0,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@ -125,7 +116,6 @@ describe('EditCreationFormular', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
it('emits update-user-data', () => {
|
it('emits update-user-data', () => {
|
||||||
expect(wrapper.emitted('update-user-data')).toBeTruthy()
|
|
||||||
expect(wrapper.emitted('update-user-data')).toEqual([
|
expect(wrapper.emitted('update-user-data')).toEqual([
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
@ -137,141 +127,35 @@ describe('EditCreationFormular', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('toast success message', () => {
|
it('emits update-creation-data', () => {
|
||||||
|
expect(wrapper.emitted('update-creation-data')).toEqual([
|
||||||
|
[
|
||||||
|
{
|
||||||
|
amount: 500,
|
||||||
|
date: expect.any(Date),
|
||||||
|
memo: 'Test Schöpfung 2',
|
||||||
|
moderator: 0,
|
||||||
|
row: expect.any(Object),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toasts a success message', () => {
|
||||||
expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_update')
|
expect(toastedSuccessMock).toBeCalledWith('creation_form.toasted_update')
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('sendForm with error', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
apolloMutateMock.mockRejectedValue({
|
|
||||||
message: 'Ouch!',
|
|
||||||
})
|
})
|
||||||
wrapper = Wrapper()
|
|
||||||
await wrapper.setProps({ type: 'singleCreation', creation: [200, 400, 600] })
|
describe('change and save memo and value with error', () => {
|
||||||
await wrapper.setData({ text: 'Test create coins' })
|
beforeEach(async () => {
|
||||||
await wrapper.setData({ value: 90 })
|
apolloMutateMock.mockRejectedValue({ message: 'Oh no!' })
|
||||||
await wrapper.findAll('input[type="radio"]').at(0).setChecked()
|
await wrapper.find('input[type="number"]').setValue(500)
|
||||||
await wrapper.setData({ rangeMin: 100 })
|
await wrapper.find('textarea').setValue('Test Schöpfung 2')
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
await wrapper.find('.test-submit').trigger('click')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('toast error message', () => {
|
it('toasts an error message', () => {
|
||||||
expect(toastedErrorMock).toBeCalledWith('Ouch!')
|
expect(toastedErrorMock).toBeCalledWith('Oh no!')
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('second radio button', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMin to 0', () => {
|
|
||||||
expect(wrapper.vm.rangeMin).toBe(0)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMax to 400', () => {
|
|
||||||
expect(wrapper.vm.rangeMax).toBe(400)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sendForm', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sends ... to apollo', () => {
|
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
variables: {
|
|
||||||
amount: 90,
|
|
||||||
creationDate: 'YYYY-MM-01',
|
|
||||||
email: 'bob@baumeister.de',
|
|
||||||
id: 0,
|
|
||||||
memo: 'Test create coins',
|
|
||||||
moderator: 0,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sendForm with error', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
apolloMutateMock.mockRejectedValue({
|
|
||||||
message: 'Ouch!',
|
|
||||||
})
|
|
||||||
wrapper = Wrapper()
|
|
||||||
await wrapper.setProps({ creation: [200, 400, 600] })
|
|
||||||
await wrapper.setData({ text: 'Test create coins' })
|
|
||||||
await wrapper.setData({ value: 100 })
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(1).setChecked()
|
|
||||||
await wrapper.setData({ rangeMin: 180 })
|
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('toast error message', () => {
|
|
||||||
expect(toastedErrorMock).toBeCalledWith('Ouch!')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('third radio button', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.setData({ rangeMin: 180 })
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(2).setChecked()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMin to 180', () => {
|
|
||||||
expect(wrapper.vm.rangeMin).toBe(180)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sets rangeMax to 700', () => {
|
|
||||||
expect(wrapper.vm.rangeMax).toBe(700)
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sendForm with success', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('sends ... to apollo', () => {
|
|
||||||
expect(apolloMutateMock).toBeCalledWith(
|
|
||||||
expect.objectContaining({
|
|
||||||
variables: {
|
|
||||||
amount: 90,
|
|
||||||
creationDate: 'YYYY-MM-DD',
|
|
||||||
email: 'bob@baumeister.de',
|
|
||||||
id: 0,
|
|
||||||
memo: 'Test create coins',
|
|
||||||
moderator: 0,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('sendForm with error', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
jest.clearAllMocks()
|
|
||||||
apolloMutateMock.mockRejectedValue({
|
|
||||||
message: 'Ouch!',
|
|
||||||
})
|
|
||||||
wrapper = Wrapper()
|
|
||||||
await wrapper.setProps({ creation: [200, 400, 600] })
|
|
||||||
await wrapper.setData({ text: 'Test create coins' })
|
|
||||||
await wrapper.setData({ value: 90 })
|
|
||||||
await wrapper.findAll('input[type="radio"]').at(2).setChecked()
|
|
||||||
await wrapper.setData({ rangeMin: 180 })
|
|
||||||
await wrapper.find('.test-submit').trigger('click')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('toast error message', () => {
|
|
||||||
expect(toastedErrorMock).toBeCalledWith('Ouch!')
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -6,65 +6,14 @@
|
|||||||
<label>{{ $t('creation_form.select_month') }}</label>
|
<label>{{ $t('creation_form.select_month') }}</label>
|
||||||
</div>
|
</div>
|
||||||
<b-row class="m-4">
|
<b-row class="m-4">
|
||||||
<b-col class="text-left">
|
<b-form-radio-group
|
||||||
<b-form-radio
|
v-model="selected"
|
||||||
id="beforeLastMonth"
|
:options="radioOptions"
|
||||||
v-model="radioSelected"
|
value-field="item"
|
||||||
:value="beforeLastMonth"
|
text-field="name"
|
||||||
:disabled="selectedOpenCreationAmount[0] === 0"
|
name="month-selection"
|
||||||
size="lg"
|
></b-form-radio-group>
|
||||||
@change="updateRadioSelected(beforeLastMonth, 0, selectedOpenCreationAmount[0])"
|
|
||||||
>
|
|
||||||
<label for="beforeLastMonth">
|
|
||||||
{{ beforeLastMonth.short }}
|
|
||||||
{{
|
|
||||||
selectedOpenCreationAmount[0] != null
|
|
||||||
? selectedOpenCreationAmount[0] + ' GDD'
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
<b-col>
|
|
||||||
<b-form-radio
|
|
||||||
id="lastMonth"
|
|
||||||
v-model="radioSelected"
|
|
||||||
:value="lastMonth"
|
|
||||||
:disabled="selectedOpenCreationAmount[1] === 0"
|
|
||||||
size="lg"
|
|
||||||
@change="updateRadioSelected(lastMonth, 1, selectedOpenCreationAmount[1])"
|
|
||||||
>
|
|
||||||
<label for="lastMonth">
|
|
||||||
{{ lastMonth.short }}
|
|
||||||
{{
|
|
||||||
selectedOpenCreationAmount[1] != null
|
|
||||||
? selectedOpenCreationAmount[1] + ' GDD'
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
<b-col class="text-right">
|
|
||||||
<b-form-radio
|
|
||||||
id="currentMonth"
|
|
||||||
v-model="radioSelected"
|
|
||||||
:value="currentMonth"
|
|
||||||
:disabled="selectedOpenCreationAmount[2] === 0"
|
|
||||||
size="lg"
|
|
||||||
@change="updateRadioSelected(currentMonth, 2, selectedOpenCreationAmount[2])"
|
|
||||||
>
|
|
||||||
<label for="currentMonth">
|
|
||||||
{{ currentMonth.short }}
|
|
||||||
{{
|
|
||||||
selectedOpenCreationAmount[2] != null
|
|
||||||
? selectedOpenCreationAmount[2] + ' GDD'
|
|
||||||
: ''
|
|
||||||
}}
|
|
||||||
</label>
|
|
||||||
</b-form-radio>
|
|
||||||
</b-col>
|
|
||||||
</b-row>
|
</b-row>
|
||||||
|
|
||||||
<div class="m-4">
|
<div class="m-4">
|
||||||
<label>{{ $t('creation_form.select_value') }}</label>
|
<label>{{ $t('creation_form.select_value') }}</label>
|
||||||
<div>
|
<div>
|
||||||
@ -76,7 +25,6 @@
|
|||||||
:max="rangeMax"
|
:max="rangeMax"
|
||||||
></b-form-input>
|
></b-form-input>
|
||||||
</b-input-group>
|
</b-input-group>
|
||||||
|
|
||||||
<b-input-group prepend="0" :append="String(rangeMax)" class="mt-3">
|
<b-input-group prepend="0" :append="String(rangeMax)" class="mt-3">
|
||||||
<b-form-input
|
<b-form-input
|
||||||
type="range"
|
type="range"
|
||||||
@ -113,7 +61,7 @@
|
|||||||
variant="success"
|
variant="success"
|
||||||
class="test-submit"
|
class="test-submit"
|
||||||
@click="submitCreation"
|
@click="submitCreation"
|
||||||
:disabled="radioSelected === '' || value <= 0 || text.length < 10"
|
:disabled="selected === '' || value <= 0 || text.length < 10"
|
||||||
>
|
>
|
||||||
{{ $t('creation_form.update_creation') }}
|
{{ $t('creation_form.update_creation') }}
|
||||||
</b-button>
|
</b-button>
|
||||||
@ -126,8 +74,11 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { updatePendingCreation } from '../graphql/updatePendingCreation'
|
import { updatePendingCreation } from '../graphql/updatePendingCreation'
|
||||||
|
import { creationMonths } from '../mixins/creationMonths'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditCreationFormular',
|
name: 'EditCreationFormular',
|
||||||
|
mixins: [creationMonths],
|
||||||
props: {
|
props: {
|
||||||
item: {
|
item: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@ -151,51 +102,26 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
radioSelected: '',
|
|
||||||
text: !this.creationUserData.memo ? '' : this.creationUserData.memo,
|
text: !this.creationUserData.memo ? '' : this.creationUserData.memo,
|
||||||
value: !this.creationUserData.amount ? 0 : this.creationUserData.amount,
|
value: !this.creationUserData.amount ? 0 : this.creationUserData.amount,
|
||||||
rangeMin: 0,
|
rangeMin: 0,
|
||||||
rangeMax: 1000,
|
rangeMax: 1000,
|
||||||
currentMonth: {
|
selected: '',
|
||||||
short: this.$moment().format('MMMM'),
|
|
||||||
long: this.$moment().format('YYYY-MM-DD'),
|
|
||||||
},
|
|
||||||
lastMonth: {
|
|
||||||
short: this.$moment().subtract(1, 'month').format('MMMM'),
|
|
||||||
long: this.$moment().subtract(1, 'month').format('YYYY-MM') + '-01',
|
|
||||||
},
|
|
||||||
beforeLastMonth: {
|
|
||||||
short: this.$moment().subtract(2, 'month').format('MMMM'),
|
|
||||||
long: this.$moment().subtract(2, 'month').format('YYYY-MM') + '-01',
|
|
||||||
},
|
|
||||||
submitObj: null,
|
|
||||||
isdisabled: true,
|
|
||||||
createdIndex: null,
|
|
||||||
selectedOpenCreationAmount: {},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
updateRadioSelected(name, index, openCreation) {
|
|
||||||
this.createdIndex = index
|
|
||||||
this.rangeMin = 0
|
|
||||||
this.rangeMax = this.creation[index]
|
|
||||||
},
|
|
||||||
submitCreation() {
|
submitCreation() {
|
||||||
this.submitObj = {
|
|
||||||
id: this.item.id,
|
|
||||||
email: this.item.email,
|
|
||||||
creationDate: this.radioSelected.long,
|
|
||||||
amount: Number(this.value),
|
|
||||||
memo: this.text,
|
|
||||||
moderator: Number(this.$store.state.moderator.id),
|
|
||||||
}
|
|
||||||
|
|
||||||
// hinweis das eine ein einzelne Schöpfung abgesendet wird an (email)
|
|
||||||
this.$apollo
|
this.$apollo
|
||||||
.mutate({
|
.mutate({
|
||||||
mutation: updatePendingCreation,
|
mutation: updatePendingCreation,
|
||||||
variables: this.submitObj,
|
variables: {
|
||||||
|
id: this.item.id,
|
||||||
|
email: this.item.email,
|
||||||
|
creationDate: this.selected.date,
|
||||||
|
amount: Number(this.value),
|
||||||
|
memo: this.text,
|
||||||
|
moderator: Number(this.$store.state.moderator.id),
|
||||||
|
},
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
this.$emit('update-user-data', this.item, result.data.updatePendingCreation.creation)
|
this.$emit('update-user-data', this.item, result.data.updatePendingCreation.creation)
|
||||||
@ -212,8 +138,6 @@ export default {
|
|||||||
email: this.item.email,
|
email: this.item.email,
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
this.submitObj = null
|
|
||||||
this.createdIndex = null
|
|
||||||
// das creation Formular reseten
|
// das creation Formular reseten
|
||||||
this.$refs.updateCreationForm.reset()
|
this.$refs.updateCreationForm.reset()
|
||||||
// Den geschöpften Wert auf o setzen
|
// Den geschöpften Wert auf o setzen
|
||||||
@ -221,7 +145,6 @@ export default {
|
|||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.error(error.message)
|
||||||
this.submitObj = null
|
|
||||||
// das creation Formular reseten
|
// das creation Formular reseten
|
||||||
this.$refs.updateCreationForm.reset()
|
this.$refs.updateCreationForm.reset()
|
||||||
// Den geschöpften Wert auf o setzen
|
// Den geschöpften Wert auf o setzen
|
||||||
@ -231,25 +154,10 @@ export default {
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
if (this.creationUserData.date) {
|
if (this.creationUserData.date) {
|
||||||
switch (this.$moment(this.creationUserData.date).format('MMMM')) {
|
const month = this.$d(new Date(this.creationUserData.date), 'month')
|
||||||
case this.currentMonth.short:
|
const index = this.radioOptions.findIndex((obj) => obj.item.short === month)
|
||||||
this.createdIndex = 2
|
this.selected = this.radioOptions[index].item
|
||||||
this.radioSelected = this.currentMonth
|
this.rangeMax = this.creation[index] + this.creationUserData.amount
|
||||||
break
|
|
||||||
case this.lastMonth.short:
|
|
||||||
this.createdIndex = 1
|
|
||||||
this.radioSelected = this.lastMonth
|
|
||||||
break
|
|
||||||
case this.beforeLastMonth.short:
|
|
||||||
this.createdIndex = 0
|
|
||||||
this.radioSelected = this.beforeLastMonth
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
throw new Error('Something went wrong')
|
|
||||||
}
|
|
||||||
this.selectedOpenCreationAmount[this.createdIndex] =
|
|
||||||
this.creation[this.createdIndex] + this.creationUserData.amount
|
|
||||||
this.rangeMax = this.selectedOpenCreationAmount[this.createdIndex]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@ -107,16 +107,7 @@ describe('UserTable', () => {
|
|||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
$moment: jest.fn(() => {
|
$d: jest.fn((d) => d),
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
subtract: jest.fn(() => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloQueryMock,
|
query: apolloQueryMock,
|
||||||
},
|
},
|
||||||
@ -199,11 +190,6 @@ describe('UserTable', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// it('expect(wrapper.html()).', () => {
|
|
||||||
// // eslint-disable-next-line no-console
|
|
||||||
// console.log(wrapper.html())
|
|
||||||
// })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('type UserListSearch', () => {
|
describe('type UserListSearch', () => {
|
||||||
@ -214,11 +200,6 @@ describe('UserTable', () => {
|
|||||||
it('has a DIV element with the class.component-user-table', () => {
|
it('has a DIV element with the class.component-user-table', () => {
|
||||||
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
// it('expect(wrapper.html()).', () => {
|
|
||||||
// // eslint-disable-next-line no-console
|
|
||||||
// console.log(wrapper.html())
|
|
||||||
// })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('type UserListMassCreation', () => {
|
describe('type UserListMassCreation', () => {
|
||||||
@ -229,11 +210,6 @@ describe('UserTable', () => {
|
|||||||
it('has a DIV element with the class.component-user-table', () => {
|
it('has a DIV element with the class.component-user-table', () => {
|
||||||
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
|
||||||
// it('expect(wrapper.html()).', () => {
|
|
||||||
// // eslint-disable-next-line no-console
|
|
||||||
// console.log(wrapper.html())
|
|
||||||
// })
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('type PageCreationConfirm', () => {
|
describe('type PageCreationConfirm', () => {
|
||||||
@ -244,48 +220,6 @@ describe('UserTable', () => {
|
|||||||
it('has a DIV element with the class.component-user-table', () => {
|
it('has a DIV element with the class.component-user-table', () => {
|
||||||
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
expect(wrapper.find('.component-user-table').exists()).toBeTruthy()
|
||||||
})
|
})
|
||||||
|
})
|
||||||
// it('expect(wrapper.html()).', () => {
|
|
||||||
// // eslint-disable-next-line no-console
|
|
||||||
// console.log(wrapper.html())
|
|
||||||
// })
|
|
||||||
})
|
|
||||||
/**
|
|
||||||
<user-table
|
|
||||||
v-if="itemsList.length > 0"
|
|
||||||
type="UserListSearch"
|
|
||||||
:itemsUser="itemsList"
|
|
||||||
:fieldsTable="Searchfields"
|
|
||||||
:criteria="criteria"
|
|
||||||
:creation="creation"
|
|
||||||
@update-item="updateItem"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<user-table
|
|
||||||
v-show="itemsMassCreation.length > 0"
|
|
||||||
class="shadow p-3 mb-5 bg-white rounded"
|
|
||||||
type="UserListMassCreation"
|
|
||||||
:itemsUser="itemsMassCreation"
|
|
||||||
:fieldsTable="fields"
|
|
||||||
:criteria="null"
|
|
||||||
:creation="creation"
|
|
||||||
@update-item="updateItem"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<user-table
|
|
||||||
class="mt-4"
|
|
||||||
type="PageCreationConfirm"
|
|
||||||
:itemsUser="confirmResult"
|
|
||||||
:fieldsTable="fields"
|
|
||||||
@remove-confirm-result="removeConfirmResult"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<user-table
|
|
||||||
type="PageUserSearch"
|
|
||||||
:itemsUser="searchResult"
|
|
||||||
:fieldsTable="fields"
|
|
||||||
:criteria="criteria"
|
|
||||||
/>
|
|
||||||
*/
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -116,7 +116,7 @@
|
|||||||
<confirm-register-mail-formular
|
<confirm-register-mail-formular
|
||||||
:checked="row.item.emailChecked"
|
:checked="row.item.emailChecked"
|
||||||
:email="row.item.email"
|
:email="row.item.email"
|
||||||
:dateLastSend="$moment().subtract(1, 'month').format('dddd, DD.MMMM.YYYY HH:mm'),"
|
:dateLastSend="$d(new Date(), 'long')"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #show-transaction-list>
|
<template #show-transaction-list>
|
||||||
@ -287,11 +287,11 @@ export default {
|
|||||||
this.overlay = false
|
this.overlay = false
|
||||||
},
|
},
|
||||||
bookmarkPush(item) {
|
bookmarkPush(item) {
|
||||||
this.$emit('update-item', item, 'push')
|
this.$emit('push-item', item)
|
||||||
},
|
},
|
||||||
bookmarkRemove(item) {
|
bookmarkRemove(item) {
|
||||||
if (this.type === 'UserListMassCreation') {
|
if (this.type === 'UserListMassCreation') {
|
||||||
this.$emit('update-item', item, 'remove')
|
this.$emit('remove-item', item)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.type === 'PageCreationConfirm') {
|
if (this.type === 'PageCreationConfirm') {
|
||||||
|
|||||||
@ -60,6 +60,15 @@ const dateTimeFormats = {
|
|||||||
hour: 'numeric',
|
hour: 'numeric',
|
||||||
minute: 'numeric',
|
minute: 'numeric',
|
||||||
},
|
},
|
||||||
|
monthShort: {
|
||||||
|
month: 'short',
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
month: 'long',
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
year: 'numeric',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
short: {
|
short: {
|
||||||
@ -75,6 +84,15 @@ const dateTimeFormats = {
|
|||||||
hour: 'numeric',
|
hour: 'numeric',
|
||||||
minute: 'numeric',
|
minute: 'numeric',
|
||||||
},
|
},
|
||||||
|
monthShort: {
|
||||||
|
month: 'short',
|
||||||
|
},
|
||||||
|
month: {
|
||||||
|
month: 'long',
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
year: 'numeric',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"toasted_update": "`Offene Schöpfung {value} GDD) für {email} wurde geändert und liegt zur Bestätigung bereit",
|
"toasted_update": "`Offene Schöpfung {value} GDD) für {email} wurde geändert und liegt zur Bestätigung bereit",
|
||||||
"update_creation": "Schöpfung aktualisieren"
|
"update_creation": "Schöpfung aktualisieren"
|
||||||
},
|
},
|
||||||
|
"date": "Datum",
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"e_mail": "E-Mail",
|
"e_mail": "E-Mail",
|
||||||
"firstname": "Vorname",
|
"firstname": "Vorname",
|
||||||
|
|||||||
@ -18,6 +18,7 @@
|
|||||||
"toasted_update": "Open creation {value} GDD) for {email} has been changed and is ready for confirmation.",
|
"toasted_update": "Open creation {value} GDD) for {email} has been changed and is ready for confirmation.",
|
||||||
"update_creation": "Creation update"
|
"update_creation": "Creation update"
|
||||||
},
|
},
|
||||||
|
"date": "Date",
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"e_mail": "E-mail",
|
"e_mail": "E-mail",
|
||||||
"firstname": "Firstname",
|
"firstname": "Firstname",
|
||||||
|
|||||||
@ -17,7 +17,6 @@ import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
|||||||
import 'bootstrap/dist/css/bootstrap.css'
|
import 'bootstrap/dist/css/bootstrap.css'
|
||||||
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
import 'bootstrap-vue/dist/bootstrap-vue.css'
|
||||||
|
|
||||||
import moment from 'vue-moment'
|
|
||||||
import Toasted from 'vue-toasted'
|
import Toasted from 'vue-toasted'
|
||||||
|
|
||||||
import { apolloProvider } from './plugins/apolloProvider'
|
import { apolloProvider } from './plugins/apolloProvider'
|
||||||
@ -26,8 +25,6 @@ Vue.use(BootstrapVue)
|
|||||||
|
|
||||||
Vue.use(IconsPlugin)
|
Vue.use(IconsPlugin)
|
||||||
|
|
||||||
Vue.use(moment)
|
|
||||||
|
|
||||||
Vue.use(VueApollo)
|
Vue.use(VueApollo)
|
||||||
|
|
||||||
Vue.use(Toasted, {
|
Vue.use(Toasted, {
|
||||||
@ -48,7 +45,6 @@ i18n.locale =
|
|||||||
store.state.moderator && store.state.moderator.language ? store.state.moderator.language : 'en'
|
store.state.moderator && store.state.moderator.language ? store.state.moderator.language : 'en'
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
moment,
|
|
||||||
router,
|
router,
|
||||||
store,
|
store,
|
||||||
i18n,
|
i18n,
|
||||||
|
|||||||
@ -6,7 +6,6 @@ import Vue from 'vue'
|
|||||||
import VueApollo from 'vue-apollo'
|
import VueApollo from 'vue-apollo'
|
||||||
import i18n from './i18n'
|
import i18n from './i18n'
|
||||||
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue'
|
||||||
import moment from 'vue-moment'
|
|
||||||
import store from './store/store'
|
import store from './store/store'
|
||||||
import router from './router/router'
|
import router from './router/router'
|
||||||
|
|
||||||
@ -14,7 +13,6 @@ jest.mock('vue')
|
|||||||
jest.mock('vue-apollo')
|
jest.mock('vue-apollo')
|
||||||
jest.mock('vuex')
|
jest.mock('vuex')
|
||||||
jest.mock('vue-i18n')
|
jest.mock('vue-i18n')
|
||||||
jest.mock('vue-moment')
|
|
||||||
jest.mock('./store/store', () => {
|
jest.mock('./store/store', () => {
|
||||||
return {
|
return {
|
||||||
state: {
|
state: {
|
||||||
@ -90,10 +88,6 @@ describe('main', () => {
|
|||||||
expect(Vue.use).toBeCalledWith(IconsPlugin)
|
expect(Vue.use).toBeCalledWith(IconsPlugin)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('calls Moment', () => {
|
|
||||||
expect(Vue.use).toBeCalledWith(moment)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('creates a store', () => {
|
it('creates a store', () => {
|
||||||
expect(Vue).toBeCalledWith(
|
expect(Vue).toBeCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
|
|||||||
35
admin/src/mixins/creationMonths.js
Normal file
35
admin/src/mixins/creationMonths.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
export const creationMonths = {
|
||||||
|
props: {
|
||||||
|
creation: [1000, 1000, 1000],
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
creationDates() {
|
||||||
|
const now = new Date(Date.now())
|
||||||
|
const dates = [now]
|
||||||
|
for (let i = 1; i < 3; i++) {
|
||||||
|
dates.push(new Date(now.getFullYear(), now.getMonth() - i, 1))
|
||||||
|
}
|
||||||
|
return dates.reverse()
|
||||||
|
},
|
||||||
|
creationDateObjects() {
|
||||||
|
const result = []
|
||||||
|
this.creationDates.forEach((date) => {
|
||||||
|
result.push({
|
||||||
|
short: this.$d(date, 'month'),
|
||||||
|
long: this.$d(date, 'short'),
|
||||||
|
year: this.$d(date, 'year'),
|
||||||
|
date: this.$d(date, 'short', 'en'),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
radioOptions() {
|
||||||
|
return this.creationDateObjects.map((obj, idx) => {
|
||||||
|
return {
|
||||||
|
item: { ...obj, creation: this.creation[idx] },
|
||||||
|
name: obj.short + (this.creation[idx] ? ' ' + this.creation[idx] + ' GDD' : ''),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
import { shallowMount } from '@vue/test-utils'
|
import { shallowMount } from '@vue/test-utils'
|
||||||
import Creation from './Creation.vue'
|
import Creation from './Creation.vue'
|
||||||
import Vue from 'vue'
|
|
||||||
|
|
||||||
const localVue = global.localVue
|
const localVue = global.localVue
|
||||||
|
|
||||||
@ -29,25 +28,23 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const toastErrorMock = jest.fn()
|
const toastErrorMock = jest.fn()
|
||||||
|
const storeCommitMock = jest.fn()
|
||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
|
$d: jest.fn((d) => d),
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloQueryMock,
|
query: apolloQueryMock,
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
$moment: jest.fn(() => {
|
$store: {
|
||||||
return {
|
commit: storeCommitMock,
|
||||||
format: jest.fn((m) => m),
|
state: {
|
||||||
subtract: jest.fn(() => {
|
userSelectedInMassCreation: [],
|
||||||
return {
|
},
|
||||||
format: jest.fn((m) => m),
|
},
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('Creation', () => {
|
describe('Creation', () => {
|
||||||
@ -59,6 +56,7 @@ describe('Creation', () => {
|
|||||||
|
|
||||||
describe('shallowMount', () => {
|
describe('shallowMount', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
jest.clearAllMocks()
|
||||||
wrapper = Wrapper()
|
wrapper = Wrapper()
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -68,7 +66,15 @@ describe('Creation', () => {
|
|||||||
|
|
||||||
describe('apollo returns user array', () => {
|
describe('apollo returns user array', () => {
|
||||||
it('calls the searchUser query', () => {
|
it('calls the searchUser query', () => {
|
||||||
expect(apolloQueryMock).toBeCalled()
|
expect(apolloQueryMock).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
variables: {
|
||||||
|
searchText: '',
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 25,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('sets the data of itemsList', () => {
|
it('sets the data of itemsList', () => {
|
||||||
@ -93,25 +99,16 @@ describe('Creation', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('update item', () => {
|
describe('push item', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks()
|
wrapper.findComponent({ name: 'UserTable' }).vm.$emit('push-item', {
|
||||||
})
|
|
||||||
|
|
||||||
describe('push', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
|
|
||||||
'update-item',
|
|
||||||
{
|
|
||||||
userId: 2,
|
userId: 2,
|
||||||
firstName: 'Benjamin',
|
firstName: 'Benjamin',
|
||||||
lastName: 'Blümchen',
|
lastName: 'Blümchen',
|
||||||
email: 'benjamin@bluemchen.de',
|
email: 'benjamin@bluemchen.de',
|
||||||
creation: [800, 600, 400],
|
creation: [800, 600, 400],
|
||||||
showDetails: false,
|
showDetails: false,
|
||||||
},
|
})
|
||||||
'push',
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
it('removes the pushed item from itemsList', () => {
|
it('removes the pushed item from itemsList', () => {
|
||||||
@ -140,36 +137,8 @@ describe('Creation', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('remove', () => {
|
it('updates userSelectedInMassCreation in store', () => {
|
||||||
beforeEach(() => {
|
expect(storeCommitMock).toBeCalledWith('setUserSelectedInMassCreation', [
|
||||||
wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
|
|
||||||
'update-item',
|
|
||||||
{
|
|
||||||
userId: 2,
|
|
||||||
firstName: 'Benjamin',
|
|
||||||
lastName: 'Blümchen',
|
|
||||||
email: 'benjamin@bluemchen.de',
|
|
||||||
creation: [800, 600, 400],
|
|
||||||
showDetails: false,
|
|
||||||
},
|
|
||||||
'remove',
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('removes the item from itemsMassCreation', () => {
|
|
||||||
expect(wrapper.vm.itemsMassCreation).toEqual([])
|
|
||||||
})
|
|
||||||
|
|
||||||
it('adds the item to itemsList', () => {
|
|
||||||
expect(wrapper.vm.itemsList).toEqual([
|
|
||||||
{
|
|
||||||
userId: 1,
|
|
||||||
firstName: 'Bibi',
|
|
||||||
lastName: 'Bloxberg',
|
|
||||||
email: 'bibi@bloxberg.de',
|
|
||||||
creation: [200, 400, 600],
|
|
||||||
showDetails: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
userId: 2,
|
userId: 2,
|
||||||
firstName: 'Benjamin',
|
firstName: 'Benjamin',
|
||||||
@ -181,33 +150,32 @@ describe('Creation', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
|
||||||
|
|
||||||
describe('error', () => {
|
describe('remove item', () => {
|
||||||
const consoleErrorMock = jest.fn()
|
|
||||||
const warnHandler = Vue.config.warnHandler
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
Vue.config.warnHandler = (w) => {}
|
|
||||||
// eslint-disable-next-line no-console
|
|
||||||
console.error = consoleErrorMock
|
|
||||||
wrapper.findComponent({ name: 'UserTable' }).vm.$emit('update-item', {}, 'no-rule')
|
|
||||||
})
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
Vue.config.warnHandler = warnHandler
|
|
||||||
})
|
|
||||||
|
|
||||||
it('throws an error', () => {
|
|
||||||
expect(consoleErrorMock).toBeCalledWith(expect.objectContaining({ message: 'no-rule' }))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('remove all bookmarks', () => {
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
await wrapper.findComponent({ name: 'UserTable' }).vm.$emit(
|
await wrapper.findComponent({ name: 'UserTable' }).vm.$emit('push-item', {
|
||||||
'update-item',
|
userId: 2,
|
||||||
|
firstName: 'Benjamin',
|
||||||
|
lastName: 'Blümchen',
|
||||||
|
email: 'benjamin@bluemchen.de',
|
||||||
|
creation: [800, 600, 400],
|
||||||
|
showDetails: false,
|
||||||
|
})
|
||||||
|
await wrapper
|
||||||
|
.findAllComponents({ name: 'UserTable' })
|
||||||
|
.at(1)
|
||||||
|
.vm.$emit('remove-item', {
|
||||||
|
userId: 2,
|
||||||
|
firstName: 'Benjamin',
|
||||||
|
lastName: 'Blümchen',
|
||||||
|
email: 'benjamin@bluemchen.de',
|
||||||
|
creation: [800, 600, 400],
|
||||||
|
showDetails: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds the removed item to itemsList', () => {
|
||||||
|
expect(wrapper.vm.itemsList).toEqual([
|
||||||
{
|
{
|
||||||
userId: 2,
|
userId: 2,
|
||||||
firstName: 'Benjamin',
|
firstName: 'Benjamin',
|
||||||
@ -216,8 +184,37 @@ describe('Creation', () => {
|
|||||||
creation: [800, 600, 400],
|
creation: [800, 600, 400],
|
||||||
showDetails: false,
|
showDetails: false,
|
||||||
},
|
},
|
||||||
'push',
|
{
|
||||||
)
|
userId: 1,
|
||||||
|
firstName: 'Bibi',
|
||||||
|
lastName: 'Bloxberg',
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
creation: [200, 400, 600],
|
||||||
|
showDetails: false,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('removes the item from itemsMassCreation', () => {
|
||||||
|
expect(wrapper.vm.itemsMassCreation).toEqual([])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('commits empty array as userSelectedInMassCreation', () => {
|
||||||
|
expect(storeCommitMock).toBeCalledWith('setUserSelectedInMassCreation', [])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('remove all bookmarks', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await wrapper.findComponent({ name: 'UserTable' }).vm.$emit('push-item', {
|
||||||
|
userId: 2,
|
||||||
|
firstName: 'Benjamin',
|
||||||
|
lastName: 'Blümchen',
|
||||||
|
email: 'benjamin@bluemchen.de',
|
||||||
|
creation: [800, 600, 400],
|
||||||
|
showDetails: false,
|
||||||
|
})
|
||||||
|
jest.clearAllMocks()
|
||||||
wrapper.findComponent({ name: 'CreationFormular' }).vm.$emit('remove-all-bookmark')
|
wrapper.findComponent({ name: 'CreationFormular' }).vm.$emit('remove-all-bookmark')
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -225,8 +222,41 @@ describe('Creation', () => {
|
|||||||
expect(wrapper.vm.itemsMassCreation).toEqual([])
|
expect(wrapper.vm.itemsMassCreation).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds all items to itemsList', () => {
|
it('commits empty array to userSelectedInMassCreation', () => {
|
||||||
expect(wrapper.vm.itemsList).toHaveLength(2)
|
expect(storeCommitMock).toBeCalledWith('setUserSelectedInMassCreation', [])
|
||||||
|
})
|
||||||
|
|
||||||
|
it('calls searchUsers', () => {
|
||||||
|
expect(apolloQueryMock).toBeCalled()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('store has items in userSelectedInMassCreation', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
mocks.$store.state.userSelectedInMassCreation = [
|
||||||
|
{
|
||||||
|
userId: 2,
|
||||||
|
firstName: 'Benjamin',
|
||||||
|
lastName: 'Blümchen',
|
||||||
|
email: 'benjamin@bluemchen.de',
|
||||||
|
creation: [800, 600, 400],
|
||||||
|
showDetails: false,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
wrapper = Wrapper()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('has only one item itemsList', () => {
|
||||||
|
expect(wrapper.vm.itemsList).toEqual([
|
||||||
|
{
|
||||||
|
userId: 1,
|
||||||
|
firstName: 'Bibi',
|
||||||
|
lastName: 'Bloxberg',
|
||||||
|
email: 'bibi@bloxberg.de',
|
||||||
|
creation: [200, 400, 600],
|
||||||
|
showDetails: false,
|
||||||
|
},
|
||||||
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -237,12 +267,28 @@ describe('Creation', () => {
|
|||||||
|
|
||||||
it('calls API when criteria changes', async () => {
|
it('calls API when criteria changes', async () => {
|
||||||
await wrapper.setData({ criteria: 'XX' })
|
await wrapper.setData({ criteria: 'XX' })
|
||||||
expect(apolloQueryMock).toBeCalled()
|
expect(apolloQueryMock).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
variables: {
|
||||||
|
searchText: 'XX',
|
||||||
|
currentPage: 1,
|
||||||
|
pageSize: 25,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('calls API when currentPage changes', async () => {
|
it('calls API when currentPage changes', async () => {
|
||||||
await wrapper.setData({ currentPage: 2 })
|
await wrapper.setData({ currentPage: 2 })
|
||||||
expect(apolloQueryMock).toBeCalled()
|
expect(apolloQueryMock).toBeCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
variables: {
|
||||||
|
searchText: '',
|
||||||
|
currentPage: 2,
|
||||||
|
pageSize: 25,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
:fieldsTable="Searchfields"
|
:fieldsTable="Searchfields"
|
||||||
:criteria="criteria"
|
:criteria="criteria"
|
||||||
:creation="creation"
|
:creation="creation"
|
||||||
@update-item="updateItem"
|
@push-item="pushItem"
|
||||||
/>
|
/>
|
||||||
<b-pagination
|
<b-pagination
|
||||||
pills
|
pills
|
||||||
@ -35,7 +35,7 @@
|
|||||||
:fieldsTable="fields"
|
:fieldsTable="fields"
|
||||||
:criteria="null"
|
:criteria="null"
|
||||||
:creation="creation"
|
:creation="creation"
|
||||||
@update-item="updateItem"
|
@remove-item="removeItem"
|
||||||
/>
|
/>
|
||||||
<div v-if="itemsMassCreation.length === 0">
|
<div v-if="itemsMassCreation.length === 0">
|
||||||
{{ $t('multiple_creation_text') }}
|
{{ $t('multiple_creation_text') }}
|
||||||
@ -65,52 +65,15 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showArrays: false,
|
showArrays: false,
|
||||||
Searchfields: [
|
|
||||||
{ key: 'bookmark', label: 'bookmark' },
|
|
||||||
{ key: 'firstName', label: this.$t('firstname') },
|
|
||||||
{ key: 'lastName', label: this.$t('lastname') },
|
|
||||||
{
|
|
||||||
key: 'creation',
|
|
||||||
// label: this.$t('open_creation') + 'Jan | Feb | März',
|
|
||||||
label:
|
|
||||||
this.$moment().subtract(2, 'month').format('MMM') +
|
|
||||||
' | ' +
|
|
||||||
this.$moment().subtract(1, 'month').format('MMM') +
|
|
||||||
' | ' +
|
|
||||||
this.$moment().format('MMM'),
|
|
||||||
formatter: (value, key, item) => {
|
|
||||||
return String(value[0]) + ` | ` + String(value[1]) + ` | ` + String(value[2])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ key: 'email', label: this.$t('e_mail') },
|
|
||||||
],
|
|
||||||
fields: [
|
|
||||||
{ key: 'email', label: this.$t('e_mail') },
|
|
||||||
{ key: 'firstName', label: this.$t('firstname') },
|
|
||||||
{ key: 'lastName', label: this.$t('lastname') },
|
|
||||||
{
|
|
||||||
key: 'creation',
|
|
||||||
// label: this.$t('open_creation') + 'Jan | Feb | März',
|
|
||||||
label:
|
|
||||||
this.$moment().subtract(2, 'month').format('MMM') +
|
|
||||||
' | ' +
|
|
||||||
this.$moment().subtract(1, 'month').format('MMM') +
|
|
||||||
' | ' +
|
|
||||||
this.$moment().format('MMM'),
|
|
||||||
formatter: (value, key, item) => {
|
|
||||||
return String(value[0]) + ` | ` + String(value[1]) + ` | ` + String(value[2])
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ key: 'bookmark', label: this.$t('remove') },
|
|
||||||
],
|
|
||||||
itemsList: [],
|
itemsList: [],
|
||||||
itemsMassCreation: [],
|
itemsMassCreation: this.$store.state.userSelectedInMassCreation,
|
||||||
radioSelectedMass: '',
|
radioSelectedMass: '',
|
||||||
criteria: '',
|
criteria: '',
|
||||||
creation: [null, null, null],
|
creation: [null, null, null],
|
||||||
rows: 0,
|
rows: 0,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
perPage: 25,
|
perPage: 25,
|
||||||
|
now: Date.now(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async created() {
|
async created() {
|
||||||
@ -136,37 +99,81 @@ export default {
|
|||||||
showDetails: false,
|
showDetails: false,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
if (this.itemsMassCreation.length !== 0) {
|
||||||
|
const selectedIndices = this.itemsMassCreation.map((item) => item.userId)
|
||||||
|
this.itemsList = this.itemsList.filter((item) => !selectedIndices.includes(item.userId))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.$toasted.error(error.message)
|
this.$toasted.error(error.message)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateItem(e, event) {
|
pushItem(selectedItem) {
|
||||||
let index = 0
|
this.itemsMassCreation = [
|
||||||
let findArr = {}
|
this.itemsList.find((item) => selectedItem.userId === item.userId),
|
||||||
|
...this.itemsMassCreation,
|
||||||
switch (event) {
|
]
|
||||||
case 'push':
|
this.itemsList = this.itemsList.filter((item) => selectedItem.userId !== item.userId)
|
||||||
findArr = this.itemsList.find((item) => e.userId === item.userId)
|
this.$store.commit('setUserSelectedInMassCreation', this.itemsMassCreation)
|
||||||
index = this.itemsList.indexOf(findArr)
|
},
|
||||||
this.itemsList.splice(index, 1)
|
removeItem(selectedItem) {
|
||||||
this.itemsMassCreation.push(findArr)
|
this.itemsList = [
|
||||||
break
|
this.itemsMassCreation.find((item) => selectedItem.userId === item.userId),
|
||||||
case 'remove':
|
...this.itemsList,
|
||||||
findArr = this.itemsMassCreation.find((item) => e.userId === item.userId)
|
]
|
||||||
index = this.itemsMassCreation.indexOf(findArr)
|
this.itemsMassCreation = this.itemsMassCreation.filter(
|
||||||
this.itemsMassCreation.splice(index, 1)
|
(item) => selectedItem.userId !== item.userId,
|
||||||
this.itemsList.push(findArr)
|
)
|
||||||
break
|
this.$store.commit('setUserSelectedInMassCreation', this.itemsMassCreation)
|
||||||
default:
|
|
||||||
throw new Error(event)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
removeAllBookmark() {
|
removeAllBookmark() {
|
||||||
this.itemsMassCreation = []
|
this.itemsMassCreation = []
|
||||||
|
this.$store.commit('setUserSelectedInMassCreation', [])
|
||||||
this.getUsers()
|
this.getUsers()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
Searchfields() {
|
||||||
|
return [
|
||||||
|
{ key: 'bookmark', label: 'bookmark' },
|
||||||
|
{ key: 'firstName', label: this.$t('firstname') },
|
||||||
|
{ key: 'lastName', label: this.$t('lastname') },
|
||||||
|
{
|
||||||
|
key: 'creation',
|
||||||
|
label: this.creationLabel,
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return value.join(' | ')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'email', label: this.$t('e_mail') },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
fields() {
|
||||||
|
return [
|
||||||
|
{ key: 'email', label: this.$t('e_mail') },
|
||||||
|
{ key: 'firstName', label: this.$t('firstname') },
|
||||||
|
{ key: 'lastName', label: this.$t('lastname') },
|
||||||
|
{
|
||||||
|
key: 'creation',
|
||||||
|
label: this.creationLabel,
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return value.join(' | ')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'bookmark', label: this.$t('remove') },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
creationLabel() {
|
||||||
|
const now = new Date(this.now)
|
||||||
|
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1)
|
||||||
|
const beforeLastMonth = new Date(now.getFullYear(), now.getMonth() - 2, 1)
|
||||||
|
return [
|
||||||
|
this.$d(beforeLastMonth, 'monthShort'),
|
||||||
|
this.$d(lastMonth, 'monthShort'),
|
||||||
|
this.$d(now, 'monthShort'),
|
||||||
|
].join(' | ')
|
||||||
|
},
|
||||||
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentPage() {
|
currentPage() {
|
||||||
this.getUsers()
|
this.getUsers()
|
||||||
|
|||||||
@ -39,6 +39,7 @@ const apolloMutateMock = jest.fn().mockResolvedValue({})
|
|||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
|
$d: jest.fn((d) => d),
|
||||||
$store: {
|
$store: {
|
||||||
commit: storeCommitMock,
|
commit: storeCommitMock,
|
||||||
},
|
},
|
||||||
@ -50,11 +51,6 @@ const mocks = {
|
|||||||
error: toastedErrorMock,
|
error: toastedErrorMock,
|
||||||
success: toastedSuccessMock,
|
success: toastedSuccessMock,
|
||||||
},
|
},
|
||||||
$moment: jest.fn((value) => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((format) => value),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('CreationConfirm', () => {
|
describe('CreationConfirm', () => {
|
||||||
|
|||||||
@ -96,9 +96,9 @@ export default {
|
|||||||
{ key: 'memo', label: 'Text' },
|
{ key: 'memo', label: 'Text' },
|
||||||
{
|
{
|
||||||
key: 'date',
|
key: 'date',
|
||||||
label: 'Datum',
|
label: this.$t('date'),
|
||||||
formatter: (value) => {
|
formatter: (value) => {
|
||||||
return this.$moment(value).format('ll')
|
return this.$d(new Date(value), 'short')
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ key: 'moderator', label: 'Moderator' },
|
{ key: 'moderator', label: 'Moderator' },
|
||||||
|
|||||||
@ -24,22 +24,13 @@ const toastErrorMock = jest.fn()
|
|||||||
|
|
||||||
const mocks = {
|
const mocks = {
|
||||||
$t: jest.fn((t) => t),
|
$t: jest.fn((t) => t),
|
||||||
|
$d: jest.fn((d) => d),
|
||||||
$apollo: {
|
$apollo: {
|
||||||
query: apolloQueryMock,
|
query: apolloQueryMock,
|
||||||
},
|
},
|
||||||
$toasted: {
|
$toasted: {
|
||||||
error: toastErrorMock,
|
error: toastErrorMock,
|
||||||
},
|
},
|
||||||
$moment: jest.fn(() => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
subtract: jest.fn(() => {
|
|
||||||
return {
|
|
||||||
format: jest.fn((m) => m),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('UserSearch', () => {
|
describe('UserSearch', () => {
|
||||||
|
|||||||
@ -44,41 +44,14 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showArrays: false,
|
showArrays: false,
|
||||||
fields: [
|
|
||||||
{ key: 'email', label: this.$t('e_mail') },
|
|
||||||
{ key: 'firstName', label: this.$t('firstname') },
|
|
||||||
{ key: 'lastName', label: this.$t('lastname') },
|
|
||||||
{
|
|
||||||
key: 'creation',
|
|
||||||
label: [
|
|
||||||
this.$moment().subtract(2, 'month').format('MMM'),
|
|
||||||
this.$moment().subtract(1, 'month').format('MMM'),
|
|
||||||
this.$moment().format('MMM'),
|
|
||||||
].join(' | '),
|
|
||||||
formatter: (value, key, item) => {
|
|
||||||
return value.join(' | ')
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ key: 'show_details', label: this.$t('details') },
|
|
||||||
{ key: 'confirm_mail', label: this.$t('confirmed') },
|
|
||||||
{ key: 'transactions_list', label: this.$t('transaction') },
|
|
||||||
],
|
|
||||||
searchResult: [],
|
searchResult: [],
|
||||||
massCreation: [],
|
massCreation: [],
|
||||||
criteria: '',
|
criteria: '',
|
||||||
currentMonth: {
|
|
||||||
short: this.$moment().format('MMMM'),
|
|
||||||
},
|
|
||||||
lastMonth: {
|
|
||||||
short: this.$moment().subtract(1, 'month').format('MMMM'),
|
|
||||||
},
|
|
||||||
beforeLastMonth: {
|
|
||||||
short: this.$moment().subtract(2, 'month').format('MMMM'),
|
|
||||||
},
|
|
||||||
filterCheckedEmails: false,
|
filterCheckedEmails: false,
|
||||||
rows: 0,
|
rows: 0,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
perPage: 25,
|
perPage: 25,
|
||||||
|
now: Date.now(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -111,6 +84,37 @@ export default {
|
|||||||
this.getUsers()
|
this.getUsers()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
lastMonthDate() {
|
||||||
|
const now = new Date(this.now)
|
||||||
|
return new Date(now.getFullYear(), now.getMonth() - 1, 1)
|
||||||
|
},
|
||||||
|
beforeLastMonthDate() {
|
||||||
|
const now = new Date(this.now)
|
||||||
|
return new Date(now.getFullYear(), now.getMonth() - 2, 1)
|
||||||
|
},
|
||||||
|
fields() {
|
||||||
|
return [
|
||||||
|
{ key: 'email', label: this.$t('e_mail') },
|
||||||
|
{ key: 'firstName', label: this.$t('firstname') },
|
||||||
|
{ key: 'lastName', label: this.$t('lastname') },
|
||||||
|
{
|
||||||
|
key: 'creation',
|
||||||
|
label: [
|
||||||
|
this.$d(this.beforeLastMonthDate, 'monthShort'),
|
||||||
|
this.$d(this.lastMonthDate, 'monthShort'),
|
||||||
|
this.$d(this.now, 'monthShort'),
|
||||||
|
].join(' | '),
|
||||||
|
formatter: (value, key, item) => {
|
||||||
|
return value.join(' | ')
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ key: 'show_details', label: this.$t('details') },
|
||||||
|
{ key: 'confirm_mail', label: this.$t('confirmed') },
|
||||||
|
{ key: 'transactions_list', label: this.$t('transaction') },
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getUsers()
|
this.getUsers()
|
||||||
},
|
},
|
||||||
|
|||||||
@ -24,6 +24,9 @@ export const mutations = {
|
|||||||
moderator: (state, moderator) => {
|
moderator: (state, moderator) => {
|
||||||
state.moderator = moderator
|
state.moderator = moderator
|
||||||
},
|
},
|
||||||
|
setUserSelectedInMassCreation: (state, userSelectedInMassCreation) => {
|
||||||
|
state.userSelectedInMassCreation = userSelectedInMassCreation
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const actions = {
|
export const actions = {
|
||||||
@ -44,6 +47,7 @@ const store = new Vuex.Store({
|
|||||||
token: CONFIG.DEBUG_DISABLE_AUTH ? 'validToken' : null,
|
token: CONFIG.DEBUG_DISABLE_AUTH ? 'validToken' : null,
|
||||||
moderator: null,
|
moderator: null,
|
||||||
openCreations: 0,
|
openCreations: 0,
|
||||||
|
userSelectedInMassCreation: [],
|
||||||
},
|
},
|
||||||
// Syncronous mutation of the state
|
// Syncronous mutation of the state
|
||||||
mutations,
|
mutations,
|
||||||
|
|||||||
@ -10,6 +10,7 @@ const {
|
|||||||
resetOpenCreations,
|
resetOpenCreations,
|
||||||
setOpenCreations,
|
setOpenCreations,
|
||||||
moderator,
|
moderator,
|
||||||
|
setUserSelectedInMassCreation,
|
||||||
} = mutations
|
} = mutations
|
||||||
const { logout } = actions
|
const { logout } = actions
|
||||||
|
|
||||||
@ -64,6 +65,14 @@ describe('Vuex store', () => {
|
|||||||
expect(state.openCreations).toEqual(12)
|
expect(state.openCreations).toEqual(12)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('setUserSelectedInMassCreation', () => {
|
||||||
|
it('sets userSelectedInMassCreation to given value', () => {
|
||||||
|
const state = { userSelectedInMassCreation: [] }
|
||||||
|
setUserSelectedInMassCreation(state, [0, 1, 2])
|
||||||
|
expect(state.userSelectedInMassCreation).toEqual([0, 1, 2])
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('actions', () => {
|
describe('actions', () => {
|
||||||
|
|||||||
@ -9032,11 +9032,6 @@ mkdirp@0.x, mkdirp@^0.5.1, mkdirp@^0.5.3, mkdirp@^0.5.5, mkdirp@~0.5.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
minimist "^1.2.5"
|
minimist "^1.2.5"
|
||||||
|
|
||||||
moment@^2.19.2, moment@^2.29.1:
|
|
||||||
version "2.29.1"
|
|
||||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
|
|
||||||
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
|
|
||||||
|
|
||||||
move-concurrently@^1.0.1:
|
move-concurrently@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
|
||||||
@ -12491,13 +12486,6 @@ vue-loader@^15.9.2:
|
|||||||
vue-hot-reload-api "^2.3.0"
|
vue-hot-reload-api "^2.3.0"
|
||||||
vue-style-loader "^4.1.0"
|
vue-style-loader "^4.1.0"
|
||||||
|
|
||||||
vue-moment@^4.1.0:
|
|
||||||
version "4.1.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/vue-moment/-/vue-moment-4.1.0.tgz#092a8ff723a96c6f85a0a8e23ad30f0bf320f3b0"
|
|
||||||
integrity sha512-Gzisqpg82ItlrUyiD9d0Kfru+JorW2o4mQOH06lEDZNgxci0tv/fua1Hl0bo4DozDV2JK1r52Atn/8QVCu8qQw==
|
|
||||||
dependencies:
|
|
||||||
moment "^2.19.2"
|
|
||||||
|
|
||||||
vue-router@^3.5.3:
|
vue-router@^3.5.3:
|
||||||
version "3.5.3"
|
version "3.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.3.tgz#041048053e336829d05dafacf6a8fb669a2e7999"
|
resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.5.3.tgz#041048053e336829d05dafacf6a8fb669a2e7999"
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import dotenv from 'dotenv'
|
|||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
const constants = {
|
const constants = {
|
||||||
DB_VERSION: '0012-login_user_backups_unify_wordlist',
|
DB_VERSION: '0016-transaction_signatures',
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = {
|
const server = {
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import { UpdatePendingCreation } from '../model/UpdatePendingCreation'
|
|||||||
import { RIGHTS } from '../../auth/RIGHTS'
|
import { RIGHTS } from '../../auth/RIGHTS'
|
||||||
import { TransactionRepository } from '../../typeorm/repository/Transaction'
|
import { TransactionRepository } from '../../typeorm/repository/Transaction'
|
||||||
import { TransactionCreationRepository } from '../../typeorm/repository/TransactionCreation'
|
import { TransactionCreationRepository } from '../../typeorm/repository/TransactionCreation'
|
||||||
import { LoginPendingTasksAdminRepository } from '../../typeorm/repository/LoginPendingTasksAdmin'
|
|
||||||
import { UserRepository } from '../../typeorm/repository/User'
|
import { UserRepository } from '../../typeorm/repository/User'
|
||||||
import CreatePendingCreationArgs from '../arg/CreatePendingCreationArgs'
|
import CreatePendingCreationArgs from '../arg/CreatePendingCreationArgs'
|
||||||
import UpdatePendingCreationArgs from '../arg/UpdatePendingCreationArgs'
|
import UpdatePendingCreationArgs from '../arg/UpdatePendingCreationArgs'
|
||||||
@ -23,7 +22,7 @@ import { UserTransactionRepository } from '../../typeorm/repository/UserTransact
|
|||||||
import { BalanceRepository } from '../../typeorm/repository/Balance'
|
import { BalanceRepository } from '../../typeorm/repository/Balance'
|
||||||
import { calculateDecay } from '../../util/decay'
|
import { calculateDecay } from '../../util/decay'
|
||||||
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
|
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
|
||||||
import { LoginPendingTasksAdmin } from '@entity/LoginPendingTasksAdmin'
|
import { AdminPendingCreation } from '@entity/AdminPendingCreation'
|
||||||
|
|
||||||
@Resolver()
|
@Resolver()
|
||||||
export class AdminResolver {
|
export class AdminResolver {
|
||||||
@ -68,16 +67,15 @@ export class AdminResolver {
|
|||||||
const creations = await getUserCreations(user.id)
|
const creations = await getUserCreations(user.id)
|
||||||
const creationDateObj = new Date(creationDate)
|
const creationDateObj = new Date(creationDate)
|
||||||
if (isCreationValid(creations, amount, creationDateObj)) {
|
if (isCreationValid(creations, amount, creationDateObj)) {
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const adminPendingCreation = AdminPendingCreation.create()
|
||||||
const loginPendingTaskAdmin = loginPendingTasksAdminRepository.create()
|
adminPendingCreation.userId = user.id
|
||||||
loginPendingTaskAdmin.userId = user.id
|
adminPendingCreation.amount = BigInt(amount * 10000)
|
||||||
loginPendingTaskAdmin.amount = BigInt(amount * 10000)
|
adminPendingCreation.created = new Date()
|
||||||
loginPendingTaskAdmin.created = new Date()
|
adminPendingCreation.date = creationDateObj
|
||||||
loginPendingTaskAdmin.date = creationDateObj
|
adminPendingCreation.memo = memo
|
||||||
loginPendingTaskAdmin.memo = memo
|
adminPendingCreation.moderator = moderator
|
||||||
loginPendingTaskAdmin.moderator = moderator
|
|
||||||
|
|
||||||
await loginPendingTasksAdminRepository.save(loginPendingTaskAdmin)
|
await AdminPendingCreation.save(adminPendingCreation)
|
||||||
}
|
}
|
||||||
return getUserCreations(user.id)
|
return getUserCreations(user.id)
|
||||||
}
|
}
|
||||||
@ -116,8 +114,7 @@ export class AdminResolver {
|
|||||||
const userRepository = getCustomRepository(UserRepository)
|
const userRepository = getCustomRepository(UserRepository)
|
||||||
const user = await userRepository.findByEmail(email)
|
const user = await userRepository.findByEmail(email)
|
||||||
|
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const pendingCreationToUpdate = await AdminPendingCreation.findOneOrFail({ id })
|
||||||
const pendingCreationToUpdate = await loginPendingTasksAdminRepository.findOneOrFail({ id })
|
|
||||||
|
|
||||||
if (pendingCreationToUpdate.userId !== user.id) {
|
if (pendingCreationToUpdate.userId !== user.id) {
|
||||||
throw new Error('user of the pending creation and send user does not correspond')
|
throw new Error('user of the pending creation and send user does not correspond')
|
||||||
@ -137,7 +134,7 @@ export class AdminResolver {
|
|||||||
pendingCreationToUpdate.date = new Date(creationDate)
|
pendingCreationToUpdate.date = new Date(creationDate)
|
||||||
pendingCreationToUpdate.moderator = moderator
|
pendingCreationToUpdate.moderator = moderator
|
||||||
|
|
||||||
await loginPendingTasksAdminRepository.save(pendingCreationToUpdate)
|
await AdminPendingCreation.save(pendingCreationToUpdate)
|
||||||
const result = new UpdatePendingCreation()
|
const result = new UpdatePendingCreation()
|
||||||
result.amount = parseInt(amount.toString())
|
result.amount = parseInt(amount.toString())
|
||||||
result.memo = pendingCreationToUpdate.memo
|
result.memo = pendingCreationToUpdate.memo
|
||||||
@ -151,8 +148,7 @@ export class AdminResolver {
|
|||||||
@Authorized([RIGHTS.SEARCH_PENDING_CREATION])
|
@Authorized([RIGHTS.SEARCH_PENDING_CREATION])
|
||||||
@Query(() => [PendingCreation])
|
@Query(() => [PendingCreation])
|
||||||
async getPendingCreations(): Promise<PendingCreation[]> {
|
async getPendingCreations(): Promise<PendingCreation[]> {
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const pendingCreations = await AdminPendingCreation.find()
|
||||||
const pendingCreations = await loginPendingTasksAdminRepository.find()
|
|
||||||
|
|
||||||
const pendingCreationsPromise = await Promise.all(
|
const pendingCreationsPromise = await Promise.all(
|
||||||
pendingCreations.map(async (pendingCreation) => {
|
pendingCreations.map(async (pendingCreation) => {
|
||||||
@ -179,18 +175,15 @@ export class AdminResolver {
|
|||||||
@Authorized([RIGHTS.DELETE_PENDING_CREATION])
|
@Authorized([RIGHTS.DELETE_PENDING_CREATION])
|
||||||
@Mutation(() => Boolean)
|
@Mutation(() => Boolean)
|
||||||
async deletePendingCreation(@Arg('id') id: number): Promise<boolean> {
|
async deletePendingCreation(@Arg('id') id: number): Promise<boolean> {
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const entity = await AdminPendingCreation.findOneOrFail(id)
|
||||||
const entity = await loginPendingTasksAdminRepository.findOneOrFail(id)
|
const res = await AdminPendingCreation.delete(entity)
|
||||||
const res = await loginPendingTasksAdminRepository.delete(entity)
|
|
||||||
return !!res
|
return !!res
|
||||||
}
|
}
|
||||||
|
|
||||||
@Authorized([RIGHTS.CONFIRM_PENDING_CREATION])
|
@Authorized([RIGHTS.CONFIRM_PENDING_CREATION])
|
||||||
@Mutation(() => Boolean)
|
@Mutation(() => Boolean)
|
||||||
async confirmPendingCreation(@Arg('id') id: number, @Ctx() context: any): Promise<boolean> {
|
async confirmPendingCreation(@Arg('id') id: number, @Ctx() context: any): Promise<boolean> {
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const pendingCreation = await AdminPendingCreation.findOneOrFail(id)
|
||||||
const pendingCreation = await loginPendingTasksAdminRepository.findOneOrFail(id)
|
|
||||||
|
|
||||||
const userRepository = getCustomRepository(UserRepository)
|
const userRepository = getCustomRepository(UserRepository)
|
||||||
const moderatorUser = await userRepository.findByPubkeyHex(context.pubKey)
|
const moderatorUser = await userRepository.findByPubkeyHex(context.pubKey)
|
||||||
if (moderatorUser.id === pendingCreation.userId)
|
if (moderatorUser.id === pendingCreation.userId)
|
||||||
@ -202,7 +195,6 @@ export class AdminResolver {
|
|||||||
transaction.transactionTypeId = 1
|
transaction.transactionTypeId = 1
|
||||||
transaction.memo = pendingCreation.memo
|
transaction.memo = pendingCreation.memo
|
||||||
transaction.received = receivedCallDate
|
transaction.received = receivedCallDate
|
||||||
transaction.blockchainTypeId = 1
|
|
||||||
transaction = await transactionRepository.save(transaction)
|
transaction = await transactionRepository.save(transaction)
|
||||||
if (!transaction) throw new Error('Could not create transaction')
|
if (!transaction) throw new Error('Could not create transaction')
|
||||||
|
|
||||||
@ -251,7 +243,7 @@ export class AdminResolver {
|
|||||||
userBalance.modified = receivedCallDate
|
userBalance.modified = receivedCallDate
|
||||||
userBalance.recordDate = receivedCallDate
|
userBalance.recordDate = receivedCallDate
|
||||||
await balanceRepository.save(userBalance)
|
await balanceRepository.save(userBalance)
|
||||||
await loginPendingTasksAdminRepository.delete(pendingCreation)
|
await AdminPendingCreation.delete(pendingCreation)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -280,12 +272,12 @@ async function getUserCreations(id: number): Promise<number[]> {
|
|||||||
.orderBy('target_month', 'ASC')
|
.orderBy('target_month', 'ASC')
|
||||||
.getRawMany()
|
.getRawMany()
|
||||||
|
|
||||||
const loginPendingTasksAdminRepository = getCustomRepository(LoginPendingTasksAdminRepository)
|
const pendingAmountsQuery = await AdminPendingCreation.createQueryBuilder(
|
||||||
const pendingAmountsQuery = await loginPendingTasksAdminRepository
|
'admin_pending_creations',
|
||||||
.createQueryBuilder('login_pending_tasks_admin')
|
)
|
||||||
.select('MONTH(login_pending_tasks_admin.date)', 'target_month')
|
.select('MONTH(admin_pending_creations.date)', 'target_month')
|
||||||
.addSelect('SUM(login_pending_tasks_admin.amount)', 'sum')
|
.addSelect('SUM(admin_pending_creations.amount)', 'sum')
|
||||||
.where('login_pending_tasks_admin.userId = :id', { id })
|
.where('admin_pending_creations.userId = :id', { id })
|
||||||
.andWhere({
|
.andWhere({
|
||||||
date: Raw((alias) => `${alias} >= :date and ${alias} < :endDate`, {
|
date: Raw((alias) => `${alias} >= :date and ${alias} < :endDate`, {
|
||||||
date: dateBeforeLastMonth,
|
date: dateBeforeLastMonth,
|
||||||
@ -336,7 +328,7 @@ async function getUserCreations(id: number): Promise<number[]> {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCreations(creations: number[], pendingCreation: LoginPendingTasksAdmin): number[] {
|
function updateCreations(creations: number[], pendingCreation: AdminPendingCreation): number[] {
|
||||||
const dateMonth = moment().format('YYYY-MM')
|
const dateMonth = moment().format('YYYY-MM')
|
||||||
const dateLastMonth = moment().subtract(1, 'month').format('YYYY-MM')
|
const dateLastMonth = moment().subtract(1, 'month').format('YYYY-MM')
|
||||||
const dateBeforeLastMonth = moment().subtract(2, 'month').format('YYYY-MM')
|
const dateBeforeLastMonth = moment().subtract(2, 'month').format('YYYY-MM')
|
||||||
|
|||||||
@ -36,172 +36,6 @@ import { hasUserAmount, isHexPublicKey } from '../../util/validate'
|
|||||||
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
|
import { LoginUserRepository } from '../../typeorm/repository/LoginUser'
|
||||||
import { RIGHTS } from '../../auth/RIGHTS'
|
import { RIGHTS } from '../../auth/RIGHTS'
|
||||||
|
|
||||||
/*
|
|
||||||
# Test
|
|
||||||
|
|
||||||
## Prepare
|
|
||||||
> sudo systemctl start docker
|
|
||||||
> docker-compose up mariadb
|
|
||||||
> DROP all databases
|
|
||||||
> docker-compose down
|
|
||||||
> docker compose up mariadb database
|
|
||||||
> verify there is exactly one database `gradido_community`
|
|
||||||
|
|
||||||
TODO:
|
|
||||||
INSERT INTO `login_groups` (`id`, `alias`, `name`, `url`, `host`, `home`, `description`) VALUES
|
|
||||||
(1, 'docker', 'docker gradido group', 'localhost', 'nginx', '/', 'gradido test group for docker and stage2 with blockchain db');
|
|
||||||
|
|
||||||
>> Database is cool
|
|
||||||
|
|
||||||
### Start login server
|
|
||||||
> docker-compose up login-server community-server nginx
|
|
||||||
>> Login & community servers and nginx proxy are up and running
|
|
||||||
|
|
||||||
## Build database
|
|
||||||
> cd database
|
|
||||||
> yarn
|
|
||||||
> yarn build
|
|
||||||
> cd ..
|
|
||||||
>> Database has been built successful
|
|
||||||
|
|
||||||
### Start backend (no docker for debugging)
|
|
||||||
> cd backend
|
|
||||||
> yarn
|
|
||||||
> yarn dev
|
|
||||||
>> Backend is up and running
|
|
||||||
|
|
||||||
### Create users
|
|
||||||
> chromium http://localhost:4000/graphql
|
|
||||||
> mutation{createUser(email: "receiver@user.net", firstName: "Receiver", lastName: "user", password: "123!AAAb", language: "de")}
|
|
||||||
> mutation{createUser(email: "sender@user.net", firstName: "Sender", lastName: "user", password: "123!AAAb", language: "de")}
|
|
||||||
> mutation{createUser(email: "creator@user.net", firstName: "Creator", lastName: "user", password: "123!AAAb", language: "de")}
|
|
||||||
>> Verify you have 3 entries in `login_users`, `login_user_backups` and `state_users`
|
|
||||||
|
|
||||||
### make creator an admin
|
|
||||||
> INSERT INTO login_user_roles (id, user_id, role_id) VALUES (NULL, '3', '1');
|
|
||||||
> UPDATE login_users SET email_checked = 1 WHERE id = 3;
|
|
||||||
> uncomment line: 19 in community_server/src/Controller/ServerUsersController.php
|
|
||||||
> chromium http://localhost/server-users/add
|
|
||||||
> create user `creator` `123` `creator@different.net`
|
|
||||||
>> verify you have 1 entry in `server_users`
|
|
||||||
> login with user on http://localhost/server-users
|
|
||||||
> activate server user by changing the corresponding flag in the interface
|
|
||||||
> navigate to http://localhost/transaction-creations/create-multi
|
|
||||||
> create 1000GDD for user sender@user.net
|
|
||||||
> navigate to http://localhost
|
|
||||||
> login with `creator@user.net` `123!AAAb`
|
|
||||||
> confirm transaction (top right corner - click the thingy, click the green button `Transaktion abschließen`)
|
|
||||||
|
|
||||||
### the test:
|
|
||||||
> chromium http://localhost:4000/graphql
|
|
||||||
> query{login(email: "sender@user.net", password: "123!AAAb"){pubkey}}
|
|
||||||
>> copy token from network tab (inspect)
|
|
||||||
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
|
|
||||||
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
|
|
||||||
> Headers: {"Authorization": "Bearer ${token}"}
|
|
||||||
>> Verify via Database that stuff is as it should see `state_balance` & `transaction_send_coins`
|
|
||||||
|
|
||||||
### create decay block
|
|
||||||
> chromium http://localhost/transactions/add
|
|
||||||
> login with `creator` `123`
|
|
||||||
> select `decay start`
|
|
||||||
> press submit
|
|
||||||
> wait for at least 0.02 display of decay on user sender@user.net on old frontend, this should be aprox 10min
|
|
||||||
> chromium http://localhost:4000/graphql
|
|
||||||
> query{login(email: "sender@user.net", password: "123!AAAb"){pubkey}}
|
|
||||||
>> copy token from network tab (inspect)
|
|
||||||
> mutation{sendCoins(email: "receiver@user.net", amount: 10.0, memo: "Hier!")}
|
|
||||||
>> verify in `transaction_send_coins` that a decay was taken into account
|
|
||||||
>> same in `state_balances`
|
|
||||||
>> now check the old frontend
|
|
||||||
>>> sender@user.net should have a decay of 0.02
|
|
||||||
>>> while receiver@user.net should have zero decay on anything (old frontend)
|
|
||||||
|
|
||||||
### Export data
|
|
||||||
> docker-compose up phpmyadmin
|
|
||||||
> chromium http://localhost:8074/
|
|
||||||
> select gradido_community
|
|
||||||
> export
|
|
||||||
> select custom
|
|
||||||
> untick structure
|
|
||||||
> ok
|
|
||||||
|
|
||||||
## Results
|
|
||||||
NOTE: We decided not to write the `transaction_signatures` since its unused. This is the main difference.
|
|
||||||
NOTE: We fixed a bug in the `state_user_transactions code` with the new implementation of apollo
|
|
||||||
|
|
||||||
|
|
||||||
Master:
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `state_user_transactions`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `state_user_transactions` (`id`, `state_user_id`, `transaction_id`, `transaction_type_id`, `balance`, `balance_date`) VALUES
|
|
||||||
(1, 2, 1, 1, 10000000, '2021-11-05 12:45:18'),
|
|
||||||
(2, 2, 2, 2, 9900000, '2021-11-05 12:48:35'),
|
|
||||||
(3, 1, 2, 2, 100000, '2021-11-05 12:48:35'),
|
|
||||||
(4, 2, 3, 2, 9800000, '2021-11-05 12:49:07'),
|
|
||||||
(5, 1, 3, 2, 200000, '2021-11-05 12:49:07'),
|
|
||||||
(6, 2, 5, 2, 9699845, '2021-11-05 13:03:50'),
|
|
||||||
(7, 1, 5, 2, 99996, '2021-11-05 13:03:50');
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `transactions`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `transactions` (`id`, `state_group_id`, `transaction_type_id`, `tx_hash`, `memo`, `received`, `blockchain_type_id`) VALUES
|
|
||||||
(1, NULL, 1, 0x9ccdcd01ccb6320c09c2d1da2f0bf735a95ece0e7c1df6bbff51918fbaec061700000000000000000000000000000000, '', '2021-11-05 12:45:18', 1),
|
|
||||||
(2, NULL, 2, 0x58d7706a67fa4ff4b8038168c6be39a2963d7e28e9d3872759ad09c519fe093700000000000000000000000000000000, 'Hier!', '2021-11-05 12:48:35', 1),
|
|
||||||
(3, NULL, 2, 0x427cd214f92ef35af671129d50edc5a478c53d1e464f285b7615d9794a69f69b00000000000000000000000000000000, 'Hier!', '2021-11-05 12:49:07', 1),
|
|
||||||
(4, NULL, 9, 0x32807368f0906a21b94c072599795bc9eeab88fb565df82e85cc62a4fdcde48500000000000000000000000000000000, '', '2021-11-05 12:51:51', 1),
|
|
||||||
(5, NULL, 2, 0x75eb729e0f60a1c8cead1342955853d2440d7a2ea57dfef6d4a18bff0d94491e00000000000000000000000000000000, 'Hier!', '2021-11-05 13:03:50', 1);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `transaction_signatures`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `transaction_signatures` (`id`, `transaction_id`, `signature`, `pubkey`) VALUES
|
|
||||||
(1, 1, 0x5888edcdcf77aaadad6d321882903bc831d7416f17213fd5020a764365b5fcb336e4c7917385a1278ea44ccdb31eac4a09e448053b5e3f8f1fe5da3baf53c008, 0xd5b20f8dee415038bfa2b6b0e1b40ff54850351109444863b04d6d28825b7b7d),
|
|
||||||
(2, 2, 0xf6fef428f8f22faf7090f7d740e6088d1d90c58ae92d757117d7d91d799e659f3a3a0c65a3fd97cbde798e761f9d23eff13e8810779a184c97c411f28e7c4608, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a),
|
|
||||||
(3, 3, 0x8ebe9730c6cf61f56ef401d6f2bd229f3c298ca3c2791ee9137e4827b7af6c6d6566fca616eb1fe7adc2e4d56b5c7350ae3990c9905580630fa75ecffca8e001, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a),
|
|
||||||
(4, 5, 0x50cf418f7e217391e89ab9c2879ae68d7c7c597d846b4fe1c082b5b16e5d0c85c328fbf48ad3490bcfe94f446700ae0a4b0190e76d26cc752abced58f480c80f, 0xdc74a589004377ab14836dce68ce2ca34e5b17147cd78ad4b3afe8137524ae8a);
|
|
||||||
|
|
||||||
This Feature Branch:
|
|
||||||
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `state_user_transactions`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `state_user_transactions` (`id`, `state_user_id`, `transaction_id`, `transaction_type_id`, `balance`, `balance_date`) VALUES
|
|
||||||
(1, 2, 1, 1, 10000000, '2021-11-05 00:25:46'),
|
|
||||||
(12, 2, 7, 2, 9900000, '2021-11-05 00:55:37'),
|
|
||||||
(13, 1, 7, 2, 100000, '2021-11-05 00:55:37'),
|
|
||||||
(14, 2, 8, 2, 9800000, '2021-11-05 01:00:04'),
|
|
||||||
(15, 1, 8, 2, 200000, '2021-11-05 01:00:04'),
|
|
||||||
(16, 2, 10, 2, 9699772, '2021-11-05 01:17:41'),
|
|
||||||
(17, 1, 10, 2, 299995, '2021-11-05 01:17:41');
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `transactions`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `transactions` (`id`, `state_group_id`, `transaction_type_id`, `tx_hash`, `memo`, `received`, `blockchain_type_id`) VALUES
|
|
||||||
(1, NULL, 1, 0xdd030d475479877587d927ed9024784ba62266cf1f3d87862fc98ad68f7b26e400000000000000000000000000000000, '', '2021-11-05 00:25:46', 1),
|
|
||||||
(7, NULL, 2, NULL, 'Hier!', '2021-11-05 00:55:37', 1),
|
|
||||||
(8, NULL, 2, NULL, 'Hier!', '2021-11-05 01:00:04', 1),
|
|
||||||
(9, NULL, 9, 0xb1cbedbf126aa35f5edbf06e181c415361d05228ab4da9d19a4595285a673dfa00000000000000000000000000000000, '', '2021-11-05 01:05:34', 1),
|
|
||||||
(10, NULL, 2, NULL, 'Hier!', '2021-11-05 01:17:41', 1);
|
|
||||||
|
|
||||||
--
|
|
||||||
-- Dumping data for table `transaction_signatures`
|
|
||||||
--
|
|
||||||
|
|
||||||
INSERT INTO `transaction_signatures` (`id`, `transaction_id`, `signature`, `pubkey`) VALUES
|
|
||||||
(1, 1, 0x60d632479707e5d01cdc32c3326b5a5bae11173a0c06b719ee7b552f9fd644de1a0cd4afc207253329081d39dac1a63421f51571d836995c649fc39afac7480a, 0x48c45cb4fea925e83850f68f2fa8f27a1a4ed1bcba68cdb59fcd86adef3f52ee);
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Helper function
|
// Helper function
|
||||||
async function calculateAndAddDecayTransactions(
|
async function calculateAndAddDecayTransactions(
|
||||||
userTransactions: dbUserTransaction[],
|
userTransactions: dbUserTransaction[],
|
||||||
|
|||||||
@ -1,5 +0,0 @@
|
|||||||
import { EntityRepository, Repository } from '@dbTools/typeorm'
|
|
||||||
import { LoginPendingTasksAdmin } from '@entity/LoginPendingTasksAdmin'
|
|
||||||
|
|
||||||
@EntityRepository(LoginPendingTasksAdmin)
|
|
||||||
export class LoginPendingTasksAdminRepository extends Repository<LoginPendingTasksAdmin> {}
|
|
||||||
@ -1,25 +1,34 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
|
||||||
import { TransactionCreation } from './TransactionCreation'
|
import { TransactionCreation } from '../TransactionCreation'
|
||||||
import { TransactionSendCoin } from './TransactionSendCoin'
|
import { TransactionSendCoin } from '../TransactionSendCoin'
|
||||||
|
|
||||||
@Entity('transactions')
|
@Entity('transactions')
|
||||||
export class Transaction extends BaseEntity {
|
export class Transaction extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn()
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
@Column({ name: 'transaction_type_id' })
|
@Column({ name: 'state_group_id', unsigned: true, default: null })
|
||||||
|
stateGroupId: number
|
||||||
|
|
||||||
|
@Column({ name: 'transaction_type_id', unsigned: true, nullable: false })
|
||||||
transactionTypeId: number
|
transactionTypeId: number
|
||||||
|
|
||||||
@Column({ name: 'tx_hash', type: 'binary', length: 48 })
|
@Column({ name: 'tx_hash', type: 'binary', length: 48, default: null })
|
||||||
txHash: Buffer
|
txHash: Buffer
|
||||||
|
|
||||||
@Column()
|
@Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
|
||||||
memo: string
|
memo: string
|
||||||
|
|
||||||
@Column({ type: 'timestamp' })
|
@Column({ type: 'timestamp', nullable: false, default: () => 'CURRENT_TIMESTAMP' })
|
||||||
received: Date
|
received: Date
|
||||||
|
|
||||||
@Column({ name: 'blockchain_type_id' })
|
@Column({
|
||||||
|
name: 'blockchain_type_id',
|
||||||
|
type: 'bigint',
|
||||||
|
unsigned: true,
|
||||||
|
nullable: false,
|
||||||
|
default: 1,
|
||||||
|
})
|
||||||
blockchainTypeId: number
|
blockchainTypeId: number
|
||||||
|
|
||||||
@OneToOne(() => TransactionSendCoin, (transactionSendCoin) => transactionSendCoin.transaction)
|
@OneToOne(() => TransactionSendCoin, (transactionSendCoin) => transactionSendCoin.transaction)
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
||||||
import { Transaction } from './Transaction'
|
import { Transaction } from '../Transaction'
|
||||||
|
|
||||||
@Entity('transaction_creations')
|
@Entity('transaction_creations')
|
||||||
export class TransactionCreation extends BaseEntity {
|
export class TransactionCreation extends BaseEntity {
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
||||||
import { Transaction } from './Transaction'
|
import { Transaction } from '../Transaction'
|
||||||
|
|
||||||
@Entity('transaction_send_coins')
|
@Entity('transaction_send_coins')
|
||||||
export class TransactionSendCoin extends BaseEntity {
|
export class TransactionSendCoin extends BaseEntity {
|
||||||
|
|||||||
@ -1,21 +1,21 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne, JoinColumn } from 'typeorm'
|
||||||
import { Transaction } from './Transaction'
|
import { Transaction } from '../Transaction'
|
||||||
|
|
||||||
@Entity('transaction_signatures')
|
@Entity('transaction_signatures')
|
||||||
export class TransactionSignature extends BaseEntity {
|
export class TransactionSignature extends BaseEntity {
|
||||||
@PrimaryGeneratedColumn()
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
id: number
|
id: number
|
||||||
|
|
||||||
@Column({ name: 'transaction_id' })
|
@Column({ name: 'transaction_id' })
|
||||||
transactionId: number
|
transactionId: number
|
||||||
|
|
||||||
@Column({ type: 'binary', length: 64 })
|
@Column({ type: 'binary', length: 64, nullable: false })
|
||||||
signature: Buffer
|
signature: Buffer
|
||||||
|
|
||||||
@Column({ type: 'binary', length: 32 })
|
@Column({ type: 'binary', length: 32, nullable: false })
|
||||||
pubkey: Buffer
|
pubkey: Buffer
|
||||||
|
|
||||||
@ManyToOne(() => Transaction)
|
@OneToOne(() => Transaction)
|
||||||
@JoinColumn({ name: 'transaction_id' })
|
@JoinColumn({ name: 'transaction_id' })
|
||||||
transaction: Transaction
|
transaction: Transaction
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm'
|
||||||
import { UserSetting } from './UserSetting'
|
import { UserSetting } from '../UserSetting'
|
||||||
|
|
||||||
// Moriz: I do not like the idea of having two user tables
|
// Moriz: I do not like the idea of having two user tables
|
||||||
@Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
|
@Entity('state_users', { engine: 'InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci' })
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm'
|
||||||
import { User } from './User'
|
import { User } from '../User'
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class UserSetting extends BaseEntity {
|
export class UserSetting extends BaseEntity {
|
||||||
|
|||||||
@ -0,0 +1,25 @@
|
|||||||
|
import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from 'typeorm'
|
||||||
|
|
||||||
|
@Entity('admin_pending_creations')
|
||||||
|
export class AdminPendingCreation extends BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ unsigned: true, nullable: false })
|
||||||
|
userId: number
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
created: Date
|
||||||
|
|
||||||
|
@Column({ type: 'datetime', nullable: false })
|
||||||
|
date: Date
|
||||||
|
|
||||||
|
@Column({ length: 256, nullable: true, default: null })
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Column({ type: 'bigint', nullable: false })
|
||||||
|
amount: BigInt
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
moderator: number
|
||||||
|
}
|
||||||
34
database/entity/0016-transaction_signatures/Transaction.ts
Normal file
34
database/entity/0016-transaction_signatures/Transaction.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { BaseEntity, Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
|
||||||
|
import { TransactionCreation } from '../TransactionCreation'
|
||||||
|
import { TransactionSendCoin } from '../TransactionSendCoin'
|
||||||
|
|
||||||
|
@Entity('transactions')
|
||||||
|
export class Transaction extends BaseEntity {
|
||||||
|
// TODO the id is defined as bigint(20) - there might be problems with that: https://github.com/typeorm/typeorm/issues/2400
|
||||||
|
@PrimaryGeneratedColumn('increment', { unsigned: true })
|
||||||
|
id: number
|
||||||
|
|
||||||
|
@Column({ name: 'transaction_type_id', unsigned: true, nullable: false })
|
||||||
|
transactionTypeId: number
|
||||||
|
|
||||||
|
@Column({ name: 'tx_hash', type: 'binary', length: 48, default: null })
|
||||||
|
txHash: Buffer
|
||||||
|
|
||||||
|
@Column({ length: 255, nullable: false, collation: 'utf8mb4_unicode_ci' })
|
||||||
|
memo: string
|
||||||
|
|
||||||
|
@Column({ type: 'timestamp', nullable: false, default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
received: Date
|
||||||
|
|
||||||
|
@Column({ type: 'binary', length: 64, nullable: true, default: null })
|
||||||
|
signature: Buffer
|
||||||
|
|
||||||
|
@Column({ type: 'binary', length: 32, nullable: true, default: null })
|
||||||
|
pubkey: Buffer
|
||||||
|
|
||||||
|
@OneToOne(() => TransactionSendCoin, (transactionSendCoin) => transactionSendCoin.transaction)
|
||||||
|
transactionSendCoin: TransactionSendCoin
|
||||||
|
|
||||||
|
@OneToOne(() => TransactionCreation, (transactionCreation) => transactionCreation.transaction)
|
||||||
|
transactionCreation: TransactionCreation
|
||||||
|
}
|
||||||
1
database/entity/AdminPendingCreation.ts
Normal file
1
database/entity/AdminPendingCreation.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { AdminPendingCreation } from './0015-admin_pending_creations/AdminPendingCreation'
|
||||||
@ -1 +0,0 @@
|
|||||||
export { LoginPendingTasksAdmin } from './0005-admin_tables/LoginPendingTasksAdmin'
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export { LoginUserRoles } from './0003-login_server_tables/LoginUserRoles'
|
|
||||||
@ -1 +1 @@
|
|||||||
export { Transaction } from './0001-init_db/Transaction'
|
export { Transaction } from './0016-transaction_signatures/Transaction'
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
export { TransactionSignature } from './0001-init_db/TransactionSignature'
|
|
||||||
@ -2,34 +2,30 @@ import { Balance } from './Balance'
|
|||||||
import { LoginElopageBuys } from './LoginElopageBuys'
|
import { LoginElopageBuys } from './LoginElopageBuys'
|
||||||
import { LoginEmailOptIn } from './LoginEmailOptIn'
|
import { LoginEmailOptIn } from './LoginEmailOptIn'
|
||||||
import { LoginUser } from './LoginUser'
|
import { LoginUser } from './LoginUser'
|
||||||
import { LoginUserRoles } from './LoginUserRoles'
|
|
||||||
import { LoginUserBackup } from './LoginUserBackup'
|
import { LoginUserBackup } from './LoginUserBackup'
|
||||||
import { Migration } from './Migration'
|
import { Migration } from './Migration'
|
||||||
import { ServerUser } from './ServerUser'
|
import { ServerUser } from './ServerUser'
|
||||||
import { Transaction } from './Transaction'
|
import { Transaction } from './Transaction'
|
||||||
import { TransactionCreation } from './TransactionCreation'
|
import { TransactionCreation } from './TransactionCreation'
|
||||||
import { TransactionSignature } from './TransactionSignature'
|
|
||||||
import { TransactionSendCoin } from './TransactionSendCoin'
|
import { TransactionSendCoin } from './TransactionSendCoin'
|
||||||
import { User } from './User'
|
import { User } from './User'
|
||||||
import { UserSetting } from './UserSetting'
|
import { UserSetting } from './UserSetting'
|
||||||
import { UserTransaction } from './UserTransaction'
|
import { UserTransaction } from './UserTransaction'
|
||||||
import { LoginPendingTasksAdmin } from './LoginPendingTasksAdmin'
|
import { AdminPendingCreation } from './AdminPendingCreation'
|
||||||
|
|
||||||
export const entities = [
|
export const entities = [
|
||||||
|
AdminPendingCreation,
|
||||||
Balance,
|
Balance,
|
||||||
LoginElopageBuys,
|
LoginElopageBuys,
|
||||||
LoginEmailOptIn,
|
LoginEmailOptIn,
|
||||||
LoginUser,
|
LoginUser,
|
||||||
LoginUserRoles,
|
|
||||||
LoginUserBackup,
|
LoginUserBackup,
|
||||||
Migration,
|
Migration,
|
||||||
ServerUser,
|
ServerUser,
|
||||||
Transaction,
|
Transaction,
|
||||||
TransactionCreation,
|
TransactionCreation,
|
||||||
TransactionSignature,
|
|
||||||
TransactionSendCoin,
|
TransactionSendCoin,
|
||||||
User,
|
User,
|
||||||
UserSetting,
|
UserSetting,
|
||||||
UserTransaction,
|
UserTransaction,
|
||||||
LoginPendingTasksAdmin,
|
|
||||||
]
|
]
|
||||||
|
|||||||
142
database/migrations/0013-drop_unused_tables.ts
Normal file
142
database/migrations/0013-drop_unused_tables.ts
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
/* MIGRATION TO DROP UNUSED TABLES
|
||||||
|
*
|
||||||
|
* This migration removes all tables without data and entity definition.
|
||||||
|
* Base for evaluation are the production data from 27.01.2022 which had 40 tables present
|
||||||
|
* The migration reduces the amount of tables to 28
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`DROP TABLE \`login_app_access_tokens\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`pending_transactions\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`roles\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_created\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_groups\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_group_addresses\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_group_relationships\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_relationship_types\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_user_roles\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`transaction_group_addaddress\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`transaction_group_allowtrades\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`transaction_group_creates\`;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE IF NOT EXISTS \`login_app_access_tokens\` (
|
||||||
|
\`id\` int unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`user_id\` int NOT NULL,
|
||||||
|
\`access_code\` bigint unsigned NOT NULL,
|
||||||
|
\`created\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
\`updated\` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
UNIQUE KEY \`access_code\` (\`access_code\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`pending_transactions\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transactionID\` varchar(25) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`service\` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`method\` varchar(20) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`h_server_id\` int(11) NOT NULL,
|
||||||
|
\`timeout\` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
UNIQUE KEY \`transactionID\` (\`transactionID\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`roles\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`title\` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_created\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transaction_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`month\` tinyint(3) unsigned NOT NULL,
|
||||||
|
\`year\` smallint(5) unsigned NOT NULL,
|
||||||
|
\`state_user_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`created\` datetime NOT NULL,
|
||||||
|
\`short_ident_hash\` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
KEY \`short_ident_hash\` (\`short_ident_hash\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_groups\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`index_id\` varbinary(64) NOT NULL,
|
||||||
|
\`name\` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`root_public_key\` binary(32) NOT NULL,
|
||||||
|
\`user_count\` smallint(5) unsigned NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_group_addresses\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`group_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`public_key\` binary(32) NOT NULL,
|
||||||
|
\`address_type_id\` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
UNIQUE KEY \`public_key\` (\`public_key\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_group_relationships\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`group1_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`group2_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`state_relationship_id\` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_relationship_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(25) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`text\` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_user_roles\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`state_user_id\` int(11) NOT NULL,
|
||||||
|
\`role_id\` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`transaction_group_addaddress\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transaction_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`address_type_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`remove_from_group\` tinyint(1) DEFAULT 0,
|
||||||
|
\`public_key\` binary(32) NOT NULL,
|
||||||
|
\`state_user_id\` int(10) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`transaction_group_allowtrades\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transaction_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`remote_group_id\` varbinary(64) NOT NULL,
|
||||||
|
\`allow\` tinyint(4) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`transaction_group_creates\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transaction_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`group_public_key\` binary(32) NOT NULL,
|
||||||
|
\`group_id\` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`name\` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
}
|
||||||
351
database/migrations/0014-drop_unused_tables_with_data.ts
Normal file
351
database/migrations/0014-drop_unused_tables_with_data.ts
Normal file
@ -0,0 +1,351 @@
|
|||||||
|
/* MIGRATION TO DROP UNUSED TABLES
|
||||||
|
*
|
||||||
|
* This migration removes all tables with static or unused data and entity definition.
|
||||||
|
* Base for evaluation are the production data from 27.01.2022 which had 28 tables present
|
||||||
|
* The migration reduces the amount of tables to 16
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`DROP TABLE \`address_types\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`admin_errors\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`blockchain_types\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`community_profiles\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`login_email_opt_in_types\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`login_groups\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`login_roles\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`login_user_roles\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`operators\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`operator_types\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`state_errors\`;`)
|
||||||
|
await queryFn(`DROP TABLE \`transaction_types\`;`)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`address_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`text\` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`address_types\` VALUES
|
||||||
|
(1,'user main','user main address');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`admin_errors\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`state_user_id\` int(11) NOT NULL,
|
||||||
|
\`controller\` varchar(255) NOT NULL,
|
||||||
|
\`action\` varchar(255) NOT NULL,
|
||||||
|
\`state\` varchar(255) NOT NULL,
|
||||||
|
\`msg\` varchar(255) NOT NULL,
|
||||||
|
\`details\` varchar(255) DEFAULT NULL,
|
||||||
|
\`created\` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=155 DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
// NOTE: This data is no longer generated
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`admin_errors\` VALUES
|
||||||
|
(54,272,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2020-11-04 17:57:07'),
|
||||||
|
(55,272,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2020-11-04 17:57:16'),
|
||||||
|
(56,193,'StateBalancesController','overview','error','server response status code isn\\'t 200','403','2020-11-24 12:44:31'),
|
||||||
|
(57,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2020-12-31 19:17:52'),
|
||||||
|
(58,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2020-12-31 19:18:04'),
|
||||||
|
(59,44,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-12 20:58:45'),
|
||||||
|
(60,44,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-12 21:02:02'),
|
||||||
|
(61,44,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-12 21:02:04'),
|
||||||
|
(62,44,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-12 21:02:19'),
|
||||||
|
(63,20,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-13 22:32:59'),
|
||||||
|
(64,20,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-14 23:54:19'),
|
||||||
|
(65,161,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-27 10:29:09'),
|
||||||
|
(66,161,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-27 10:29:11'),
|
||||||
|
(67,161,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-01-27 10:29:23'),
|
||||||
|
(68,20,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-02-03 00:27:36'),
|
||||||
|
(69,685,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-02-06 11:48:09'),
|
||||||
|
(70,685,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-02-06 11:53:14'),
|
||||||
|
(71,685,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-02-06 11:53:20'),
|
||||||
|
(72,502,'TransactionCreations','createMulti','error','json exception','System exception: cannot unlock mutex','2021-03-24 21:22:14'),
|
||||||
|
(73,502,'TransactionCreations','createMulti','error','json exception','System exception: cannot unlock mutex','2021-03-24 21:23:38'),
|
||||||
|
(74,259,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-02 15:07:07'),
|
||||||
|
(75,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 20:31:50'),
|
||||||
|
(76,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 20:31:57'),
|
||||||
|
(77,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 20:32:23'),
|
||||||
|
(78,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 20:32:57'),
|
||||||
|
(79,199,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 21:43:13'),
|
||||||
|
(80,199,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 21:43:47'),
|
||||||
|
(81,199,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 21:44:45'),
|
||||||
|
(82,272,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 22:57:10'),
|
||||||
|
(83,272,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-14 22:57:18'),
|
||||||
|
(84,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:50:53'),
|
||||||
|
(85,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:51:27'),
|
||||||
|
(86,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:51:32'),
|
||||||
|
(87,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:51:54'),
|
||||||
|
(88,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:52:29'),
|
||||||
|
(89,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:53:33'),
|
||||||
|
(90,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-21 12:53:37'),
|
||||||
|
(91,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-23 12:27:57'),
|
||||||
|
(92,1162,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-23 12:28:02'),
|
||||||
|
(93,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 18:59:08'),
|
||||||
|
(94,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 18:59:16'),
|
||||||
|
(95,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 18:59:27'),
|
||||||
|
(96,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 19:00:51'),
|
||||||
|
(97,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 19:01:18'),
|
||||||
|
(98,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 19:04:22'),
|
||||||
|
(99,900,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 19:04:39'),
|
||||||
|
(100,1087,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-27 19:43:18'),
|
||||||
|
(101,240,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-28 22:00:05'),
|
||||||
|
(102,240,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-28 22:00:35'),
|
||||||
|
(103,240,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-28 22:00:37'),
|
||||||
|
(104,240,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-28 22:00:44'),
|
||||||
|
(105,90,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-29 14:05:59'),
|
||||||
|
(106,90,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-29 14:06:07'),
|
||||||
|
(107,90,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-29 14:06:15'),
|
||||||
|
(108,90,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-04-29 14:07:13'),
|
||||||
|
(109,79,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-01 10:18:03'),
|
||||||
|
(110,20,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-08 00:25:20'),
|
||||||
|
(111,84,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-08 22:34:27'),
|
||||||
|
(112,84,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-08 22:35:47'),
|
||||||
|
(113,776,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-12 10:24:55'),
|
||||||
|
(114,776,'TransactionSendCoins','create','success','(Leere Message)','(Leere Details)','2021-05-13 13:47:07'),
|
||||||
|
(115,1339,'StateBalancesController','overview','success','(Leere Message)','(Leere Details)','2021-07-13 08:54:30'),
|
||||||
|
(116,1339,'StateBalancesController','overview','success','(Leere Message)','(Leere Details)','2021-07-13 08:54:30'),
|
||||||
|
(117,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:46:40'),
|
||||||
|
(118,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:05'),
|
||||||
|
(119,943,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:05'),
|
||||||
|
(120,751,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:20'),
|
||||||
|
(121,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:21'),
|
||||||
|
(122,943,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:21'),
|
||||||
|
(123,751,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:22'),
|
||||||
|
(124,751,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:22'),
|
||||||
|
(125,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:36'),
|
||||||
|
(126,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:43'),
|
||||||
|
(127,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:43'),
|
||||||
|
(128,11,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:43'),
|
||||||
|
(129,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:46'),
|
||||||
|
(130,943,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:47:46'),
|
||||||
|
(131,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:48:47'),
|
||||||
|
(132,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:48:52'),
|
||||||
|
(133,11,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:48:52'),
|
||||||
|
(134,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:49:24'),
|
||||||
|
(135,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:49:26'),
|
||||||
|
(136,943,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:49:26'),
|
||||||
|
(137,751,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:49:58'),
|
||||||
|
(138,751,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:50:00'),
|
||||||
|
(139,751,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:50:00'),
|
||||||
|
(140,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:50:57'),
|
||||||
|
(141,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:51:01'),
|
||||||
|
(142,943,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:51:02'),
|
||||||
|
(143,11,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-08-12 14:51:10'),
|
||||||
|
(144,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:51:10'),
|
||||||
|
(145,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:52:39'),
|
||||||
|
(146,943,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:52:44'),
|
||||||
|
(147,82,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:54:25'),
|
||||||
|
(148,284,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-08-12 14:54:35'),
|
||||||
|
(149,1439,'StateBalancesController','overview','success','(Leere Message)','(Leere Details)','2021-09-16 15:44:16'),
|
||||||
|
(150,1439,'StateBalancesController','overview','success','(Leere Message)','(Leere Details)','2021-09-16 15:44:27'),
|
||||||
|
(151,11,'StateBalancesController','overview','error','server response status code isn\\'t 200','500','2021-09-22 11:03:10'),
|
||||||
|
(152,11,'StateBalancesController','ajaxGdtOverview','error','server response status code isn\\'t 200','500','2021-09-22 11:16:33'),
|
||||||
|
(153,82,'StateBalancesController','overview','error','server response status code isn\\'t 200','403','2021-11-23 16:03:57'),
|
||||||
|
(154,82,'StateBalancesController','overview','error','server response status code isn\\'t 200','403','2021-11-23 16:04:10');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`blockchain_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`text\` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
\`symbol\` varchar(10) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`blockchain_types\` VALUES
|
||||||
|
(1,'mysql','use mysql db as blockchain, work only with single community-server',NULL),
|
||||||
|
(2,'hedera','use hedera for transactions','HBAR');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`community_profiles\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`state_user_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`profile_img\` longblob DEFAULT NULL,
|
||||||
|
\`profile_desc\` varchar(2000) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
KEY \`state_user_id\` (\`state_user_id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: The data was removed due to large binary images in the database. If this data is needed please get it from the backup file.
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_email_opt_in_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(255) NOT NULL,
|
||||||
|
\`description\` varchar(255) NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`login_email_opt_in_types\` VALUES
|
||||||
|
(1,'register','Email Verification Code for register from new User.'),
|
||||||
|
(2,'resetPassword','Email Verification Code for reset Password (only if passphrase is known)');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_groups\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`alias\` varchar(190) NOT NULL,
|
||||||
|
\`name\` varchar(255) NOT NULL,
|
||||||
|
\`url\` varchar(255) NOT NULL,
|
||||||
|
\`host\` varchar(255) DEFAULT '/',
|
||||||
|
\`home\` varchar(255) DEFAULT '/',
|
||||||
|
\`description\` text DEFAULT NULL,
|
||||||
|
PRIMARY KEY (\`id\`),
|
||||||
|
UNIQUE KEY \`alias\` (\`alias\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`login_groups\` VALUES
|
||||||
|
(1,'gdd1','gdd1','gdd1.gradido.com','','/','gdd1 group');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_roles\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(255) NOT NULL,
|
||||||
|
\`description\` varchar(255) NOT NULL,
|
||||||
|
\`flags\` bigint(20) NOT NULL DEFAULT 0,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`login_roles\` VALUES
|
||||||
|
(1,'admin','darf einfach alles',0);
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_user_roles\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`user_id\` int(11) NOT NULL,
|
||||||
|
\`role_id\` int(11) NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
|
||||||
|
`)
|
||||||
|
// NOTE: This data is not used - therefore we remove it.
|
||||||
|
// This data is aligned to the `server_users` table except the entry 4,
|
||||||
|
// this one is missing in the other table
|
||||||
|
// and after checking with administration, we figured out that
|
||||||
|
// this is a data fragement no longer needed.
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`login_user_roles\` VALUES
|
||||||
|
(1,28,1),
|
||||||
|
(2,37,1),
|
||||||
|
(3,50,1),
|
||||||
|
(4,44,1),
|
||||||
|
(5,872,1);
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`operators\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`username\` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`user_pubkey\` binary(32) NOT NULL,
|
||||||
|
\`data_base64\` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`modified\` datetime NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: This data seems not to have any use
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`operators\` VALUES
|
||||||
|
(5,'einhornimmond',0x78DCFAA8341B3A39B3C5502B4D9ACDBC4B181A10CC0D94187498E0A0C74288E0,'i99a5/wWGmQN4AF8ilUXhHJVV/3At82f6CNNh3ewdVyTTAqugcdeG53DEMNUxCTFwk7KIg==','2019-09-17 13:08:22');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`operator_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(25) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`text\` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`operator_types\` VALUES
|
||||||
|
(1,'hedera','Hedera Keys for sign and pay hedera transactions'),
|
||||||
|
(2,'gradido-user','default gradido user keys'),
|
||||||
|
(3,'gradido-group','default gradido group root keys, other address are derived');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`state_errors\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`state_user_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`transaction_type_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`created\` datetime NOT NULL,
|
||||||
|
\`message_json\` text COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=161 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: This data is no longer generated
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`state_errors\` VALUES
|
||||||
|
(9,11,1,'2020-08-07 10:40:03','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(17,528,2,'2021-02-10 08:04:32','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"sender 0 hasn\\'t enough GDD"}]}'),
|
||||||
|
(115,82,1,'2021-09-01 11:14:25','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(119,82,1,'2021-09-06 18:55:55','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(138,502,1,'2021-10-31 00:00:32','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(139,502,1,'2021-11-02 19:50:36','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(140,502,1,'2021-11-07 13:32:11','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(141,502,1,'2021-11-16 22:04:59','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(142,502,1,'2021-11-21 23:47:14','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(143,502,1,'2021-11-22 00:14:40','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(144,502,1,'2021-11-25 21:40:15','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(145,502,1,'2021-11-25 22:45:06','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(146,502,1,'2021-11-29 12:52:12','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(147,502,1,'2021-12-04 01:56:10','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(148,502,1,'2021-12-06 13:12:08','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(149,502,1,'2021-12-06 13:18:20','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(150,502,1,'2021-12-16 21:06:34','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(151,502,1,'2021-12-20 23:11:44','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(152,502,1,'2022-01-04 13:19:31','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(153,502,1,'2022-01-04 13:54:33','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(154,502,1,'2022-01-04 13:55:32','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(155,502,1,'2022-01-04 14:02:35','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(156,502,1,'2022-01-04 14:50:49','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(157,502,1,'2022-01-04 14:51:41','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(158,502,1,'2022-01-19 00:32:46','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(159,502,1,'2022-01-19 00:52:42','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}'),
|
||||||
|
(160,502,1,'2022-01-25 08:31:57','{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1.000 GDD per Month for in target_date not allowed"}]}');
|
||||||
|
`)
|
||||||
|
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`transaction_types\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`name\` varchar(90) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
\`text\` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||||
|
`)
|
||||||
|
// NOTE: Static data might be needed as enum definitions
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO \`transaction_types\` VALUES
|
||||||
|
(1,'creation','create new gradidos for member and also for group (in development)'),
|
||||||
|
(2,'transfer','send gradidos from one member to another, also cross group transfer'),
|
||||||
|
(3,'group create','create a new group, trigger creation of new hedera topic and new blockchain on node server'),
|
||||||
|
(4,'group add member','add user to a group or move if he was already in a group'),
|
||||||
|
(5,'group remove member','remove user from group, maybe he was moved elsewhere'),
|
||||||
|
(6,'hedera topic create','create new topic on hedera'),
|
||||||
|
(7,'hedera topic send message','send consensus message over hedera topic'),
|
||||||
|
(8,'hedera account create','create new account on hedera for holding some founds with unencrypted keys'),
|
||||||
|
(9,'decay start','signalize the starting point for decay calculation, allowed only once per chain');
|
||||||
|
`)
|
||||||
|
}
|
||||||
35
database/migrations/0015-admin_pending_creations.ts
Normal file
35
database/migrations/0015-admin_pending_creations.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* MIGRATION TO PROPERLY STORE PENDING CREATIONS
|
||||||
|
*
|
||||||
|
* There were two tables for the pending tasks,
|
||||||
|
* since the login_server used some crypto to store its
|
||||||
|
* tasks there. It was easier to create a new table.
|
||||||
|
* This migration drops the old unused table and renames
|
||||||
|
* the new table to properly describe what it does
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
// drop duplicate table, it was unused
|
||||||
|
await queryFn('DROP TABLE `login_pending_tasks`;')
|
||||||
|
|
||||||
|
// rename the new pending creations table to a proper table name
|
||||||
|
await queryFn('RENAME TABLE `login_pending_tasks_admin` TO `admin_pending_creations`;')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn('RENAME TABLE `admin_pending_creations` TO `login_pending_tasks_admin`;')
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`login_pending_tasks\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`user_id\` int(10) unsigned DEFAULT 0,
|
||||||
|
\`request\` varbinary(2048) NOT NULL,
|
||||||
|
\`created\` datetime NOT NULL,
|
||||||
|
\`finished\` datetime DEFAULT '2000-01-01 00:00:00',
|
||||||
|
\`result_json\` text DEFAULT NULL,
|
||||||
|
\`param_json\` text DEFAULT NULL,
|
||||||
|
\`task_type_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`child_pending_task_id\` int(10) unsigned DEFAULT 0,
|
||||||
|
\`parent_pending_task_id\` int(10) unsigned DEFAULT 0,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=795 DEFAULT CHARSET=utf8mb4
|
||||||
|
`)
|
||||||
|
}
|
||||||
60
database/migrations/0016-transaction_signatures.ts
Normal file
60
database/migrations/0016-transaction_signatures.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* MIGRATION TO CLEANUP TRANSACTIONS TABLE
|
||||||
|
*
|
||||||
|
* This migration cleans up the transactions table and
|
||||||
|
* combines its data with transaction_signatures.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export async function upgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
// Drop column `state_group_id` since it only contains "0" as value, no variation.
|
||||||
|
// Furthermore it was not present in our model itself (meaning that newly created )
|
||||||
|
await queryFn('ALTER TABLE `transactions` DROP COLUMN `state_group_id`;')
|
||||||
|
|
||||||
|
// Drop column `blockchain_type_id` since it only contains "1" as value, no variation.
|
||||||
|
await queryFn('ALTER TABLE `transactions` DROP COLUMN `blockchain_type_id`;')
|
||||||
|
|
||||||
|
// Create `signature` column - for data from `transaction_signatures` table.
|
||||||
|
await queryFn(
|
||||||
|
'ALTER TABLE `transactions` ADD COLUMN `signature` binary(64) DEFAULT NULL AFTER `received`;',
|
||||||
|
)
|
||||||
|
|
||||||
|
// Create `pubkey` column - for data from `transaction_signatures` table.
|
||||||
|
await queryFn(
|
||||||
|
'ALTER TABLE `transactions` ADD COLUMN `pubkey` binary(32) DEFAULT NULL AFTER `signature`;',
|
||||||
|
)
|
||||||
|
|
||||||
|
// Transfer data from `transaction_signatures` table to `transactions` table
|
||||||
|
await queryFn(`
|
||||||
|
UPDATE transactions
|
||||||
|
INNER JOIN transaction_signatures ON transactions.id = transaction_signatures.transaction_id
|
||||||
|
SET transactions.signature = transaction_signatures.signature, transactions.pubkey = transaction_signatures.pubkey;
|
||||||
|
`)
|
||||||
|
|
||||||
|
// Drop `transaction_signatures` table
|
||||||
|
await queryFn('DROP TABLE `transaction_signatures`;')
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function downgrade(queryFn: (query: string, values?: any[]) => Promise<Array<any>>) {
|
||||||
|
await queryFn(`
|
||||||
|
CREATE TABLE \`transaction_signatures\` (
|
||||||
|
\`id\` int(10) unsigned NOT NULL AUTO_INCREMENT,
|
||||||
|
\`transaction_id\` int(10) unsigned NOT NULL,
|
||||||
|
\`signature\` binary(64) NOT NULL,
|
||||||
|
\`pubkey\` binary(32) NOT NULL,
|
||||||
|
PRIMARY KEY (\`id\`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||||
|
`)
|
||||||
|
await queryFn(`
|
||||||
|
INSERT INTO transaction_signatures (transaction_id, signature, pubkey)
|
||||||
|
(SELECT id as transaction_id, signature, pubkey FROM transactions WHERE signature IS NOT NULL and pubkey IS NOT NULL);
|
||||||
|
`)
|
||||||
|
await queryFn('ALTER TABLE `transactions` DROP COLUMN `pubkey`;')
|
||||||
|
await queryFn('ALTER TABLE `transactions` DROP COLUMN `signature`;')
|
||||||
|
await queryFn(
|
||||||
|
'ALTER TABLE `transactions` ADD COLUMN `blockchain_type_id` bigint(20) unsigned NOT NULL DEFAULT 1 AFTER `received` ;',
|
||||||
|
)
|
||||||
|
await queryFn(
|
||||||
|
'ALTER TABLE `transactions` ADD COLUMN `state_group_id` int(10) unsigned DEFAULT NULL AFTER `id`;',
|
||||||
|
)
|
||||||
|
// We have to set the correct values previously in the table , since its not the same as the column's default
|
||||||
|
await queryFn('UPDATE `transactions` SET `state_group_id` = 0;')
|
||||||
|
}
|
||||||
@ -1,16 +0,0 @@
|
|||||||
import Faker from 'faker'
|
|
||||||
import { define } from 'typeorm-seeding'
|
|
||||||
import { LoginUserRoles } from '../../entity/LoginUserRoles'
|
|
||||||
import { LoginUserRolesContext } from '../interface/UserContext'
|
|
||||||
|
|
||||||
define(LoginUserRoles, (faker: typeof Faker, context?: LoginUserRolesContext) => {
|
|
||||||
if (!context) context = {}
|
|
||||||
if (!context.userId) throw new Error('LoginUserRoles: No userId present!')
|
|
||||||
if (!context.roleId) throw new Error('LoginUserRoles: No roleId present!')
|
|
||||||
|
|
||||||
const userRoles = new LoginUserRoles()
|
|
||||||
userRoles.userId = context.userId
|
|
||||||
userRoles.roleId = context.roleId
|
|
||||||
|
|
||||||
return userRoles
|
|
||||||
})
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import Faker from 'faker'
|
|
||||||
import { define } from 'typeorm-seeding'
|
|
||||||
import { TransactionSignature } from '../../entity/TransactionSignature'
|
|
||||||
import { TransactionSignatureContext } from '../interface/TransactionContext'
|
|
||||||
import { randomBytes } from 'crypto'
|
|
||||||
|
|
||||||
define(TransactionSignature, (faker: typeof Faker, context?: TransactionSignatureContext) => {
|
|
||||||
if (!context || !context.transaction) {
|
|
||||||
throw new Error('TransactionSignature: No transaction present!')
|
|
||||||
}
|
|
||||||
|
|
||||||
const transactionSignature = new TransactionSignature()
|
|
||||||
transactionSignature.signature = context.signature ? context.signature : randomBytes(64)
|
|
||||||
transactionSignature.pubkey = context.pubkey ? context.pubkey : randomBytes(32)
|
|
||||||
transactionSignature.transaction = context.transaction
|
|
||||||
|
|
||||||
return transactionSignature
|
|
||||||
})
|
|
||||||
@ -12,7 +12,8 @@ define(Transaction, (faker: typeof Faker, context?: TransactionContext) => {
|
|||||||
transaction.txHash = context.txHash ? context.txHash : randomBytes(48)
|
transaction.txHash = context.txHash ? context.txHash : randomBytes(48)
|
||||||
transaction.memo = context.memo || context.memo === '' ? context.memo : faker.lorem.sentence()
|
transaction.memo = context.memo || context.memo === '' ? context.memo : faker.lorem.sentence()
|
||||||
transaction.received = context.received ? context.received : new Date()
|
transaction.received = context.received ? context.received : new Date()
|
||||||
transaction.blockchainTypeId = context.blockchainTypeId ? context.blockchainTypeId : 1
|
transaction.signature = context.signature ? context.signature : randomBytes(64)
|
||||||
|
transaction.pubkey = context.signaturePubkey ? context.signaturePubkey : randomBytes(32)
|
||||||
if (context.transactionSendCoin) transaction.transactionSendCoin = context.transactionSendCoin
|
if (context.transactionSendCoin) transaction.transactionSendCoin = context.transactionSendCoin
|
||||||
if (context.transactionCreation) transaction.transactionCreation = context.transactionCreation
|
if (context.transactionCreation) transaction.transactionCreation = context.transactionCreation
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,8 @@ export interface TransactionContext {
|
|||||||
memo?: string
|
memo?: string
|
||||||
received?: Date
|
received?: Date
|
||||||
blockchainTypeId?: number
|
blockchainTypeId?: number
|
||||||
|
signature?: Buffer
|
||||||
|
signaturePubkey?: Buffer
|
||||||
transactionSendCoin?: TransactionSendCoin
|
transactionSendCoin?: TransactionSendCoin
|
||||||
transactionCreation?: TransactionCreation
|
transactionCreation?: TransactionCreation
|
||||||
}
|
}
|
||||||
@ -43,10 +45,6 @@ export interface UserTransactionContext {
|
|||||||
transactionTypeId?: number
|
transactionTypeId?: number
|
||||||
balance?: number
|
balance?: number
|
||||||
balanceDate?: Date
|
balanceDate?: Date
|
||||||
}
|
|
||||||
|
|
||||||
export interface TransactionSignatureContext {
|
|
||||||
signature?: Buffer
|
signature?: Buffer
|
||||||
pubkey?: Buffer
|
pubkey?: Buffer
|
||||||
transaction?: Transaction
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,17 +10,14 @@ import {
|
|||||||
TransactionContext,
|
TransactionContext,
|
||||||
TransactionCreationContext,
|
TransactionCreationContext,
|
||||||
UserTransactionContext,
|
UserTransactionContext,
|
||||||
TransactionSignatureContext,
|
|
||||||
} from '../../interface/TransactionContext'
|
} from '../../interface/TransactionContext'
|
||||||
import { UserInterface } from '../../interface/UserInterface'
|
import { UserInterface } from '../../interface/UserInterface'
|
||||||
import { User } from '../../../entity/User'
|
import { User } from '../../../entity/User'
|
||||||
import { LoginUser } from '../../../entity/LoginUser'
|
import { LoginUser } from '../../../entity/LoginUser'
|
||||||
import { LoginUserBackup } from '../../../entity/LoginUserBackup'
|
import { LoginUserBackup } from '../../../entity/LoginUserBackup'
|
||||||
import { ServerUser } from '../../../entity/ServerUser'
|
import { ServerUser } from '../../../entity/ServerUser'
|
||||||
import { LoginUserRoles } from '../../../entity/LoginUserRoles'
|
|
||||||
import { Balance } from '../../../entity/Balance'
|
import { Balance } from '../../../entity/Balance'
|
||||||
import { Transaction } from '../../../entity/Transaction'
|
import { Transaction } from '../../../entity/Transaction'
|
||||||
import { TransactionSignature } from '../../../entity/TransactionSignature'
|
|
||||||
import { UserTransaction } from '../../../entity/UserTransaction'
|
import { UserTransaction } from '../../../entity/UserTransaction'
|
||||||
import { TransactionCreation } from '../../../entity/TransactionCreation'
|
import { TransactionCreation } from '../../../entity/TransactionCreation'
|
||||||
import { Factory } from 'typeorm-seeding'
|
import { Factory } from 'typeorm-seeding'
|
||||||
@ -33,10 +30,6 @@ export const userSeeder = async (factory: Factory, userData: UserInterface): Pro
|
|||||||
|
|
||||||
if (userData.isAdmin) {
|
if (userData.isAdmin) {
|
||||||
await factory(ServerUser)(createServerUserContext(userData)).create()
|
await factory(ServerUser)(createServerUserContext(userData)).create()
|
||||||
|
|
||||||
// This is crazy: we just need the relation to roleId but no role at all
|
|
||||||
// It works with LoginRoles empty!!
|
|
||||||
await factory(LoginUserRoles)(createLoginUserRolesContext(loginUser)).create()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userData.addBalance) {
|
if (userData.addBalance) {
|
||||||
@ -51,9 +44,6 @@ export const userSeeder = async (factory: Factory, userData: UserInterface): Pro
|
|||||||
await factory(UserTransaction)(
|
await factory(UserTransaction)(
|
||||||
createUserTransactionContext(userData, user, transaction),
|
createUserTransactionContext(userData, user, transaction),
|
||||||
).create()
|
).create()
|
||||||
await factory(TransactionSignature)(
|
|
||||||
createTransactionSignatureContext(userData, transaction),
|
|
||||||
).create()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,16 +156,7 @@ const createUserTransactionContext = (
|
|||||||
transactionTypeId: transaction.transactionTypeId,
|
transactionTypeId: transaction.transactionTypeId,
|
||||||
balance: context.amount,
|
balance: context.amount,
|
||||||
balanceDate: context.recordDate,
|
balanceDate: context.recordDate,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const createTransactionSignatureContext = (
|
|
||||||
context: UserInterface,
|
|
||||||
transaction: Transaction,
|
|
||||||
): TransactionSignatureContext => {
|
|
||||||
return {
|
|
||||||
signature: context.signature,
|
signature: context.signature,
|
||||||
pubkey: context.signaturePubkey,
|
pubkey: context.signaturePubkey,
|
||||||
transaction,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user