src/Money/Module/Budget/Controller/Budget.php
public function ajaxEdit()
    {
        if (!Server::getInstance()->isAjax()) {
            throw new \RuntimeException();
        }

        $response = new Api();
        $response->setHttpCode(200);
        $response->setIsSuccess(true);

        $responseData = array();
        try {
            $post = Post::getInstance();

            $accountId  = (int) $post->get('accountId');
            $account    = $this->verifyAccount($accountId);

            //~ New item
            $itemMapper = new BudgetMapper(Database::get('money'));
            $item       = $itemMapper->findById((int) $post->get('itemId'));

            if ($item->getAccountId() !== $account->getId()) {
                throw new \Exception('Bad budget id!');
            }

            //~ edit item
            $item->setName(trim($post->get('itemName')));
            $item->setAmountDefault((float) $post->get('itemAmountDefault'));
            $item->setParentId((int) $post->get('itemParentId'));

            $dateStart = trim($post->get('itemDateStart'));
            $dateStart = \DateTimeImmutable::createFromFormat('d/m/Y', $dateStart);
            $item->setDateStart($dateStart->format('Y-m-d'));

            $dateEnd = trim($post->get('itemDateEnd'));
            if (!empty($dateEnd)) {
                $dateEnd = \DateTimeImmutable::createFromFormat('d/m/Y', $dateEnd);
                $item->setDateEnd($dateEnd->format('Y-m-d'));
            }

            $monthRecurrent = $post->get('itemMonthRecurrent');
            $item->setMonthBitmask(0); // Reset bitmask
            if (!empty($monthRecurrent) && is_array($monthRecurrent)) {
                foreach ($monthRecurrent as $month) {
                    $month = (int) $month;

                    if ($month === 0) {
                        $item->setIsRecurrent(false);
                        $item->setMonthBitmask(0);
                        break;
                    }

                    if ($month === 13) {
                        $item->setIsRecurrent(true);
                        $item->setMonthBitmask(4095); // All months
                        break;
                    }

                    $item->setIsRecurrent(true);
                    $item->addMonthToBitmask($month);
                }
            }

            Database::get('money')->beginTransaction();

            $amountMonth = (float) trim($post->get('itemAmountMonth'));
            $isEditMonth = ($item->getAmountDefault() !== $amountMonth);

            //~ update item
            $itemMapper->update($item);

            $date = \DateTimeImmutable::createFromFormat('d/m/Y', trim($post->get('currentDate')));
            $budgetMonthMapper = new BudgetMonthMapper(Database::get('money'));
            $budgetMonth = $budgetMonthMapper->findByBudgetId($item->getId(), $date);
            $budgetMonth->setAmount($amountMonth);
            $budgetMonthMapper->update($budgetMonth);

            //~ Insert categories linked
            $categories           = $post->get('itemCategoriesId');
            $categoryMapper       = new CategoryMapper(Database::get('money'));
            $budgetCategoryMapper = new BudgetCategoryMapper(Database::get('money'));

            $list = $item->getAllBudgetCategory();
            $budgetCategories = array();
            foreach ($list as $budgetCategory) {
                $budgetCategories[$budgetCategory->getCategoryId()] = $budgetCategory;
            }

            if (!empty($categories) && is_array($categories)) {

                foreach ($categories as $categoryId) {
                    //~ Skip existing categories
                    if (isset($budgetCategories[$categoryId])) {
                        unset($budgetCategories[$categoryId]);
                        continue;
                    }

                    $responseData['categoriesId'] = implode('|', $categories);

                    $category = $categoryMapper->findById((int) $categoryId);
                    if ($category->getAccountId() !== $accountId) {
                        throw new \RangeException('Category id is not valid for this account!');
                    }

                    //~ Add new budget categories
                    $budgetCategory = $budgetCategoryMapper->newDataInstance();
                    $budgetCategory->setCategoryId($categoryId);
                    $budgetCategory->setBudgetId($item->getId());
                    $budgetCategoryMapper->insert($budgetCategory);
                    $responseData[] = 'Add new budget category: ' . $category->getName() . ' to budget ' . $item->getName();
                    unset($budgetCategories[$categoryId]);
                }

                //~ Remove old budget categories
                foreach ($budgetCategories as $budgetCategory) {
                    $budgetCategoryMapper->delete($budgetCategory);
                }
            }

            Database::get('money')->commit();

            $response->setContent($responseData);

        } catch (\Exception $exception) {
            if (Database::get('money')->inTransaction()) {
                Database::get('money')->rollBack();
            }

            $response->setIsSuccess(false)
                ->setHttpCode(500)
                ->setErrorCode($exception->getCode())
                ->setErrorMessage($exception->getMessage())
                ->setContent($responseData);
        }

        return $response;
    }
