Skip to content

Commit

Permalink
Update README and workflows for Econumo CE.
Browse files Browse the repository at this point in the history
  • Loading branch information
deeravenger committed Dec 2, 2024
1 parent a421914 commit b0037f7
Show file tree
Hide file tree
Showing 17 changed files with 558 additions and 16 deletions.
10 changes: 1 addition & 9 deletions .github/workflows/build-econumo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,6 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Clone EconumoFamilyBundle repository
uses: actions/checkout@v4
with:
repository: econumo/econumo-family-bundle
ref: main
token: ${{ secrets.BUILD_USER_TOKEN }}
path: src/EconumoFamilyBundle

- name: Clone EconumoCloudBundle repository
uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -53,7 +45,7 @@ jobs:
QASE_TOKEN: ${{ secrets.APP_QASE_TOKEN }}
QASE_PROJECT: "EA"

- name: Test Econumo Family
- name: Test Econumo CE
if: success()
run: |
docker run --volume shared-volume:/var/www/var/db ${DOCKER_IMAGE} rm -f src/EconumoFamilyBundle/.disabled
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
.DS_Store
src/*Bundle/
!src/EconumoBundle/
!src/EconumoFamilyBundle/
!src/EconumoDemoBundle/
src/*Bundle/.disabled*
###< econumo ###


Expand Down
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
</p>

<p align="center">
A getting started guide to self-hosting <a href="https://econumo.com/" target="_blank">Econumo</a>
A getting started guide to self-hosting <a href="https://econumo.com/" target="_blank">Econumo CE</a>
</p>

---

## Description

This is the main backend repository for Econumo, containing the backend for [Econumo One](https://econumo.com/docs/edition/).
This is the main backend repository for Econumo, containing the backend for [Econumo CE](https://econumo.com/docs/edition/).
The backend is built using PHP, Symfony, and SQLite.

## Contribution
Expand All @@ -24,10 +24,6 @@ Run the Application
3. Create a `.env.local` to override the default `.env`
4. Run `task up`

### For Econumo Family Users

1. Clone `[email protected]:econumo/econumo-family-bundle.git` into the `src/EconumoFamilyBundle` directory

### Run tests

Run `task test` to execute all tests, or use arguments for Codeception: `task test -- unit`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
namespace App\EconumoBundle\Domain\Service\Currency;


use App\EconumoBundle\Domain\Entity\Currency;
use App\EconumoBundle\Domain\Entity\CurrencyRate;
use App\EconumoBundle\Domain\Entity\ValueObject\CurrencyCode;
use App\EconumoBundle\Domain\Entity\ValueObject\Id;
Expand Down Expand Up @@ -177,9 +178,10 @@ private function convertInternalById(
$baseCurrencyId = $this->baseCurrencyId;
} else {
$baseCurrency = $this->currencyRepository->getByCode($this->baseCurrency);
if (null === $baseCurrency) {
if (!$baseCurrency instanceof Currency) {
throw new DomainException('Base Currency not found');
}

$baseCurrencyId = $baseCurrency->getId();
$this->baseCurrencyId = $baseCurrencyId;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

declare(strict_types=1);


namespace App\EconumoFamilyBundle\Application\UseCase\ConnectUsers;


use App\EconumoBundle\Domain\Events\UserRegisteredEvent;
use App\EconumoBundle\Domain\Repository\UserRepositoryInterface;
use App\EconumoBundle\Domain\Service\EventHandlerInterface;

readonly class ConnectUsersEventHandler implements EventHandlerInterface
{
public function __construct(
private UserRepositoryInterface $userRepository
) {
}

public function __invoke(UserRegisteredEvent $event): void
{
$users = $this->userRepository->getAll();
$newUser = $this->userRepository->get($event->getUserId());
$toSave = [
$newUser->getId()->getValue() => $newUser
];
foreach ($users as $user) {
if ($user->getId()->isEqual($event->getUserId())) {
continue;
}

$user->connectUser($newUser);
$newUser->connectUser($user);
$toSave[$user->getId()->getValue()] = $user;
}

$this->userRepository->save($toSave);
}
}
15 changes: 15 additions & 0 deletions src/EconumoFamilyBundle/EconumoFamilyBundle.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace App\EconumoFamilyBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class EconumoFamilyBundle extends Bundle
{
public function isActive(): bool
{
return !file_exists(__DIR__.'/.disabled');
}
}
3 changes: 3 additions & 0 deletions src/EconumoFamilyBundle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Description

An additional bundle for Econumo CE to enable shared access support.
Empty file.
4 changes: 4 additions & 0 deletions src/EconumoFamilyBundle/Resources/config/routes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# src/EconumoFamilyBundle/Resources/config/routes.yaml
econumo_family:
resource: '../../UI/Controller/'
type: annotation
20 changes: 20 additions & 0 deletions src/EconumoFamilyBundle/Resources/config/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
services:
_defaults:
autowire: true
autoconfigure: true

App\EconumoFamilyBundle\:
resource: '../../*'
exclude:
- '../../tests'
- '../../**/{Dto,ValueObject,Model,Entity,Exception}/*.php'
- '../../Domain/{Exception,Traits,Entity,Event}'
- '../../Domain/{Exception,Traits,Entity,Event}/*.php'
- '../../Domain/{Exception,Traits,Entity,Event}/**/*.php'

