[guadec-web-regcfp/develop] Add desk system beginning



commit d20987e9113000e70517a6d6e927f3ff71dfc38e
Author: Patrick Uiterwijk <puiterwijk redhat com>
Date:   Tue Aug 4 13:47:52 2015 +0200

    Add desk system beginning

 app.js                 |    9 +++
 routes/desk.js         |  171 ++++++++++++++++++++++++++++++++++++++++++++++++
 routes/registration.js |    7 --
 views/desk/add.hbs     |   37 ++++++++++
 views/desk/added.hbs   |   21 ++++++
 views/desk/finish.hbs  |   16 +++++
 views/desk/main.hbs    |  102 ++++++++++++++++++++++++++++
 views/index/index.hbs  |    6 ++
 views/layouts/main.hbs |    3 +-
 9 files changed, 364 insertions(+), 8 deletions(-)
---
diff --git a/app.js b/app.js
index 5a0bc7e..0517514 100644
--- a/app.js
+++ b/app.js
@@ -14,6 +14,7 @@ var routes_index = require('./routes/index');
 var routes_auth = require('./routes/auth');
 var routes_papers = require('./routes/papers');
 var routes_registration = require('./routes/registration');
+var routes_desk = require('./routes/desk');
 
 var app = express();
 
@@ -46,6 +47,13 @@ var hbs = handlebars.create({
       } else {
         return options.inverse(this);
       }
+    },
+    ifGT: function(v1, v2, options) {
+      if(v1 > v2) {
+        return options.fn(this);
+      } else {
+        return options.inverse(this);
+      }
     }
   }
 });
@@ -90,6 +98,7 @@ app.use('/', routes_index);
 app.use('/auth', routes_auth);
 app.use('/papers', routes_papers);
 app.use('/registration', routes_registration);
