tested and fixed bugs, update api docu

This commit is contained in:
Dario Rekowski on RockPI 2021-05-10 17:59:34 +00:00
parent 394bfb71ef
commit be26bf2758
12 changed files with 165 additions and 78 deletions

View File

@ -1,6 +1,6 @@
CREATE TABLE `transaction_types` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(45) COLLATE utf8mb4_unicode_ci NOT NULL,
`name` varchar(90) COLLATE utf8mb4_unicode_ci NOT NULL,
`text` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

View File

@ -166,7 +166,7 @@ class AppController extends Controller
}
$php_data_version = 2;
if($current_db_version < $php_data_version) {
$this->redirect(['controller' => 'Migrations', 'action' => 'migrate', $html, $current_db_version]);
$this->redirect(['controller' => 'Migrations', 'action' => 'migrate', 'html' => $html, 'db_version' => $current_db_version]);
}
}

View File

@ -13,6 +13,12 @@ use Cake\ORM\TableRegistry;
*/
class MigrationsController extends AppController
{
public function initialize()
{
parent::initialize();
$this->Auth->allow('migrate');
}
/**
* Index method
*
@ -36,8 +42,12 @@ class MigrationsController extends AppController
return ['success' => true];
}
public function migrate($html, $current_db_version)
public function migrate()
{
$html = $this->request->getQuery('html');
$current_db_version = $this->request->getQuery('db_version');
$startTime = microtime(true);
$stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions');
$transactionsTable = TableRegistry::getTableLocator()->get('Transactions');
@ -52,10 +62,10 @@ class MigrationsController extends AppController
if($current_db_version == 1) {
$stateUserTransactionsTable->truncate();
$commands = [
[$transactionsTable, 'fillStateUserTransactions'],
[$stateBalancesTable, 'updateAllBalances'],
[$blockchainTypesTable, 'fillWithDefault'],
[$transactionTypesTable, 'fillWithDefault']
[$transactionTypesTable, 'fillWithDefault'],
[$transactionsTable, 'fillStateUserTransactions'],
[$stateBalancesTable, 'updateAllBalances']
];
$new_db_version = 2;
}

View File

@ -44,9 +44,7 @@ class StateBalance extends Entity
} else if(method_exists($dateOrTime, 'i18nFormat')) {
return $dateOrTime->i18nFormat(Time::UNIX_TIMESTAMP_FORMAT);
} else {
var_dump($dateOrTime);
debug_print_backtrace(0, 6);
die("date or time unexpected object");
return 0;
}
}
@ -59,8 +57,12 @@ class StateBalance extends Entity
// SELECT TIMESTAMPDIFF(SECOND, modified, CURDATE()) AS age_in_seconds from state_balances
// decay_for_duration = decay_factor^seconds
// decay = gradido_cent * decay_for_duration
$decay_duration = intval(Time::now()->getTimestamp() - $this->convertToTimestamp($this->record_date));
$startDate = $this->convertToTimestamp($this->record_date);
if($startDate == 0) {
return $this->amount;
}
$decay_duration = intval(Time::now()->getTimestamp() - $startDate);
if($decay_duration === 0) {
return $this->amount;
}

View File

@ -1,5 +1,7 @@
<?php
namespace App\Model\Table;
use Cake\ORM\Table;
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
@ -15,9 +17,24 @@ class AppTable extends Table
public function truncate()
{
$truncateCommands = $this->schema()->truncateSql($this->connection());
$truncateCommands = $this->getSchema()->truncateSql($this->getConnection());
foreach ($truncateCommands as $truncateCommand) {
$this->connection()->query($truncateCommand);
$this->getConnection()->query($truncateCommand);
}
$this->getConnection()->query('ALTER TABLE ' . $this->getSchema()->name() . ' AUTO_INCREMENT=1');
}
public function saveManyWithErrors($entities)
{
$save_results = $this->saveMany($entities);
// save all at once failed, no try one by one to get error message
if($save_results === false) {
foreach($entities as $entity) {
if(!$this->save($entity)) {
return ['success' => false, 'errors' => $entity->getErrors()];
}
}
} else {
return ['success' => true];
}
}
}

View File

@ -84,18 +84,11 @@ class BlockchainTypesTable extends AppTable
];
$entities = $this->newEntities($entry_contents);
$this->truncate();
$save_results = $this->saveMany($entities);
$errors = [];
foreach($save_results as $i => $result)
{
if(!$result) {
$errors[] = $entities[$i]->getErrors();
}
$save_results = $this->saveManyWithErrors($entities);
if(!$save_results['success']) {
$save_results['msg'] = 'error by saving default transaction types';
}
if(count($errors) > 0) {
return ['success' => false, 'msg' => 'error by saving blockchain types', 'errors' => $errors];
}
return ['success' => true];
return $save_results;
}
}

View File

@ -91,25 +91,38 @@ class StateBalancesTable extends Table
return $rules;
}
public static function calculateDecay($startBalance, FrozenTime $startDate, FrozenTime $endDate)
public function calculateDecay($startBalance, FrozenTime $startDate, FrozenTime $endDate, $withInterval = false)
{
$decayStartDate = self::getDecayStartDateCached();
// if no start decay block exist, we just return input
// if start date for decay is after enddate, we also just return input
if($decayStartDate === null || $decayStartDate >= $endDate) {
return $startBalance;
if($withInterval) {
return ['balance' => $startBalance, 'interval' => new \DateInterval('PT0S')];
} else {
return $startBalance;
}
}
$state_balance = $this->newEntity();
$state_balance->amount = $startBalance;
$interval = null;
// if decay start date is before start date we calculate decay for full duration
if($decayStartDate < $startDate) {
$state_balance->record_date = $startDate;
$interval = $endDate->diff($startDate);
}
// if decay start in between start date and end date we caculcate decay from decay start time to end date
else {
$state_balance->record_date = $decayStartDate;
$interval = $endDate->diff($decayStartDate);
}
return $state_balance->partDecay($endDate);
$decay = $state_balance->partDecay($endDate);
if($withInterval) {
return ['balance' => $decay, 'interval' => $interval];
} else {
return $decay;
}
}

View File

@ -55,7 +55,7 @@ class TransactionTypesTable extends AppTable
$validator
->scalar('name')
->maxLength('name', 24)
->maxLength('name', 45)
->requirePresence('name', 'create')
->notEmptyString('name');
@ -111,17 +111,10 @@ class TransactionTypesTable extends AppTable
];
$entities = $this->newEntities($entry_contents);
$this->truncate();
$save_results = $this->saveMany($entities);
$errors = [];
foreach($save_results as $i => $result)
{
if(!$result) {
$errors[] = $entities[$i]->getErrors();
}
$save_results = $this->saveManyWithErrors($entities);
if(!$save_results['success']) {
$save_results['msg'] = 'error by saving default transaction types';
}
if(count($errors) > 0) {
return ['success' => false, 'msg' => 'error by saving transaction types', 'errors' => $errors];
}
return ['success' => true];
return $save_results;
}
}

View File

@ -1,12 +1,12 @@
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\ORM\TableRegistry;
use Cake\I18n\Number;
use Cake\I18n\FrozenTime;
/**
* Transactions Model
*
@ -172,24 +172,25 @@ class TransactionsTable extends Table
//var_dump($su_transaction);
//die("step");
// add decay transactions
if($i > 0 && $decay == true)
{
$prev = null;
if($i > 0 ) {
$prev = $stateUserTransactions[$i-1];
}
if($prev && $decay == true)
{
if($prev->balance > 0) {
// var_dump($stateUserTransactions);
$current = $su_transaction;
//echo "decay between " . $prev->transaction_id . " and " . $current->transaction_id . "<br>";
$interval = $current->balance_date->diff($prev->balance_date);
$state_balance->amount = $prev->balance;
$state_balance->record_date = $prev->balance_date;
$diff_amount = $state_balance->partDecay($current->balance_date);
$calculated_decay = $stateBalancesTable->calculateDecay($prev->balance, $prev->balance_date, $current->balance_date, true);
//echo $interval->format('%R%a days');
//echo "prev balance: " . $prev->balance . ", diff_amount: $diff_amount, summe: " . (-intval($prev->balance - $diff_amount)) . "<br>";
$final_transactions[] = [
'type' => 'decay',
'balance' => floatval(intval($prev->balance - $diff_amount)),
'decay_duration' => $interval->format('%a days, %H hours, %I minutes, %S seconds'),
'balance' => floatval($prev->balance - $calculated_decay['balance']),
'decay_duration' => $calculated_decay['interval']->format('%a days, %H hours, %I minutes, %S seconds'),
'memo' => ''
];
}
@ -207,13 +208,16 @@ class TransactionsTable extends Table
echo "<br>";*/
if($su_transaction->transaction_type_id == 1) { // creation
$creation = $transaction->transaction_creation;
$balance = $stateBalancesTable->calculateDecay($creation->amount, $creation->target_date, $transaction->received);
$final_transactions[] = [
'name' => 'Gradido Akademie',
'type' => 'creation',
'transaction_id' => $transaction->id,
'date' => $transaction->received,// $creation->target_date,
'target_date' => $creation->target_date,
'balance' => $creation->amount,
'creation_amount' => $creation->amount,
'balance' => $balance,
'memo' => $transaction->memo
];
} else if($su_transaction->transaction_type_id == 2) { // transfer or send coins
@ -253,12 +257,18 @@ class TransactionsTable extends Table
}
if($i == $stateUserTransactionsCount-1 && $decay == true) {
$state_balance->amount = $su_transaction->balance;
$state_balance->record_date = $su_transaction->balance_date;
$calculated_decay = $stateBalancesTable->calculateDecay(
$su_transaction->balance,
$su_transaction->balance_date, new FrozenTime(), true);
$decay_start_date = $stateBalancesTable->getDecayStartDateCached();
$duration = $su_transaction->balance_date->timeAgoInWords();
if($decay_start_date > $su_transaction->balance_date) {
$duration = $decay_start_date->timeAgoInWords();
}
$final_transactions[] = [
'type' => 'decay',
'balance' => floatval(intval($su_transaction->balance - $state_balance->decay)),
'decay_duration' => $su_transaction->balance_date->timeAgoInWords(),
'balance' => floatval($su_transaction->balance - $calculated_decay['balance']),
'decay_duration' => $duration,
'memo' => ''
];
}
@ -337,12 +347,13 @@ class TransactionsTable extends Table
}
public function fillStateUserTransactions()
{
{
$missing_transaction_ids = [];
$transaction_ids = $this
->find('all')
->select(['id', 'transaction_type_id'])
->order(['id'])
->where(['transaction_type_id <' => 6])
->all()
;
$state_user_transaction_ids = $this->StateUserTransactions
@ -422,21 +433,10 @@ class TransactionsTable extends Table
}
}
$results = $this->StateUserTransactions->saveMany($finalEntities);
$errors = [];
foreach($results as $i => $res) {
if($res == false) {
$errors[] = $finalEntities[$i]->getErrors();
}
$save_results = $this->StateUserTransactions->saveManyWithErrors($finalEntities);
if(!$save_results['success']) {
$save_results['msg'] = 'error by saving at least one state user transaction';
}
if(count($errors) == 0) {
$result = ['success' => true];
} else {
$result = ['success' => false, 'msg' => 'error by saving at least one state user transaction', 'errors' => $errors];
}
return $result;
return $save_results;
}
}