# controllers are imported separately to make sure services can be injected
# as action arguments even if you don't extend any base controller class
App\EconumoFamilyBundle\UI\Controller\:
resource: '../../UI/Controller'
tags: ['controller.service_arguments']
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\EconumoFamilyBundle\UI\Controller\Api\Budget\Access;

use App\EconumoBundle\Application\Budget\AccessService;
use App\EconumoBundle\Application\Budget\Dto\AcceptAccessV1RequestDto;
use App\EconumoBundle\UI\Controller\Api\Budget\Access\Validation\AcceptAccessV1Form;
use App\EconumoBundle\Application\Exception\ValidationException;
use App\EconumoBundle\Domain\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\EconumoBundle\UI\Service\Validator\ValidatorInterface;
use App\EconumoBundle\UI\Service\Response\ResponseFactory;
use Symfony\Component\Routing\Annotation\Route;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;

class AcceptAccessV1Controller extends AbstractController
{
public function __construct(private readonly AccessService $accessService, private readonly ValidatorInterface $validator)
{
}

/**
* Accept a budget access
*
* @OA\Tag(name="Budget"),
* @OA\RequestBody(@OA\JsonContent(ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\AcceptAccessV1RequestDto::class))),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/JsonResponseOk"),
* @OA\Schema(
* @OA\Property(
* property="data",
* ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\AcceptAccessV1ResultDto::class)
* )
* )
* }
* )
* ),
* @OA\Response(response=400, description="Bad Request", @OA\JsonContent(ref="#/components/schemas/JsonResponseError")),
* @OA\Response(response=401, description="Unauthorized", @OA\JsonContent(ref="#/components/schemas/JsonResponseUnauthorized")),
* @OA\Response(response=500, description="Internal Server Error", @OA\JsonContent(ref="#/components/schemas/JsonResponseException")),
*
*
* @return Response
* @throws ValidationException
*/
#[Route(path: '/api/v1/budget/accept-access', name: 'api_budget_accept_access', methods: ['POST'])]
public function __invoke(Request $request): Response
{
$dto = new AcceptAccessV1RequestDto();
$this->validator->validate(AcceptAccessV1Form::class, $request->request->all(), $dto);
/** @var User $user */
$user = $this->getUser();
$result = $this->accessService->acceptAccess($dto, $user->getId());

return ResponseFactory::createOkResponse($request, $result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\EconumoFamilyBundle\UI\Controller\Api\Budget\Access;

use App\EconumoBundle\Application\Budget\AccessService;
use App\EconumoBundle\Application\Budget\Dto\DeclineAccessV1RequestDto;
use App\EconumoBundle\UI\Controller\Api\Budget\Access\Validation\DeclineAccessV1Form;
use App\EconumoBundle\Application\Exception\ValidationException;
use App\EconumoBundle\Domain\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\EconumoBundle\UI\Service\Validator\ValidatorInterface;
use App\EconumoBundle\UI\Service\Response\ResponseFactory;
use Symfony\Component\Routing\Annotation\Route;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;

class DeclineAccessV1Controller extends AbstractController
{
public function __construct(private readonly AccessService $accessService, private readonly ValidatorInterface $validator)
{
}

/**
* Decline a budget access
*
* @OA\Tag(name="Budget"),
* @OA\RequestBody(@OA\JsonContent(ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\DeclineAccessV1RequestDto::class))),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/JsonResponseOk"),
* @OA\Schema(
* @OA\Property(
* property="data",
* ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\DeclineAccessV1ResultDto::class)
* )
* )
* }
* )
* ),
* @OA\Response(response=400, description="Bad Request", @OA\JsonContent(ref="#/components/schemas/JsonResponseError")),
* @OA\Response(response=401, description="Unauthorized", @OA\JsonContent(ref="#/components/schemas/JsonResponseUnauthorized")),
* @OA\Response(response=500, description="Internal Server Error", @OA\JsonContent(ref="#/components/schemas/JsonResponseException")),
*
*
* @return Response
* @throws ValidationException
*/
#[Route(path: '/api/v1/budget/decline-access', name: 'api_budget_decline_access', methods: ['POST'])]
public function __invoke(Request $request): Response
{
$dto = new DeclineAccessV1RequestDto();
$this->validator->validate(DeclineAccessV1Form::class, $request->request->all(), $dto);
/** @var User $user */
$user = $this->getUser();
$result = $this->accessService->declineAccess($dto, $user->getId());

return ResponseFactory::createOkResponse($request, $result);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\EconumoFamilyBundle\UI\Controller\Api\Budget\Access;

use App\EconumoBundle\Application\Budget\AccessService;
use App\EconumoBundle\Application\Budget\Dto\GrantAccessV1RequestDto;
use App\EconumoBundle\UI\Controller\Api\Budget\Access\Validation\GrantAccessV1Form;
use App\EconumoBundle\Application\Exception\ValidationException;
use App\EconumoBundle\Domain\Entity\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\EconumoBundle\UI\Service\Validator\ValidatorInterface;
use App\EconumoBundle\UI\Service\Response\ResponseFactory;
use Symfony\Component\Routing\Annotation\Route;
use Nelmio\ApiDocBundle\Annotation\Model;
use OpenApi\Annotations as OA;

class GrantAccessV1Controller extends AbstractController
{
public function __construct(private readonly AccessService $accessService, private readonly ValidatorInterface $validator)
{
}

/**
* Grant a budget access
*
* @OA\Tag(name="Budget"),
* @OA\RequestBody(@OA\JsonContent(ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\GrantAccessV1RequestDto::class))),
* @OA\Response(
* response=200,
* description="OK",
* @OA\JsonContent(
* type="object",
* allOf={
* @OA\Schema(ref="#/components/schemas/JsonResponseOk"),
* @OA\Schema(
* @OA\Property(
* property="data",
* ref=@Model(type=\App\EconumoBundle\Application\Budget\Dto\GrantAccessV1ResultDto::class)
* )
* )
* }
* )
* ),
* @OA\Response(response=400, description="Bad Request", @OA\JsonContent(ref="#/components/schemas/JsonResponseError")),
* @OA\Response(response=401, description="Unauthorized", @OA\JsonContent(ref="#/components/schemas/JsonResponseUnauthorized")),
* @OA\Response(response=500, description="Internal Server Error", @OA\JsonContent(ref="#/components/schemas/JsonResponseException")),
*
*
* @return Response
* @throws ValidationException
*/
#[Route(path: '/api/v1/budget/grant-access', name: 'api_budget_grant_access', methods: ['POST'])]
public function __invoke(Request $request): Response
{
$dto = new GrantAccessV1RequestDto();
$this->validator->validate(GrantAccessV1Form::class, $request->request->all(), $dto);
/** @var User $user */
$user = $this->getUser();
$result = $this->accessService->grantAccess($dto, $user->getId());

return ResponseFactory::createOkResponse($request, $result);
}
}
Loading

0 comments on commit b0037f7

Please sign in to comment.