wiki:AdvancedApplicationDevelopment

Version 3 (modified by 211012, 2 weeks ago) ( diff )

--

Напреден апликативен развој

Во последната верзија апликацијата имплементирани се следните сценарија (сите од прототипот и дополнителни):

ID UseCase
1 Прегледува избирачки список
2 Ажурира избирачки список
3 Прегледува изборни единици
4 Ажурира изборни единици
5 Прегледува гласачки места
6 Aжурира гласачки места
7 Креира инстанца од избори
8 Пријавува учество на партија и кандидати
9 Назначува членови на комисија
10 Гласа онлајн
11 Доделува идентификациски код за гласање со физичко присуство
12 Гласа со физичко присуство
13 Прегледува вкупна излезност
14 Прегледува статистики од излезност по критериуми
15 Прегледува вкунпи резултати од избори со кандидат
16 Прегледува вкунпи резултати од избори со кандидатски листи
16 Прегледува статистики од резултати од избори по критериуми
17 Поднесува приговор
18 Одлучува по приговорот
19 Пријавува учество на кандидатски листи

Назначува членови на комисија

Администраторот пристапува на адреса /admin/committee каде му се отвора страница на која се прикажани сите комисии и формулар за внесување податоци за нова комисија. За ова е одговорен следниот контролер:

    @GetMapping("admin/committee")
    public String showCommittee(Model m) {
        m.addAttribute("realizations", electionRealizationService.findAll());
        m.addAttribute("committeeMembers", committeeMemberService.findAll());
        m.addAttribute("pollingStations", addressService.findAllPollingStations());
        m.addAttribute("committees", committeeService.findAll());
        m.addAttribute("committeeForm", new Committee());
        m.addAttribute("replaceTemplate", "add_comitee");
        return "admin";
    }

По внесување на податоците и клик на копчето „Запиши“ се праќа POST барање до контролерот кој ги обработува.

    @PostMapping("/admin/committee")
    public String addCommittee(
            @RequestParam(required = false) Long id,
            @RequestParam Long electionRealization,
            @RequestParam Long pollingStation,
            @RequestParam List<Long> membersId
    ) {
        committeeService.update(id, pollingStation, electionRealization, membersId);
        return "redirect:/admin/committee";
    }

Контролерот повикува функција од committeeService за додавање и ажурирање на комисии каде се креира нова инстанца од објектот Committee, и за истиот се полнат добиентите податоци од формуларот. Дополнително, се додаваат и членовите на комисијата кои се во many-to-many релација со комисијата. Оттаму се повикува функцијата save од committeeRepository кој наследува од JpaRepository. Таа служи за зачувување на новиот објект во базата. За да се обезбеди интегритет и конзистентност на податоците, методот е анотиран со @Transactional, односно функцијата успешно ќе заврши ако и само ако успешно се запишат и комисијата и членовите.

    @Transactional
    @Override
    public Committee update(Long id, Long pollingStationId, Long electionRealizationId, List<Long> membersId) {
        Committee committee;
        if (id != null){
            committee = findById(id);
        } else {
            committee = new Committee();
        }

        committee.setPollingStation(addressService.findPollingStationById(pollingStationId));
        committee.setElectionRealization(electionRealizationService.    findById(electionRealizationId));
        committeeRepository.save(committee);
        membersId.forEach(memberId -> addMemberToCommittee(committee.getId(), memberId));
        return committeeRepository.save(committee);
    }

Истава имплементација, преточена во SQL прашалникот кој се извршува позадински би изгледала вака:

DO $$
    DECLARE
        new_kom_id BIGINT;
    BEGIN
        INSERT INTO komisii (im_id, ri_id) VALUES (1, 1)
        RETURNING kom_id INTO new_kom_id;
    
        INSERT INTO se_clenovi_na (g_id, kom_id) VALUES (20, new_kom_id);
        INSERT INTO se_clenovi_na (g_id, kom_id) VALUES (21, new_kom_id);
        INSERT INTO se_clenovi_na (g_id, kom_id) VALUES (22, new_kom_id);
        INSERT INTO se_clenovi_na (g_id, kom_id) VALUES (23, new_kom_id);
        INSERT INTO se_clenovi_na (g_id, kom_id) VALUES (24, new_kom_id);
    
        COMMIT;
    END $$;

Доделува идентификациски код за гласање со физичко присуство

Корисниците со улога членови на комисија, можат да се најават на системот и пристапат на адресата /admin/electionRealizationInterface, при што добиваат преглед на избирачкиот список од реализацијата којашто се одржува на деновите на најава, за гласачкото место во кое се одговорни. Дополнително, на крајот на редот достапна е акцијата „Гласај“ со што можат да генерираат идентификациски код за гласање доколку гласачот сака да го оствари правото на глас со физичко присуство. Контролерот кој ја опслужува оваа акција е следен:

    @GetMapping("/admin/electionRealizationInterface")
    public String showElectionRealization(Model m, Principal p, Authentication authentication) {
        UserProfile userProfile = (UserProfile) authentication.getPrincipal();
        m.addAttribute("realization", committeeService.findElectionRealizationByCitizen(userProfile.getCitizen().getId()));
        m.addAttribute("citizens", committeeService.getCitizens(userProfile.getCitizen().getId()));
        m.addAttribute("replaceTemplate","election_realization_interface");
        return "index";
    }

За да се избегнат било какви манипулации и приказ на информации кои не треба да се достапни за најавениот корисник, неговиот идентитет се утврдува директно на серверска страна, од најавениот корисник. Дополнително во сервисите се процесираат реализацијата и избирачкиот список кој треба да го гледа корисникот.

    @Override
    public List<Citizen> getCitizens(Long committeeId) {
        CommitteeMember committeeMember = committeeMemberRepository.findById(committeeId).orElseThrow(RuntimeException::new);
        Committee committee = committeeRepository.findCommitteeByMembersContainsAndElectionRealization_DateIsAfter(committeeMember, LocalDate.now().minusDays(1));
        PollingStation pollingStation = committee.getPollingStation();
        return citizenRepository.findAllByAddress_PollingStation(pollingStation.getId()).stream().filter(x -> x instanceof Citizen).toList();
    }

Во committeeService-от се пронаѓа членот на комисија кој го претставува корисничкиот профил, комисијата во која е член, како и избирачкиот список за гласачкото местоо за кое е одговорна. Во програмската имплементација, ова се прави со повик на соодветни методи од Spring Data JPA, а во SQL би изгледало вака:

    select *
    from komisii k
    join se_clenovi_na ck on k.kom_id = ck.kom_id
    join realizacii_na_izbori ri on ri.ri_id = k.ri_id
    where ck.g_id = 1 and ri.ri_id = 1 and ri.ri_datum = CURRENT_DATE
    limit 1

Attachments (9)

Download all attachments as: .zip

Note: See TracWiki for help on using the wiki.