Merge branch 'master' into add-client-request-time

This commit is contained in:
Moriz Wahl 2022-09-22 14:18:14 +02:00 committed by GitHub
commit 25dd12b18b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 121 additions and 129 deletions

View File

@ -8,10 +8,7 @@ import { Context, getUser } from '@/server/context'
import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql' import { Resolver, Query, Args, Authorized, Ctx, Mutation } from 'type-graphql'
import { getCustomRepository, getConnection } from '@dbTools/typeorm' import { getCustomRepository, getConnection } from '@dbTools/typeorm'
import { import { sendTransactionReceivedEmail } from '@/mailer/sendTransactionReceivedEmail'
sendTransactionLinkRedeemedEmail,
sendTransactionReceivedEmail,
} from '@/mailer/sendTransactionReceivedEmail'
import { Transaction } from '@model/Transaction' import { Transaction } from '@model/Transaction'
import { TransactionList } from '@model/TransactionList' import { TransactionList } from '@model/TransactionList'
@ -38,6 +35,7 @@ import Decimal from 'decimal.js-light'
import { BalanceResolver } from './BalanceResolver' import { BalanceResolver } from './BalanceResolver'
import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const' import { MEMO_MAX_CHARS, MEMO_MIN_CHARS } from './const/const'
import { sendTransactionLinkRedeemedEmail } from '@/mailer/sendTransactionLinkRedeemed'
export const executeTransaction = async ( export const executeTransaction = async (
amount: Decimal, amount: Decimal,
@ -154,7 +152,6 @@ export const executeTransaction = async (
email: recipient.email, email: recipient.email,
senderEmail: sender.email, senderEmail: sender.email,
amount, amount,
memo,
overviewURL: CONFIG.EMAIL_LINK_OVERVIEW, overviewURL: CONFIG.EMAIL_LINK_OVERVIEW,
}) })
if (transactionLink) { if (transactionLink) {

View File

@ -0,0 +1,44 @@
import { sendEMail } from './sendEMail'
import Decimal from 'decimal.js-light'
import { sendTransactionLinkRedeemedEmail } from './sendTransactionLinkRedeemed'
jest.mock('./sendEMail', () => {
return {
__esModule: true,
sendEMail: jest.fn(),
}
})
describe('sendTransactionLinkRedeemedEmail', () => {
beforeEach(async () => {
await sendTransactionLinkRedeemedEmail({
email: 'bibi@bloxberg.de',
senderFirstName: 'Peter',
senderLastName: 'Lustig',
recipientFirstName: 'Bibi',
recipientLastName: 'Bloxberg',
senderEmail: 'peter@lustig.de',
amount: new Decimal(42.0),
memo: 'Vielen Dank dass Du dabei bist',
overviewURL: 'http://localhost/overview',
})
})
it('calls sendEMail', () => {
expect(sendEMail).toBeCalledWith({
to: `Bibi Bloxberg <bibi@bloxberg.de>`,
subject: 'Gradido-Link wurde eingelöst',
text:
expect.stringContaining('Hallo Bibi Bloxberg') &&
expect.stringContaining(
'Peter Lustig (peter@lustig.de) hat soeben deinen Link eingelöst.',
) &&
expect.stringContaining('Betrag: 42,00 GDD,') &&
expect.stringContaining('Memo: Vielen Dank dass Du dabei bist') &&
expect.stringContaining(
'Details zur Transaktion findest du in deinem Gradido-Konto: http://localhost/overview',
) &&
expect.stringContaining('Bitte antworte nicht auf diese E-Mail!'),
})
})
})

View File

@ -0,0 +1,28 @@
import { backendLogger as logger } from '@/server/logger'
import Decimal from 'decimal.js-light'
import { sendEMail } from './sendEMail'
import { transactionLinkRedeemed } from './text/transactionLinkRedeemed'
export const sendTransactionLinkRedeemedEmail = (data: {
email: string
senderFirstName: string
senderLastName: string
recipientFirstName: string
recipientLastName: string
senderEmail: string
amount: Decimal
memo: string
overviewURL: string
}): Promise<boolean> => {
logger.info(
`sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName},
<${data.email}>,
subject=${transactionLinkRedeemed.de.subject},
text=${transactionLinkRedeemed.de.text(data)}`,
)
return sendEMail({
to: `${data.recipientFirstName} ${data.recipientLastName} <${data.email}>`,
subject: transactionLinkRedeemed.de.subject,
text: transactionLinkRedeemed.de.text(data),
})
}

View File

@ -19,7 +19,6 @@ describe('sendTransactionReceivedEmail', () => {
email: 'peter@lustig.de', email: 'peter@lustig.de',
senderEmail: 'bibi@bloxberg.de', senderEmail: 'bibi@bloxberg.de',
amount: new Decimal(42.0), amount: new Decimal(42.0),
memo: 'Vielen herzlichen Dank für den neuen Hexenbesen!',
overviewURL: 'http://localhost/overview', overviewURL: 'http://localhost/overview',
}) })
}) })
@ -33,7 +32,6 @@ describe('sendTransactionReceivedEmail', () => {
expect.stringContaining('42,00 GDD') && expect.stringContaining('42,00 GDD') &&
expect.stringContaining('Bibi Bloxberg') && expect.stringContaining('Bibi Bloxberg') &&
expect.stringContaining('(bibi@bloxberg.de)') && expect.stringContaining('(bibi@bloxberg.de)') &&
expect.stringContaining('Vielen herzlichen Dank für den neuen Hexenbesen!') &&
expect.stringContaining('http://localhost/overview'), expect.stringContaining('http://localhost/overview'),
}) })
}) })

