Version 1.1 Laboration 3 - Java och databaser Laborationen fokuserar på det som behandlades i föreläsningarna 7 och 8. Inhämtade kunskaper från föregående föreläsningar och laborationer i kursen förutsätts liksom kunskaper från den nyligen avslutade kursen Databaser och datamodellering. Räkna också med, att du kan komma att behöva studera dokumentation om Java (t.ex. Javas egen dokumentation). Uppgiftsbeskrivningen är given i berättande form - ungefär som det kan vara efter att man har sammanställt sina anteckningar efter ett möte med beställaren. Företaget Köp & Sälj AB behöver ett program för att hantera kundernas köp. Du har fått uppdraget att utföra design och implementation av detta. När en kund har kommit till kassan, ska expediten mata in de köpta varorna en och en i kassaprogrammet genom att ange produktnumret och antal köpta exemplar eller volymmängd (liter, kilo ) av denna produkt. Programmet ska svara genom att visa produktens namn, styckpriset, antal köpta och vad detta kostar (brukar kallas för radbelopp eller subtotal). Dessutom visas totalsumman för köpet. Exempel: Kunden har köpt två enliterspaket med mjölk och 3,5 kilo apelsiner. Inmatningen blir 21-302 för att tala om att de är enliterspaket med mjölk. Sedan en tvåa för att tala om att det är två paket. Programmet visar sedan detta: Mjölk 1L 2 3,60 7,20 Totalt: 7,20 Sedan matas apelsinerna in: 31-23 för apelsiner och sedan 3,5 för vikten. Programmet visar: Apelsiner 3,5 14,75 51,62 Totalt: 58,83 Kommentar 1: "Mjölk 1L" är produktnamnet. Det finns även "Mjölk 2L", "Mjölk 3dl" osv. Kommentar 2: Värdena visas i exemplet åtskilda med ett mellanslag. Du får gärna använda ett annat sätt så länge som det används konsekvent. Kommentar 3: Värdena visas i exemplet som decimaltal. Du får gärna använda ett annat format så länge som det används konsekvent. Regler: Radbeloppet avrundas neråt till närmsta antalet ören. Apelsinernas radbelopp var 51,625 som då avrundades till 51,62. Beloppen ska alltid visa två siffror för beloppen, exempelvis får 7 kr 20 öre inte visas som 7,2. När kundens sista vara har registrerats, talar expediten om det för programmet. Du avgör hur. Programmet räknar ut hur mycket kunden ska betala totalt, visar detta, och begär att få veta hur mycket kunden betalade. Efter att detta har matats in tillsammans med uppgift om kunden betalade kontant eller med kort räknar programmet ut hur mycket kunden ska få tillbaka och skriver ut ett kvitto. På kvittot finns samma information om varje köpt vara, som visades, när de hade matats in (namnet, antalet, styckpriset och radbeloppet skrivet på samma rad). Totalbeloppet för köpet visas, och slutligen en rad som talar om hur mycket av totalbeloppet som är Moms. Dessutom visas ett unikt kvittonummer på en lämplig plats. Alla kvitton ska vara i nummerordning utan hack i nummerföljden - även efter att programmet har startats om.
Regler: Om kunden betalade kontant: Beloppet som kunden ska betala avrundas neråt till närmast hela antal kronor. Detta visas som totalbelopp på kvittot med en ledtext i stil med "Att betala:" eller "Totalbelopp:". Om kunden betalade med kort: Totalbeloppet avrundas ej. Kunden ska betala även örena. Momsbeloppet beräknas på det betalade totalbeloppet, som räknades ut enligt reglerna ovan. Bakgrundsinformation: En kort förklaring av momssystemet (kallas VAT i engelskspråkiga länder). Momssystemet används av staten som ett sätt att få näringsidkare att agera skatteindrivare från kunderna. Om du köper något av affären, som den egentligen vill ha 100 kronor för, ska du dessutom betala 25% av detta (25 kronor) i moms till staten. Affären tar då betalt 125 kronor av dig och skickar sedan via skattesystems momsredovisningsdel in 25 kronor av detta till staten. Antag, att affären köpte varan för 60 kronor. Eftersom moms är en skatt på värdeökningen, behöver företaget inte betala in hela momsen för de 125 kronorna (25 kr). Det får dra av den del av inköpspriset, som är moms (12 kronor av de 60, dvs leverantörsföretaget fick egentligen 48 kronor): 25-12 = 13 kronor. Dessa 13 kronor kan också räknas ut så här: 100-48 = 52 och sedan 25% av 52 = 13. Dessa 13 kr är alltså skatten för varans värdeökningen mellan dessa två led i kedjan (leverantören har motsvarande uträkning mot sin leverantör osv till den som ursprungligen sålde varan). Allt ska fortsätta att fungera efter reglerna, även efter att programmet har stängts och sedan startas om. Informationen om produkterna ska hämtas från en MySQL-databas. Om varje produkt lagras följande i databasen: Produktnumret (två siffror för produktkategorin, ett bindestreck och sedan två eller tre siffror för numret). Produktens benämning (t.ex. Apelsiner). Styckpris (örena med två siffror). Använd för databasen den datatyp som MySQL rekommenderar för pengabelopp. Regel för beloppen i Java: Beloppsvärdena måste alltid vara exakta på öret. Använd i Java en datatyp eller datatyper, som göra att denna regel kan upprätthållas. Det räcker med att du har en handfull produkter i databasen för att man ska kunna se om din lösning fungerar (5-10 stycken räcker). Data om varan hämtas från databasen efter att expediten har matat in uppgifterna om hur mycket kunden har köpt av den. I det inledande exemplet ovan sker detta efter att expediten har matat in produktnumret 21-302 och antalet 2. Efter fullbordat köp lagras uppgifter om detta i databasen i en tabell med namnet Kvitton: Ett unikt kvittonummer, datum med klockslag för köpet, totalbeloppet som betalades och momsbeloppet. Programmet ska sedan vara redo för registrering av nästa kunds inköp. Kortvariga kunderbjudanden Ett rabatterbjudande kan gälla för en så kort tid som en dag eller fram till ett visst klockslag på dagen. Det lagras inga data för sådana kortvariga kampanjpriser o.dyl. i databasen. Data om dessa rabatter läses vid programstarten i stället in från en textfil till Javas Properties-objekt och hämtas sedan däri-
från av de metoder, som behöver dem för att kunna göra sitt jobb. (Angående hanteringen av Properties: Se föreläsningsmaterialet och Javas egen dokumentation.) I denna laboration nöjer vi oss med en förenklad variant av rabattreglerna. Det finns två former av rabatt: I textfilen anges produktnumret, ett antal, hur mycket rabatt som ska ges om kunden köper minst detta antal. Rabatten är då ett visst krontal. I textfilen anges produktnumret, ett belopp, hur många procents rabatt som kunden får när köpet av denna vara uppgår till minst detta belopp. Du finner själv ett sätt för programmet att skilja mellan dessa typer av rabatter. Detta kan finnas flera produkter som samtidigt har rabatterbjudanden. Det ska också finnas ett annat program (Rabattprogrammet kan det förslagsvis kallas), där någon av butikens personal registrerar nya rabatterbjudanden, tar bort rabatterbjudanden och ändrar befintliga. Efter ändringarna sparas den nya uppsättningen rabatterbjudanden i textfilen. Nästa gång kassaprogrammet startas läses dessa ändringar in. Programmets struktur Hanteringen av programlogiken ska separeras från in- och utmatning av data: En klass som tar emot inmatade data och visar programmets svar. Det går också bra att göra detta som två klasser. En klass som sköter läsning från databasen och skrivning till den. En eller flera klasser som är inblandade i affärslogiken, dvs gör uträkningar mm. Dessutom: Objekten kommunicerar med varandra medelst anrop till metoder och att skicka data/objekt med som parametrar i anropen. Vid behov returnerar metoden data/objekt till den som anropade. Någon annan form av överföring av värden eller objekt mellan olika objekt är inte tillåten. Metoder som endast används internt i en klass ska vara privata. För att kunna hålla reda på allt under transaktionen med en kund behövs någon form av lista/array (troligen mer än en). För vissa data/objekt gäller det bara att stoppa in dem i en lista och sedan plocka fram dem genom att loopa genom hela listan. I andra fall ska man hitta ett visst av listans objekt, t.ex. en viss produkt när produktnumret är känt. Tänk på att olika slags Collection-klasser är gjorda för olika ändamål så att du gör dig själv en tjänst genom att välja en typ som passar ändamålet. Genom ditt val visar du också hur pass väl du har förstått den delen av kursinnehållet. Du väljer själv om du som användargränssnitt vill använda Swing, BufferedReader, Scanner eller något annat. Använd det dock genomgående.
Individuell uppgift för betyget VG: Nedanstående skillnader och tillägg gäller för betyget VG. Programmet ska kunna hantera att olika varukategorier har olika momssatser (differentierad moms). För närvarande används tre momssatser i Sverige: Allmän moms: 25%. Livsmedel och övernattningar: 12%. Dagstidningar, resor, kultur och konst: 6% Databasen måste även innehålla uppgifter om dessa momssatser så att programmet använder rätt momssats för varje produkt. En tabell med dessa momskategorier lagras i databasen. För varje produkt anges vilken av dem, som den tillhör (det finns en ur databasteoretisk synvinkel bättre lösning, men den skulle här bara tillföra mer Javakod att skriva och åtminstone ännu en tabell i databasen). Om en momssats ändras, behöver man bara ändra ett enda värde i databasen. Uppgifterna om samtliga produkter inklusive momssatserna hämtas från databasen till programmet direkt när programmet startas. Detta är det enda tillfälle då läsningen görs från databasen för att få uppgifter om produkternas namn, pris och momssatser. När expediten matar in kundens köpta varor, hämtas namn och pris från de inlästa värdena. Ett förslag till hur detta skulle kunna hanteras: Varje produkt blir ett objekt av en produktklass (den kan heta Produkt, Vara eller något i den stilen). För att kunna hitta bland dem behöver de samlas i ett Colllection-objekt av en typ, som du finner lämpligt för ändamålet. I anropet till detta Collection-objekt skickas produktnumret med. Collection-objektet letar upp rätt produktobjekt. Du kan sedan välja mellan dessa två fortsättningar: o Collection-objektet returnerar det hittade produktobjekt till den som anropade. Sedan hämtas produkten namn och pris ur det returnerade produktobjektet, o Collection-objektet hämtar ut produktnamnet och priset och returnerar dem till den som anropade. Kommentar: Det som vid första anblicken ser lättast ut kanske inte är det, när man har gått hela vägen i programmeringen för användningen av produktdata. Det hör till uppgiften att du hanterar i alla fall en av vägarna och på så vis får förstahandserfarenhet av för- och nackdelarna med den. Efter fullbordat köp lagras uppgifter om detta i databasen: Varje köpt produkt: produktnummer, styckpris, antal, radbelopp. Ett unikt kvittonummer, datum med klockslag för köpet, totalbeloppet, momsbeloppet. Detta kan lagras i en eller två tabeller. Om du kan din databasteori och ser till att undvika redundans, blir det två tabeller (kanske rent av tre, men det är onödigt för denna uppgift). Annars får det räcka med en tabell (full med redundans). Ändringen av rabatterbjudandena ska göras i kassaprogrammet, dvs inget separat program som i fallet med G-uppgiften. De ska som i G-uppgiften sparas i textfilen. De ska till skillnad från G-uppgiften gälla och användas direkt, när nästa kunds inköp registreras, dvs programmet ska inte behöva startas om för att de ska kunna användas. Man kan tänka sig olika sätt att göra detta. Kommentar: Vid den första genomläsningen kanske du tycker, att det handlar om att skrota mycket av det som du har gjort tillsammans med din gruppkamrat i G-uppgiften. Det är inte fallet. Vissa metodanrop kan behöva bytas ut mot anrop till en annan metod (kanske i en ny klass). Nya klasser, metoder och attribut tillkommer. Nya bearbetnings- och uträkningsregler tillkommer. Vissa av dem kan ersätta de som finns i G-uppgiften. Med en vettig uppdelning i klasser och metoder i G-uppgiften blir det knappt något i den lösningen som behöver skrotas.
Redovisning. Följande ska lämnas in via epost till ivan.nilsson@liu.se: En fil med ett skript som skapar MySQL-databasen med tabellinnehåll. MySQL Workbench har en exportfunktion i "Server Administration" som skapar ett sådant skript. Projektmappen från Netbeans innehållande Javaklasserna och Properties-textfilen (som kodexemplen till Föreläsningarna 7 och 8). Ett dokument med algoritmen för programmet. Programmet ska givetvis utföra det som visas i algoritmen. Senast inlämningsdag: Sista dagen på kursen.