add dynamic error email if transaction failed

This commit is contained in:
Dario Rekowski on RockPI 2021-05-17 18:20:46 +00:00
parent 248e6b9e71
commit 23b3534a87
7 changed files with 150 additions and 14 deletions

View File

@ -323,23 +323,33 @@ class AppRequestsController extends AppController
$this->addAdminError('StateBalancesController', 'overview', $gdtEntries, $user['id'] ? $user['id'] : 0); $this->addAdminError('StateBalancesController', 'overview', $gdtEntries, $user['id'] ? $user['id'] : 0);
} }
$stateUserTransactions_total = $stateUserTransactionsTable
->find()
->select(['id'])
->where(['state_user_id' => $user['id']])
->contain([]);
$stateUserTransactionsQuery = $stateUserTransactionsTable $stateUserTransactionsQuery = $stateUserTransactionsTable
->find() ->find()
->where(['state_user_id' => $user['id']]) ->where(['state_user_id' => $user['id']])
->order(['balance_date' => 'ASC']) ->order(['balance_date' => $orderDirection])
->contain([]) ->contain([])
->limit($count) ->limit($count)
->page($page) ->page($page)
; ;
$decay = true; $decay = true;
$transactions = []; $transactions = [];
$transactions_from_db = $stateUserTransactionsQuery->toArray();
if($stateUserTransactionsQuery->count() > 0) { if($stateUserTransactionsQuery->count() > 0) {
$transactions = $transactionsTable->listTransactionsHumanReadable($stateUserTransactionsQuery->toArray(), $user, $decay); if($orderDirection == 'DESC') {
$transactions_from_db = array_reverse($transactions_from_db);
}
$transactions = $transactionsTable->listTransactionsHumanReadable($transactions_from_db, $user, $decay);
if($orderDirection == 'DESC') { if($orderDirection == 'DESC') {
$transactions = array_reverse($transactions); $transactions = array_reverse($transactions);
} }
} }
$state_balance = $stateBalancesTable->find()->where(['state_user_id' => $user['id']])->first(); $state_balance = $stateBalancesTable->find()->where(['state_user_id' => $user['id']])->first();
@ -348,7 +358,7 @@ class AppRequestsController extends AppController
'state' => 'success', 'state' => 'success',
'transactions' => $transactions, 'transactions' => $transactions,
'transactionExecutingCount' => $session->read('Transactions.executing'), 'transactionExecutingCount' => $session->read('Transactions.executing'),
'count' => count($transactions), 'count' => $stateUserTransactions_total->count(),
'gdtSum' => $gdtSum, 'gdtSum' => $gdtSum,
'timeUsed' => microtime(true) - $startTime 'timeUsed' => microtime(true) - $startTime
]; ];

View File