View File

@ -1,7 +1,7 @@
import { backendLogger as logger } from '@/server/logger' import { backendLogger as logger } from '@/server/logger'
import Decimal from 'decimal.js-light' import Decimal from 'decimal.js-light'
import { sendEMail } from './sendEMail' import { sendEMail } from './sendEMail'
import { transactionLinkRedeemed, transactionReceived } from './text/transactionReceived' import { transactionReceived } from './text/transactionReceived'
export const sendTransactionReceivedEmail = (data: { export const sendTransactionReceivedEmail = (data: {
senderFirstName: string senderFirstName: string
@ -11,7 +11,6 @@ export const sendTransactionReceivedEmail = (data: {
email: string email: string
senderEmail: string senderEmail: string
amount: Decimal amount: Decimal
memo: string
overviewURL: string overviewURL: string
}): Promise<boolean> => { }): Promise<boolean> => {
logger.info( logger.info(
@ -26,27 +25,3 @@ export const sendTransactionReceivedEmail = (data: {
text: transactionReceived.de.text(data), text: transactionReceived.de.text(data),
}) })
} }
export const sendTransactionLinkRedeemedEmail = (data: {
email: string
senderFirstName: string
senderLastName: string
recipientFirstName: string
recipientLastName: string
senderEmail: string
amount: Decimal
memo: string
overviewURL: string
}): Promise<boolean> => {
logger.info(
`sendEmail(): to=${data.recipientFirstName} ${data.recipientLastName},
<${data.email}>,
subject=${transactionLinkRedeemed.de.subject},
text=${transactionLinkRedeemed.de.text(data)}`,
)
return sendEMail({
to: `${data.recipientFirstName} ${data.recipientLastName} <${data.email}>`,
subject: transactionLinkRedeemed.de.subject,
text: transactionLinkRedeemed.de.text(data),
})
}

View File

@ -14,9 +14,10 @@ export const contributionConfirmed = {
}): string => }): string =>
`Hallo ${data.recipientFirstName} ${data.recipientLastName}, `Hallo ${data.recipientFirstName} ${data.recipientLastName},
Dein Gradido Schöpfungsantrag "${data.contributionMemo}" wurde soeben von ${data.senderFirstName} ${ Dein eingereichter Gemeinwohl-Beitrag "${data.contributionMemo}" wurde soeben von ${
data.senderLastName data.senderFirstName
} bestätigt. } ${data.senderLastName} bestätigt.
Betrag: ${data.contributionAmount.toFixed(2).replace('.', ',')} GDD Betrag: ${data.contributionAmount.toFixed(2).replace('.', ',')} GDD
Bitte antworte nicht auf diese E-Mail! Bitte antworte nicht auf diese E-Mail!

