Inschrijf/reserveringensysteem met specifieke functies

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Durk Houtsma

durk Houtsma

19/11/2023 18:34:52
Quote Anchor link
Goedenavond,

Voor mijn kanovereniging waar ik lid ben, zitten wij te kijken naar het upgraden van de website voor de Biesbosch Kano Experience.
Tot op heden moest men een formulier invullen, die bij de secretaris uit kwam. Die moest dit doorsturen naar de werkgroep Biesbosch Kano Experience. De betalingen kwamen bij de penningmeester, die dit weer met de werkgroep moest communiceren. De bedragen moesten handmatig berekend worden door degene die boekt, en dit handmatig overmaken.

Om één en ander te optimaliseren had ik het voorstel gezet om de opties te bekijken voor een upgrade aan de website.
Dit zou dan een reserveringsformulier moeten worden met de volgende specifieke functies:
- Selecteren welke dagen (volledig weekend 3 dagen, alleen de za en zo, alleen op za of alleen op zo etc).
Hierbij heeft elk item een vaste prijs.
- Selecteren of je gebruik maakt van de camping voor 2 nachten of voor 1 nacht.
Eveneens een vaste prijs per item.
- Aantal personen, die op basis van bovenstaande vermenigvuldigd met aantal personen een prijs betalen.
Als je voor meerdere tegelijk boekt, kan je niet per persoon een aparte keuze uit de dagen/camping invullen.
- Lid van welke kanovereniging (tekstvak, leeg laten indien geen lid)

- Een meerkeuze selectievakken uit de aangeboden tochten
- Een meerkeuze selectie uit workshops
Bovenstaande zit bij de prijs inbegrepen qua dagtochten en workshops, maar dienen wel gereserveerd te worden.

- Deelname aan de barbecue ja/nee.

Na invullen van alle gegevens en de totale prijs berekend is het aanbieden van betalen per iDeal.
Na succesvolle betaling wordt dit geregistreerd in de backend of per mail naar een ingesteld emailadres dat er betaald is. Een volledige backend is dus niet nodig, maar bijvoorbeeld dat dit gemaild wordt dat de betaling geslaagd is met alle ingevulde gegevens, zou ook prima werken.

Voorbeeld:
Boeker vult in dat hij het volledig weekend aanwezig is (€25), gebruik maakt van beide nachten camping (€15) en met 2 personen komt. Ook maakt hij gebruik ban de BBQ. Totaalprijs is dan 25+15+10=50, maar met 2 personen €100.

Het zou helemaal top zijn als je ook een soort van "voorraad" kan aangeven. Bijvoorbeeld dat er plek is voor 50 man, en dat je na 50 personen die gereserveerd hebben, niet meer online kan reserveren.

Is er iemand die een idee heeft of er al iets vergelijkbaars ergens te verkrijgen is, en mij de goede weg op kan helpen hierheen? Of hoe ik dit zelf het beste kan maken? Heb zelf wel eea aan ervaring met dingen bouwen, maar met de keuzes en bedragen wordt het toch wat ingewikkelder.

Online had ik al gezocht, en kom dan eigenlijk uit op een soort van webshop, maar ik heb het idee dat dat eenvoudiger moet kunnen.
Onze vereniging is niet uit op winst, en het is enkel om het voor de werkgroep voor aankomend jaar eenvoudiger te maken.

Alvast bedankt voor enige hulp!
Gewijzigd op 19/11/2023 19:18:15 door Durk Houtsma
 
PHP hulp

PHP hulp

12/10/2024 15:14:30
 

20/11/2023 08:27:38
Quote Anchor link
Gezien dat je de vraag hier stelt, neem ik aan dat je zelf niet over de kennis en/of tijd beschikt om dit te bouwen.
Een complete back-end is niet nodig, en ook financiëel niet aantrekkelijk, zeker niet voor een club zonder winstoogmerk.

Blijft over dat je een ZZP-er aantrekt die het er wel bij wil klussen. De grote moeilijkheid is om er eentje te vinden die kwalitatief werk levert en die je voor langere tijd aan de vereniging kunt binden. Bijvoorbeeld een lid van de vereniging of iemand uit je kennisenkring. Wel met referenties, zodat je weet dat iemand het ook echt aan kan. Kostenplaatje schat ik op 500 tot 1000 euro.

Aan de andere kant is wat je vraagt ook weer niet heel bijzonder, je zou het met wat inspanning en hulp van hier ook zelf kunnen bouwen. Het grootste probleem is het veilig kunnen inloggen op de website, omdat je niet wilt dat iedereen er bij kan. Als die horde is genomen is het formulier niet zo moeilijk meer.
 
