public function exec($request)
    {
        assert($request instanceof ARequest);
        $result = new AResponse();
        $operationTypeId = $request->getOperationTypeId();
        $operationTypeCode = $request->getOperationTypeCode();
        $datePerformed = $request->getDatePerformed();
        $note = $request->getOperationNote();
        $transactions = $request->getTransactions();
        $asRef = $request->getAsTransRef();
        $customerId = $request->getCustomerId();
        $adminUserId = $request->getAdminUserId();


        if (empty($datePerformed)) {
            $datePerformed = $this->hlpDate->getUtcNowForDb();
        }
        /* add operation itself */
        if (!$operationTypeId) {
            $operationTypeId = $this->daoTypeOper->getIdByCode($operationTypeCode);
        }
        $bindToAdd = [
            EOperation::A_TYPE_ID => $operationTypeId,
            EOperation::A_DATE_PREFORMED => $datePerformed
        ];
        if (!is_null($note)) {
            $bindToAdd[EOperation::A_NOTE] = $note;
        }
        $validTrans = $this->validateTransactions($transactions);
        if ($validTrans == AResponse::ERR_NO_ERROR) {
            /**
             * Better this nested transaction will break outer transaction than we will clean up data manually.
             */
            $def = $this->manTrans->begin();
            try {

                $operId = $this->daoOper->create($bindToAdd);
                if ($operId) {
                    $transIds = $this->ownAdd->exec($operId, $transactions, $datePerformed, $asRef);
                    $result->setOperationId($operId);
                    $result->setTransactionsIds($transIds);
                    /* extract IDs from sessions if both are empty */
                    list($customerId, $adminUserId) = $this->prepareLogIds($customerId, $adminUserId);
                    /* log customer link */
                    if ($customerId) {
                        $log = new \Praxigento\Accounting\Repo\Data\Log\Change\Customer();
                        $log->setCustomerRef($customerId);
                        $log->setOperationRef($operId);
                        $this->daoELogChangeCust->create($log);
                    }
                    /* log admin link */
                    if ($adminUserId) {
                        $log = new \Praxigento\Accounting\Repo\Data\Log\Change\Admin();
                        $log->setUserRef($adminUserId);
                        $log->setOperationRef($operId);
                        $this->daoELogChangeAdmin->create($log);
                    }
                    $this->manTrans->commit($def);
                    $result->markSucceed();
                }

            } finally {
                /* rollback transaction if not committed (on exception, for example) */
                $this->manTrans->end($def);
            }
        } else {
            $dump = var_export($request, true);
            $this->logger->error("Validation error: $validTrans. Details: $dump.");
            $result->setErrorCode($validTrans);
        }
        return $result;
    }