View File

@ -14,17 +14,15 @@ export const contributionMessageReceived = {
}): string => }): string =>
`Hallo ${data.recipientFirstName} ${data.recipientLastName}, `Hallo ${data.recipientFirstName} ${data.recipientLastName},
Du hast soeben zu deinem eingereichten Gradido Schöpfungsantrag "${data.contributionMemo}" eine Rückfrage von ${data.senderFirstName} ${data.senderLastName} erhalten. du hast soeben zu deinem eingereichten Gemeinwohl-Beitrag "${data.contributionMemo}" eine Rückfrage von ${data.senderFirstName} ${data.senderLastName} erhalten.
Die Rückfrage lautet:
${data.message} Bitte beantworte die Rückfrage in deinem Gradido-Konto im Menü "Gemeinschaft" im Tab "Meine Beiträge zum Gemeinwohl"!
Link zu deinem Konto: ${data.overviewURL}
Bitte antworte nicht auf diese E-Mail! Bitte antworte nicht auf diese E-Mail!
Mit freundlichen Grüßen, Mit freundlichen Grüßen,
dein Gradido-Team dein Gradido-Team`,
Link zu deinem Konto: ${data.overviewURL}`,
}, },
} }

View File

@ -0,0 +1,33 @@
import Decimal from 'decimal.js-light'
export const transactionLinkRedeemed = {
de: {
subject: 'Gradido-Link wurde eingelöst',
text: (data: {
email: string
senderFirstName: string
senderLastName: string
recipientFirstName: string
recipientLastName: string
senderEmail: string
amount: Decimal
memo: string
overviewURL: string
}): string =>
`Hallo ${data.recipientFirstName} ${data.recipientLastName}
${data.senderFirstName} ${data.senderLastName} (${
data.senderEmail
}) hat soeben deinen Link eingelöst.
Betrag: ${data.amount.toFixed(2).replace('.', ',')} GDD,
Memo: ${data.memo}
Details zur Transaktion findest du in deinem Gradido-Konto: ${data.overviewURL}
Bitte antworte nicht auf diese E-Mail!
Mit freundlichen Grüßen,
dein Gradido-Team`,
},
}

View File

@ -11,7 +11,6 @@ export const transactionReceived = {
email: string email: string
senderEmail: string senderEmail: string
amount: Decimal amount: Decimal
memo: string
overviewURL: string overviewURL: string
}): string => }): string =>
`Hallo ${data.recipientFirstName} ${data.recipientLastName} `Hallo ${data.recipientFirstName} ${data.recipientLastName}
@ -19,47 +18,12 @@ export const transactionReceived = {
Du hast soeben ${data.amount.toFixed(2).replace('.', ',')} GDD von ${data.senderFirstName} ${ Du hast soeben ${data.amount.toFixed(2).replace('.', ',')} GDD von ${data.senderFirstName} ${
data.senderLastName data.senderLastName
} (${data.senderEmail}) erhalten. } (${data.senderEmail}) erhalten.
${data.senderFirstName} ${data.senderLastName} schreibt:
${data.memo} Details zur Transaktion findest du in deinem Gradido-Konto: ${data.overviewURL}
Bitte antworte nicht auf diese E-Mail! Bitte antworte nicht auf diese E-Mail!
Mit freundlichen Grüßen, Mit freundlichen Grüßen,
dein Gradido-Team dein Gradido-Team`,
Link zu deinem Konto: ${data.overviewURL}`,
},
}
export const transactionLinkRedeemed = {
de: {
subject: 'Gradido link eingelösst',
text: (data: {
email: string
senderFirstName: string
senderLastName: string
recipientFirstName: string
recipientLastName: string
senderEmail: string
amount: Decimal
memo: string
overviewURL: string
}): string =>
`Hallo ${data.recipientFirstName} ${data.recipientLastName}
${data.senderFirstName} ${data.senderLastName} (${
data.senderEmail
}) hat soeben deinen Link eingelösst.
Betrag: ${data.amount.toFixed(2).replace('.', ',')} GDD,
Memo: ${data.memo}
Bitte antworte nicht auf diese E-Mail!
Mit freundlichen Grüßen,
dein Gradido-Team
Link zu deinem Konto: ${data.overviewURL}`,
}, },
} }