View File

@ -12,6 +12,9 @@ $body['gdtSum'] = $this->element('centToFloat', ['cent' => $body['gdtSum'], 'pre
foreach($body['transactions'] as $i => $transaction) {
$body['transactions'][$i]['balance'] = $this->element('centToFloat', ['cent' => $transaction['balance'], 'precision' => 4]);
if(isset($transaction['creation_amount'])) {
$body['transactions'][$i]['creation_amount'] = $this->element('centToFloat', ['cent' => $transaction['creation_amount'], 'precision' => 4]);
}
}
?><?= json_encode($body) ?>

View File

@ -10,7 +10,7 @@
<p>Migrate from Version <?= $db_version ?></p>
<?php if($result['success']) : ?>
<h3><success>Success</success></h3>
<?php elseif : ?>
<?php else : ?>
<h3><error>Error</error></h3>
<p><?= json_encode($result) ?></p>
<?php endif; ?>

View File

@ -23,13 +23,13 @@ Additional session can be provided as GET-Parameter
```json
{
"state":"success",
"balance":1590.60,
"balance":15906078,
"decay":15873851,
"decay_date":"2021-04-16T11:47:21+00:00"
}
```
- `balance` : balance describes gradido
- `balance` : balance describes gradido cents which are 4 digits behind the separator. A balance value of 174500 equals therefor 17,45 GDD
- `decay` : balance with decay on it at the time in decay_date, so it is the precise balance of user at time of calling this function
- `decay_date`: date and time for decay amount, should be the time and date of function call
@ -59,16 +59,32 @@ Assuming: session is valid
{
"state":"success",
"transactions": [
{
"type": "decay",
"balance": "14.74",
"decay_duration": "4 days, 2 hours ago",
"memo": ""
},
{
"name": "Max Mustermann",
"email": "Maxim Mustermann",
"type": "send",
"transaction_id": 2,
"date": "2021-02-19T13:25:36+00:00",
"balance": 192.0,
"balance": 192,
"memo": "a piece of cake :)",
"pubkey": "038a6f93270dc57b91d76bf110ad3863fcb7d1b08e7692e793fcdb4467e5b6a7"
}
},
{
"name": "Gradido Akademie",
"type": "creation",
"transaction_id": 10,
"date": "2021-04-15T11:19:45+00:00",
"target_date": "2021-02-01T00:00:00+00:00",
"creation_amount": "1000",
"balance": "1000",
"memo": "AGE Februar 2021"
}
],
"transactionExecutingCount": 0,
"count": 1,
@ -95,8 +111,11 @@ Transaction:
- `receiver`: user has received gradidos from another user
- `transaction_id`: id of transaction in db, in stage2 also the hedera sequence number of transaction
- `date`: date of ordering transaction (booking date)
- `balance`: Gradido
- `balance`: Gradido as float, max 2 Nachkommastellen, by creation balance after subtract decay amount
- `memo`: Details about transaction
- `decay_duration`: only for decay, time duration for decay calculation in english text
- `creation_amount`: only for creation transaction, created account before decay
- `target_date`: only by creation transaction, target date for creation, start time for decay calculation (if < as global decay start time)
## Creation transaction
Makes a creation transaction to create new Gradido
@ -150,7 +169,6 @@ with
- `session_id`: optional, only used if cookie GRADIDO_LOGIN not exist and no sesion_id in php session
- `email` or `username` or `pubkey`: used to identify how gets the gradidos (email and username are only aliases for pubkey)
- `amount`: gdd amount to transfer in gradido cent (10000000 = 1000,00 GDD)
- `target_date`: target date for creation, can be max 3 months before current date, but not after current date, allowed formats do you find here: https://pocoproject.org/docs/Poco.DateTimeFormat.html
- `memo`: text for receiver, currently saved as clear text in blockchain
- `auto_sign`: if set to true, transaction will be directly signed on login-server and proceed if needed signs are there
if set to false, transaction must be signed after on `http://localhost/account/checkTransactions`
@ -245,3 +263,41 @@ Without auto-sign the transaction is pending on the login-server and waits for t
// TODO Is this in line with our usability goals?
// TODO Should this not be handled client side?
# Klicktipp
## Subscribe
Subscribe current logged in user to gradido newsletter
### Request
`GET http://localhost/api/klicktipp_subscribe/[session_id]`
Parts symbolized by [] are optional
- session_id: session will be searched in php session and GRADIDO_LOGIN cookie and if not found use this
### Response
Assuming: session is valid
```json
{
"state": "success",
"redirect_url": "<redirect url from klicktipp>"
}
````
## Unsubscribe
Unsubscribe current logged in user from gradido newsletter
### Request
`GET http://localhost/api/klicktipp_unsubscribe/[session_id]`
Parts symbolized by [] are optional
- session_id: session will be searched in php session and GRADIDO_LOGIN cookie and if not found use this
### Response
Assuming: session is valid
```json
{
"state": "success"
}
````