Durk Houtsma

durk Houtsma

20/11/2023 10:47:44
Quote Anchor link
Bedankt voor de reactie.

Iemand inhuren voor het genoemde bedrag is geen budget voor.
Zelf heb ik wel ervaring met websites bouwen, en heb nu ook 2 websites live. 1 daarvan is met een complete zelfgebouwde backend en frontend met PHP en SQL.

Qua wensen kom ik zelf al een heel eind met de formulieren. Echter het deel met de kosten berekenen en optellen etc wordt voor mij een stap verder. Waarschijnlijk kan dit eenvoudiger dan ik verwacht.
Als ik in de goede richting gestuurd wordt, zal ik er op internet eea over inlezen en met zelf proberen een heel eind komen.
Zo heb ik de website containerchauffeurs.nl ook gebouwd, en steeds verder bezig met alles optimaliseren. Zo kan ik gelijk mijn kennis uitbreiden en op peil houden. Zo heb ik dit weekend de website geüpgraded naar php 8.1, en daarin is bijvoorbeeld strftime functie niet meer ondersteund. En zo blijf ik bezig.
 

20/11/2023 15:15:09
Quote Anchor link
Ja met PHP blijf je aan de gang, al was het maar omdat je minstens elke 3 jaar moet upgraden naar iets veiligers, waarbij je elke keer bestaande code moet aanpassen.

En iemand inhuren voor zo'n klus is ook wel een beetje zonde van het geld, het meeste gaat toch op aan belastingen. Het liefst doe je dat met gesloten beurs. Maar als je het zelf wilt doen kan dat ook.

Eigenlijk hoef je geen inlogsysteem voor het invullen van het formulier, wel zou je dan moeten verifieren dat het formulier echt door een mens wordt ingevuld. Gebruik hiervoor geen Google-rommel (AVG!) maar iets anders, of maak zelf een simpele captcha of andere challenge.

Blijft over het formulier, hiervoor is het gebruikelijk om een paar database tabellen aan te maken met wat queries.
Voorstel voor een layout (in pseudo SQL):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
tabel: tocht
kolom: id - bigint not null auto_increment "ID"
kolom: naam - text not null "Naam"

tabel: workshop
kolom: id - bigint not null auto_increment "ID"
kolom: naam - text not null "Naam"

tabel: reservering
kolom: id - bigint not null auto_increment "ID"
kolom: ts - timestamp not null default current_timestamp "Ingestuurd"
kolom: naam - text not null "Naam"
kolom: contact - text not null "Contactgegevens etc."
kolom: van - date not null "Van"
kolom: tot - date not null "Tot" (niet tot en met)
kolom: personen - bigint not null default 1 "Aantal personen"
kolom: vereniging - text not null default '' "Vereniging"
kolom: bbq - bool not null default false "Barbeque deelname"
check constraint: van < tot
check constraint: personen > 1 and personen < [maximum aantal personen per reservering]
check constraint: van > (current_date + '[aantal dagen van te voren reserveren] DAY'::interval)

tabel: reserveringtocht
kolom: reservering_id bigint not null
kolom: tocht_id bigint not null
foreign key constraint: reservering_id references reservering.id
foreign key constraint: tocht_id references tocht.id

tabel reserveringworkshop
kolom: reservering_id bigint not null
kolom: workshop_id bigint not null
foreign key constraint: reservering_id references reservering.id
foreign key constraint: workshopid references workshop.id

De meerkeuze opties sla je op in koppeltabellen. Is de combinatie aanwezig, dan is de optie (tocht of reservering) aangevinkt. En als een optie is uitgevinkt dan moet de combinatie verwijderd uit de koppeltabel.

De berekening kan je met een enkele SQL-query doen, het liefst met commentaar (in SQL) wat je aan het berekenen bent. Als jij of iemand anders over 4 jaar de prijzen moet bijstellen dan kan je makkelijk terugvinden waar je dat precies moet doen.

Toevoeging op 20/11/2023 15:20:26:

Ow en meerkeuzevelden maak je door meerdere checkboxes onder elkaar te zetten van <input type="checkbox">, met een andere naam per optie, dus:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
<label for="tocht_1">Ene tocht</label><input type="checkbox" id="tocht_1" name="tocht[1]"/>
<label for="tocht_2">Andere tocht</label><input type="checkbox" id="tocht_2" name="tocht[2]"/>

