Doctrine: Correctness of Using persist and flush in postPersist Lifecycle Event

I’m building a double entry accounting system. The balance of each account is calculated using a simple sum algorithm and maintained as a field on each account. The only way which I’ve discovered to update an accounts balance when a post happens for an account is to use a postPersist event handler to update the account. I think this is the right way to do it but I’m not 100% sure. Everything seems to work in my testing. Below is my doctrine subscriber.

Also I’m a little concerned about the race condition of two accounts being updated simultaneously. Which is a very likely case for the account(s) associated with the site rather than an individual customer. However, the only other way I can think to do this is to use triggers. However, that seems as if it would defeat the whole purpose of Doctrine in the first place.

<?php namespace Modules\Accounting\Subscribers;

use Doctrine\Common\EventSubscriber;
use Doctrine\ORM\Events;
use Doctrine\Common\Persistence\Event\LifecycleEventArgs;
use Modules\Customer\Entities\Customer as CustomerEntity;
use Modules\Accounting\Entities\Account as AccountEntity;
use Modules\Sales\Entities\Sale as SaleEntity;
use Modules\Accounting\Repositories\AccountTypeRepository;
use Modules\Accounting\Repositories\PostingEventRepository;
use Modules\Accounting\Repositories\AssetTypeRepository;
use Modules\Accounting\Repositories\AccountRepository;
use Carbon\Carbon;
use Modules\Accounting\Entities\Posting as PostingEntity;

class DoctrineSubscriber implements EventSubscriber {

    public function getSubscribedEvents() {

        return [
            Events::postPersist,
        ];

    }

    /**
     * postPersist handler
     *
     * @param LifecycleEventArgs $event
     */
    public function postPersist(LifecycleEventArgs $event) {

        $em = $event->getObjectManager();
        $entity = $event->getObject();

        if($entity instanceof PostingEntity) {
            $this->recalculateAccountBalance($event);
        }

    }

    /**
     * Recalculate the balance of the associated account.
     *
     * @param LifecycleEventArgs $event
     */
    protected function recalculateAccountBalance(LifecycleEventArgs $event) {

        $em = $event->getObjectManager();
        $posting = $event->getObject();

        $accountRepo = app(AccountRepository::class);
        $account = $posting->getAccount();
        
        $balance = $accountRepo->calculateAccountBalance($account);
        $account->setBalance($balance);

        // Is it appropriate to be calling these in postPersist :/
        $em->persist($account);
        $em->flush();

    }

}

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.