\chapter{Proof of concept}\label{subsection:ProofOfConcept}
Pro zjištění funkčnosti technologií a architektury vytváříme proof of concept. Zaměřujeme se na komponenty, které zajišťují ukládání a správu účtenek a správu zboží. Ostatní komponenty jako správu obchodníků a spotřebitelů, implementujeme pouze do míry potřebné k uložení účtenek. Hlavními komponenty celého systému jsou generátor účtenek, správce zboží a správce účtenek.


\section{Generátor účtenek}

Generátor je velice specifická komponenta která se přizpůsobí účetnímu systému obchodníka. Kvůli tomu zde implementujeme ukázkovou implementaci od které se ostatní generátory účtenek odvíjejí.

Jak již bylo zmíněno, generátor účtenek má na starosti převážně transformaci účtenek do kompatibilní struktury a ověřovaní zda systém může přijmout danou transakci. Z toho nám vyplývá že jediné informace které ukládáme jsou hashe platebních karet které dokážeme zpracovat. Protože nepotřebujeme ukládat mnoho informací nebudeme vytvářet externí databázi a spolehneme se na Kafku. Při startu aplikace se načtou data z Kafka topiku ve kterém jsou události o platebních kartách do in-memory databáze (viz. EDA architektura sekce \ref{subsection:eda}). Do tohoto topiku postupně přibývají další události o platebních kartách, které se zpracovávají a tím tak zůstává generátor účtenek aktuální.

Služba obsahuje pouze dva koncové body a to ověření že karta kterou spotřebitel zaplatil je evidovaná v systému a poslaní účtenky do systému. Zde si ukážeme důležité části kódu generátoru účtenek. 

\begin{code}
\usemintedstyle{colorful}
\begin{minted}{java}
//Tato anotace rika ze se jedna o entitu v databazy
@Entity
public class PodporovaneKarty {
    //Tato anotace rekne hibernate 
    //ze se tato promena ma pouzit jako primarni klic
    @Id
    private String hashKaretnichDetailu;
}
\end{minted}
\captionof{listing}{Data potřebná k uchovávaní dat v generátoru účtenek}
\label{code:generatorUctenekData}
\end{code}

\begin{code}
\usemintedstyle{colorful}
\begin{minted}{java}
//Tato anotace řekne že se má tato třída používat ve Springu
@Service
public class UdalostiKaret {

	//Tento objekt zpracovává všechny karetní procesy
	@Autowired
	private ProcessorKaret processorKaret;

	//Zde se nastaví jaky topik se má zpracovávat
	@KafkaListener(topics = "KaretniUdalosti", 
	               groupId = "GeneratorUctenek")
	//Objekt KaretniUdalost má v sobe všechny potřebné informace 
	//k zpracovaní karetní události
	public void zpracovani(KaretniUdalost udalost){

		//Tato funkce přidá a nebo odebere hashe karty které
		//mohou být zpracovávány
		processorKaret.zpracovaniKaretniUdalosti
		    (udalost.getUdalostKarty(), udalost.getHashKarty());

	}
}

\end{minted}
\captionof{listing}{Zpracovaní karetních událostí}
\label{code:generatorUctenekKafka}
\end{code}

\begin{code}
\usemintedstyle{colorful}
\begin{minted}{java}
//Tyto anotace řeknou že se má tato třída používat ve Springu jako REST api
@RestController
@RequestMapping("/uctenka")
public class UctenkovyController {
	//Tento objekt zpracovává všechny karetní procesy
    @Autowired
    private ProcessorKaret processorKaret;
    @Autowired
    //Tento objekt zpracovává všechny uctenkove procesy
    private ProcessorUctenek processorUctenek;
    
    //Tato anotace řekne že Spring má vytvořit REST GET koncový bod
    //Celkově tento koncový bod ověří že daný hash karty se nachází v systému
    @GetMapping(value = "/{hashKarty}")
    public ResponseEntity<Void> podporaKarty(@PathVariable String hashKarty) {
        boolean podporaKarty = processorKaret.podporaKarty(hashKarty);
        if(podporaKarty){
            return new ResponseEntity<>(HttpStatus.ACCEPTED);
        }else{
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);

        }
    }
    
    //Tato anotace řekne že Spring má vytvořit REST POST koncový bod
    //Celkově tento koncový bod posle účtenku do systému. 
    //Systém tuto účtenku zpracuje a přiřadí spotřebiteli
    @PostMapping
    public ResponseEntity<Void> odeslaniUctenky(@RequestBody Uctenka uctenka) {
        processorUctenek.odelsatUctenku(uctenka);
        return new ResponseEntity<>(HttpStatus.ACCEPTED);
    }

}
\end{minted}
\captionof{listing}{API generátoru účtenek}
\label{code:generatorUctenekAPI}
\end{code}