+app.use('/desk', routes_desk);
 
 // catch 404 and forward to error handler
 app.use(function(req, res, next) {
diff --git a/routes/desk.js b/routes/desk.js
new file mode 100644
index 0000000..8d54a3b
--- /dev/null
+++ b/routes/desk.js
@@ -0,0 +1,171 @@
+var express = require('express');
+var router = express.Router();
+
+var utils = require('../utils');
+
+var models = require('../models');
+var User = models.User;
+var Registration = models.Registration;
+var RegistrationPayment = models.RegistrationPayment;
+
+var env       = process.env.NODE_ENV || "development";
+var config = require('../config/config.json')[env];
+
+var paypal = require('paypal-rest-sdk');
+paypal.configure(config['paypal']);
+
+
+router.all('/', utils.require_user);
+router.all('/', utils.require_permission('registration/desk'));
+router.get('/', function(req, res, next) {
+  message = null;
+  if(req.query.new_id) {
+    message = "Registration " + req.query.new_id + " was added";
+  }
+  else if(req.query.paid) {
+    message = "Registration " + req.query.paid + " was marked as paid";
+  }
+  else if(req.query.cleared) {
+    message = "Payments for " + req.query.cleared + " were cleared";
+  }
+  else if(req.query.added) {
+    message = "Payment of " + req.query.amount + " registered for " + req.query.added;
+  }
+  else if(req.query.printed) {
+    message = "Registration " + req.query.printed + " was finished!";
+  }
+
+  Registration
+    .findAll({
+      include: [User, RegistrationPayment]
+    })
+    .complete(function(err, registrations) {
+      res.render('desk/main', { registrations: registrations, message: message });
+    });
+});
+
+router.get('/add', function(req, res, next) {
+  res.render('desk/add');
+});
+
+router.post('/add', function(req, res, next) {
+  var user_info = {
+    email: req.body.email.trim(),
+    name: req.body.name.trim()
+  };
+  User
+    .create(user_info)
+    .complete(function(err, new_user) {
+      if(!!err) {
+        res.status(500).send("Error saving user: " + err);
+      } else {
+        var reg_info = {
+          irc: req.body.irc.trim(),
+          gender: req.body.gender.trim(),
+          country: req.body.country.trim(),
+          is_public: req.body.is_public.indexOf('false') == -1,
+          badge_printed: false,
+          receipt_sent: false,
+          UserId: new_user.id
+        };
+        Registration.create(reg_info)
+          .complete(function(err, reg) {
+            if(!!err) {
+              res.status(500).send('Error saving reg: ' + err);
+            } else {
+              res.render('desk/added', { regid: reg.id });
+            }
+          });
+      }
+    });
+});
+
+router.get('/receipt', function(req, res, next) {
+  var regid = req.query.regid;
+  Registration.findOne({where: {id:regid}, include: [User, RegistrationPayment]})
+    .then(function(registration) {
+      if(registration.paid < config.registration.min_amount_for_receipt) {
+        res.status(401).send('Not enough paid for receipt');
+      } else {
+        res.render('registration/receipt', { registration: registration , layout:false });
+      }
+    });
+});
+
+router.post('/finish', function(req, res, next) {
+  var regid = req.body.regid;
+  Registration.findOne({where: {id:regid}, include: [User, RegistrationPayment]})
+    .then(function(registration) {
+      registration.badge_printed = true;
+      registration.save();
+
+      res.render('desk/finish', { registration: registration} );
+    });
+});
+
+// TODO: BADGE PRINTING
+router.get('/badge', function(req, res, next) {
+  var regid = req.query.regid;
+  Registration.findOne({where: {id:regid}, include: [RegistrationPayment]})
+    .then(function(registration) {
+      res.status(200).send('Registration: ' + registration);
+    });
+});
+
+router.post('/payment/markpaid', function(req, res, next) {
+  var regid = req.body.regid;
+  Registration.findOne({where: {id:regid}, include: [RegistrationPayment]})
+    .then(function(registration) {
+      for(payment in registration.RegistrationPayments) {
+        payment = registration.RegistrationPayments[payment];
+        if(!payment.paid && payment.type == 'onsite') {
+          payment.paid = true;
+          payment.save();
+        }
+      }
+      res.redirect('/desk?paid=' + regid);
+    });
+});
+
+router.post('/payment/clear', function(req, res, next) {
+  var regid = req.body.regid;
+  Registration.findOne({where: {id:regid}, include: [RegistrationPayment]})
+    .then(function(registration) {
+      for(payment in registration.RegistrationPayments) {
+        payment = registration.RegistrationPayments[payment];
+        if(!payment.paid && payment.type == 'onsite') {
+          payment.destroy();
+        }
+      }
+      res.redirect('/desk?cleared=' + regid);
+    });
+});
+
+router.post('/payment/add', function(req, res, next) {
+  var regid = req.body.regid;
+  Registration.findOne({where: {id:regid}})
+    .then(function(registration) {
+      var payment_info = {
+        amount: req.body.amount,
+        paid: true,
+        type: 'onsite',
+      };
+      RegistrationPayment.create(payment_info)
+        .complete(function(err, payment) {
+          if(!!err) {
+            res.status(500).send('Error saving payment: ' + err);
+          } else {
+            registration.addRegistrationPayment(payment)
+              .complete(function(err) {
+                if(!!err) {
+                  res.status(500).send('Error attaching payment to reg: ' + err);
+                } else {
+                  res.redirect('/desk?added=' + regid + '&amount=' + req.body.amount);
+                }
+              });
+          }
+        });
+    });
+});
+
+module.exports = router;
diff --git a/routes/registration.js b/routes/registration.js
index c990d96..aa1b2bf 100644
--- a/routes/registration.js
+++ b/routes/registration.js
@@ -316,11 +316,4 @@ function handle_registration(req, res, next) {
   });
 };
 
-
-router.all('/admin/list', utils.require_user);
-router.all('/admin/list', utils.require_permission('registration/view_all'));
-router.get('/admin/list', function(req, res, next) {
-  next();
-});
-
 module.exports = router;
