Compare commits

...

9 Commits

Author SHA1 Message Date
fc9ebbd327 upd: importmap
* add moment library
2025-01-24 11:20:13 -05:00
4cddccdf6e upd: twig nav
* remove case notes nav in favor of navigating through case data
* rename Case Addresses to Addresses
2025-01-24 11:19:06 -05:00
3d786f1f16 upd: twig list-notes
* correct link for adding a new note
* remove display of present members
2025-01-24 11:16:25 -05:00
e5f09bd8cc upd: Libs
Permissions checking
* Add checkPermissions method to check the permissions of the user to the case to make sure they have permissions to add or edit.
2025-01-24 10:35:46 -05:00
77d90ed691 fix: NoteForms
* change members field to unmapped
2025-01-24 10:34:12 -05:00
0d69b51ff9 upd: CommunityResource
* Add method to convert class to Location object
2025-01-24 10:19:43 -05:00
df29fd0d99 fix: NoteController
Save members
* get note members working, still need to setup editing
2025-01-24 10:18:56 -05:00
09ae2756c2 upd: ItineraryController
* remove unnecessary use statements
2025-01-24 10:17:43 -05:00
520409b0b4 fix: CaseController
* add permission validation
2025-01-24 10:15:49 -05:00
10 changed files with 99 additions and 17 deletions

@ -88,4 +88,7 @@ return [
'tinymce' => [
'version' => '7.6.0',
],
'moment' => [
'version' => '2.30.1',
],
];

@ -8,6 +8,7 @@ use App\Entity\CompanyDocument;
use App\Entity\Location;
use App\Entity\Member;
use App\Entity\MemberCase;
use App\Entity\MemberDocument;
use App\Entity\ReferralSource;
use App\Entity\User;
use App\Entity\UserCase;
@ -23,7 +24,9 @@ use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
class CaseController extends AbstractController
@ -39,6 +42,10 @@ class CaseController extends AbstractController
#[Route('/my-cases', name: 'app_my_cases')]
public function myCases(#[CurrentUser()] User $user, Request $request): Response
{
if (!$this->isGranted('IS_AUTHENTICATED_FULLY')) {
return $this->redirectToRoute('app_login');
}
$this->navLinks['my_cases'] = NavList::PRESENT_LINK;
$this->navLinks['case_list'] = NavList::DEFAULT;
@ -58,7 +65,7 @@ class CaseController extends AbstractController
'breadcrumbs' => [
(
strpos($request->server->get('HTTP_REFERER'), 'list-cases') !== false
? new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases')
? new Breadcrumb($this->generateUrl('app_list_cases'), 'Cases')
: new Breadcrumb($this->generateUrl('app_my_cases'), 'My Cases')
),
],
@ -103,7 +110,9 @@ class CaseController extends AbstractController
$case = $this->entityManager->getRepository(MemberCase::class)->find($caseId);
/** @todo validate user has access to case, check for admin, case manager of case worker */
//$uc = $this->entityManager->getRepository(UserCase::class)
if (!Libs::checkPermissions($user, $case, $this->entityManager)) {
throw new AccessDeniedException();
}
$sources = $this->entityManager->getRepository(ReferralSource::class)->findAll();
@ -115,7 +124,7 @@ class CaseController extends AbstractController
'case' => $case,
'sources' => $sources,
'breadcrumbs' => [
new Breadcrumb($this->generateUrl('app_list_cases'), 'List Cases'),
new Breadcrumb($this->generateUrl('app_list_cases'), 'Cases'),
new Breadcrumb($this->generateUrl('app_view_case', ['caseId' => $case->getId()]), 'View Case')
],
'notifications' => Libs::getMessages($user, $this->entityManager),
@ -452,10 +461,4 @@ class CaseController extends AbstractController
)
);
}
#[Route('/sign-case-doc/{caseId}/{docId}/{memberId}', name: 'app_display_case_document')]
public function displayCaseDocument(string $caseId, string $docId, Request $request, #[CurrentUser()] User $user): Response
{
return new Response();
}
}

@ -3,8 +3,6 @@
namespace App\Controller;
use App\Entity\CaseItinerary;
use App\Entity\CaseLocation;
use App\Entity\Location;
use App\Entity\MemberCase;
use App\Entity\User;
use App\Entity\UserCase;
@ -17,7 +15,6 @@ use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\UX\Map\InfoWindow;

@ -84,7 +84,7 @@ class NoteController extends AbstractController
$referral = $this->entityManager->getRepository(Referral::class)->find($referralId);
$this->entityManager->getRepository(Referral::class)->populateNotes($referral);
$members = $this->entityManager->getRepository(Member::class)->findBy(['caseId' => $referral->getMemberCase()]);
$members = $this->entityManager->getRepository(Member::class)->findBy(['memberCase' => $referral->getMemberCase()]);
$defaultMethod = NoteMethod::BILLABLE;
$defaultLocation = NoteLocation::COMMUNITY_OUTING;
$form = $this->createForm(StandardNoteFormType::class, null, ['members' => $members]);
@ -113,6 +113,27 @@ class NoteController extends AbstractController
$this->entityManager->persist($note);
$this->entityManager->flush();
if ($form->get('members')->getData()) {
foreach ($form->get('members')->getData() as $mem) {
if ($referral->getServiceCode() == ReferralServiceType::VS_THBB) {
$nm = new VisitNoteMembers();
$nm->setVisitNote($note)
->setPerson($mem)
;
} else {
$nm = new StandardNoteMember();
$nm->setStandardNote($note)
->setPerson($mem)
;
}
$this->entityManager->persist($nm);
$this->entityManager->flush();
}
}
$this->addFlash('success', 'Note added successfully');
return $this->redirectToRoute('app_list_notes');
}
@ -127,6 +148,7 @@ class NoteController extends AbstractController
'notifications' => Libs::getMessages($user, $this->entityManager),
'referral' => $referral,
'form' => $form,
'members' => $members,
'default_method' => $defaultMethod,
'default_location' => $defaultLocation,
]