\section{Správce účtenek}

Jedna z nejhlavnějších služeb je správce účtenek. Když se však koukneme do technické dokumentace uvidíme velice jednoduchý set operací které musí podporovat. Jediná operace která nás zde bude zajímat je uložení účtenky a ohlášení že přišla účtenka uživateli. 

Pro přehlednost jsem zde nebudeme ukazovat jak vypadá databázová struktura vypadala by vsak podstatě stejně jak byla data popsaná v tabulkách: \ref{table:dataHlavicka}, \ref{table:dataSazba}, \ref{table:dataTelo}, \ref{table:dataProdukt}. 

Účtenka se vygeneruje v generátoru účtenek ověří se a přiřadí se k ní uživatel. Účtenka která má přiraženého uživatele přijde do správce účtenek a ten ji následně uloží. Pokud dojde k úspěšnému uloženi účtenky systém pošle notifikaci o projmuté účtence.

\begin{code}
\usemintedstyle{colorful}
\begin{minted}{java}
//Tato anotace řekne že se má tato třída používat ve Springu
@Service
public class UdalostiUctenek {

	//Tento objekt zpracovává všechny účtenkové procesy
	@Autowired
	private ProcessorUctenek processorUctenek;

	//Zde se nastaví jaký topik se má zpracovávat
	@KafkaListener(topics = "PrirazenaUctenka", groupId = "spravceUctenek")
	//Objekt PrirazenaUctenka má v sobě všechny potřebné informace 
	//k uložení a odeslaní notifikace o příchozí účtence
	public void zpracovani(PrirazenaUctenka prirazenaUctenka){

		//Tato funkce uloží účtenku
		processorUctenek.ulozitUctenku(prirazenaUctenka.getUctenka(),
		                               prirazenaUctenka.getUzivatel());
		//Tato funkce oznámí všem kteří poslouchají,
		//že přišla uživatelovi účtenka
		processorUctenek
		    .oznameniOPrijetiUctenky(prirazenaUctenka.getUctenka(), 
		                             prirazenaUctenka.getUzivatel());

	}

}
\end{minted}
\captionof{listing}{Zpracovaní účtenkových událostí správce účtenek}
\label{code:spravceUctenekKafka}
\end{code}

\section{Správce zboží}

Stejně jako správce účtenek i správce zboží je relativně jednoduchá služba která má na starosti relativně málo úloh. Pro tento proof of concept vyžadujeme pouze ověření že je dané zboží uloženo a kompletní v databázi. V případě že zboží v databázi není toto zboží se založí a nastaví se jako nekompletní. Informace o nekompletním zboží se následně pošlou obchodníkovy.

Stejně jako u správce účtenek ani zde nebudeme ukazovat databázoví model, vypadal by stejně jako u tabulek: \ref{table:dataElektro}, \ref{table:dataJidlo}. Ukážeme zde pouze Kafka rozhraní pro přehled všeho co správce bude dělat.



\begin{code}
\usemintedstyle{colorful}
\begin{minted}{java}
//Tato anotace rekne ze se ma tato trida pouzivat ve Springu
@Service
public class UdalostiZbozi {

	//Tento objekt zpracovava vsechny procesy se zbozim
	@Autowired
	ProcessorZbozi processorZbozi;

	//Zde se nastavi jaky topik se ma spracovavat
	@KafkaListener(topics = "PrijateUctenky", groupId = "spravceZbozi")
	//Objekt PrijataUctenka ma v sobe vsechny potrebne informace 
	//k zpracovani prijate uctenky
	public void zpracovani(PrijataUctenka prijataUctenka){
		
	   for(Zbozi zbozi : prijataUctenka.getZbozi()){
             Optional<Zbozi> zboziPotrebneKDoplneni =
                processorZbozi.overeniUlozeniZbozi(zbozi);
                
             zboziPotrebneKDoplneni.ifPresent(
                i->processorZbozi.odeslatPozadavekODoplneniZbozi(
                   i,prijataUctenka.getObchodnik()
                )
             );
	   }
    }

}
\end{minted}
\captionof{listing}{Zpracovaní událostí správce zboží}
\label{code:spravceZboziKafka}
\end{code}