@ -4,9 +4,9 @@ namespace App\Controller;
use App\Controller\AppController; use App\Controller\AppController;
use Cake\ORM\TableRegistry; use Cake\ORM\TableRegistry;
use Cake\Routing\Router;
use Cake\Http\Client; use Cake\Http\Client;
use Cake\Core\Configure; use Cake\Core\Configure;
use Cake\Mailer\Email;
use Model\Transactions\TransactionTransfer; use Model\Transactions\TransactionTransfer;
use Model\Transactions\Transaction; use Model\Transactions\Transaction;
@ -333,32 +333,71 @@ class JsonRequestHandlerController extends AppController {
return $this->returnJson(['state' => 'success']); return $this->returnJson(['state' => 'success']);
} }
private function sendEMailTransactionFailed($transaction, $reason_type)
{
$disable_email = Configure::read('disableEmail', false);
if($disable_email) {
return;
}
$transaction_body = $transaction->getTransactionBody();
$transaction_type_name = $transaction_body->getTransactionTypeName();
$senderUser = null;
if($transaction_type_name === 'transfer') {
$senderUser = $transaction_body->getSpecificTransaction()->getSenderUser();
} else if($transaction_type_name === 'creation') {
$senderUser = $transaction->getFirstSigningUser();
}
// send notification email
$noReplyEmail = Configure::read('noReplyEmail');
if($senderUser) {
try {
$email = new Email();
$emailViewBuilder = $email->viewBuilder();
$emailViewBuilder->setTemplate('notificationTransactionFailed')
->setVars(['user' => $senderUser, 'transaction' => $transaction, 'reason' => $reason_type]);
$receiverNames = $senderUser->getNames();
if($receiverNames == '' || $senderUser->email == '') {
$this->addError('TransactionCreation::sendNotificationEmail', 'to email is empty for user: ' . $senderUser->id);
return false;
}
$email->setFrom([$noReplyEmail => 'Gradido (nicht antworten)'])
->setTo([$senderUser->email => $senderUser->getNames()])
->setSubject(__('Gradido Transaktion fehlgeschlagen!'))
->send();
} catch(Exception $e) {
$this->addAdminError('JsonRequestController', 'sendEMailTransactionFailed', [$e->getMessage(), $reason_type], $senderUser->id);
}
}
}
private function putTransaction($transactionBase64) { private function putTransaction($transactionBase64) {
$transaction = new Transaction($transactionBase64); $transaction = new Transaction($transactionBase64);
//echo "after new transaction<br>"; //echo "after new transaction<br>";
if($transaction->hasErrors()) { if($transaction->hasErrors()) {
$this->sendEMailTransactionFailed($transaction, 'parse');
return $this->returnJson(['state' => 'error', 'msg' => 'error parsing transaction', 'details' => $transaction->getErrors()]); return $this->returnJson(['state' => 'error', 'msg' => 'error parsing transaction', 'details' => $transaction->getErrors()]);
} }
//echo "after check on errors<br>"; //echo "after check on errors<br>";
if(!$transaction->validate()) { if(!$transaction->validate()) {
//$transaction_details
$this->sendEMailTransactionFailed($transaction, 'validate');
return $this->returnJsonSaveError($transaction, ['state' => 'error', 'msg' => 'error validate transaction', 'details' => $transaction->getErrors()]); return $this->returnJsonSaveError($transaction, ['state' => 'error', 'msg' => 'error validate transaction', 'details' => $transaction->getErrors()]);
} }
//echo "after validate <br>"; //echo "after validate <br>";
if ($transaction->save()) { if ($transaction->save()) {
// success // success
return $this->returnJson(['state' => 'success']); return $this->returnJson(['state' => 'success']);
} else { } else {
$this->sendEMailTransactionFailed($transaction, 'save');
return $this->returnJsonSaveError($transaction, [ return $this->returnJsonSaveError($transaction, [
'state' => 'error', 'state' => 'error',
'msg' => 'error saving transaction in db', 'msg' => 'error saving transaction in db',
'details' => json_encode($transaction->getErrors()) 'details' => json_encode($transaction->getErrors())
]); ]);
} }
return $this->returnJson(['state' => 'success']);
} }
private function moveTransaction($pubkeys, $memo, $session_id) { private function moveTransaction($pubkeys, $memo, $session_id) {

View File

@ -98,6 +98,11 @@ class Transaction extends TransactionBase {
return $sigPairs[0]->getPubKey(); return $sigPairs[0]->getPubKey();
} }
public function getFirstSigningUser()
{
return $this->getStateUserFromPublickey($this->getFirstPublic());
}
public function getId() { public function getId() {
return $this->mProtoTransaction->getId(); return $this->mProtoTransaction->getId();
} }

View File

@ -61,6 +61,16 @@ class TransactionBase {
return NULL; return NULL;
} }
protected function getStateUserFromPublickey($publicKey) {
$stateUsersTable = self::getTable('state_users');
$stateUser = $stateUsersTable->find('all')->where(['public_key' => $publicKey])->first();
if($stateUser) {
return $stateUser;
}
return NULL;
}
protected function updateStateBalance($stateUserId, $addAmountCent, $recordDate) { protected function updateStateBalance($stateUserId, $addAmountCent, $recordDate) {
$stateBalancesTable = self::getTable('stateBalances'); $stateBalancesTable = self::getTable('stateBalances');

View File

@ -72,7 +72,12 @@ class TransactionCreation extends TransactionBase {
return $this->protoTransactionCreation->getReceiver()->getPubkey(); return $this->protoTransactionCreation->getReceiver()->getPubkey();
} }
public function getReceiverUser() {
return $this->getStateUserFromPublickey($this->getReceiverPublic());
}
public function getTargetDate() {
return new FrozenDate($this->protoTransactionCreation->getTargetDate()->getSeconds());
}
public function validate($sigPairs) { public function validate($sigPairs) {
// check if receiver public is not in signature list // check if receiver public is not in signature list

View File

@ -186,11 +186,9 @@ class TransactionTransfer extends TransactionBase {
$local_transfer = $this->protoTransactionTransfer->getLocal(); $local_transfer = $this->protoTransactionTransfer->getLocal();
$sender = $local_transfer->getSender(); $sender = $local_transfer->getSender();
$senderAmount = $sender->getAmount(); $senderAmount = $sender->getAmount();
$senderUserId = $this->getStateUserId($sender->getPubkey()); $senderUser = $this->getStateUserFromPublickey($sender->getPubkey());
$receiverUserId = $this->getStateUserId($local_transfer->getReceiver()); $receiverUser = $this->getStateUserFromPublickey($local_transfer->getReceiver());
$receiverUser = $this->getStateUser($receiverUserId);
$senderUser = $this->getStateUser($senderUserId);
$serverAdminEmail = Configure::read('ServerAdminEmail'); $serverAdminEmail = Configure::read('ServerAdminEmail');
try { try {
@ -218,6 +216,25 @@ class TransactionTransfer extends TransactionBase {
return true; return true;
} }
public function getSenderUser()
{
$local_transfer = $this->protoTransactionTransfer->getLocal();
return $this->getStateUserFromPublickey($local_transfer->getSender()->getPubkey());
}
public function getReceiverUser()
{
$local_transfer = $this->protoTransactionTransfer->getLocal();
return $this->getStateUserFromPublickey($local_transfer->getReceiver());
}
public function getAmount()
{
$local_transfer = $this->protoTransactionTransfer->getLocal();
$sender = $local_transfer->getSender();
return $sender->getAmount();
}
static public function fromEntity($transactionTransferEntity) static public function fromEntity($transactionTransferEntity)
{ {
$protoTransfer = new \Proto\Gradido\GradidoTransfer(); $protoTransfer = new \Proto\Gradido\GradidoTransfer();

View File

@ -0,0 +1,50 @@
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
$this->assign('title', __('Gradido Transaktion fehlgeschlagen'));
$transaction_body = $transaction->getTransactionBody();
$specific_transaction = $transaction_body->getSpecificTransaction();
$transaction_type_name = $transaction_body->getTransactionTypeName();
?><?= __('Hallo') ?> <?= $user->first_name ?> <?= $user->last_name ?>,
<?= __('Deine letzte Transaktion ist leider fehlgeschlagen.') ?>
<?php if($reason != 'parse') :
if($transaction_type_name === 'creation') : ?><?= __('Du wolltest {0} für {1} schöpfen.',
$this->element('printGradido', ['number' => $specific_transaction->getAmount(), 'raw' => true]),
$specific_transaction->getReceiverUser()->getEmailWithName()) ?>
<?= __('Das Zieldatum war: ') . $specific_transaction->getTargetDate()->format('d.m.Y') ?>
<?php elseif($transaction_type_name === 'transfer'): ?>
<?= __('Du wolltest {0} an {1} senden.',
$this->element('printGradido', ['number' => $specific_transaction->getAmount(), 'raw' => true]),
$specific_transaction->getReceiverUser()->getEmailWithName()) ?>
<?php endif; endif; ?>
<?= __('Das ist schief gelaufen: ') ?>
<?php switch($reason) {
case 'save': echo __('Fehler beim speichern in der Datenbank. Bitte versuche es später erneut'); break;
case 'parse': echo __('Fehler beim parsen der Transaktion. Bitte versuche es später erneut'); break;
case 'validate':
$errors = $transaction->getErrors();
foreach($errors as $error) {
//echo "\t".json_encode($error);
echo "\n\t".$error[array_keys($error)[0]]."\n";
}
}?>
<?= __('Bitte antworte nicht auf diese E-Mail!'); ?>
<?= __('Mit freundlichen Grüßen'); ?>
Gradido Community Server