View File

@ -3,7 +3,7 @@
<redeem-information v-bind="linkData" :isContributionLink="isContributionLink" /> <redeem-information v-bind="linkData" :isContributionLink="isContributionLink" />
<b-jumbotron> <b-jumbotron>
<div class="mb-3 text-center"> <div class="mb-3 text-center">
<b-button variant="primary" @click="$emit('redeem-link', linkData.amount)" size="lg"> <b-button variant="primary" @click="$emit('mutation-link', linkData.amount)" size="lg">
{{ $t('gdd_per_link.redeem') }} {{ $t('gdd_per_link.redeem') }}
</b-button> </b-button>
</div> </div>

View File

@ -178,7 +178,6 @@
"no-redeem": "Du darfst deinen eigenen Link nicht einlösen!", "no-redeem": "Du darfst deinen eigenen Link nicht einlösen!",
"not-copied": "Dein Gerät lässt das Kopieren leider nicht zu! Bitte kopiere den Link von Hand!", "not-copied": "Dein Gerät lässt das Kopieren leider nicht zu! Bitte kopiere den Link von Hand!",
"redeem": "Einlösen", "redeem": "Einlösen",
"redeem-text": "Willst du den Betrag jetzt einlösen?",
"redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.", "redeemed": "Erfolgreich eingelöst! Deinem Konto wurden {n} GDD gutgeschrieben.",
"redeemed-at": "Der Link wurde bereits am {date} eingelöst.", "redeemed-at": "Der Link wurde bereits am {date} eingelöst.",
"redeemed-title": "eingelöst", "redeemed-title": "eingelöst",

View File

@ -178,7 +178,6 @@
"no-redeem": "You not allowed to redeem your own link!", "no-redeem": "You not allowed to redeem your own link!",
"not-copied": "Unfortunately, your device does not allow copying! Please copy the link by hand!", "not-copied": "Unfortunately, your device does not allow copying! Please copy the link by hand!",
"redeem": "Redeem", "redeem": "Redeem",
"redeem-text": "Do you want to redeem the amount now?",
"redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.", "redeemed": "Successfully redeemed! Your account has been credited with {n} GDD.",
"redeemed-at": "The link was already redeemed on {date}.", "redeemed-at": "The link was already redeemed on {date}.",
"redeemed-title": "redeemed", "redeemed-title": "redeemed",

View File

@ -180,7 +180,6 @@
"no-redeem": "No puedes canjear tu propio enlace!", "no-redeem": "No puedes canjear tu propio enlace!",
"not-copied": "¡Desafortunadamente, su dispositivo no permite copiar! Copie el enlace manualmente!", "not-copied": "¡Desafortunadamente, su dispositivo no permite copiar! Copie el enlace manualmente!",
"redeem": "Canjear", "redeem": "Canjear",
"redeem-text": "¿Quieres canjear el importe ahora?",
"redeemed": "¡Canjeado con éxito! Tu cuenta ha sido acreditada con {n} GDD.", "redeemed": "¡Canjeado con éxito! Tu cuenta ha sido acreditada con {n} GDD.",
"redeemed-at": "El enlace ya se canjeó el {date}.", "redeemed-at": "El enlace ya se canjeó el {date}.",
"redeemed-title": "canjeado", "redeemed-title": "canjeado",

View File