diff --git a/views/desk/add.hbs b/views/desk/add.hbs
new file mode 100644
index 0000000..fedc609
--- /dev/null
+++ b/views/desk/add.hbs
@@ -0,0 +1,37 @@
+<form action="/desk/add" method="post">
+<table class="submission-form">
+<tr><td>Your name</td><td><input type="text" id="name" name="name"></td></tr>
+<tr><td>Your email</td><td><input type="text" id="email1" name="email"></td></tr>
+<tr><td>Confirm email</td><td><input type="text" id="email2" name="email2"></td></tr>
+<tr><td>IRC nickname</td><td><input type="text" name="irc"></td></tr>
+<input type="hidden" name="is_public" value="true">
+
+
+<tr><td>Gender</td><td><input type="text" name="gender" value="{{registration.gender}}" 
placeholder="(optional: male, female, genderqueer, etc.)"><br/><p class="note">We will not publish gender 
data.<br/> It will only be used for attendee statistics and for an invitation to the women's 
dinner.</p></td></tr>
+
+<tr><td>Country</td><td><input type="text" name="country" value="{{registration.country}}" 
placeholder="(optional)"><br/><p class="note">We will not publish country data.<br/> It will only be used for 
attendee statistics.</p></td></tr>
+
+
+<tr><td>&nbsp;</td><td><input type="checkbox" value="false" name="is_public"> Hide my name in the public 
list of attendees</td></tr>
+<tr><td>&nbsp;</td>
+<td><input class="submit-talk" type="submit" value="Submit" /></td>
+</tr>
+
+</table>
+</form>
+
+
+<script type="text/javascript">
+$(function() {
+    $('form').submit(function(event) {
+        if($('#name').val() == '') {
+            window.alert("Please enter your name");
+            return false;
+        }
+        if($('#email1').val() == '' || $('#email1').val() != $('#email2').val()) {
+            window.alert("Please check your email address");
+            return false;
+        }
+    });
+});
+</script>
diff --git a/views/desk/added.hbs b/views/desk/added.hbs
new file mode 100644
index 0000000..b7baa0c
--- /dev/null
+++ b/views/desk/added.hbs
@@ -0,0 +1,21 @@
+Thanks, you have been assigned registration id {{regid}}.<br />
+Please return the laptop to the desk.<br /><br />
+
+<form action="/desk">
+    <input type="hidden" name="new_id" value="{{regid}}">
+    <input type="submit" value="Desk person: please click to return">
+</form>
+
+
+<script type="text/javascript">
+    $(function() {
+        $('form').submit(function(event) {
+            return window.prompt('Enter secret word') == '{{config.registration.desk_word}}';
+        });
+        $('a').click(function(event) {
+            if(window.prompt('Enter secret word') != '{{config.registration.desk_word}}') {
+                event.preventDefault();
+            };
+        });
+    });
+</script>
diff --git a/views/desk/finish.hbs b/views/desk/finish.hbs
new file mode 100644
index 0000000..d188e84
--- /dev/null
+++ b/views/desk/finish.hbs
@@ -0,0 +1,16 @@
+You have finished the registration of {{registration.User.name}}!<br />
+
+{{#ifGTE registration.paid config.registration.min_amount_for_receipt}}
+    Receipt: <a href="/desk/receipt?regid={{registration.id}}" target="_blank">Click here to print 
receipt</a><br />
+    <b>Note: The user can also log in to the applicaton and get his receipt at any time.</b><br />
+{{else}}
+    The user did not pay enough for a receipt.<br />
+{{/ifGTE}}
+<br />
+
+<b>Badge: <a href="/desk/badge?regid={{registration.id}}" target="_blank">Click here to print 
badge</a></b><br />
+<br />
+<form action="/desk">
+    <input type="hidden" name="printed" value="{{registration.id}}">
+    <input type="submit" value="Return to desk">
+</form>
diff --git a/views/desk/main.hbs b/views/desk/main.hbs
new file mode 100644
index 0000000..27ca999
--- /dev/null
+++ b/views/desk/main.hbs
@@ -0,0 +1,102 @@
+{{#if message}}
+    <h2>{{message}}</h2>
+{{/if}}
+
+
+<h2>Donations:</h2>
+<form action="/desk/donate" method="post">
+    Amount donated:
+    <select name="currency">
+    <option value="EUR">€</option>
+    <option value="SEK">kr</option>
+    </select>
+    <input type="text" name="amount"><br />
+    Items received:<br />
+    {{#each config.registration.donation_items}}
+
+    {{/each}}
+    <input type="submit" value="Register donation">
+</form><br />
+
+
+
+<h2>Registrations:</h2>
+<table border="1">
+<tr><th>Reg Nr.</th><th>Name</th><th>Email</th><th>IRC Nick</th><th>Actions</th></tr>
+<!-- New entry -->
+<tr>
+    <td colspan=5>
+        <a href="/desk/add">New registration</a>
+    </td>
+</tr>
+<!-- End new entry -->
+
+{{#each registrations}}
+<tr>
+    <td>{{this.id}}</td>
+    <td>{{this.User.name}}</td>
+    <td>{{this.User.email}}</td>
+    <td>{{this.irc}}</td>
+    <td>
+        {{#if this.badge_printed}}
+            BADGE PRINTED (<a href="/desk/badge?regid={{this.id}}" target="_blank">reprint</a>)
+        {{else}}
+            {{#ifGT this.outstanding_onsite 0}}
+                Outstanding: {{this.outstanding_onsite}}<br />
+                <form method="post" action="/desk/payment/markpaid" data-message="Really mark 
'{{this.User.name}}' as having paid {{this.outstanding_onsite}}?">
+                    <input type="hidden" name="regid" value="{{this.id}}">
+                    <input type="submit" value="Mark as paid">
+                </form>
+                <form method="post" action="/desk/payment/clear" data-message="Really clear payments of 
'{{this.User.name}}'?">
+                    <input type="hidden" name="regid" value="{{this.id}}">
+                    <input type="submit" value="Clear">
+                </form>
+            {{else}}
+                <form class="payment_add_form" method="post" action="/desk/payment/add" 
data-name="{{this.User.name}}">
+                    <input type="hidden" name="regid" value="{{this.id}}">
+                    <input type="submit" value="Add payment">
+                </form>
+                <form class="finish_reg_form" method="post" action="/desk/finish" data-message="Really 
finish registration for '{{this.User.name}}' and print badge?" data-amount={{this.paid}}>
+                    <input type="hidden" name="regid" value="{{this.id}}">
+                    <input type="submit" value="Print badge">
+                </form>
+            {{/ifGT}}
+        {{/if}}
+    </td>
+</tr>
+{{/each}}
+</table>
+
+<script type="text/javascript">
+var min_for_receipt = {{config.registration.min_amount_for_receipt}};
+
+$(function() {
+    $('form').submit(function(event) {
+        if($(event.target).data('message') === undefined) {
+            return true;
+        } else {
+            return window.confirm($(event.target).data('message'));
+        }
+    });
+
+    $('.finish_reg_form').submit(function(event) {
+        var amount = $(event.target).data('amount');
+        if(amount < min_for_receipt) {
+            return !window.confirm('CAUTION: User did not pay enough for receipt (paid: ' + amount + ', 
needed: ' + min_for_receipt + '). Do you want to cancel?');
+        }
+    });
+
+    $('.payment_add_form').submit(function(event) {
+        var name = $(event.target).data('name');
+        var amount = window.prompt("What amount has '" + name + "' paid?", "0.00");
+        if(amount != null && parseFloat(amount) != 0 && !isNaN(parseFloat(amount))) {
+            $(event.target).append('<input type="hidden" name="amount" value="' + amount + '">');
+            $(event.target).off('submit');
+            $(event.target).submit();
+            return false;
+        } else {
+            return false;
+        }
+    });
+});
+</script>
diff --git a/views/index/index.hbs b/views/index/index.hbs
index 4438710..d9b4587 100644
--- a/views/index/index.hbs
+++ b/views/index/index.hbs
@@ -9,6 +9,12 @@ You can log in with your Persona Account or with a persona provider, for example
 {{else}}
 Welcome, {{name}}<br />
 
+
+{{#has_permission "registration/desk"}}
+<div class="button"><a href="/desk">Desk</a></div>
+{{/has_permission}}
+
+
 {{#if config.papers.enabled}}
 
 <h2>Papers management</h2>
diff --git a/views/layouts/main.hbs b/views/layouts/main.hbs
index a5c81ec..ced82b1 100644
--- a/views/layouts/main.hbs
+++ b/views/layouts/main.hbs
@@ -4,7 +4,8 @@
         <title>Event registration</title>
 
         <meta http-equiv="X-UA-Compatible" content="IE=Edge">
-        <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.3.min.js";></script>
+        <script type="text/javascript" src="https://code.jquery.com/jquery-2.1.4.min.js";></script>
+        <script type="text/javascript" src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js";></script>
         <script type="text/javascript" src="https://login.persona.org/include.js";></script>
 
         <script type="text/javascript">



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]