diff --git a/locales/en/gate.json b/locales/en/gate.json index 52da3f516..41f835c07 100644 --- a/locales/en/gate.json +++ b/locales/en/gate.json @@ -15,5 +15,6 @@ "reason": "Reason", "force_reason_placeholder": "10 Characters minimum", "entrance_group": "Entrance group", - "early_arrival": "Early Arrival" + "early_arrival": "Early Arrival", + "prod_approval": "Approved by production for early arrival" } diff --git a/locales/he/gate.json b/locales/he/gate.json index d3a6c9001..7c9e7733d 100644 --- a/locales/he/gate.json +++ b/locales/he/gate.json @@ -15,7 +15,8 @@ "reason": "סיבה", "force_reason_placeholder": "תארו את הסיבה ב- 10 תווים לפחות", "entrance_group": "קבוצת הקצאה", - "early_arrival": "הגעה מוקדמת" + "early_arrival": "הגעה מוקדמת", + "prod_approval": "מאושר להגעה מוקדמת על ידי ההפקה" } diff --git a/routes/api/api_gate_routes.js b/routes/api/api_gate_routes.js index a25b7ee28..07a370d92 100644 --- a/routes/api/api_gate_routes.js +++ b/routes/api/api_gate_routes.js @@ -54,7 +54,7 @@ async function getTicketBySearchTerms(req, res) { gate_status = event.attributes.gate_status; } if (!req.body.event_id || !event) { - return sendError(res, 500, "EVENT_ID_IS_MISSING"); + throw new Error("EVENT_ID_IS_MISSING"); } // Setting the search terms for the ticket. @@ -65,7 +65,7 @@ async function getTicketBySearchTerms(req, res) { searchTerms = {event_id: event_id, ticket_id: req.body.ticket, order_id: req.body.order}; } else { - return sendError(res, 500, "BAD_SEARCH_PARAMETERS"); + throw new Error("BAD_SEARCH_PARAMETERS"); } // Loading data from the DB. @@ -74,7 +74,7 @@ async function getTicketBySearchTerms(req, res) { return [ticket, gate_status]; } else { - return sendError(res, 404, "TICKET_NOT_FOUND"); + throw new Error("TICKET_NOT_FOUND"); } } @@ -157,89 +157,101 @@ router.post('/get-ticket/', async function (req, res) { }); } catch (err) { - return sendError(res, 500, null, err); + let status = err.message === 'TICKET_NOT_FOUND' ? 404 : 500; + if (ERRORS[err.message]) { + return sendError(res, status, err.message); + } + return sendError(res, status, null, err); } }); router.post('/gate-enter', async function (req, res) { + try { - // Loading ticket data from the DB. - let [ticket, gate_status] = await getTicketBySearchTerms(req, res); - const isEarlyArrival = gate_status === "early_arrival"; - if (!ticket) { - return sendError(res, 500, "TICKET_NOT_FOUND"); - } - if (ticket.attributes.inside_event) { - return sendError(res, 500, "ALREADY_INSIDE"); - } - - if (req.body.force === "true") { - let force_pwd = req.body.force_pwd; - if (_incorrect_force_entry_password(force_pwd)) { - return sendError(res, 500, "INCORRECT_FORCE_ENTRY_PASSWORD"); + // Loading ticket data from the DB. + let [ticket, gate_status] = await getTicketBySearchTerms(req, res); + const isEarlyArrival = gate_status === "early_arrival"; + if (!ticket) { + return sendError(res, 500, "TICKET_NOT_FOUND"); + } + if (ticket.attributes.inside_event) { + return sendError(res, 500, "ALREADY_INSIDE"); } - log.warn('Forced ticket entrance', ticket.attributes.ticket_number); - ticket.attributes.forced_entrance = true; - ticket.attributes.forced_entrance_reason = req.body.force_reason; - } - else { - if (gate_status === "closed") { - return sendError(res, 500, "EVENT_CLOSED"); + if (req.body.force === "true") { + let force_pwd = req.body.force_pwd; + if (_incorrect_force_entry_password(force_pwd)) { + return sendError(res, 500, "INCORRECT_FORCE_ENTRY_PASSWORD"); + } + log.warn('Forced ticket entrance', ticket.attributes.ticket_number); + ticket.attributes.forced_entrance = true; + ticket.attributes.forced_entrance_reason = req.body.force_reason; } + else { - let holder = ticket.relations.holder; - if (isEarlyArrival) - // Finding the right users group and updating it. - { - let production_early_arrival = false; - production_early_arrival = await volunteersAPI.hasEarlyEntry(holder.attributes.email); - log.debug(`get-ticket - user ${holder.attributes.email} is a production volunteer`); - if (req.body.group_id) { - let group = await UsersGroup.forge({group_id: req.body.group_id}).fetch({withRelated: ['users']}); + if (gate_status === "closed") { + return sendError(res, 500, "EVENT_CLOSED"); + } - if (!group) { - return sendError(res, 500, "TICKET_NOT_IN_GROUP"); - } + let holder = ticket.relations.holder; + if (isEarlyArrival) + // Finding the right users group and updating it. + { + let production_early_arrival = false; + production_early_arrival = await volunteersAPI.hasEarlyEntry(holder.attributes.email); + log.debug(`get-ticket - user ${holder.attributes.email} is a production volunteer`); + if (req.body.group_id) { + let group = await UsersGroup.forge({group_id: req.body.group_id}).fetch({withRelated: ['users']}); - let groupMembership = await UsersGroupMembership.forge({group_id: req.body.group_id, user_id: ticket.attributes.holder_id}).fetch(); + if (!group) { + return sendError(res, 500, "TICKET_NOT_IN_GROUP"); + } - if (!groupMembership) { - return sendError(res, 500, "TICKET_NOT_IN_GROUP"); - } + let groupMembership = await UsersGroupMembership.forge({group_id: req.body.group_id, user_id: ticket.attributes.holder_id}).fetch(); + + if (!groupMembership) { + return sendError(res, 500, "TICKET_NOT_IN_GROUP"); + } - if (await group.quotaReached) { - return sendError(res, 500, "QUOTA_REACHED"); + if (await group.quotaReached) { + return sendError(res, 500, "QUOTA_REACHED"); + } + } + else if (!production_early_arrival) + { + return sendError(res, 500, "TICKET_NOT_IN_GROUP"); } - } - else if (!production_early_arrival) - { - return sendError(res, 500, "TICKET_NOT_IN_GROUP"); } } - } - // Saving the entrance. - ticket.attributes.entrance_timestamp = new Date(); - ticket.attributes.entrance_group_id = req.body.group_id || null; - ticket.attributes.last_exit_timestamp = null; - ticket.attributes.inside_event = true; - if (!ticket.attributes.first_entrance_timestamp) { - ticket.attributes.first_entrance_timestamp = new Date(); - } - await ticket.save(); - // We want to add to the counter based on entry type (we don't use await to not break ticketing due to counter errors...) - const entryType = isEarlyArrival ? 'early_arrival' : 'regular'; - knex(constants.ENTRIES_TABLE_NAME).insert({timestamp: new Date(), direction: 'arrival', event_id: req.body.event_id, type: entryType}) - .catch(err => { - log.warn('A ticket entry count failed', err); - }); - // TODO PATCH - Notifying Drupal that this ticket is now non-transferable. Remove with Drupal. - drupalSync.passTicket(ticket.attributes.barcode); + // Saving the entrance. + ticket.attributes.entrance_timestamp = new Date(); + ticket.attributes.entrance_group_id = req.body.group_id || null; + ticket.attributes.last_exit_timestamp = null; + ticket.attributes.inside_event = true; + if (!ticket.attributes.first_entrance_timestamp) { + ticket.attributes.first_entrance_timestamp = new Date(); + } + await ticket.save(); + // We want to add to the counter based on entry type (we don't use await to not break ticketing due to counter errors...) + const entryType = isEarlyArrival ? 'early_arrival' : 'regular'; + knex(constants.ENTRIES_TABLE_NAME).insert({timestamp: new Date(), direction: 'arrival', event_id: req.body.event_id, type: entryType}) + .catch(err => { + log.warn('A ticket entry count failed', err); + }); + // TODO PATCH - Notifying Drupal that this ticket is now non-transferable. Remove with Drupal. + drupalSync.passTicket(ticket.attributes.barcode); - return res.status(200).json({ - message: "Ticket entered successfully" - }); + return res.status(200).json({ + message: "Ticket entered successfully" + }); + } catch (err) { + let status = err.message === 'TICKET_NOT_FOUND' ? 500 : 404; + if (ERRORS[err.message]) { + return sendError(res, status, err.message); + } + return sendError(res, status, null, err); + } }); router.post('/gate-exit', async function (req, res) { @@ -276,6 +288,10 @@ router.post('/gate-exit', async function (req, res) { }); } catch (err) { + let status = err.message === 'TICKET_NOT_FOUND' ? 404 : 500; + if (ERRORS[err.message]) { + return sendError(res, status, err.message); + } return sendError(res, 500, null, err) } }) diff --git a/views/pages/gate.jade b/views/pages/gate.jade index 785936153..48fc89208 100644 --- a/views/pages/gate.jade +++ b/views/pages/gate.jade @@ -57,11 +57,15 @@ block content b=t('gate:ticket_type') | :  span( id='modal_type') + P( id="prod_approval" style="color: green") + span.glyphicon.glyphicon-ok + b=t('gate:prod_approval') P( id="ticket_groups") b=t('gate:ticket_group') | :  .list-group(id="ticket_groups_list") + .modal-footer button.Btn.Btn__green(type='button', data-dismiss='modal', id='entrance_button')=t('gate:enter_ticket') button.Btn(type='button', data-dismiss='modal')=t('cancel') @@ -163,6 +167,7 @@ block scripts }); $(document).on("click", ".entranceAction", function () { + $("#prod_approval").hide(); clearModal(); $.post("/api/gate/get-ticket", { barcode: this.id, @@ -184,9 +189,11 @@ block scripts let entranceButton = $("#entrance_button")[0]; entranceButton.innerHTML = "#{t('gate:enter_ticket')}"; - + if (data.gate_status === "early_arrival"){ - + if (data.ticket.production_early_arrival) { + $("#prod_approval").show(); + } if ( !data.ticket.production_early_arrival && (data.ticket.groups && data.ticket.groups.length > 0)) { entranceButton.disabled = true; let groupsElement = $("#ticket_groups_list")[0]; @@ -204,6 +211,7 @@ block scripts $("#modal_group_id")[0].innerHTML = $(this)[0].id; }); } + } else { let groupsElement = $("#ticket_groups_list")[0]; @@ -219,7 +227,6 @@ block scripts event_id: "#{event_id}" }, function (data, status) { - console.log(data); if (data) { $("#modal_full_name")[0].innerHTML = "#{t('gate:more_details')} - " + data.ticket.holder_name; $("#modal_first_entrance_timestamp")[0].innerHTML = dateFormat(data.ticket.first_entrance_timestamp);