mostly working ticket selection for non-seatplan

This commit is contained in:
2023-08-07 17:35:20 +02:00
parent ed38edd880
commit 9b7eb913ae
5 changed files with 68 additions and 46 deletions

View File

@@ -20,6 +20,7 @@ const endpointSecret = stripConfig[ 'endpointSecret' ];
let sessionReference = {}; let sessionReference = {};
let waitingClients = {}; let waitingClients = {};
let pendingPayments = {};
let paymentOk = {}; let paymentOk = {};
// TODO: Remove all selected tickets if timestamp more than user defined amount ago // TODO: Remove all selected tickets if timestamp more than user defined amount ago
@@ -40,7 +41,6 @@ module.exports = ( app, settings ) => {
if ( dat[ 0 ] ) { if ( dat[ 0 ] ) {
db.getJSONData( 'events' ).then( events => { db.getJSONData( 'events' ).then( events => {
let data = JSON.parse( dat[ 0 ].data ); let data = JSON.parse( dat[ 0 ].data );
console.log( data );
( async () => { ( async () => {
for ( let event in data ) { for ( let event in data ) {
for ( let item in data[ event ] ) { for ( let item in data[ event ] ) {
@@ -58,6 +58,7 @@ module.exports = ( app, settings ) => {
} }
const session = await stripe.checkout.sessions.create( purchase ); const session = await stripe.checkout.sessions.create( purchase );
sessionReference[ session.id ] = { 'tok': req.session.id, 'email': req.session.username }; sessionReference[ session.id ] = { 'tok': req.session.id, 'email': req.session.username };
pendingPayments[ req.session.id ] = true;
res.send( session.url ); res.send( session.url );
} )(); } )();
} ); } );
@@ -84,19 +85,21 @@ module.exports = ( app, settings ) => {
response.write( 'data: connected\n\n' ); response.write( 'data: connected\n\n' );
waitingClients[ request.session.id ] = response; waitingClients[ request.session.id ] = response;
const ping = setInterval( () => { const ping = setInterval( () => {
const stat = TicketGenerator.getGenerationStatus( request.session.id ); if ( !pendingPayments[ request.session.id ] ) {
if ( stat === 'done' ) { const stat = TicketGenerator.getGenerationStatus( request.session.id );
clearInterval( ping ); if ( stat === 'done' ) {
setTimeout( () => { clearInterval( ping );
response.write( 'data: ready\n\n' ); setTimeout( () => {
response.write( 'data: ready\n\n' );
response.end();
delete waitingClients[ request.session.id ];
}, 2000 );
} else if ( stat === 'noTicket' ) {
clearInterval( ping );
response.write( 'data: noData\n\n' );
response.end(); response.end();
delete waitingClients[ request.session.id ]; delete waitingClients[ request.session.id ];
}, 2000 ); }
} else if ( stat === 'noTicket' ) {
clearInterval( ping );
response.write( 'data: noData\n\n' );
response.end();
delete waitingClients[ request.session.id ];
} }
}, 2000 ); }, 2000 );
} ); } );
@@ -139,26 +142,26 @@ module.exports = ( app, settings ) => {
db.getDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).then( dat => { db.getDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).then( dat => {
db.getDataSimple( 'users', 'email', sessionReference[ event.data.object.id ][ 'email' ] ).then( user => { db.getDataSimple( 'users', 'email', sessionReference[ event.data.object.id ][ 'email' ] ).then( user => {
if ( user[ 0 ] ) { if ( user[ 0 ] ) {
console.log( sessionReference[ event.data.object.id ][ 'tok' ] );
const tickets = JSON.parse( dat[ 0 ].data ); const tickets = JSON.parse( dat[ 0 ].data );
db.writeDataSimple( 'orders', 'account_id', user[ 0 ].account_id, { 'account_id': user[ 0 ].account_id, 'tickets': dat[ 0 ].data, 'order_name': sessionReference[ event.data.object.id ][ 'tok' ] } ).then( () => { db.writeDataSimple( 'orders', 'account_id', user[ 0 ].account_id, { 'account_id': user[ 0 ].account_id, 'tickets': dat[ 0 ].data, 'order_name': sessionReference[ event.data.object.id ][ 'tok' ] } ).then( () => {
console.log( sessionReference[ event.data.object.id ][ 'tok' ] );
delete pendingPayments[ sessionReference[ event.data.object.id ][ 'tok' ] ];
TicketGenerator.generateTickets( sessionReference[ event.data.object.id ] ); TicketGenerator.generateTickets( sessionReference[ event.data.object.id ] );
} ); db.getJSONData( 'booked' ).then( ret => {
db.getJSONData( 'booked' ).then( ret => { let booked = ret ?? {};
let booked = ret ?? {}; for ( let event in tickets ) {
for ( let event in tickets ) { if ( !booked[ String( event ) ] ) {
if ( !booked[ String( event ) ] ) { booked[ String( event ) ] = {};
booked[ String( event ) ] = {}; }
for ( let tik in tickets[ event ] ) {
booked[ event ][ tik ] = tickets[ event ][ tik ];
}
} }
for ( let tik in tickets[ event ] ) { db.writeJSONData( 'booked', booked );
booked[ event ][ tik ] = tickets[ event ][ tik ]; db.deleteDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).catch( error => {
} console.error( '[ STRIPE ] ERROR whilst deleting data from DB: ' + error );
} } );
db.writeJSONData( 'booked', booked ); } );
} );
db.deleteDataSimple( 'temp', 'user_id', sessionReference[ event.data.object.id ][ 'tok' ] ).catch( error => {
console.error( '[ STRIPE ] ERROR whilst deleting data from DB: ' + error );
} ); } );
} else { } else {
console.log( sessionReference[ event.data.object.id ][ 'email' ] ); console.log( sessionReference[ event.data.object.id ][ 'email' ] );

View File

@@ -35,11 +35,10 @@ class TicketGenerator {
this.runningTickets = {}; this.runningTickets = {};
} }
// TODO: Save to disk / DB in case of crash of server / reboot / whatever // TODO: continue processing once back online
// and continue processing once back online
generateTickets ( order ) { generateTickets ( order ) {
this.ticketQueue[ this.jobId ] = { 'order': order }; this.ticketQueue[ this.jobId ] = { 'order': order };
this.runningTickets[ order ] = 'processing'; this.runningTickets[ order.tok ] = 'processing';
this.jobId += 1; this.jobId += 1;
this.queueHandler(); this.queueHandler();
} }

View File

@@ -8,7 +8,6 @@
body { body {
font-family: sans-serif; font-family: sans-serif;
width: 100%; width: 100%;
height: 800px;
margin: 0; margin: 0;
display: flex; display: flex;
justify-content: center; justify-content: center;
@@ -18,7 +17,7 @@
.content { .content {
width: 80%; width: 80%;
height: 90%; height: 800px;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;

View File

@@ -16,7 +16,7 @@
</td> </td>
<td> <td>
<span class="material-symbols-outlined controls" @click="selectTicket( ticket.id, ticketOption.id )">add</span> <span class="material-symbols-outlined controls" @click="selectTicket( ticket.id, ticketOption.id )">add</span>
{{ cart[ event.name ] ? ( cart[ event.name ][ 'tickets' ][ ticket.id + '_' + ticketOption.id ] ? cart[ event.name ][ 'tickets' ][ ticket.id + '_' + ticketOption.id ][ 'count' ] : 0 ) : 0 }} {{ cart[ event.eventID ] ? ( cart[ event.eventID ][ 'tickets' ][ ticket.id + '_' + ticketOption.id ] ? cart[ event.eventID ][ 'tickets' ][ ticket.id + '_' + ticketOption.id ][ 'count' ] : 0 ) : 0 }}
<span class="material-symbols-outlined controls" @click="deselectTicket( ticket.id, ticketOption.id )">remove</span> <span class="material-symbols-outlined controls" @click="deselectTicket( ticket.id, ticketOption.id )">remove</span>
</td> </td>
</tr> </tr>
@@ -41,7 +41,7 @@ export default {
data () { data () {
return { return {
tickets: { 'ticket1': { 'name': 'Ticket 1', 'id': 'ticket1', 'category': 1, 'free': 20 }, 'ticket2': { 'name': 'Ticket 2', 'id': 'ticket2', 'category': 2, 'free': 20 } }, tickets: { 'ticket1': { 'name': 'Ticket 1', 'id': 'ticket1', 'category': 1, 'free': 20 }, 'ticket2': { 'name': 'Ticket 2', 'id': 'ticket2', 'category': 2, 'free': 20 } },
event: { 'name': 'TestEvent', 'location': 'TestLocation', 'date': 'TestDate', 'RoomName': 'TestRoom', 'currency': 'CHF', 'categories': { '1': { 'price': { '1':25, '2':35 }, 'bg': 'black', 'fg': 'white', 'name': 'Category 1' }, '2': { 'price': { '1':15, '2':20 }, 'bg': 'green', 'fg': 'white', 'name': 'Category 2' } }, 'ageGroups': { '1':{ 'id': 1, 'name':'Child', 'age':'0 - 15.99 years' }, '2':{ 'id': 2, 'name': 'Adult', 'age': null } }, 'stage': true }, event: { 'name': 'TestEvent2', 'location': 'TestLocation2', 'eventID': 'test2', 'date': '2023-07-15', 'currency': 'CHF', 'categories': { '1': { 'price': { '1':25, '2':35 }, 'bg': 'black', 'fg': 'white', 'name': 'Category 1' }, '2': { 'price': { '1':15, '2':20 }, 'bg': 'green', 'fg': 'white', 'name': 'Category 2' } }, 'ageGroups': { '1':{ 'id': 1, 'name':'Child', 'age':'0 - 15.99' }, '2':{ 'id': 2, 'name': 'Adult' } }, 'maxTickets': 2 },
cart: {}, cart: {},
} }
}, },
@@ -65,20 +65,41 @@ export default {
} else { } else {
this.cartHandling( 'select', this.tickets[ id ], option ); this.cartHandling( 'select', this.tickets[ id ], option );
} }
// TODO: make call to server to reserve ticket
}, },
cartHandling ( operation, data, option ) { cartHandling ( operation, data, option ) {
if ( operation === 'select' ) { if ( operation === 'select' ) {
if ( this.cart[ this.event.eventID ] ) { const options = {
if ( this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] ) { method: 'post',
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ][ 'count' ] += 1; body: JSON.stringify( { 'id': data.id + '_' + option, 'component': data.category, 'ticketOption': option, 'eventID': this.event.eventID, 'count': ( this.cart[ this.event.eventID ] ? ( this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] ? this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ][ 'count' ] : 0 ) : 0 ) + 1, 'category': data.category, 'name': 'Ticket ' + data.category + ' (' + this.event.ageGroups[ option ].name + ')' } ),
} else { headers: {
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] = { 'displayName': data.name + ' (' + this.event.ageGroups[ option ].name + ')', 'price': this.event.categories[ data.category ].price[ option ], 'id': data.id + '_' + option, 'count': 1 }; 'Content-Type': 'application/json',
'charset': 'utf-8'
} }
} else { };
this.cart[ this.event.eventID ] = { 'displayName': this.event.name, 'tickets': {} }; fetch( localStorage.getItem( 'url' ) + '/API/reserveTicket', options ).then( res => {
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] = { 'displayName': data.name + ' (' + this.event.ageGroups[ option ].name + ')', 'price': this.event.categories[ data.category ].price[ option ], 'id': data.id + '_' + option, 'count': 1 }; if ( res.status === 200 ) {
} if ( this.cart[ this.event.eventID ] ) {
if ( this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] ) {
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ][ 'count' ] += 1;
} else {
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] = { 'displayName': data.name + ' (' + this.event.ageGroups[ option ].name + ')', 'price': this.event.categories[ data.category ].price[ option ], 'id': data.id + '_' + option, 'count': 1 };
}
} else {
this.cart[ this.event.eventID ] = { 'displayName': this.event.name, 'tickets': {} };
this.cart[ this.event.eventID ][ 'tickets' ][ data.id + '_' + option ] = { 'displayName': data.name + ' (' + this.event.ageGroups[ option ].name + ')', 'price': this.event.categories[ data.category ].price[ option ], 'id': data.id + '_' + option, 'count': 1 };
}
} else if ( res.status === 409 ) {
setTimeout( () => {
this.$refs.popups.openPopup( 'Unfortunately, the seat you just tried to select was reserved by somebody else since the last time the seat plan was refreshed. Please select another one. We are sorry for the inconvenience.', {}, 'string' );
}, 300 );
}
if ( Object.keys( this.cart[ this.event.eventID ][ 'tickets' ] ).length < 1 ) {
delete this.cart[ this.event.eventID ];
}
this.$refs.cart.calculateTotal();
localStorage.setItem( 'cart', JSON.stringify( this.cart ) );
} );
} else if ( operation === 'deselect' ) { } else if ( operation === 'deselect' ) {
if ( this.cart[ this.event.eventID ][ 'tickets' ][ data + '_' + option ][ 'count' ] === 1 ) { if ( this.cart[ this.event.eventID ][ 'tickets' ][ data + '_' + option ][ 'count' ] === 1 ) {
delete this.cart[ this.event.eventID ][ 'tickets' ][ data + '_' + option ]; delete this.cart[ this.event.eventID ][ 'tickets' ][ data + '_' + option ];

View File

@@ -50,7 +50,7 @@
}, },
data() { data() {
return { return {
hasSeatplan: true, hasSeatplan: false,
eventID: '', eventID: '',
} }
}, },