public function ajaxEdit()
    {
        if (!Server::getInstance()->isAjax()) {
            throw new \RuntimeException();
        }

        $response = new Api();
        $response->setHttpCode(200);
        $response->setIsSuccess(true);

        $responseData = array();
        try {
            $post = Post::getInstance();

            $accountId  = (int) $post->get('accountId');
            $account    = $this->verifyAccount($accountId);

            //~ New item
            $itemMapper = new BudgetMapper(Database::get('money'));
            $item       = $itemMapper->findById((int) $post->get('itemId'));

            if ($item->getAccountId() !== $account->getId()) {
                throw new \Exception('Bad budget id!');
            }

            //~ edit item
            $item->setName(trim($post->get('itemName')));
            $item->setAmountDefault((float) $post->get('itemAmountDefault'));
            $item->setParentId((int) $post->get('itemParentId'));

            $dateStart = trim($post->get('itemDateStart'));
            $dateStart = \DateTimeImmutable::createFromFormat('d/m/Y', $dateStart);
            $item->setDateStart($dateStart->format('Y-m-d'));

            $dateEnd = trim($post->get('itemDateEnd'));
            if (!empty($dateEnd)) {
                $dateEnd = \DateTimeImmutable::createFromFormat('d/m/Y', $dateEnd);
                $item->setDateEnd($dateEnd->format('Y-m-d'));
            }

            $monthRecurrent = $post->get('itemMonthRecurrent');
            $item->setMonthBitmask(0); // Reset bitmask
            if (!empty($monthRecurrent) && is_array($monthRecurrent)) {
                foreach ($monthRecurrent as $month) {
                    $month = (int) $month;

                    if ($month === 0) {
                        $item->setIsRecurrent(false);
                        $item->setMonthBitmask(0);
                        break;
                    }

                    if ($month === 13) {
                        $item->setIsRecurrent(true);
                        $item->setMonthBitmask(4095); // All months
                        break;
                    }

                    $item->setIsRecurrent(true);
                    $item->addMonthToBitmask($month);
                }
            }

            Database::get('money')->beginTransaction();

            $amountMonth = (float) trim($post->get('itemAmountMonth'));
            $isEditMonth = ($item->getAmountDefault() !== $amountMonth);

            //~ update item
            $itemMapper->update($item);

            $date = \DateTimeImmutable::createFromFormat('d/m/Y', trim($post->get('currentDate')));
            $budgetMonthMapper = new BudgetMonthMapper(Database::get('money'));
            $budgetMonth = $budgetMonthMapper->findByBudgetId($item->getId(), $date);
            $budgetMonth->setAmount($amountMonth);
            $budgetMonthMapper->update($budgetMonth);

            //~ Insert categories linked
            $categories           = $post->get('itemCategoriesId');
            $categoryMapper       = new CategoryMapper(Database::get('money'));
            $budgetCategoryMapper = new BudgetCategoryMapper(Database::get('money'));

            $list = $item->getAllBudgetCategory();
            $budgetCategories = array();
            foreach ($list as $budgetCategory) {
                $budgetCategories[$budgetCategory->getCategoryId()] = $budgetCategory;
            }

            if (!empty($categories) && is_array($categories)) {

                foreach ($categories as $categoryId) {
                    //~ Skip existing categories
                    if (isset($budgetCategories[$categoryId])) {
                        unset($budgetCategories[$categoryId]);
                        continue;
                    }

                    $responseData['categoriesId'] = implode('|', $categories);

                    $category = $categoryMapper->findById((int) $categoryId);
                    if ($category->getAccountId() !== $accountId) {
                        throw new \RangeException('Category id is not valid for this account!');
                    }

                    //~ Add new budget categories
                    $budgetCategory = $budgetCategoryMapper->newDataInstance();
                    $budgetCategory->setCategoryId($categoryId);
                    $budgetCategory->setBudgetId($item->getId());
                    $budgetCategoryMapper->insert($budgetCategory);
                    $responseData[] = 'Add new budget category: ' . $category->getName() . ' to budget ' . $item->getName();
                    unset($budgetCategories[$categoryId]);
                }

                //~ Remove old budget categories
                foreach ($budgetCategories as $budgetCategory) {
                    $budgetCategoryMapper->delete($budgetCategory);
                }
            }

            Database::get('money')->commit();

            $response->setContent($responseData);

        } catch (\Exception $exception) {
            if (Database::get('money')->inTransaction()) {
                Database::get('money')->rollBack();
            }

            $response->setIsSuccess(false)
                ->setHttpCode(500)
                ->setErrorCode($exception->getCode())
                ->setErrorMessage($exception->getMessage())
                ->setContent($responseData);
        }

        return $response;
    }
Ajax edit category.

@return ResponseInterface