@ -180,7 +180,6 @@
"no-redeem": "Vous n´êtes pas autorisé à percevoir votre propre lien!", "no-redeem": "Vous n´êtes pas autorisé à percevoir votre propre lien!",
"not-copied": "Malheureusement votre appareil ne permet pas de copier! Veuillez copier le lien manuellement svp!", "not-copied": "Malheureusement votre appareil ne permet pas de copier! Veuillez copier le lien manuellement svp!",
"redeem": "Encaisser", "redeem": "Encaisser",
"redeem-text": "Voulez-vous percevoir le montant maintenant?",
"redeemed": "Encaissé avec succès! Votre compte est crédité de {n} GDD.", "redeemed": "Encaissé avec succès! Votre compte est crédité de {n} GDD.",
"redeemed-at": "Le lien a déjà été perçu le {date}.", "redeemed-at": "Le lien a déjà été perçu le {date}.",
"redeemed-title": "encaisser", "redeemed-title": "encaisser",

View File

@ -180,7 +180,6 @@
"no-redeem": "Je mag je eigen link niet inwisselen!", "no-redeem": "Je mag je eigen link niet inwisselen!",
"not-copied": "Jouw apparaat laat het kopiëren helaas niet toe! Kopieer de link alsjeblieft met de hand!", "not-copied": "Jouw apparaat laat het kopiëren helaas niet toe! Kopieer de link alsjeblieft met de hand!",
"redeem": "Inwisselen", "redeem": "Inwisselen",
"redeem-text": "Wil je het bedrag nu inwisselen?",
"redeemed": "Succesvol ingewisseld! Op jouw rekening werden {n} GDD bijgeschreven.", "redeemed": "Succesvol ingewisseld! Op jouw rekening werden {n} GDD bijgeschreven.",
"redeemed-at": "De link werd al op {date} ingewisseld.", "redeemed-at": "De link werd al op {date} ingewisseld.",
"redeemed-title": "ingewisseld", "redeemed-title": "ingewisseld",

View File

@ -282,19 +282,11 @@ describe('TransactionLink', () => {
}) })
describe('redeem link with success', () => { describe('redeem link with success', () => {
let spy
beforeEach(async () => { beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
apolloMutateMock.mockResolvedValue() apolloMutateMock.mockResolvedValue()
spy.mockImplementation(() => Promise.resolve(true))
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
}) })
it('opens the modal', () => {
expect(spy).toBeCalledWith('gdd_per_link.redeem-text')
})
it('calls the API', () => { it('calls the API', () => {
expect(apolloMutateMock).toBeCalledWith( expect(apolloMutateMock).toBeCalledWith(
expect.objectContaining({ expect.objectContaining({
@ -316,37 +308,9 @@ describe('TransactionLink', () => {
}) })
}) })
describe('cancel redeem link', () => {
let spy
beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
apolloMutateMock.mockResolvedValue()
spy.mockImplementation(() => Promise.resolve(false))
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
})
it('does not call the API', () => {
expect(apolloMutateMock).not.toBeCalled()
})
it('does not toasts a success message', () => {
expect(mocks.$t).not.toBeCalledWith('gdd_per_link.redeemed', { n: '22' })
expect(toastSuccessSpy).not.toBeCalled()
})
it('does not push the route', () => {
expect(routerPushMock).not.toBeCalled()
})
})
describe('redeem link with error', () => { describe('redeem link with error', () => {
let spy
beforeEach(async () => { beforeEach(async () => {
spy = jest.spyOn(wrapper.vm.$bvModal, 'msgBoxConfirm')
apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' }) apolloMutateMock.mockRejectedValue({ message: 'Oh Noo!' })
spy.mockImplementation(() => Promise.resolve(true))
await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click') await wrapper.findComponent({ name: 'RedeemValid' }).find('button').trigger('click')
}) })

View File

@ -14,7 +14,7 @@
<redeem-valid <redeem-valid
:linkData="linkData" :linkData="linkData"
:isContributionLink="isContributionLink" :isContributionLink="isContributionLink"
@redeem-link="redeemLink" @mutation-link="mutationLink"
/> />
</template> </template>
@ -98,11 +98,6 @@ export default {
this.$router.push('/overview') this.$router.push('/overview')
}) })
}, },
redeemLink(amount) {
this.$bvModal.msgBoxConfirm(this.$t('gdd_per_link.redeem-text')).then((value) => {
if (value) this.mutationLink(amount)
})
},
}, },
computed: { computed: {
isContributionLink() { isContributionLink() {