mirror of
https://github.com/IT4Change/gradido.git
synced 2025-12-13 07:45:54 +00:00
Adding Notification Emails and make larger textbox for creation transactions
This commit is contained in:
parent
b4e7ad02aa
commit
2862d7824d
@ -6,6 +6,7 @@ use App\Controller\AppController;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Routing\Router;
|
||||
|
||||
|
||||
use Model\Transactions\Transaction;
|
||||
/*!
|
||||
* @author: Dario Rekowski#
|
||||
@ -63,6 +64,8 @@ class JsonRequestHandlerController extends AppController {
|
||||
}
|
||||
|
||||
if ($transaction->save()) {
|
||||
|
||||
|
||||
// success
|
||||
return $this->returnJson(['state' => 'success']);
|
||||
} else {
|
||||
|
||||
@ -15,7 +15,7 @@ class CreationForm extends Form
|
||||
//->addField('receiver_pubkey_hex', ['type' => 'string'])
|
||||
->addField('receiver', ['type' => 'select'])
|
||||
->addField('amount', ['type' => 'decimal', 'precision' => 2])
|
||||
->addField('memo', ['type' =>'string', 'default' => '']);
|
||||
->addField('memo', ['type' =>'text', 'default' => '', 'rows' => 5, 'maxlength' => 150]);
|
||||
}
|
||||
|
||||
function validationDefault(Validator $validator)
|
||||
|
||||
@ -43,4 +43,12 @@ class StateUser extends Entity
|
||||
'transaction_creations' => true,
|
||||
'transaction_send_coins' => true
|
||||
];
|
||||
|
||||
public function getEmailWithName() {
|
||||
return $this->first_name . ' ' . $this->last_name . ' <' . $this->email . '>';
|
||||
}
|
||||
|
||||
public function getNames() {
|
||||
return $this->first_name . ' ' . $this->last_name;
|
||||
}
|
||||
}
|
||||
|
||||
@ -151,9 +151,10 @@ class Transaction extends TransactionBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$connection->commit();
|
||||
|
||||
$this->mTransactionBody->getSpecificTransaction()->sendNotificationEmail($this->mTransactionBody->getMemo());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ use Cake\ORM\TableRegistry;
|
||||
|
||||
class TransactionBase {
|
||||
private $errors = [];
|
||||
static $stateUsersTable = null;
|
||||
|
||||
public function getErrors() {
|
||||
return $this->errors;
|
||||
@ -23,8 +24,18 @@ class TransactionBase {
|
||||
return count($this->errors) > 0;
|
||||
}
|
||||
|
||||
public static function getStateUsersTable()
|
||||
{
|
||||
if(!self::$stateUsersTable) {
|
||||
self::$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
|
||||
}
|
||||
return self::$stateUsersTable;
|
||||
}
|
||||
|
||||
|
||||
protected function getStateUserId($publicKey) {
|
||||
$stateUsersTable = TableRegistry::getTableLocator()->get('state_users');
|
||||
|
||||
$stateUsersTable = self::getStateUsersTable();
|
||||
$stateUser = $stateUsersTable->find('all')->select(['id'])->where(['public_key' => $publicKey])->first();
|
||||
if($stateUser) {
|
||||
return $stateUser->id;
|
||||
@ -41,6 +52,17 @@ class TransactionBase {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
protected function getStateUser($id) {
|
||||
$stateUsersTable = self::getStateUsersTable();
|
||||
$stateUser = $stateUsersTable->get($id);
|
||||
if($stateUser) {
|
||||
return $stateUser;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
protected function updateStateBalance($stateUserId, $addAmountCent) {
|
||||
$finalBalance = 0;
|
||||
$stateBalancesTable = TableRegistry::getTableLocator()->get('stateBalances');
|
||||
|
||||
@ -90,10 +90,15 @@ class TransactionBody extends TransactionBase {
|
||||
$previousTxHash = null;
|
||||
if($this->mTransactionID > 1) {
|
||||
try {
|
||||
$previousTransaction = $transactionsTable->get($this->mTransactionID - 1, [
|
||||
$previousTransaction = $transactionsTable
|
||||
->find('all', ['contain' => false])
|
||||
->select(['tx_hash'])
|
||||
->where(['id' => $this->mTransactionID - 1])
|
||||
->first();
|
||||
/*$previousTransaction = $transactionsTable->get($this->mTransactionID - 1, [
|
||||
'contain' => false,
|
||||
'fields' => ['tx_hash']
|
||||
]);
|
||||
]);*/
|
||||
} catch(Cake\Datasource\Exception\RecordNotFoundException $ex) {
|
||||
$this->addError('TransactionBody::save', 'previous transaction (with id ' . ($this->mTransactionID-1) . ' not found');
|
||||
return false;
|
||||
@ -105,7 +110,17 @@ class TransactionBody extends TransactionBase {
|
||||
}
|
||||
$previousTxHash = $previousTransaction->tx_hash;
|
||||
}
|
||||
$transactionEntity->received = $transactionsTable->get($transactionEntity->id, ['contain' => false, 'fields' => ['received']])->received;
|
||||
try {
|
||||
//$transactionEntity->received = $transactionsTable->get($transactionEntity->id, ['contain' => false, 'fields' => ['received']])->received;
|
||||
$transactionEntity->received = $transactionsTable
|
||||
->find('all', ['contain' => false])
|
||||
->where(['id' => $transactionEntity->id])
|
||||
->select(['received'])->first()->received;
|
||||
} catch(Cake\Datasource\Exception\RecordNotFoundException $ex) {
|
||||
$this->addError('TransactionBody::save', 'current transaction (with id ' . ($transactionEntity->id) . ' not found');
|
||||
$this->addError('exception: ', $ex->getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
// calculate tx hash
|
||||
// previous tx hash + id + received + sigMap as string
|
||||
|
||||
@ -5,6 +5,8 @@ namespace Model\Transactions;
|
||||
//use App\Model\Transactions\TransactionBase;
|
||||
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Mailer\Email;
|
||||
|
||||
class TransactionCreation extends TransactionBase {
|
||||
|
||||
@ -135,12 +137,12 @@ class TransactionCreation extends TransactionBase {
|
||||
|
||||
// state user id
|
||||
//$state_user_id = $this->getStateUserId($firstPublic);
|
||||
$receiverUser = $this->getStateUserId($this->getReceiverPublic());
|
||||
if(!$receiverUser) {
|
||||
$receiverUserId = $this->getStateUserId($this->getReceiverPublic());
|
||||
if(!$receiverUserId) {
|
||||
$this->addError('TransactionCreation::save', 'couldn\'t get state user id');
|
||||
return false;
|
||||
}
|
||||
$transactionCreationEntity->state_user_id = $receiverUser;
|
||||
$transactionCreationEntity->state_user_id = $receiverUserId;
|
||||
$transactionCreationEntity->amount = $this->getAmount();
|
||||
$transactionCreationEntity->ident_hash = $this->getIdentHash();
|
||||
|
||||
@ -150,10 +152,34 @@ class TransactionCreation extends TransactionBase {
|
||||
}
|
||||
|
||||
// update state balance
|
||||
if(false === $this->updateStateBalance($receiverUser, $this->getAmount())) {
|
||||
if(false === $this->updateStateBalance($receiverUserId, $this->getAmount())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sendNotificationEmail($memo)
|
||||
{
|
||||
// send notification email
|
||||
$receiverUserId = $this->getStateUserId($this->getReceiverPublic());
|
||||
$receiverUser = $this->getStateUser($receiverUserId);
|
||||
$noReplyEmail = Configure::read('noReplyEmail');
|
||||
|
||||
try {
|
||||
$email = new Email();
|
||||
$emailViewBuilder = $email->viewBuilder();
|
||||
$emailViewBuilder->setTemplate('notificationCreation')
|
||||
->setVars(['user' => $receiverUser, 'gdd_cent' => $this->getAmount(), 'memo' => $memo]);
|
||||
$email->setFrom([$noReplyEmail => 'Nicht antworten'])
|
||||
->setTo([$receiverUser->email => $receiverUser->getNames()])
|
||||
->setSubject(__('Gradido Schöpfung erhalten'))
|
||||
->send();
|
||||
} catch(Exception $e) {
|
||||
$this->addError('TransactionCreation::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -4,6 +4,8 @@ namespace Model\Transactions;
|
||||
|
||||
//use App\Model\Transactions\TransactionBase;
|
||||
use Cake\ORM\TableRegistry;
|
||||
use Cake\Core\Configure;
|
||||
use Cake\Mailer\Email;
|
||||
|
||||
class TransactionTransfer extends TransactionBase {
|
||||
private $protoTransactionTransfer;
|
||||
@ -167,7 +169,7 @@ class TransactionTransfer extends TransactionBase {
|
||||
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
|
||||
|
||||
if(count($this->protoTransactionTransfer->getReceiverAmounts()) !== 1) {
|
||||
$this->addError($functionName, 'not more tahn one receiver currently supported');
|
||||
$this->addError($functionName, 'not more than one receiver currently supported');
|
||||
return false;
|
||||
}
|
||||
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
|
||||
@ -201,11 +203,48 @@ class TransactionTransfer extends TransactionBase {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//$this->addError('TransactionTransfer::save', 'not implemented yet');
|
||||
//return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function sendNotificationEmail($memo)
|
||||
{
|
||||
// send notification email
|
||||
|
||||
$senderAmount = $this->protoTransactionTransfer->getSenderAmounts()[0];
|
||||
$receiverAmount = $this->protoTransactionTransfer->getReceiverAmounts()[0];
|
||||
$senderUserId = $this->getStateUserId($senderAmount->getEd25519SenderPubkey());
|
||||
$receiverUserId = $this->getStateUserId($receiverAmount->getEd25519ReceiverPubkey());
|
||||
|
||||
$receiverUser = $this->getStateUser($receiverUserId);
|
||||
$senderUser = $this->getStateUser($senderUserId);
|
||||
$serverAdminEmail = Configure::read('ServerAdminEmail');
|
||||
|
||||
try {
|
||||
$email = new Email();
|
||||
$emailViewBuilder = $email->viewBuilder();
|
||||
$emailViewBuilder->setTemplate('notificationTransfer')
|
||||
->setVars(['receiverUser' => $receiverUser,
|
||||
'senderUser' => $senderUser,
|
||||
'gdd_cent' => $receiverAmount->getAmount(),
|
||||
'memo' => $memo]);
|
||||
|
||||
$email->setFrom([$serverAdminEmail => $senderUser->getNames() . ' via Gradido Community'])
|
||||
->setTo([$receiverUser->email => $receiverUser->getNames()])
|
||||
->setReplyTo($senderUser->email)
|
||||
->setSubject(__('Gradidos erhalten'))
|
||||
->send();
|
||||
} catch(Exception $e) {
|
||||
$this->addError('TransactionTransfer::sendNotificationEmail', 'error sending notification email: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static public function fromEntity($transactionTransferEntity)
|
||||
{
|
||||
$protoTransfer = new \Model\Messages\Gradido\Transfer();
|
||||
|
||||
@ -15,7 +15,10 @@ if($number < 0) {
|
||||
$class = 'grd-negative-currency';
|
||||
}
|
||||
|
||||
?>
|
||||
?><?php if(isset($raw) && true == $raw): ?>
|
||||
<?= $this->Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' GDD';?>
|
||||
<?php else : ?>
|
||||
<span class="<?php echo $class;?>">
|
||||
<?= $this->Number->format(intval($number) / 10000.0, ['precision' => 2]) . ' GDD';?>
|
||||
</span>
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
@ -24,7 +24,7 @@ $this->assign('title', __('Fehlermeldungen'));
|
||||
$type = $transactionTypes[$error->transaction_type_id-1];
|
||||
$errorMessage = "";
|
||||
$errorArray = json_decode($error->message_json, true);
|
||||
if(isset($errorArray['details'])) {
|
||||
if(isset($errorArray['details']) && is_array($errorArray['details'])) {
|
||||
|
||||
foreach($errorArray['details'][0] as $function => $errorString) {
|
||||
$errorMessage = '<b>' . $function . '</b><br> ' . $errorString;
|
||||
|
||||
@ -1,174 +0,0 @@
|
||||
<?php
|
||||
namespace App\Test\TestCase\Controller;
|
||||
|
||||
use App\Controller\JsonRequestHandlerController;
|
||||
use Cake\TestSuite\IntegrationTestTrait;
|
||||
use Cake\TestSuite\TestCase;
|
||||
|
||||
/**
|
||||
* App\Controller\TransactionJsonRequestHandlerController Test Case
|
||||
*
|
||||
* @uses \App\Controller\TransactionJsonRequestHandlerController
|
||||
*/
|
||||
class TransactionJsonRequestHandlerControllerTest extends TestCase
|
||||
{
|
||||
use IntegrationTestTrait;
|
||||
|
||||
/**
|
||||
* Fixtures
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $fixtures = [
|
||||
'app.TransactionCreations',
|
||||
'app.Transactions',
|
||||
'app.StateUsers',
|
||||
'app.StateErrors',
|
||||
'app.TransactionSignatures',
|
||||
'app.TransactionSendCoins',
|
||||
'app.StateBalances',
|
||||
'app.TransactionTypes'
|
||||
];
|
||||
|
||||
public $transactions = [
|
||||
'validCreation' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQJ8wF12eZo3hcMAlAKKJ9WLT-zuSkNmGh7D98UEqH4KoIysnCkXqEya9EBZl9o11_nJ8xmm_nOevuVjR-GfLMQ8qSQoOSGFsbG8gV2VsdCAxMjMSBgiZm4ruBUovCicKIJSuE1uTzZ8zdStOVcQZA6P6oTp1u5C_1BHqHUoaXnEfEKDakwEQtYntlgo',
|
||||
'validCreation900' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQNVZ8Ae3Zbg3G0wZ840fzKan6N4KtTcSe0KYi17kQwFmsl18oFxXv8_s6j1xXFrIKjy1_1Olq0a7xYLErDMkjwYqORIGCNb5iu4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgNHKCBC1ie2WCg',
|
||||
'validCreation1200' => 'GmYKZAogYbkjwhjLY6ZKjGLzhgEhKDuVd_N00KMVkLoCzcKRKZkSQEEey5QMAdldoOTP_jTETHgOQriGsixEY0cziQeRfT_J5YtbI_A6AizEYD-JcxmRmXzv1xjjTgsV39Y32ta2CQkqORIGCIeGi-4FSi8KJwoglK4TW5PNnzN1K05VxBkDo_qhOnW7kL_UEeodShpecR8QgOy4CxC1ie2WCg',
|
||||
'notBase64' => 'CgpIYWxsbyBXZW-0EgYIyfSG7gV_LwonCiCboKikqwjZfes9xuqgthFH3',
|
||||
'validTransfer' => 'GmYKZAoggZC9pYXuXx2fv30G6B5p7BjhM3YQTP9Ut0V-t9PvcQ0SQDddHyKzAX3LBV0PuDiPc6lxkUipss5tyuLRpMtFJQnT30tsbYIkA1FXimjMKOoiuLswf4OLLV3bAIYehW-b9AgqYQoFSGFsbG8SBgiJlaPvBUJQCiYKIIGQvaWF7l8dn799BugeaewY4TN2EEz_VLdFfrfT73ENEICfSRImCiDtdleSLxhUgEbMW9DpqIwsykFj3-z_enKEOuGnXrmW8xCAn0k',
|
||||
'errornusTransfer' => 'ClxGcm9oZXMgTmV1ZXMgSmFociB1bmQgREFOS0UsIGRhc3MgZHUgZGljaCBzbyBlaW5zZXR6dCBmw7xyIEdyYWRpZG8hIEhlcnpsaWNoZSBHcsO8w59lIFRlcmVzYRIGCPjjgvEFQlAKJgogUQwFYeVlGlfWDrkXNN7rHwejoCDJKt+YkYJfbJVyj3EQwIQ9EiYKIPXIRnUhVJ/zCs5+y/VaTBjTIoYizJNwS+JC//xsbQrHEMCEPQ=='
|
||||
];
|
||||
|
||||
/*public function setUp() {
|
||||
parent::setUp();
|
||||
}
|
||||
*/
|
||||
public function testWrongMethod()
|
||||
{
|
||||
$this->configRequest([
|
||||
'headers' => ['Accept' => 'application/json']
|
||||
]);
|
||||
$this->get('/TransactionJsonRequestHandler');
|
||||
$this->assertResponseOk();
|
||||
|
||||
$expected = json_encode(['state' => 'error', 'msg' => 'no post']);
|
||||
$this->assertEquals($expected, (string)$this->_response->getBody());
|
||||
}
|
||||
|
||||
public function testInvalidJson()
|
||||
{
|
||||
$this->configRequest([
|
||||
'headers' => ['Accept' => 'application/json']
|
||||
]);
|
||||
$this->post('/TransactionJsonRequestHandler', '{This isn\'t valid json}');
|
||||
$this->assertResponseOk();
|
||||
|
||||
$expected = json_encode(['state' => 'error', 'msg' => 'parameter error']);
|
||||
$this->assertEquals($expected, (string)$this->_response->getBody());
|
||||
}
|
||||
|
||||
public function testNotSetTransaction()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction'],
|
||||
['state' => 'error', 'msg' => 'parameter error']
|
||||
);
|
||||
}
|
||||
public function testNotSetMethod()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['transaction' => $this->transactions['validCreation']],
|
||||
['state' => 'error', 'msg' => 'parameter error']
|
||||
);
|
||||
}
|
||||
|
||||
public function testUnknownMethod()
|
||||
{
|
||||
//$this->post('/TransactionJsonRequestHandler', ['method' => 'putTransaction', 'transaction' => 'CgpIYWxsbyBXZWx0EgYIyfSG7gVKLwonCiCboKikqwjZfes9xuqgthFH3/cHHaWchkUhWiGhQjB23xCg2pMBELWJ7ZYK']);
|
||||
$this->postAndParse(
|
||||
['method' => 'foobar', 'transaction' => $this->transactions['validCreation']],
|
||||
['state' => 'error', 'msg' => 'unknown method', 'details' => 'foobar']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function testInvalidEncodedTransaction() {
|
||||
//"msg":"error parsing transaction","details":[{"Transaction":"base64 decode error"}]
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => $this->transactions['notBase64']],
|
||||
['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [
|
||||
['Transaction' => 'invalid base64 string']
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
public function testInvalidTransaction() {
|
||||
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => base64_encode('Hallo Miau Welt')],
|
||||
['state' => 'error', 'msg' => 'error parsing transaction', 'details' => [
|
||||
['Transaction' => 'Error occurred during parsing: Unexpected wire type.']
|
||||
]]
|
||||
);
|
||||
}
|
||||
|
||||
public function testToLargeCreationSum()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation900']],
|
||||
'{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}'
|
||||
);
|
||||
}
|
||||
|
||||
public function testToLargeCreation()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation1200']],
|
||||
'{"state":"error","msg":"error validate transaction","details":[{"TransactionCreation::validate":"Creation more than 1000 gr per Month not allowed"}]}'
|
||||
);
|
||||
}
|
||||
|
||||
public function testValidTransfer()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => $this->transactions['validTransfer']],
|
||||
['state' => 'success']
|
||||
);
|
||||
}
|
||||
|
||||
/*public function testMissingPreviousTransaction()
|
||||
{
|
||||
|
||||
}*/
|
||||
|
||||
public function testValidTransaction()
|
||||
{
|
||||
$this->postAndParse(
|
||||
['method' => 'putTransaction', 'transaction' => $this->transactions['validCreation']],
|
||||
['state' => 'success']
|
||||
);
|
||||
}
|
||||
|
||||
private function postAndParse($params, $expected)
|
||||
{
|
||||
|
||||
$this->configRequest([
|
||||
'headers' => ['Accept' => 'application/json']
|
||||
]);
|
||||
|
||||
$this->disableErrorHandlerMiddleware();
|
||||
$this->post('/TransactionJsonRequestHandler', json_encode($params));
|
||||
|
||||
// Check that the response was a 200
|
||||
$this->assertResponseOk();
|
||||
|
||||
$responseBodyString = (string)$this->_response->getBody();
|
||||
$json = json_decode($responseBodyString);
|
||||
$this->assertNotFalse($json);
|
||||
|
||||
if(is_array($expected)) {
|
||||
$expected = json_encode($expected);
|
||||
}
|
||||
$this->assertEquals($expected, $responseBodyString);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user