Merge branch 'master' into insert-missing-contributions-migration

This commit is contained in:
Moriz Wahl 2022-07-26 13:51:20 +02:00 committed by GitHub
commit bd957c38f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 113 additions and 56 deletions

View File

@ -28,7 +28,7 @@ const propsData = {
amount: 210,
memo: 'Aktives Grundeinkommen für Januar 2022',
date: '2022-01-01T00:00:00.000Z',
moderator: 1,
moderator: null,
creation: [790, 1000, 1000],
__typename: 'PendingCreation',
},
@ -66,7 +66,7 @@ const propsData = {
},
},
{ key: 'moderator', label: 'moderator' },
{ key: 'edit_creation', label: 'edit' },
{ key: 'editCreation', label: 'edit' },
{ key: 'confirm', label: 'save' },
],
toggleDetails: false,
@ -113,6 +113,10 @@ describe('OpenCreationsTable', () => {
expect(wrapper.findAll('tr').at(1).find('.bi-pencil-square').exists()).toBe(true)
})
it('has no button.bi-pencil-square for user contribution ', () => {
expect(wrapper.findAll('tr').at(2).find('.bi-pencil-square').exists()).toBe(false)
})
describe('show edit details', () => {
beforeEach(async () => {
await wrapper.findAll('tr').at(1).find('.bi-pencil-square').trigger('click')

View File

@ -11,8 +11,14 @@
<b-icon icon="x" variant="light"></b-icon>
</b-button>
</template>
<template #cell(edit_creation)="row">
<b-button variant="info" size="md" @click="rowToggleDetails(row, 0)" class="mr-2">
<template #cell(editCreation)="row">
<b-button
v-if="row.item.moderator"
variant="info"
size="md"
@click="rowToggleDetails(row, 0)"
class="mr-2"
>
<b-icon :icon="row.detailsShowing ? 'x' : 'pencil-square'" aria-label="Help"></b-icon>
</b-button>
</template>

View File

@ -35,6 +35,7 @@
"creation_form": {
"creation_failed": "Ausstehende Schöpfung für {email} konnte nicht erzeugt werden.",
"creation_for": "Aktives Grundeinkommen für",
"deleteNow": "Möchtest du diesen Beitrag zur Gemeinschaft wirklich löschen?",
"enter_text": "Text eintragen",
"form": "Schöpfungsformular",
"min_characters": "Mindestens 10 Zeichen eingeben",

View File

@ -35,6 +35,7 @@
"creation_form": {
"creation_failed": "Could not create pending creation for {email}",
"creation_for": "Active Basic Income for",
"deleteNow": "Do you really want to delete this contribution to the community?",
"enter_text": "Enter text",
"form": "Creation form",
"min_characters": "Enter at least 10 characters",

View File

@ -18,7 +18,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
amount: 500,
memo: 'Danke für alles',
date: new Date(),
moderator: 0,
moderator: 2,
},
{
id: 2,
@ -28,7 +28,7 @@ const apolloQueryMock = jest.fn().mockResolvedValue({
amount: 1000000,
memo: 'Gut Ergattert',
date: new Date(),
moderator: 0,
moderator: 2,
},
],
},
@ -80,28 +80,54 @@ describe('CreationConfirm', () => {
})
describe('remove creation with success', () => {
beforeEach(async () => {
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
let spy
it('calls the adminDeleteContribution mutation', () => {
expect(apolloMutateMock).toBeCalledWith({
mutation: adminDeleteContribution,
variables: { id: 1 },
describe('admin confirms deletion', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
it('opens a modal', () => {
expect(spy).toBeCalled()
})
it('calls the adminDeleteContribution mutation', () => {
expect(apolloMutateMock).toBeCalledWith({
mutation: adminDeleteContribution,
variables: { id: 1 },
})
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_delete')
})
})
it('commits openCreationsMinus to store', () => {
expect(storeCommitMock).toBeCalledWith('openCreationsMinus', 1)
})
describe('admin cancels deletion', () => {
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve(false))
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})
it('toasts a success message', () => {
expect(toastSuccessSpy).toBeCalledWith('creation_form.toasted_delete')
it('does not call the adminDeleteContribution mutation', () => {
expect(apolloMutateMock).not.toBeCalled()
})
})
})
describe('remove creation with error', () => {
let spy
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
spy.mockImplementation(() => Promise.resolve('some value'))
apolloMutateMock.mockRejectedValue({ message: 'Ouchhh!' })
await wrapper.findAll('tr').at(1).findAll('button').at(0).trigger('click')
})

View File

@ -34,20 +34,23 @@ export default {
},
methods: {
removeCreation(item) {
this.$apollo
.mutate({
mutation: adminDeleteContribution,
variables: {
id: item.id,
},
})
.then((result) => {
this.updatePendingCreations(item.id)
this.toastSuccess(this.$t('creation_form.toasted_delete'))
})
.catch((error) => {
this.toastError(error.message)
})
this.$bvModal.msgBoxConfirm(this.$t('creation_form.deleteNow')).then(async (value) => {
if (value)
await this.$apollo
.mutate({
mutation: adminDeleteContribution,
variables: {
id: item.id,
},
})
.then((result) => {
this.updatePendingCreations(item.id)
this.toastSuccess(this.$t('creation_form.toasted_delete'))
})
.catch((error) => {
this.toastError(error.message)
})
})
},
confirmCreation() {
this.$apollo
@ -114,7 +117,7 @@ export default {
},
},
{ key: 'moderator', label: this.$t('moderator') },
{ key: 'edit_creation', label: this.$t('edit') },
{ key: 'editCreation', label: this.$t('edit') },
{ key: 'confirm', label: this.$t('save') },
]
},

View File

@ -35,12 +35,17 @@ export const creationFactory = async (
if (creation.confirmed) {
await mutate({ mutation: confirmContribution, variables: { id: pendingCreation.id } })
const confirmedCreation = await Contribution.findOneOrFail({ id: pendingCreation.id })
if (creation.moveCreationDate) {
const transaction = await Transaction.findOneOrFail({
where: { userId: user.id, creationDate: new Date(creation.creationDate) },
order: { balanceDate: 'DESC' },
})
if (transaction.decay.equals(0) && transaction.creationDate) {
confirmedCreation.contributionDate = new Date(
nMonthsBefore(transaction.creationDate, creation.moveCreationDate),
)
transaction.creationDate = new Date(
nMonthsBefore(transaction.creationDate, creation.moveCreationDate),
)
@ -48,6 +53,7 @@ export const creationFactory = async (
nMonthsBefore(transaction.balanceDate, creation.moveCreationDate),
)
await transaction.save()
await confirmedCreation.save()
}
}
} else {

View File

@ -23,6 +23,9 @@ describe('ContributionForm', () => {
creation: ['1000', '1000', '1000'],
},
},
$i18n: {
locale: 'en',
},
}
const Wrapper = () => {

View File

@ -18,6 +18,7 @@
id="contribution-date"
v-model="form.date"
size="lg"
:locale="$i18n.locale"
:max="maximalDate"
:min="minimalDate"
class="mb-4"
@ -25,25 +26,27 @@
:label-no-date-selected="$t('contribution.noDateSelected')"
required
></b-form-datepicker>
<label class="mt-3">{{ $t('contribution.activity') }}</label>
<b-form-textarea
id="contribution-memo"
v-model="form.memo"
rows="3"
max-rows="6"
required
:minlength="minlength"
:maxlength="maxlength"
></b-form-textarea>
<div
v-show="form.memo.length > 0"
class="text-right"
:class="form.memo.length < minlength ? 'text-danger' : 'text-success'"
<validation-provider
:rules="{
required: true,
min: minlength,
max: maxlength,
}"
:name="$t('form.message')"
v-slot="{ errors }"
>
{{ form.memo.length }}
<span v-if="form.memo.length < minlength">{{ $t('math.lower') }} {{ minlength }}</span>
<span v-else>{{ $t('math.divide') }} {{ maxlength }}</span>
</div>
<label class="mt-3">{{ $t('contribution.activity') }}</label>
<b-form-textarea
id="contribution-memo"
v-model="form.memo"
rows="3"
max-rows="6"
required
></b-form-textarea>
<b-col v-if="errors">
<span v-for="error in errors" class="errors" :key="error">{{ error }}</span>
</b-col>
</validation-provider>
<label class="mt-3">{{ $t('form.amount') }}</label>
<b-input-group size="lg" prepend="GDD" append=".00">
<b-form-input
@ -90,7 +93,7 @@ export default {
},
data() {
return {
minlength: 50,
minlength: 5,
maxlength: 255,
maximalDate: new Date(),
form: this.value,
@ -166,3 +169,8 @@ export default {
},
}
</script>
<style>
span.errors {
color: red;
}
</style>

View File

@ -203,10 +203,8 @@
"login": "Anmeldung",
"math": {
"aprox": "~",
"divide": "/",
"equal": "=",
"exclaim": "!",
"lower": "<",
"minus": "",
"pipe": "|"
},

View File

@ -203,10 +203,8 @@
"login": "Login",
"math": {
"aprox": "~",
"divide": "/",
"equal": "=",
"exclaim": "!",
"lower": "<",
"minus": "",
"pipe": "|"
},

View File

@ -26,6 +26,9 @@ describe('Community', () => {
creation: ['1000', '1000', '1000'],
},
},
$i18n: {
locale: 'en',
},
}
const Wrapper = () => {