Je kunt dan in PHP in de variabele $_POST[tocht] de opties uitlezen als een hashmap (= associatieve array).

Toevoeging op 20/11/2023 15:35:25:

Je kunt aan de HTML invoervelden nog een onchange event hangen en met JavaScript controleren of alles wel goed is ingevuld, voordat iemand de reservering instuurt. Voorbeeld:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
<input type="date" onchange="
if ((new Date(this.value)).getDay() % 6 == 0) { alert('Weekeinde'); }
else { alert('Doordeweeks'); }
"/>
 
Ivo P

Ivo P

20/11/2023 17:40:59
Quote Anchor link
Het kan geen kwaad om de ID's als bigint op te slaan, maar de kans dat TS aan een int (bereik van -2147483648 tot +2147483648, of het dubbele als je alleen positieve getallen op wilt slaan), acht ik klein.

Dat geldt nog meer voor het aantal personen. Waarschijnlijk komt geen enkele groep met meer dan 1 miljard man.

Net als dat ik TEXT als kolomtype voor een naam wat groot vind. VARCHAR 100 is waarschijnlijk wel groot genoeg.
En dan ga ik even uit van MySQL als database type.

En om onverwachte aanpassingen van de kolom Ingestuurd te vermijden, raad ik DATETIME aan. Timestamp wil nog wel eens "vanzelf" aanpassen als je toevallig een status aanpast, of bijvoorbeeld het aantal personen verandert.
 
Durk Houtsma

durk Houtsma

20/11/2023 20:23:31
Quote Anchor link
Bedankt voor de antwoorden.
Qua ID zal ik er een INT van maken, zo heb ik dat altijd al gedaan.
De input van een aantal gegevens zal ook gevalideerd moeten worden, zoals het mailadres. Dat zal ik via HTML/Javascript doen.
De input naar SQL had ik nog niet aan de koppeltabellen gedacht, maar dat klinkt logisch.
De tabel Workshop en Reserveringen zal ik dan echter nog uitbreiden met een datum/tijd notatie dat de tour plaats gaat vinden. Misschien niet gelijk nodig, maar misschien bij verdere stappen in de website wel handig.
Het lijkt mij het eenvoudigst aanstaande week het formulier op te gaan bouwen en een totaalbedrag gaan tonen, en als het formulier naar behoren werkt de financiële hoek erbij toe te voegen qua afrekenen etc.

Bedankt om mij in de goede richting te wijzen, ik denk dat ik er een eind mee kan komen.
 

20/11/2023 23:03:39
Quote Anchor link
Mijn bias is PostgreSQL, die maakt geen onderscheid tussen wel of niet signed integers. Gebruik wat je uitkomt, maar ga er niet van uit dat het met een paar duizend reserveringen ook maar iets wezenlijks uitmaakt in performance of opslagruimte vandaag de dag.

Ook is er geen wezenlijk verschil tussen een TEXT-veld met een constraint van een maximum aantal karakters, of een varchar veld met een maximum aantal karakters. Let wel dat in PostgreSQL het maximum staat voor het aantal karakters, en in MySQL (inferieur vergeleken met PostgreSQL) het maximum staat voor het aantal bytes. Dan moet je zelf gaan nadenken over opslagruimte van multibyte character encodings. Moet je maar willen.

@Ivo P, datetime adviseren boven timestamp is pure onzin, omdat een timestamp hetzelfde is als een datetime. Wat je bedoelt is dat je bij die kolom "ts" geen default waarde CURRENT_TIMESTAMP wilt, omdat je dan juist wel onbedoeld automatisch de originele tijdstempel kunt overschrijven.

PostgreSQL kent geen datetime. Er is alleen date, time en timestamp. Het verschil tussen datetime en timezone is in MySQL zo onduidelijk dat iedereen daar vragen over heeft, getuige deze draad op Stack Overflow:
https://stackoverflow.com/questions/409286/should-i-use-the-datetime-or-timestamp-data-type-in-mysql
Volgens mij is het enige verschil in MySQL / MariaDB dat timestamp een tijdzone (UTC) heeft, en altijd geldige data bevat en geen rommel als niet bestaande datums die je kunt configureren met de NO_ZERO_DATE optie.

Toevoeging op 20/11/2023 23:10:55:

@durk Ja ik denk dat het je prima gaat lukken. De eerste stap is de gegevens opslaan in de database.
Bij nader inzien, als je het rekensommetje wil tonen tijdens het invullen van het formulier kan je het client side doen met JavaScript, of server side via PHP en eventueel SQL.

