initial commit

This commit is contained in:
2024-07-25 10:54:27 +02:00
parent 3a922fd5bc
commit d2ae809b98
113 changed files with 19295 additions and 2522 deletions
+78
View File
@@ -0,0 +1,78 @@
<?php
namespace App\Command;
use App\Entity\Clients;
use App\Entity\Reports;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'recount-reports-number',
description: 'Add a short description for your command',
)]
class RecountReports extends Command
{
public function __construct(
private EntityManagerInterface $entityManager
)
{
parent::__construct();
}
protected function configure(): void
{
$this
->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$reports = $this->entityManager->getRepository(Reports::class)->findBy([],["dateStart"=>"ASC"]);
$io = new SymfonyStyle($input, $output);
$clientToReport=[];
$clients=[];
foreach ($reports as $report) {
if (!isset($clients[$report->getClient()->getId()])) {
$clients[$report->getClient()->getId()]=$report->getClient();
}
$clientToReport[$report->getClient()->getId()][] = $report;
}
foreach ($clientToReport as $clientId => $reports) {
$client = $clients[$clientId];
$io->writeln($client->getStrName());
$i=1;
foreach ($reports as $report) {
$io->writeln($report->getDateStart()->format("Y-m-d") . ": " . $i);
$report->setNumber($i);
$this->entityManager->persist($report);
$i++;
}
$io->writeln("");
}
$this->entityManager->flush();
$io->success('All reports have been recorded');
//
// $a = '0123456789abcdef';
// $secret = '';
// for ($i = 0; $i < 32; $i++) {
// $secret .= $a[rand(0, 15)];
// }
//
// $r = shell_exec('sed -i -E "s/^APP_SECRET=.{32}$/APP_SECRET=' . $secret . '/" .env');
//
// $io->success('New APP_SECRET was generated: ' . $secret);
return 0;
}
}
@@ -0,0 +1,48 @@
<?php
namespace App\Command;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'regenerate-app-secret',
description: 'Add a short description for your command',
)]
class RegenerateAppSecretCommand extends Command
{
public function __construct()
{
parent::__construct();
}
protected function configure(): void
{
$this
->addArgument('arg1', InputArgument::OPTIONAL, 'Argument description')
->addOption('option1', null, InputOption::VALUE_NONE, 'Option description')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$a = '0123456789abcdef';
$secret = '';
for ($i = 0; $i < 32; $i++) {
$secret .= $a[rand(0, 15)];
}
$r = shell_exec('sed -i -E "s/^APP_SECRET=.{32}$/APP_SECRET=' . $secret . '/" .env');
$io->success('New APP_SECRET was generated: ' . $secret);
return 0;
}
}
View File
+74
View File
@@ -0,0 +1,74 @@
<?php
namespace App\Controller;
use App\Entity\Clients;
use App\Entity\Reports;
use App\Entity\ReportsTodo;
use App\Enum\Months;
use App\Enum\ReportStatus;
use App\Enum\ReportTodoEnum;
use App\Helper\MonthHelper;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class BaseController extends AbstractController
{
private MonthHelper $monthHelper;
public function __construct(){
$this->monthHelper = new MonthHelper();
}
#[Route('/', name: 'index')]
public function index(): Response
{
if (!$this->isGranted('reportView')) {
return $this->redirectToRoute('app_schedule');
}
return $this->redirectToRoute('app_base');
}
#[Route('/reports/{monthId}', name: 'app_base')]
#[IsGranted('reportView')]
public function reportsIndex(EntityManagerInterface $entityManager, int $monthId = 0) : Response
{
if ($this->getUser())
if ($monthId > -1) {
$monthCurrent = $this->monthHelper->getCurrentMonth($monthId);
$reportsAll = $entityManager->getRepository(Reports::class)->findAllInMonth($monthCurrent);
} else {
$reportsAll = $entityManager->getRepository(Reports::class)->findAllOverdue();
}
$reports = [];
foreach (ReportStatus::cases() as $case) {
$reports[$case->value] = [
'status' => $case,
'reports' => []
];
}
/** @var Reports $report */
foreach ($reportsAll as $report) {
$reports[$report->takeStatusTodo()->value]['reports'][] = $report;
}
ksort($reports);
return $this->render('reports/list.html.twig', [
'reportsGroup' => $reports,
'months' => $this->monthHelper->takeMonths(),
'currentMonth' => $monthCurrent ?? null,
'reportToDoList' => ReportTodoEnum::cases()
]);
}
}
+164
View File
@@ -0,0 +1,164 @@
<?php
namespace App\Controller;
use App\Entity\Clients;
use App\Entity\Notes;
use App\Entity\Reports;
use App\Entity\Schedule;
use App\Services\AddReports;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\DateType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\IntegerType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\TextareaType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class ClientController extends AbstractController
{
#[Route('/klienci', name: 'app_customers_list')]
#[IsGranted('clientView')]
public function customersList(EntityManagerInterface $entityManager) : Response
{
$customers = $entityManager->getRepository(Clients::class)->findBy(["isDeleted" => false]);
return $this->render("customers/list.html.twig",['customers' => $customers]);
}
#[Route('/klient/{id}', name: 'app_client')]
#[IsGranted('clientView')]
public function takeClient(Clients $clients, Request $request, EntityManagerInterface $entityManager) : Response
{
if ($clients->isDeleted()) {
return new Response("Konto usunięte!", Response::HTTP_BAD_REQUEST);
}
if ($request->getPayload()->get("toDelete") &&
$this->isCsrfTokenValid('delete-item',$request->getPayload()->get("token"))) {
$this->denyAccessUnlessGranted('clientDelete');
$entityManager->getRepository(Clients::class)->deleteUser($clients);
return $this->redirect($request->getPayload()->get("backUrl"));
}
$schedules = $entityManager->getRepository(Schedule::class)->findOneBy(["client" => $clients->getId()]);
$reports = $entityManager->getRepository(Reports::class)->findBy(["client" => $clients->getId()],["number"=>"DESC"]);
$notes = $entityManager->getRepository(Notes::class)->findOneBy(["clientId" => $clients->getId()]);
return $this->render('customers/show.html.twig', [
'client' => $clients,
'schedules' => $schedules,
'reports' => $reports,
'notes' => $notes,
'backUrl' => $request->headers->get('referer')
]);
}
#[Route('/dodaj_klienta/{id}', name: 'app_add_client', defaults: ['id'=>0])]
#[IsGranted('clientAdd')]
public function addClient(Request $request, EntityManagerInterface $entityManager, AddReports $addReports, Clients $clients = null): Response
{
$isEdit = true;
if (!$clients) {
$clients = new Clients();
$isEdit = false;
}
$form = $this->takeForm($clients);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var Clients $newClient */
$newClient = $form->getData();
$entityManager->persist($newClient);
$entityManager->flush();
if (!$isEdit) {
$addReports->setClient($newClient);
$addReports->init();
}
if ($isEdit || $form->getClickedButton() === $form->get('submitAndRedirect')) {
return $this->redirectToRoute('app_client', ['id'=>$newClient->getId()]);
}
return $this->redirectToRoute('app_add_client');
}
return $this->render("customers/add.html.twig",[
'form' => $form->createView(),
'client' => $clients,
'isEdit' => $isEdit,
'state' => []
]);
}
#[Route('/klient/{clientId}/edit-note', name: 'app_edit_client_note')]
#[IsGranted('clientEdit')]
public function addNotes(Request $request, int $clientId, EntityManagerInterface $entityManager) : Response
{
$notes = $entityManager->getRepository(Notes::class)->findOneBy(["clientId" => $clientId]);
if (!$notes) {
$notes = new Notes();
}
$form = $this->createFormBuilder($notes)
->add('description', TextareaType::class)
->add('save', SubmitType::class)
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var Notes $newNote */
$newNote = $form->getData();
$newNote->setClientId($clientId);
$entityManager->persist($newNote);
$entityManager->flush();
return $this->redirectToRoute("app_client", ['id'=>$clientId]);
}
return $this->render('customers/add_note.html.twig', [
'form' => $form->createView()
]);
}
#[Route('/klient/{id}/is-complete', name: 'app_set_complete')]
#[IsGranted('clientEdit')]
public function setComplete(Clients $clients, Request $request, EntityManagerInterface $entityManager): Response
{
if ($request->getPayload()->get("toComplete") ||
$this->isCsrfTokenValid('set-complete-item',$request->getPayload()->get("token"))) {
$isComplete = true;
if ($clients->isComplete()) {
$isComplete = false;
}
$clients->setComplete($isComplete);
$entityManager->persist($clients);
$entityManager->flush();
}
return $this->redirectToRoute('app_client', ['id'=>$clients->getId()]);
}
private function takeForm(Clients $clients): FormInterface
{
return $this->createFormBuilder($clients)
->add('strName',TextType::class, ['label' => 'Imię i nazwisko'])
->add('intNIP', IntegerType::class, ['label' => 'NIP'])
->add('strAddress', TextType::class, ['label' => 'Adres'])
->add('strEmail',EmailType::class, ['label' => 'E-mail'])
->add('intPhone',IntegerType::class, ['label' => 'Numer telefonu','required'=>false])
->add('dateLegitimacy', DateType::class, [
'label' => 'Data prawomocności',
'widget' => 'single_text',
])
->add('dateProclamation', DateType::class, [
'label' => 'Data obwieszczenia',
'widget' => 'single_text'
])
->add('submit', SubmitType::class)
->add('submitAndRedirect', SubmitType::class, )
->getForm();
}
}
@@ -0,0 +1,92 @@
<?php
namespace App\Controller;
use App\Entity\Clients;
use App\Entity\Reports;
use App\Entity\ReportsTodo;
use App\Enum\ReportTodoEnum;
use App\Services\AddReports;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class ReportsController extends AbstractController
{
#[Route('/set-status-todo', name: 'app_set_status_todo')]
#[IsGranted('reportEdit')]
public function setStatusTodo(EntityManagerInterface $entityManager, AddReports $reportsService, Request $request): Response
{
$reportId = $request->getPayload()->get('reportId');
$token = $request->getPayload()->get("token");
if ($reportId && $this->isCsrfTokenValid('report-status', $token)) {
$report = $entityManager->getRepository(Reports::class)->find($reportId);
$reportsService->setClient($report->getClient());
$isDone = false;
foreach (ReportTodoEnum::cases() as $case) {
$todo = $entityManager->getRepository(ReportsTodo::class)->findOneBy([
"report" => $report->getId(),
"name" => $case->value
]);
if (!$todo) {
$todo = new ReportsTodo();
$todo->setReport($report);
$todo->setName($case);
}
if (isset($_POST[$case->value])){
$todo->setDeleted(false);
} else {
$todo->setDeleted(true);
}
if ($todo->getName() === ReportTodoEnum::COMPLETE && !$todo->isDeleted()) {
$isDone = true;
}
$entityManager->persist($todo);
}
$report->setDone($isDone);
$entityManager->persist($report);
$entityManager->flush();
$reportsService->tryAddNextReport();
}
return $this->redirect($request->headers->get('referer'));
}
#[Route('/add-next-report', name: 'app_add_next_report')]
#[IsGranted('reportEdit')]
public function addNextReport(Request $request, EntityManagerInterface $entityManager, AddReports $addReports): Response
{
$clientId = $request->getPayload()->get('clientId');
$token = $request->getPayload()->get("token");
if ($clientId && $this->isCsrfTokenValid('add-next-report', $token)) {
$client = $entityManager->getRepository(Clients::class)->find($clientId);
$addReports->setClient($client);
$addReports->addNextReport();
}
return $this->redirect($request->headers->get('referer'));
}
#[Route('/edit-first-report', name: 'app_edit_first_report')]
#[IsGranted('reportEdit')]
public function editFirstReport(Request $request, EntityManagerInterface $entityManager): Response
{
$clientId = $request->getPayload()->get('clientId');
$date = $request->getPayload()->get('newDate');
$token = $request->getPayload()->get("token");
if ($clientId && $this->isCsrfTokenValid('edit-first-report', $token)) {
$report = $entityManager->getRepository(Reports::class)->findBy(["client" => $clientId], ["dateStart"=>"ASC"]);
$newDateStart = new \DateTime($date);
$i=0;
foreach ($report as $item) {
$tmp = clone $newDateStart;
$tmp->modify('+'.AddReports::NEXT_REPORT_MONTH * $i.' month');
$item->setDateStart($tmp);
$entityManager->persist($item);
$i++;
}
$entityManager->flush();
}
return $this->redirectToRoute('app_client', ['id'=>$clientId]);
}
}
@@ -0,0 +1,52 @@
<?php
namespace App\Controller;
use App\Entity\Clients;
use App\Entity\Schedule;
use App\Helper\MonthHelper;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class ScheduleController extends AbstractController
{
#[Route('/schedule/{typeId}', name: 'app_schedule', defaults: ['typeId' => 1])]
public function index(EntityManagerInterface $entityManager, int $typeId = 1): Response
{
if ($typeId == 1) {
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllCurrent();
} else {
$schedulesTmp = $entityManager->getRepository(Schedule::class)->findAllOverdue();
}
return $this->render('schedule/index.html.twig', [
'typeId' => $typeId,
'schedules' => $schedulesTmp,
]);
}
#[Route('/schedule_status', name: 'app_schedule_status')]
public function setDone(EntityManagerInterface $entityManager, Request $request): Response
{
$scheduleId = $request->getPayload()->get('scheduleId');
$token = $request->getPayload()->get("token");
if ($scheduleId && $this->isCsrfTokenValid('schedule-status', $token)) {
$schedule = $entityManager->getRepository(Schedule::class)->find($scheduleId);
$isDone = true;
if ($schedule->isDone()) {
$isDone = false;
}
if ($isDone) {
$schedule->setDateDone(new \DateTime());
}
$schedule->setDone($isDone);
$entityManager->persist($schedule);
$entityManager->flush();
}
return $this->redirect($request->headers->get('referer') ?? $this->generateUrl('app_schedule'));
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class LoginController extends AbstractController
{
#[Route('/login', name: 'app_login')]
public function index(): Response
{
return $this->render('login/index.html.twig', [
'controller_name' => 'LoginController',
]);
}
}
@@ -0,0 +1,38 @@
<?php
namespace App\Controller\User;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Routing\Generator\UrlGenerator;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class SecurityController extends AbstractController
{
#[Route(path: '/login', name: 'app_login')]
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser() && $this->getParameter('kernel.environment') === 'prod') {
$url=$this->generateUrl('app_base', [], UrlGeneratorInterface::ABSOLUTE_URL);
return $this->redirect(str_replace("http","https",$url));
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('security/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
#[Route(path: '/logout', name: 'app_logout')]
public function logout(): void
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}
View File
+200
View File
@@ -0,0 +1,200 @@
<?php
namespace App\Entity;
use App\Repository\ClientsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ClientsRepository::class)]
class Clients
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $strName = null;
#[ORM\Column(type: Types::BIGINT)]
private ?int $intNIP = null;
#[ORM\Column(length: 255)]
private ?string $strAddress = null;
#[ORM\Column(length: 255)]
private ?string $strEmail = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $dateLegitimacy = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $dateProclamation = null;
/**
* @var Collection<int, Schedule>
*/
#[ORM\OneToMany(targetEntity: Schedule::class, mappedBy: 'client')]
private Collection $schedules;
#[ORM\Column(options: ["default" => "0"])]
private bool $isDeleted = false;
#[ORM\Column(options: ["default" => "0"])]
private bool $isComplete = false;
#[ORM\Column(nullable: true)]
private ?int $intPhone = null;
public function __construct()
{
$this->schedules = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getStrName(): ?string
{
return $this->strName;
}
public function setStrName(string $strName): static
{
$this->strName = $strName;
return $this;
}
public function getIntNIP(): ?int
{
return $this->intNIP;
}
public function setIntNIP(int $intNIP): static
{
$this->intNIP = $intNIP;
return $this;
}
public function getStrAddress(): ?string
{
return $this->strAddress;
}
public function setStrAddress(string $strAddress): static
{
$this->strAddress = $strAddress;
return $this;
}
public function getStrEmail(): ?string
{
return $this->strEmail;
}
public function setStrEmail(string $strEmail): static
{
$this->strEmail = $strEmail;
return $this;
}
/** Data prawomocności */
public function getDateLegitimacy(): ?\DateTimeInterface
{
return $this->dateLegitimacy;
}
/** Data prawomocności */
public function setDateLegitimacy(\DateTimeInterface $dateLegitimacy): static
{
$this->dateLegitimacy = $dateLegitimacy;
return $this;
}
/** Data obwieszczenia */
public function getDateProclamation(): ?\DateTimeInterface
{
return $this->dateProclamation;
}
/** Data obwieszczenia */
public function setDateProclamation(\DateTimeInterface $dateProclamation): static
{
$this->dateProclamation = $dateProclamation;
return $this;
}
/**
* @return Collection<int, Schedule>
*/
public function getSchedules(): Collection
{
return $this->schedules;
}
public function addSchedule(Schedule $schedule): static
{
if (!$this->schedules->contains($schedule)) {
$this->schedules->add($schedule);
$schedule->setClient($this);
}
return $this;
}
public function removeSchedule(Schedule $schedule): static
{
if ($this->schedules->removeElement($schedule)) {
// set the owning side to null (unless already changed)
if ($schedule->getClient() === $this) {
$schedule->setClient(null);
}
}
return $this;
}
public function isDeleted(): bool
{
return $this->isDeleted;
}
public function setDeleted(bool $isDeleted): static
{
$this->isDeleted = $isDeleted;
return $this;
}
public function isComplete(): ?bool
{
return $this->isComplete;
}
public function setComplete(bool $isComplete): static
{
$this->isComplete = $isComplete;
return $this;
}
public function getIntPhone(): ?int
{
return $this->intPhone;
}
public function setIntPhone(?int $intPhone): static
{
$this->intPhone = $intPhone;
return $this;
}
}
+50
View File
@@ -0,0 +1,50 @@
<?php
namespace App\Entity;
use App\Repository\NotesRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: NotesRepository::class)]
class Notes
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column]
private ?int $clientId = null;
#[ORM\Column(type: Types::TEXT)]
private ?string $description = null;
public function getId(): ?int
{
return $this->id;
}
public function getClientId(): ?int
{
return $this->clientId;
}
public function setClientId(?int $clientId): void
{
$this->clientId = $clientId;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): static
{
$this->description = $description;
return $this;
}
}
+197
View File
@@ -0,0 +1,197 @@
<?php
namespace App\Entity;
use App\Enum\ReportStatus;
use App\Enum\ReportTodoEnum;
use App\Repository\ReportsRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ReportsRepository::class)]
class Reports
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(referencedColumnName: "id", nullable: false)]
private ?Clients $client = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $dateStart = null;
/**
* @var Collection<int, ReportsTodo>
*/
#[ORM\OneToMany(targetEntity: ReportsTodo::class, mappedBy: 'report', orphanRemoval: true)]
private Collection $reportsTodos;
#[ORM\Column(options: ["default" => "0"])]
private bool $isDelete = false;
private int $numberOfReport = 0;
#[ORM\Column(options: ["default" => "0"])]
private bool $isDone = false;
#[ORM\Column]
private ?int $number = null;
public function __construct()
{
$this->reportsTodos = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getDateStart(): ?\DateTimeInterface
{
return $this->dateStart;
}
public function setDateStart(\DateTimeInterface $dateStart): static
{
$this->dateStart = $dateStart;
return $this;
}
public function getClient(): ?Clients
{
return $this->client;
}
public function setClient(?Clients $client): static
{
$this->client = $client;
return $this;
}
/**
* @return Collection<int, ReportsTodo>
*/
public function getReportsTodos(): Collection
{
return $this->reportsTodos;
}
public function addReportsTodo(ReportsTodo $reportsTodo): static
{
if (!$this->reportsTodos->contains($reportsTodo)) {
$this->reportsTodos->add($reportsTodo);
$reportsTodo->setReport($this);
}
return $this;
}
public function removeReportsTodo(ReportsTodo $reportsTodo): static
{
if ($this->reportsTodos->removeElement($reportsTodo)) {
// set the owning side to null (unless already changed)
if ($reportsTodo->getReport() === $this) {
$reportsTodo->setReport(null);
}
}
return $this;
}
public function isReportsTodo(ReportTodoEnum $enum): bool
{
$return = false;
foreach ($this->getReportsTodos() as $reportsTodo) {
if ($reportsTodo->getName() === $enum) {
$return = !$reportsTodo->isDeleted();
}
}
return $return;
}
public function countTodoReports(): int
{
$count = 0;
foreach ($this->getReportsTodos() as $reportsTodo) {
if (!$reportsTodo->isDeleted()) {
$count++;
}
}
return $count;
}
public function takeStatusTodo(): ReportStatus
{
if ($this->countTodoReports() === 0) {
return ReportStatus::INSERT;
}
$status = ReportStatus::WORKING;
foreach ($this->getReportsTodos() as $reportsTodo) {
if ($reportsTodo->isDeleted()) {
continue;
}
if ($reportsTodo->getName() === ReportTodoEnum::COMPLETE) {
$status = ReportStatus::COMPLETE;
break;
}
}
return $status;
}
public function isDelete(): ?bool
{
return $this->isDelete;
}
public function setDelete(bool $isDelete): static
{
$this->isDelete = $isDelete;
return $this;
}
public function getNumberOfReport(): int
{
return $this->numberOfReport;
}
public function setNumberOfReport(int $numberOfReport): void
{
$this->numberOfReport = $numberOfReport;
}
public function isDone(): bool
{
return $this->isDone;
}
public function setDone(bool $isDone): static
{
$this->isDone = $isDone;
return $this;
}
public function getNumber(): ?int
{
return $this->number;
}
public function setNumber(int $number): static
{
$this->number = $number;
return $this;
}
}
+69
View File
@@ -0,0 +1,69 @@
<?php
namespace App\Entity;
use App\Enum\ReportStatus;
use App\Enum\ReportTodoEnum;
use App\Repository\ReportsTodoRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ReportsTodoRepository::class)]
class ReportsTodo
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(type: Types::SMALLINT, enumType: ReportTodoEnum::class)]
private ?ReportTodoEnum $name = null;
#[ORM\ManyToOne]
#[ORM\JoinColumn(referencedColumnName: 'id', nullable: false)]
private ?Reports $report = null;
#[ORM\Column(options: ["default" => false])]
private ?bool $deleted = false;
public function getId(): ?int
{
return $this->id;
}
public function getName(): ReportTodoEnum
{
return $this->name;
}
public function setName(ReportTodoEnum $name): static
{
$this->name = $name;
return $this;
}
public function getReport(): ?Reports
{
return $this->report;
}
public function setReport(?Reports $report): static
{
$this->report = $report;
return $this;
}
public function isDeleted(): ?bool
{
return $this->deleted;
}
public function setDeleted(bool $deleted): static
{
$this->deleted = $deleted;
return $this;
}
}
+107
View File
@@ -0,0 +1,107 @@
<?php
namespace App\Entity;
use App\Enum\ScheduleStatus;
use App\Repository\ScheduleRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ScheduleRepository::class)]
class Schedule
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToOne(inversedBy: 'schedules')]
#[ORM\JoinColumn(nullable: false)]
private ?Clients $client = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $dateEnd = null;
#[ORM\Column(options: ["default" => "0"])]
private bool $isDone = false;
#[ORM\Column(type: Types::DATETIME_MUTABLE, nullable: true)]
private ?\DateTimeInterface $dateDone = null;
public function getId(): ?int
{
return $this->id;
}
public function getClient(): ?Clients
{
return $this->client;
}
public function setClient(?Clients $client): static
{
$this->client = $client;
return $this;
}
public function getDateEnd(): ?\DateTimeInterface
{
return $this->dateEnd;
}
public function setDateEnd(\DateTimeInterface $dateEnd): static
{
$this->dateEnd = $dateEnd;
return $this;
}
public function isDone(): bool
{
return $this->isDone;
}
public function setDone(bool $isDone): static
{
$this->isDone = $isDone;
return $this;
}
public function getTimeLeft(): int
{
$today = new \DateTime();
$diff = $today->diff($this->getDateEnd());
// $diff = $this->getDateEnd()->diff($today);
return $diff->format("%r%a");
}
public function getDateDone(): ?\DateTimeInterface
{
return $this->dateDone;
}
public function setDateDone(?\DateTimeInterface $dateDone): static
{
$this->dateDone = $dateDone;
return $this;
}
public function getStatus(): ScheduleStatus
{
$enum = ScheduleStatus::TODO;
if ($this->getTimeLeft() < 7){
$enum = ScheduleStatus::INCOMING;
}
if ($this->getTimeLeft() < 2){
$enum = ScheduleStatus::OVERDUE;
}
if ($this->isDone()){
$enum = ScheduleStatus::COMPLETED;
}
return $enum;
}
}
+108
View File
@@ -0,0 +1,108 @@
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[ORM\UniqueConstraint(name: 'UNIQ_IDENTIFIER_USERNAME', fields: ['username'])]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180)]
private ?string $username = null;
/**
* @var list<string> The user roles
*/
#[ORM\Column]
private array $roles = [];
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
public function getId(): ?int
{
return $this->id;
}
public function getUsername(): ?string
{
return $this->username;
}
public function setUsername(string $username): static
{
$this->username = $username;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->username;
}
/**
* @see UserInterface
*
* @return list<string>
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
/**
* @param list<string> $roles
*/
public function setRoles(array $roles): static
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials(): void
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
}
+29
View File
@@ -0,0 +1,29 @@
<?php
namespace App\Enum;
enum Months: int {
case JANUARY = 1;
case FEBRUARY = 2;
case MARCH = 3;
case APRIL = 4;
case MAY = 5;
case JUNE = 6;
case JULY = 7;
case AUGUST = 8;
case SEPTEMBER = 9;
case OCTOBER = 10;
case NOVEMBER = 11;
case DECEMBER = 12;
public static function tryFromName(string $name) : ?Months
{
$name = strtoupper($name);
foreach (self::cases() as $v) {
if ($name === $v->name) {
return $v;
}
}
return null;
}
}
+59
View File
@@ -0,0 +1,59 @@
<?php
namespace App\Enum;
enum ReportStatus: int {
case INSERT = 1;
case WORKING = 2;
case COMPLETE = 3;
public function checkboxColor() : string
{
return match ($this)
{
ReportStatus::INSERT => 'primary',
ReportStatus::WORKING => 'success',
ReportStatus::COMPLETE => 'dark',
};
}
public function backgroundColor() : string
{
return match ($this)
{
ReportStatus::INSERT => 'light',
ReportStatus::WORKING => 'warning',
ReportStatus::COMPLETE => 'success',
};
}
public function textColor() : string
{
return match ($this)
{
ReportStatus::WORKING, ReportStatus::INSERT => 'dark',
ReportStatus::COMPLETE => 'white',
};
}
public function linkColor() : string
{
return match ($this)
{
ReportStatus::WORKING, ReportStatus::INSERT => 'dark',
ReportStatus::COMPLETE => 'light',
};
}
public function takeLang() : string
{
return match ($this) {
ReportStatus::INSERT => 'Oczekujące',
ReportStatus::WORKING => 'W trakcie',
ReportStatus::COMPLETE => 'Zakończony',
};
}
public function next() : ?ReportStatus
{
return ReportStatus::tryFrom($this->value+1);
}
}
+38
View File
@@ -0,0 +1,38 @@
<?php
namespace App\Enum;
enum ReportTodoEnum: int {
case SENT_EMAIL = 1;
case MAKE_PHONE_CALL = 2;
case INVOICE_SEND = 4;
case COMPLETE = 3;
public function takeLang() : string
{
return match ($this) {
self::SENT_EMAIL => "Wysłano E-Mail",
self::MAKE_PHONE_CALL => "Wykonano połączenie",
self::COMPLETE => "Zakończono",
self::INVOICE_SEND => "Wysłano fakturę"
};
}
public function backgroundColor(): string
{
return match ($this) {
self::SENT_EMAIL,self::MAKE_PHONE_CALL,self::INVOICE_SEND => "info",
self::COMPLETE => "success",
};
}
public function takeIcon(): string
{
return match ($this) {
self::SENT_EMAIL => "envelope",
self::MAKE_PHONE_CALL => "phone",
self::COMPLETE => "check",
self::INVOICE_SEND => "file-invoice",
};
}
}
+21
View File
@@ -0,0 +1,21 @@
<?php
namespace App\Enum;
enum ScheduleStatus: int
{
case TODO = 1;
case INCOMING = 2;
case OVERDUE = 3;
case COMPLETED = 4;
public function backgroundColor(): string
{
return match ($this)
{
ScheduleStatus::TODO => 'white',
ScheduleStatus::INCOMING => 'warning',
ScheduleStatus::OVERDUE => 'danger',
ScheduleStatus::COMPLETED => 'success',
};
}
}
+26
View File
@@ -0,0 +1,26 @@
<?php
namespace App\Form;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ClientsType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('strCompanyName', "text", ['required' => true])
->add('intNIP',"integer", ['required' => true])
->add('strAddress',"text", ['required' => true])
->add('strEmail',"text", ['required' => true,'email' => true]);
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
// Configure your form options here
]);
}
}
+39
View File
@@ -0,0 +1,39 @@
<?php
namespace App\Helper;
class MonthHelper
{
public function takeMonths() : array
{
$startDate = new \DateTime("-6 months");
$return = [];
for ($i=1; $i<=12; $i++) {
$tmp = clone $startDate;
$tmp->modify("+$i month");
$return[$i] = $tmp;
}
return $return;
}
public function getCurrentMonth(int $monthId) : \DateTime
{
$months = $this->takeMonths();
if ($monthId==0) {
$currentMonth = intval(date("n"));
foreach ($months as $mId => $monthObj) {
if ($monthObj->format("m") == $currentMonth) {
$monthCurrent = $monthObj;
$monthId = $mId;
break;
}
}
} else {
$monthCurrent = $months[$monthId];
}
return $monthCurrent;
}
}
+11
View File
@@ -0,0 +1,11 @@
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}
View File
@@ -0,0 +1,73 @@
<?php
namespace App\Repository;
use App\Entity\Clients;
use App\Entity\Reports;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Clients>
*/
class ClientsRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Clients::class);
}
public function deleteUser(Clients $client): void
{
$client->setDeleted(true);
$this->getEntityManager()->persist($client);
$this->getEntityManager()->flush();
$this->getEntityManager()->getRepository(Reports::class)->deleteAllByClient($client);
}
/**
* @return Clients[] Returns an array of Clients objects
*/
// public function findAllInMonth(\DateTime $date): array
// {
// $dateStart = clone $date;
// $dateStart->modify("first day of this month");
// $dateEnd = clone $date;
// $dateEnd->modify("last day of this month");
// return $this->createQueryBuilder('r')
// ->where('r.dateStart >= :dateStart')
// ->andWhere('r.dateStart <= :dateEnd')
// ->andWhere('r.isDelete = :deleted')
// ->setParameter('dateStart', $dateStart->format('Y-m-d'))
// ->setParameter('dateEnd', $dateEnd->format('Y-m-d'))
// ->setParameter('deleted', 0)
//// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// /**
// * @return Clients[] Returns an array of Clients objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Clients
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\Notes;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Notes>
*/
class NotesRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Notes::class);
}
// /**
// * @return Notes[] Returns an array of Notes objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('n')
// ->andWhere('n.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('n.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Notes
// {
// return $this->createQueryBuilder('n')
// ->andWhere('n.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,143 @@
<?php
namespace App\Repository;
use App\Entity\Clients;
use App\Entity\Reports;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\DBAL\Exception;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Reports>
*/
class ReportsRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Reports::class);
}
public function findBy(array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
if (!isset($criteria['isDelete'])) {
$criteria['isDelete'] = 0;
}
return parent::findBy($criteria, $orderBy, $limit, $offset); // TODO: Change the autogenerated stub
}
public function findAllOverdue()
{
$dateEnd = new \DateTime();
$dateEnd->modify("last day of previous month");
$reports = $this->createQueryBuilder('r')
->where('r.isDelete = :isDelete')
->andWhere('r.dateStart < :dateEnd')
->andWhere('r.isDone = :isDone')
->setParameter('isDone', 0)
->setParameter('isDelete', 0)
->setParameter('dateEnd', $dateEnd)
->orderBy("r.number","ASC")
->getQuery()
->getResult();
// $this->countReport($reports);
return $reports;
}
/**
* @return Reports[] Returns an array of Reports objects
*/
public function findAllInMonth(\DateTime $date): array
{
$dateStart = clone $date;
$dateStart->modify("first day of this month");
$dateEnd = clone $date;
$dateEnd->modify("last day of this month");
$reports = $this->createQueryBuilder('r')
->where('r.dateStart >= :dateStart')
->andWhere('r.dateStart <= :dateEnd')
->andWhere('r.isDelete = :deleted')
->setParameter('dateStart', $dateStart->format('Y-m-d'))
->setParameter('dateEnd', $dateEnd->format('Y-m-d'))
->setParameter('deleted', 0)
->orderBy("r.number","ASC")
// ->setMaxResults(10)
->getQuery()
->getResult()
;
// $this->countReport($reports);
return $reports;
}
/**
* @throws Exception
*/
public function deleteAllByClient(Clients $client): void
{
$clientId = $client->getId();
if ($clientId) {
$db = $this->getEntityManager()->getConnection();
$statement = $db->prepare("UPDATE reports SET is_delete = 1 WHERE client_id = :clientId");
$statement->bindValue('clientId', $clientId);
$statement->executeQuery();
}
}
private function countReport(array $reports) : bool
{
$clientIds=[];
foreach ($reports as $report) {
$clientIds[] = $report->getClient()->getId();
}
if (!count($clientIds)) {
return false;
}
$findAllForClients = $this->createQueryBuilder('r')
->where('r.isDelete = :deleted')
->andWhere('r.client IN (:clients)')
->setParameter('deleted', 0)
->setParameter('clients', $clientIds)
->orderBy('r.id', 'ASC')
->getQuery()
->getResult();
$clientToReportId = [];
if (!count($findAllForClients)) {
return false;
}
foreach ($findAllForClients as $item) {
$clientToReportId[$item->getClient()->getId()][] = $item->getId();
}
foreach ($reports as $report) {
$id = $report->getId();
$clientReports = $clientToReportId[$report->getClient()->getId()];
for ($i = 0; $i < count($clientReports); $i++) {
$tmp = $clientReports[$i];
if ($tmp == $id) {
$report->setNumberOfReport($i + 1);
break;
}
}
}
return true;
}
// public function findOneBySomeField($value): ?Reports
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\ReportsTodo;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<ReportsTodo>
*/
class ReportsTodoRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ReportsTodo::class);
}
// /**
// * @return ReportsTodo[] Returns an array of ReportsTodo objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('r.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?ReportsTodo
// {
// return $this->createQueryBuilder('r')
// ->andWhere('r.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,84 @@
<?php
namespace App\Repository;
use App\Entity\Schedule;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<Schedule>
*/
class ScheduleRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, Schedule::class);
}
public function findAllOverdue()
{
$dateEnd = new \DateTime("now");
$reports = $this->createQueryBuilder('s')
->where('s.isDone = :isDone')
->andWhere('s.dateEnd < :dateEnd')
// ->andWhere('s.isDelete = :isDelete')
->setParameter('isDone', 0)
// ->setParameter('isDelete', 0)
->setParameter('dateEnd', $dateEnd)
->getQuery()
->getResult();
return $reports;
}
/**
* @return Schedule[] Returns an array of Schedule objects
*/
public function findAllCurrent(): array
{
$date = new \DateTime();
$dateStart = clone $date;
$dateStart->modify("-15 days");
$dateEnd = clone $date;
$dateEnd->modify("+30 days");
return $this->createQueryBuilder('r')
->where('r.dateEnd >= :dateStart')
->andWhere('r.dateEnd <= :dateEnd')
->andWhere('r.isDone = :isDone')
// ->andWhere('r.isDelete = :deleted')
->setParameter('dateStart', $dateStart->format('Y-m-d'))
->setParameter('dateEnd', $dateEnd->format('Y-m-d'))
->setParameter('isDone', 0)
// ->setParameter('deleted', 0)
// ->setMaxResults(10)
->orderBy('r.dateEnd', 'ASC')
->getQuery()
->getResult()
;
}
// /**
// * @return Schedule[] Returns an array of Schedule objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('s')
// ->andWhere('s.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('s.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?Schedule
// {
// return $this->createQueryBuilder('s')
// ->andWhere('s.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
@@ -0,0 +1,43 @@
<?php
namespace App\Repository;
use App\Entity\TestEntity;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<TestEntity>
*/
class TestEntityRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, TestEntity::class);
}
// /**
// * @return TestEntity[] Returns an array of TestEntity objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('t.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?TestEntity
// {
// return $this->createQueryBuilder('t')
// ->andWhere('t.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+60
View File
@@ -0,0 +1,60 @@
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* @extends ServiceEntityRepository<User>
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
// /**
// * @return User[] Returns an array of User objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('u.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?User
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}
+76
View File
@@ -0,0 +1,76 @@
<?php
namespace App\Security;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ClientsVoter extends Voter
{
const VIEW = "clientView";
const ADD = "clientAdd";
const EDIT = "clientEdit";
const DELETE = "clientDelete";
public function __construct(readonly private Security $security)
{
}
protected function supports(string $attribute, mixed $subject): bool
{
if (!in_array($attribute, [self::VIEW, self::EDIT, self::ADD, self::DELETE])) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
return match ($attribute) {
self::VIEW => $this->canView(),
self::ADD => $this->canAdd(),
self::EDIT => $this->canEdit(),
self::DELETE => $this->canDelete(),
};
}
private function canView() : bool
{
if ($this->canAdd()) {
return true;
}
return $this->security->isGranted('ROLE_CLIENT_VIEW');
}
private function canAdd() : bool
{
if ($this->canAll()){
return true;
}
return $this->security->isGranted('ROLE_CLIENT_ADD');
}
// TODO: implement
private function canEdit() : bool
{
return $this->canAdd();
}
private function canDelete() : bool
{
if ($this->canAll()){
return true;
}
return $this->security->isGranted('ROLE_CLIENT_DELETE');
}
private function canAll() : bool
{
return $this->security->isGranted('ROLE_ACCESS_ALL');
}
}
//HqmN6Egol5o_K5nY
+57
View File
@@ -0,0 +1,57 @@
<?php
namespace App\Security;
use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
class ReportsVoter extends Voter
{
const VIEW = 'reportView';
const EDIT = 'reportEdit';
public function __construct(private readonly Security $security)
{
}
protected function supports(string $attribute, mixed $subject): bool
{
if (!in_array($attribute, [self::VIEW, self::EDIT])) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, mixed $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
return match ($attribute) {
self::EDIT => $this->canEdit(),
self::VIEW => $this->canView(),
};
}
private function canEdit(): bool
{
if ($this->canAll()){
return true;
}
return $this->security->isGranted("ROLE_REPORT_EDIT");
}
private function canView(): bool
{
if ($this->canEdit()) {
return true;
}
return $this->security->isGranted("ROLE_REPORT_VIEW");
}
private function canAll() : bool
{
return $this->security->isGranted('ROLE_ACCESS_ALL');
}
}
+112
View File
@@ -0,0 +1,112 @@
<?php
namespace App\Services;
use App\Entity\Clients;
use App\Entity\Reports;
use App\Entity\Schedule;
use App\Enum\ReportTodoEnum;
use Doctrine\ORM\EntityManager;
class AddReports
{
const REPORT_COUNT_ON_INIT = 1;
const NEXT_REPORT_MONTH = 3;
const SCHEDULE_END_DAYS = 30;
protected EntityManager $manager;
protected Clients $client;
public function __construct(EntityManager $entity)
{
$this->manager = $entity;
}
/**
* @param Clients $client
*/
public function setClient(Clients $client): void
{
$this->client = $client;
}
public function init(): void
{
$newClient = $this->client;
$month = intval($newClient->getDateLegitimacy()->format('n'));
$year = $newClient->getDateLegitimacy()->format('Y');
$reportDateStart = new \DateTime("15-$month-$year");
// Add reports to do
for ($i = 1; $i <= self::REPORT_COUNT_ON_INIT; $i++) {
$monthAdd = $i * self::NEXT_REPORT_MONTH;
$reportDate = clone $reportDateStart;
$reportDate->modify("+$monthAdd months");
$report = new Reports();
$report->setClient($newClient);
$report->setDateStart($reportDate);
$report->setNumber($i);
$this->manager->persist($report);
}
// Add schedule to do
$scheduleDate = clone $newClient->getDateProclamation();
$scheduleDate->modify("+" . self::SCHEDULE_END_DAYS . " days");
$schedule = new Schedule();
$schedule->setClient($newClient);
$schedule->setDateEnd($scheduleDate);
$this->manager->persist($schedule);
// Flush
$this->manager->flush();
}
public function tryAddNextReport(): bool
{
if ($this->client->isComplete()) {
return false;
}
$reports = $this->manager->getRepository(Reports::class)->findBy(["client" => $this->client]);
$countUnDone = 0;
foreach ($reports as $report) {
if (!$report->isReportsTodo(ReportTodoEnum::COMPLETE)) {
$countUnDone++;
}
}
$numberOfReports = count($reports);
$lastReport = $reports[$numberOfReports - 1];
if ($countUnDone<self::REPORT_COUNT_ON_INIT) {
$dateNext = $lastReport->getDateStart()->modify("+".self::NEXT_REPORT_MONTH." months");
$report = new Reports();
$report->setClient($this->client);
$report->setDateStart($dateNext);
$report->setNumber($numberOfReports + 1);
$this->manager->persist($report);
$this->manager->flush();
}
return true;
}
public function addNextReport(): bool
{
$reports = $this->manager->getRepository(Reports::class)->findOneBy(["client" => $this->client], ["dateStart" => "DESC"]);
$report = new Reports();
$report->setClient($this->client);
if ($reports) {
$dateToReport = $reports->getDateStart();
$report->setNumber($reports->getNumber() + 1);
} else {
$newClient = $this->client;
$month = intval($newClient->getDateLegitimacy()->format('n'));
$year = $newClient->getDateLegitimacy()->format('Y');
$dateToReport = new \DateTime("15-$month-$year");
$report->setNumber(1);
}
$report->setDateStart($dateToReport->modify("+".self::NEXT_REPORT_MONTH." months"));
$this->manager->persist($report);
$this->manager->flush();
return true;
}
}
+25
View File
@@ -0,0 +1,25 @@
<?php
// src/Twig/AppExtension.php
namespace App\Twig;
use Twig\Extension\AbstractExtension;
use Twig\TwigFilter;
class AppExtension extends AbstractExtension
{
public function getFilters(): array
{
return [
new TwigFilter('phone', [$this, 'formatPhone']),
];
}
public function formatPhone(?int $phoneNumber): string
{
if (!$phoneNumber) {
return "Brak";
}
return number_format($phoneNumber, 0,"."," ");
}
}