Доброго времени суток, уважаемы IT-кудесники!
Я разрабатываю модуль(bundle) Транзакции в symfony. Хотел бы узнать ваши советы по поводу компонентов на которые можно разбить модуль и связи между компонентами.
В моем ТЗ счет(account) юзера разбивается на несколько типов счетов(1.
FundAccount - счет который юзер может пополнять и тратить деньги с этого счета на услуги внутри системы, но не может снимать, 2.
IncomeAccount - счет который юзер накапливает/зарабатывает за выполнение разных проектов - может снимать) и т.д. Переводить деньги со второго счета на первый можно ( + изымается комиссия), а со второго на первый перевод денег запрещен.
Возможно будет добавлены еще типы счетов. Это делается чтобы соответсвовать бизнес-модели - счета имеют разные комиссии, разные плюшки.
Так вот, как видите, различных условий достаточно. Тем более я хотел бы разработать гибкую и выразительную структуру.
Вот как я представляю решение, но все же жду от вас критики и советов!
Я хочу чтобы все запросы связанные с переводами денег(транзакциями) приходили в один контроллер. Примерно так будет выглядеть контроллер.
public function transactionAction(Request $request)
{
//Получаю необходимые данные
$sender = $this->get('security.token_storage')->getToken()->getUser();
$senderAccountType = $request->request->get('sender_account_type');
$recipient = $request->request->get('recipient');
$recipientAccountType = $request->request->get('recipient_account_type');
$amount = $request->request->get('amount');
//Передаю данные сервису TransactionChainService
try{
$this->get('acme.transaction_bundle.transaction_chain')->transfer(User $sender, $senderAccountType, User $recipient, $recipientAccountType, $amount);
return new JsonRespone(array('success' => true));
}catch(TransactionFailedException $e){
var_dump($e->getMessage()); die();
}catch(Exception $e){
var_dump($e->getMessage()); die();
}
}
В свою очередь TransactionChainService хранит менеджеров всех счетов юзера. В моем случае - пока только FundAccountManager и IncomeAccountManager. Все менеджеры обязаны реализовать метод transfer().
TransactionChainServiceclass TransactionChainServie
{
private $accountManagers = array();
public function transfer(User $sender, $senderAccountType, User $recipient, $recipientAccountType, $amount)
{
foreach($accountManagers as $manager){
$manager->transfer(User $sender, $senderAccountType, User $recipient, $recipientAccountType, $amount);
}
}
public function addManager($manager){
$this->accountManagers[] = $manager;
}
}
FundAccountManagerclass FundTransactionManager
{
protected $em;
public function __construct( EntityManager $em)
{
$this->em = $em;
}
public function transfer(User $sender, $senderAccountType, User $recipient, $recipientAccountType, $amount)
{
if($senderAccountType == "Fund")
{
//Перевод денег учитываю %комиссии для данного типа
$em = $this->em;
$em->getConnection()->beginTransaction();
$transaction = new Transaction($sender, $recipient, $amount);
$sender->setFond($sender->getFund() - $amount);
call_user_func_array($recipient['set'.$recipientAccountType], $recipient['get'.$recipientAccountType] + $amount * 0.1); //умножаем на комиссию
$em->persist($sender);
$em->persist($recipient);
$em->persist($transaction);
$em->flush();
$em->getConnection()->commit();
}
}
}
IncomeAccountManagerclass IncomeTransactionManager
{
protected $em;
public function __construct( EntityManager $em)
{
$this->em = $em;
}
public function transfer(User $sender, $senderAccountType, User $recipient, $recipientAccountType, $amount)
{
if($senderAccountType == "Income")
{
//Перевод денег учитываю %комиссии для данного типа
$em = $this->em;
$em->getConnection()->beginTransaction();
$transaction = new Transaction($sender, $recipient, $amount);
$sender->setIncome($sender->getIncome() - $amount);
call_user_func_array($recipient['set'.$recipientAccountType], $recipient['get'.$recipientAccountType] + $amount * 0.05); //умножаем на комиссию
$em->persist($sender);
$em->persist($recipient);
$em->persist($transaction);
$em->flush();
$em->getConnection()->commit();
}
}
}
Заранее извиваюсь за ошибки(код написан с целью передать мысль) и если что то непонятно описал. Жду вашей критики, советов и предложений про преобразованию структуры!