@ -683,4 +683,19 @@ class CommunityResource
{$this->getContactCard()}
EOL;
}
public function toLocation(): Location
{
$loc = new Location();
$loc->setName($this->name)
->setAddress($this->address)
->setCity($this->city)
->setState($this->state)
->setZip($this->zip)
->setLat($this->lat)
->setLon($this->lon)
;
return $loc;
}
}

@ -49,6 +49,7 @@ class StandardNoteFormType extends AbstractType
'multiple' => true,
'expanded' => true,
'choice_label' => 'name',
'mapped' => false,
])
->add('method', EnumType::class, [
'class' => NoteMethod::class,

@ -64,6 +64,7 @@ class VisitNoteFormType extends AbstractType
'multiple' => true,
'expanded' => true,
'choice_label' => 'name',
'mapped' => false,
])
->add('method', EnumType::class, [
'class' => NoteMethod::class

@ -3,8 +3,11 @@
namespace App\Libs;
use App\Entity\Location;
use App\Entity\MemberCase;
use App\Entity\Messages;
use App\Entity\Supervision;
use App\Entity\User;
use App\Entity\UserCase;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
@ -108,4 +111,41 @@ class Libs extends AbstractController
return $msgs;
}
/**
* Checks if the user has permission to access a case.
*
* @param User $user
* @param MemberCase $case
* @param EntityManagerInterface $em
*
* @return bool
*/
public static function checkPermissions(User $user, MemberCase $case, EntityManagerInterface $em): bool
{
// if user is an admin, allow the action
if (in_array('ROLE_ADMIN', $user->getRoles())) {
return true;
}
// if user is assigned to this case, allow the action
$uc = $em->getRepository(UserCase::class)->findOneBy(['user' => $user, 'memberCase' => $case]);
if ($uc) {
return true;
}
// get user of the case and check if user is a supervisor of the worker
/** @var ?UserCase $uc */
$uc = $em->getRepository(UserCase::class)->findOneBy(['memberCase' => $case]);
if ($uc) {
$sup = $em->getRepository(Supervision::class)->findOneBy(['supervisor' => $user, 'worker' => $uc->getUser()]);
if ($sup) {
return true;
}
}
// user does not have permissions to the case
return false;
}
}

@ -16,7 +16,7 @@
<h6 class="text-white text-capitalize ps-3">Referral Note List</h6>
</div>
<div>
<button type="button" class="btn btn-block btn-light mb-3" onclick="window.open('/index.php/add-note/'+document.getElementById('referralList').value, '_self')">Add Note</button>
<button type="button" class="btn btn-block btn-light mb-3" onclick="window.open('/add-note/'+document.getElementById('referralList').value, '_self')">Add Note</button>
</div>
</div>
</div>
@ -52,7 +52,6 @@
<th class="text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">DOS</th>
<th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Location</th>
<th class="text-center text-uppercase text-secondary text-xxs font-weight-bolder opacity-7">Method</th>
<th class='text-right text-uppercase text-secondary text-xxs font-weight-bolder opacity-7'>Members Present</th>
<th class="text-secondary opacity-7"></th>
</tr>
</thead>
@ -64,7 +63,6 @@
{{ n.startTime|date("g:i a", company_timezone) }}-{{ n.endTime|date("g:i a", company_timezone) }} ({{ n.calcTimeUsed() }})</td>
<td class='text-center'>{{ n.location.value }}</td>
<td class='text-center'>{{ n.method.name|lower|replace({"_": " "})|capitalize }}</td>
<td></td>
<td style='text-align: right;'>
<a href='/edit-note/{{ n.id }}' class='text-secondary' title='Edit Note'>
<i class="material-symbols-rounded opacity-5">edit</i>

@ -89,16 +89,18 @@
<span class='nav-link-text ms-1'>My Cases</span>
</a>
</li>
{#
<li class='nav-item'>
<a class='{{ case_notes }}' href='{{ path('app_list_notes') }}'>
<i class='material-symbols-rounded opacity-5'>note_add</i>
<span class='nav-link-text ms-1'>Case Notes</span>
</a>
</li>
#}
<li class='nav-item'>
<a class='{{ case_itinerary }}' href='{{ path('app_list_case_addresses') }}'>
<i class='material-symbols-rounded opacity-5'>map</i>
<span class='nav-link-text ms-1'>Case Addresses</span>
<span class='nav-link-text ms-1'>Addresses</span>
</a>
</li>
<li class='nav-item'>