Met JavaScript heb je nog niet het definitieve bedrag in de database, je zult het uiteindelijk moeten uitrekenen op de server omdat de gebruiker altijd nog zelf JavaScript code kan wijzigen. Een voordeel om het ook in JavaScript uit te rekenen is dat je bij elke aanpassing meteen kan laten zien wat het effect is op de prijs.

Een betere, alternatieve manier is om bij elke wijziging in het formulier met een JavaScript change event (onchange attribuut of nog beter, via addEventListener) via een XmlHttpRequest of Fetch verzoek het bedrag op de server te laten uitrekenen en te laten zien op de pagina. Dan hoef je maar op 1 manier op 1 plek de berekening te doen.
 
Jan R

Jan R

21/11/2023 08:48:44
Quote Anchor link
Durk Houtsma op 20/11/2023 20:23:31:
De input van een aantal gegevens zal ook gevalideerd moeten worden, zoals het mailadres. Dat zal ik via HTML/Javascript doen.


Niet doen!. Javascript is een 1° controle. Spammers en andere idioten omzeilen dit. Doe in beide plaatsen een controle. zowel clientside(javascript) als serverside (php)
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
filter_var($_POST['name'], FILTER_VALIDATE_EMAIL)
is alles wat je nodig hebt hiervoor. Wel de juiste post variabele natuurlijk.
 
Ivo P

Ivo P

21/11/2023 08:49:11
Quote Anchor link
Ad Fundum op 20/11/2023 23:03:39:
@Ivo P, datetime adviseren boven timestamp is pure onzin, omdat een timestamp hetzelfde is als een datetime. Wat je bedoelt is dat je bij die kolom "ts" geen default waarde CURRENT_TIMESTAMP wilt, omdat je dan juist wel onbedoeld automatisch de originele tijdstempel kunt overschrijven.


Dit automatisch update-gedrag van een timestamp kolom hangt niet alleen af van hoe de tabel gedefineerd is. in my.cnf kan ook aangegeven zijn of dit gedrag wel of niet gewenst is.
Vul je bij je kolomdefinitie niet expliciet in wat jij wilt, dan wordt het gedrag afhankelijk van hoe dat in de config van je server staat.

Daarnaast is dit gedrag ook nog weer verschillende voor de eerste en de volgende timestamp kolommen in je tabel.
Waarbij ik denk dat "eerste" dan nog aangepast kan worden door de kolommen te herschikken.

Al met al vind ik dergelijk gedrag een mogelijke bron van fouten, en ga ik liever voor een oplossing waarbij deze zaken in een query of in triggers geregeld worden.


Toevoeging op 21/11/2023 08:51:40:

Jan R op 21/11/2023 08:48:44:
filter_var($_POST['name'], FILTER_VALIDATE_EMAIL) is alles wat je nodig hebt hiervoor. Wel de juiste post variabele natuurlijk.


of
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
<?php $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); ?>


Wat je een extra check of de betreffende waarde wel gepost is, scheelt (dus of isset($_POST['email'])
 

21/11/2023 18:59:23
Quote Anchor link
Ivo P op 21/11/2023 08:49:11:
Dit automatisch update-gedrag van een timestamp kolom hangt niet alleen af van hoe de tabel gedefineerd is. in my.cnf kan ook aangegeven zijn of dit gedrag wel of niet gewenst is.

We zijn het er beiden mee eens dat we geen auto updates willen. Maar ik heb nog nooit meegemaakt dat MySQL een timestamp kolom uit zichzelf bijwerkt zonder een default value of iets anders.
Waarmee kan je dat aanpassen in de my.cnf?
 
Ivo P

Ivo P

21/11/2023 22:33:13
 

02/12/2023 11:55:07
Quote Anchor link
Dank voor het linkje, het bewijst in mijn ogen weer de fantastische functionaliteit weer van MySQL. Je data wordt ook nog eens op deze manier gecorrumpeerd zonder dat je er erg in hebt, tegen alle redelijke verwachtingen in.

En dat heb ik in totaal meer dan 15 jaar MySQL gebruikt in combinatie met PHP, mogelijk ben ik hier ook wel eens tegenaan gelopen zonder te weten hoe het precies gezeten heeft. Het sterkt me in het idee dat je gewoon over wilt naar PostgreSQL, omdat het zoveel meer kan en tegelijkertijd zoveel makkelijker is in gebruik.
En grotere klanten hebben naast Oracle gewoon PostgreSQL. Wanneer ik zou zeggen dat ik MySQL gebruik word ik uitgelachen.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.