Initial commit

This commit is contained in:
2026-07-05 21:52:31 +02:00
commit 93259f5b6d
35 changed files with 2389 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\ApiController;
use OCA\MoneyPlanner\Service\AccountService;
class AccountApiController extends ApiController {
private $service;
private $userId;
use Errors;
public function __construct($AppName, IRequest $request,
AccountService $service, $UserId){
parent::__construct($AppName, $request);
$this->service = $service;
$this->userId = $UserId;
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*/
public function index() {
return new DataResponse($this->service->findAll($this->userId));
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $id
*/
public function show($id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->find($id, $this->userId);
});
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param string $name
*/
public function create($name) {
return $this->service->create($name, $this->userId);
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $id
* @param string $name
*/
public function update($id, $name) {
return $this->handleNotFound(function () use ($id, $name) {
return $this->service->update($id, $name, $this->userId);
});
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $id
*/
public function destroy($id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->delete($id, $this->userId);
});
}
}
?>
+78
View File
@@ -0,0 +1,78 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use Exception;
use OCP\IRequest;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCA\MoneyPlanner\Service\AccountService;
class AccountController extends Controller {
private $service;
private $userId;
use Errors;
public function __construct(string $AppName, IRequest $request, AccountService $service, $UserId){
parent::__construct($AppName, $request);
$this->service = $service;
$this->userId = $UserId;
}
/**
* @NoAdminRequired
*/
public function index() {
return new DataResponse($this->service->findAll($this->userId));
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function show(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->find($id, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param string $name
*/
public function create(string $name) {
return $this->service->create($name, $this->userId);
}
/**
* @NoAdminRequired
*
* @param int $id
* @param string $name
*/
public function update(int $id, string $name) {
return $this->handleNotFound(function () use ($id, $name) {
return $this->service->update($id, $name, $this->userId);
});
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function destroy(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->delete($id, $this->userId);
});
}
}
?>
+25
View File
@@ -0,0 +1,25 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use Closure;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCA\MoneyPlanner\Service\NotFoundException;
trait Errors {
protected function handleNotFound (Closure $callback) {
try {
return new DataResponse($callback());
} catch(NotFoundException $e) {
$message = ['message' => $e->getMessage()];
return new DataResponse($message, Http::STATUS_NOT_FOUND);
}
}
}
?>
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
class PageController extends Controller {
private $userId;
public function __construct($AppName, IRequest $request, $UserId){
parent::__construct($AppName, $request);
$this->userId = $UserId;
}
/**
* CAUTION: the @Stuff turns off security checks; for this page no admin is
* required and no CSRF check. If you don't know what CSRF is, read
* it up in the docs or you might create a security hole. This is
* basically the only required method to add this exemption, don't
* add it to any other method if you don't exactly know what it does
*
* @NoAdminRequired
* @NoCSRFRequired
*/
public function index() {
return new TemplateResponse('moneyplanner', 'index'); // templates/index.php
}
}
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\ApiController;
use OCA\MoneyPlanner\Service\TransactionService;
class TransactionApiController extends ApiController {
private $service;
private $userId;
use Errors;
public function __construct($AppName, IRequest $request,
TransactionService $service, $UserId){
parent::__construct($AppName, $request);
$this->service = $service;
$this->userId = $UserId;
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*/
public function index() {
return new DataResponse($this->service->findAll($this->userId));
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $id
*/
public function show($id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->find($id, $this->userId);
});
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*/
public function create(
$accountFrom,
$accountTo,
$group,
$category,
$balance,
$date,
$freqNum,
$freqType
) {
return $this->service->create(
$accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType,
$this->userId
);
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*/
public function update(
$id,
$accountFrom,
$accountTo,
$group,
$category,
$balance,
$date,
$freqNum,
$freqType
) {
return $this->handleNotFound(function () use (
$id, $accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType
) {
return $this->service->update(
$id, $accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType,
$this->userId
);
});
}
/**
* @CORS
* @NoCSRFRequired
* @NoAdminRequired
*
* @param int $id
*/
public function destroy($id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->delete($id, $this->userId);
});
}
}
?>
+103
View File
@@ -0,0 +1,103 @@
<?php
namespace OCA\MoneyPlanner\Controller;
use Exception;
use OCP\IRequest;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCA\MoneyPlanner\Service\TransactionService;
class TransactionController extends Controller {
private $service;
private $userId;
use Errors;
public function __construct(string $AppName, IRequest $request, TransactionService $service, $UserId){
parent::__construct($AppName, $request);
$this->service = $service;
$this->userId = $UserId;
}
/**
* @NoAdminRequired
*/
public function index() {
return new DataResponse($this->service->findAll($this->userId));
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function show(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->find($id, $this->userId);
});
}
/**
* @NoAdminRequired
*/
public function create(
$accountFrom,
$accountTo,
$group,
$category,
$balance,
$date,
$freqNum,
$freqType
) {
return $this->service->create(
$accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType,
$this->userId
);
}
/**
* @NoAdminRequired
*/
public function update(
int $id,
$accountFrom,
$accountTo,
$group,
$category,
$balance,
$date,
$freqNum,
$freqType
) {
return $this->handleNotFound(function () use (
$id, $accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType
) {
return $this->service->update(
$id, $accountFrom, $accountTo, $group, $category,
$balance, $date, $freqNum, $freqType,
$this->userId
);
});
}
/**
* @NoAdminRequired
*
* @param int $id
*/
public function destroy(int $id) {
return $this->handleNotFound(function () use ($id) {
return $this->service->delete($id, $this->userId);
});
}
}
?>
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace OCA\MoneyPlanner\Db;
use JsonSerializable;
use OCP\AppFramework\Db\Entity;
class Account extends Entity implements JsonSerializable {
protected $name;
protected $userId;
public function jsonSerialize() {
return [
'id' => $this->id,
'userId' => $this->userId,
'name' => $this->name
];
}
}
?>
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace OCA\MoneyPlanner\Db;
use OCP\IDbConnection;
use OCP\AppFramework\Db\QBMapper;
class AccountMapper extends QBMapper {
public function __construct(IDbConnection $db) {
parent::__construct($db, 'moneyplanner_accounts', Account::class);
}
public function find(int $id, string $userId) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('id', $qb->createNamedParameter($id))
)->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
);
return $this->findEntity($qb);
}
public function findAll(string $userId) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
);
return $this->findEntities($qb);
}
}
?>
+34
View File
@@ -0,0 +1,34 @@
<?php
namespace OCA\MoneyPlanner\Db;
use JsonSerializable;
use OCP\AppFramework\Db\Entity;
class Transaction extends Entity implements JsonSerializable {
protected $userId;
protected $accountFrom;
protected $accountTo;
protected $group;
protected $category;
protected $balance;
protected $date;
protected $freqNum;
protected $freqType;
public function jsonSerialize() {
return [
'id' => $this->id,
'userId' => $this->userId,
'accountFrom' => $this->accountFrom,
'accountTo' => $this->accountTo,
'group' => $this->group,
'category' => $this->category,
'balance' => $this->balance,
'date' => $this->date,
'freqNum' => $this->freqNum,
'freqType' => $this->freqType
];
}
}
+40
View File
@@ -0,0 +1,40 @@
<?php
namespace OCA\MoneyPlanner\Db;
use OCP\IDbConnection;
use OCP\AppFramework\Db\QBMapper;
class TransactionMapper extends QBMapper {
public function __construct(IDbConnection $db) {
parent::__construct($db, 'moneyplanner_transactions', Transaction::class);
}
public function find(int $id, string $userId) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('id', $qb->createNamedParameter($id))
)->andWhere(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
);
return $this->findEntity($qb);
}
public function findAll(string $userId) {
$qb = $this->db->getQueryBuilder();
$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('user_id', $qb->createNamedParameter($userId))
);
return $this->findEntities($qb);
}
}
?>
@@ -0,0 +1,46 @@
<?php
namespace OCA\MoneyPlanner\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\SimpleMigrationStep;
use OCP\Migration\IOutput;
class Version000000Date20190320115800 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('moneyplanner_accounts')) {
$table = $schema->createTable('moneyplanner_accounts');
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
]);
$table->addColumn('user_id', 'string', [
'notnull' => true,
'length' => 64
]);
$table->addColumn('name', 'string', [
'notnull' => true,
'length' => 255
]);
$table->setPrimaryKey(['id']);
$table->addIndex(['user_id'], 'moneyplanner_accounts_user_id_index');
$table->addUniqueIndex(['user_id', 'name'], 'moneyplanner_accounts_user_name_index');
}
return $schema;
}
}
?>
@@ -0,0 +1,67 @@
<?php
namespace OCA\MoneyPlanner\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\SimpleMigrationStep;
use OCP\Migration\IOutput;
class Version000001Date20190409203900 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('moneyplanner_transactions')) {
$table = $schema->createTable('moneyplanner_transactions');
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
]);
$table->addColumn('user_id', 'string', [
'notnull' => true,
'length' => 64
]);
$table->addColumn('account_from', 'integer', [
'notnull' => false
]);
$table->addColumn('account_to', 'integer', [
'notnull' => false
]);
$table->addColumn('group', 'integer', [
'notnull' => true
]);
$table->addColumn('category', 'integer', [
'notnull' => true
]);
$table->addColumn('balance', 'decimal', [
'notnull' => true,
'length' => 65
]);
$table->addColumn('date', 'date', [
'notnull' => true
]);
$table->addColumn('freq_num', 'integer', [
'notnull' => false
]);
$table->addColumn('freq_type', 'string', [
'notnull' => true,
'length' => 1
]);
$table->setPrimaryKey(['id']);
$table->addIndex(['user_id'], 'moneyplanner_transactions_user_id_index');
}
return $schema;
}
}
?>
@@ -0,0 +1,73 @@
<?php
namespace OCA\MoneyPlanner\Migration;
use Closure;
use OCP\DB\ISchemaWrapper;
use OCP\Migration\SimpleMigrationStep;
use OCP\Migration\IOutput;
class Version000002Date20260705000000 extends SimpleMigrationStep {
/**
* @param IOutput $output
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
* @param array $options
* @return null|ISchemaWrapper
*/
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options) {
/** @var ISchemaWrapper $schema */
$schema = $schemaClosure();
if (!$schema->hasTable('moneyplanner_transactions')) {
$table = $schema->createTable('moneyplanner_transactions');
$table->addColumn('id', 'integer', [
'autoincrement' => true,
'notnull' => true,
]);
$table->addColumn('user_id', 'string', [
'notnull' => true,
'length' => 64
]);
$table->addColumn('account_from', 'integer', [
'notnull' => false
]);
$table->addColumn('account_to', 'integer', [
'notnull' => false
]);
$table->addColumn('group', 'integer', [
'notnull' => true
]);
$table->addColumn('category', 'integer', [
'notnull' => true
]);
$table->addColumn('balance', 'decimal', [
'notnull' => true,
'length' => 65
]);
$table->addColumn('date', 'date', [
'notnull' => true
]);
$table->addColumn('freq_num', 'integer', [
'notnull' => false
]);
$table->addColumn('freq_type', 'string', [
'notnull' => true,
'length' => 1
]);
$table->setPrimaryKey(['id']);
$table->addIndex(['user_id'], 'moneyplanner_transactions_user_id_index');
} else {
$table = $schema->getTable('moneyplanner_transactions');
if ($table->hasIndex('moneyplanner_transactions_user_name_index')) {
$table->dropIndex('moneyplanner_transactions_user_name_index');
}
if ($table->hasColumn('name')) {
$table->dropColumn('name');
}
}
return $schema;
}
}
+77
View File
@@ -0,0 +1,77 @@
<?php
namespace OCA\MoneyPlanner\Service;
use Exception;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCA\MoneyPlanner\Db\Account;
use OCA\MoneyPlanner\Db\AccountMapper;
class AccountService {
private $mapper;
public function __construct(AccountMapper $mapper){
$this->mapper = $mapper;
}
public function findAll(string $userId) {
return $this->mapper->findAll($userId);
}
private function handleException ($e) {
if ($e instanceof DoesNotExistException ||
$e instanceof MultipleObjectsReturnedException) {
throw new NotFoundException($e->getMessage());
} else {
throw $e;
}
}
public function find(int $id, string $userId) {
try {
return $this->mapper->find($id, $userId);
// in order to be able to plug in different storage backends like files
// for instance it is a good idea to turn storage related exceptions
// into service related exceptions so controllers and service users
// have to deal with only one type of exception
} catch(Exception $e) {
$this->handleException($e);
}
}
public function create(string $name, string $userId) {
$account = new Account();
$account->setName($name);
$account->setUserId($userId);
return $this->mapper->insert($account);
}
public function update(int $id, string $name, string $userId) {
try {
$account = $this->mapper->find($id, $userId);
$account->setName($name);
return $this->mapper->update($account);
} catch(Exception $e) {
$this->handleException($e);
}
}
public function delete(int $id, string $userId) {
try {
$account = $this->mapper->find($id, $userId);
$this->mapper->delete($account);
return $account;
} catch(Exception $e) {
$this->handleException($e);
}
}
}
?>
+7
View File
@@ -0,0 +1,7 @@
<?php
namespace OCA\MoneyPlanner\Service;
class NotFoundException extends ServiceException {}
?>
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace OCA\MoneyPlanner\Service;
use Exception;
class ServiceException extends Exception {}
?>
+99
View File
@@ -0,0 +1,99 @@
<?php
namespace OCA\MoneyPlanner\Service;
use Exception;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCA\MoneyPlanner\Db\Transaction;
use OCA\MoneyPlanner\Db\TransactionMapper;
class TransactionService {
private $mapper;
public function __construct(TransactionMapper $mapper){
$this->mapper = $mapper;
}
public function findAll(string $userId) {
return $this->mapper->findAll($userId);
}
private function handleException($e) {
if ($e instanceof DoesNotExistException ||
$e instanceof MultipleObjectsReturnedException) {
throw new NotFoundException($e->getMessage());
} else {
throw $e;
}
}
public function find(int $id, string $userId) {
try {
return $this->mapper->find($id, $userId);
} catch(Exception $e) {
$this->handleException($e);
}
}
public function create(
$accountFrom,
$accountTo,
int $group,
int $category,
string $balance,
string $date,
$freqNum,
string $freqType,
string $userId
) {
$transaction = new Transaction();
$transaction->setAccountFrom($accountFrom);
$transaction->setAccountTo($accountTo);
$transaction->setGroup($group);
$transaction->setCategory($category);
$transaction->setBalance($balance);
$transaction->setDate($date);
$transaction->setFreqNum($freqNum);
$transaction->setFreqType($freqType);
$transaction->setUserId($userId);
return $this->mapper->insert($transaction);
}
public function update(
int $id,
$accountFrom,
$accountTo,
int $group,
int $category,
string $balance,
string $date,
$freqNum,
string $freqType,
string $userId
) {
try {
$transaction = $this->mapper->find($id, $userId);
$transaction->setAccountFrom($accountFrom);
$transaction->setAccountTo($accountTo);
$transaction->setGroup($group);
$transaction->setCategory($category);
$transaction->setBalance($balance);
$transaction->setDate($date);
$transaction->setFreqNum($freqNum);
$transaction->setFreqType($freqType);
return $this->mapper->update($transaction);
} catch(Exception $e) {
$this->handleException($e);
}
}
public function delete(int $id, string $userId) {
try {
$transaction = $this->mapper->find($id, $userId);
$this->mapper->delete($transaction);
return $transaction;
} catch(Exception $e) {
$this->handleException($e);
}
}
}