From d49613671be2bbdeb09a753c7516355f5431518a Mon Sep 17 00:00:00 2001
From: Dominik Hebeler <dominik@hebeler.club>
Date: Thu, 15 Dec 2022 22:18:53 +0100
Subject: [PATCH] added form to request receipt

---
 pass/app/pdf/OrderReceipt.js   | 41 ++++++++++++++-------
 pass/config/default.json       |  8 ++--
 pass/public/styles/base.less   |  4 ++
 pass/public/styles/orders.less | 67 ++++++++++++++++++++++++++++++++++
 pass/routes/orders.js          | 16 ++++++--
 pass/views/orders/order.ejs    | 53 +++++++++++++++++++++++----
 6 files changed, 158 insertions(+), 31 deletions(-)

diff --git a/pass/app/pdf/OrderReceipt.js b/pass/app/pdf/OrderReceipt.js
index 513aacb..2a5534f 100644
--- a/pass/app/pdf/OrderReceipt.js
+++ b/pass/app/pdf/OrderReceipt.js
@@ -24,15 +24,15 @@ class OrderReceipt {
       .fontSize(10);
 
     // The header with logo and line
-    doc.image("public/images/metager.png", letter_left_margin, 20, {
+    doc.image("public/images/metager.png", letter_left_margin, 30, {
       height: 20,
     });
-    doc.image("public/images/suma-ev.png", 400, 22, {
+    doc.image("public/images/suma-ev.png", 400, 32, {
       height: 18,
     });
     doc
-      .moveTo(letter_left_margin, 50)
-      .lineTo(OrderReceipt.CM_TO_POINTS(21, false) - letter_right_margin, 50)
+      .moveTo(letter_left_margin, 60)
+      .lineTo(OrderReceipt.CM_TO_POINTS(21, false) - letter_right_margin, 60)
       .strokeColor("#515151")
       .stroke();
 
@@ -51,7 +51,7 @@ class OrderReceipt {
 */
     // General Information
     doc
-      .fontSize(10)
+      .fontSize(12)
       .text(
         "Bestellnummer: ",
         OrderReceipt.CM_TO_POINTS(21 - 8.5, false),
@@ -96,16 +96,16 @@ class OrderReceipt {
     doc
       .moveTo(
         OrderReceipt.CM_TO_POINTS(2.5, false),
-        OrderReceipt.CM_TO_POINTS(12.5, true)
+        OrderReceipt.CM_TO_POINTS(12.6, true)
       )
       .lineTo(
         OrderReceipt.CM_TO_POINTS(21 - 2, false),
-        OrderReceipt.CM_TO_POINTS(12.5, true)
+        OrderReceipt.CM_TO_POINTS(12.6, true)
       )
       .strokeColor("#ff7f00")
       .stroke();
     doc
-      .fontSize(10)
+      .fontSize(12)
       .font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
       .text(
         "Auftragsbestätigung " + order.getOrderID(),
@@ -147,12 +147,12 @@ class OrderReceipt {
       .text(order.getAmount() / 300, {
         width: OrderReceipt.CM_TO_POINTS(3.25, false),
         align: "right",
-        lineGap: 15,
+        lineGap: 8,
       })
       .text("MwSt (7%)", {
         width: OrderReceipt.CM_TO_POINTS(3.25, false),
         align: "right",
-        lineGap: 10,
+        lineGap: 8,
       })
       .font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
       .text("Gesamtbetrag", {
@@ -176,12 +176,12 @@ class OrderReceipt {
       .text(order.getNettoPrice() + " €", {
         width: OrderReceipt.CM_TO_POINTS(3.25, false),
         align: "right",
-        lineGap: 15,
+        lineGap: 8,
       })
       .text(order.getVatAmount() + " €", {
         width: OrderReceipt.CM_TO_POINTS(3.25, false),
         align: "right",
-        lineGap: 10,
+        lineGap: 8,
       })
       .font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
       .text(order.getPrice() + " €", {
@@ -191,6 +191,18 @@ class OrderReceipt {
       .font("public/fonts/liberation-sans/LiberationSans-Regular.ttf");
 
     // Footer
+    doc
+      .moveTo(
+        OrderReceipt.CM_TO_POINTS(2.5, false),
+        OrderReceipt.CM_TO_POINTS(27.2, false)
+      )
+      .lineTo(
+        OrderReceipt.CM_TO_POINTS(21 - 2, false),
+        OrderReceipt.CM_TO_POINTS(27.2, true)
+      )
+      .strokeColor("#515151")
+      .stroke();
+
     let textbox_width = doc.widthOfString("Vorstand");
     doc.fontSize(8);
     textbox_width = Math.max(
@@ -202,7 +214,7 @@ class OrderReceipt {
     let x = OrderReceipt.CM_TO_POINTS(21 - 2, false) - textbox_width;
     doc
       .font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
-      .text("Vorstand", x, OrderReceipt.CM_TO_POINTS(27.2, true), {
+      .text("Vorstand", x, OrderReceipt.CM_TO_POINTS(27.3, true), {
         lineBreak: false,
       })
       .fontSize(8)
@@ -227,8 +239,9 @@ class OrderReceipt {
 
     x = OrderReceipt.CM_TO_POINTS(2.5, false);
     doc
+      .fontSize(10)
       .font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
-      .text("SUMA-EV", x, OrderReceipt.CM_TO_POINTS(27.2, true), {
+      .text("SUMA-EV", x, OrderReceipt.CM_TO_POINTS(27.3, true), {
         lineBreak: false,
       })
       .fontSize(8)
diff --git a/pass/config/default.json b/pass/config/default.json
index 75bd7fb..7a4324c 100644
--- a/pass/config/default.json
+++ b/pass/config/default.json
@@ -26,11 +26,9 @@
     },
     "payments": {
         "paypal": {
-            "development": {
-                "base": "https://api-m.sandbox.paypal.com",
-                "secret": "<INSERT_PAYPAL_APPLICATION_SECRET>",
-                "client_id": "<INSERT_PAYPAL_CLIENT_ID>"
-            }
+            "base": "https://api-m.sandbox.paypal.com",
+            "secret": "<INSERT_PAYPAL_APPLICATION_SECRET>",
+            "client_id": "<INSERT_PAYPAL_CLIENT_ID>"
         }
     }
 }
\ No newline at end of file
diff --git a/pass/public/styles/base.less b/pass/public/styles/base.less
index e1b5f1a..e33c56a 100644
--- a/pass/public/styles/base.less
+++ b/pass/public/styles/base.less
@@ -51,6 +51,10 @@ html {
   display: none !important;
 }
 
+.bold {
+  font-weight: bold;
+}
+
 .error {
   color: #ff5858;
   display: flex;
diff --git a/pass/public/styles/orders.less b/pass/public/styles/orders.less
index d12f277..e87f653 100644
--- a/pass/public/styles/orders.less
+++ b/pass/public/styles/orders.less
@@ -1,10 +1,29 @@
 @import "./misc/vars.less";
 #order {
+  padding: 1rem 0;
+  .breadcrumbs {
+    display: flex;
+    gap: 0.5rem;
+    padding: 0;
+    list-style-type: disclosure-closed;
+    font-size: clamp(0.7rem, 4w, 1rem);
+    li {
+      margin-left: 1rem;
+      &:first-child {
+        margin-left: 0;
+        list-style-type: none;
+      }
+      a {
+        color: #777;
+      }
+    }
+  }
   grid-area: content;
   #order-details {
     display: grid;
     grid-template-columns: 1fr 4rem 4rem;
     text-align: right;
+    padding: 2rem 0;
     > div {
       &.heading {
         text-align: left;
@@ -41,5 +60,53 @@
         filter: brightness(0) invert(1);
       }
     }
+    @media (max-width: 510px) {
+      flex-direction: column;
+      align-items: center;
+    }
+  }
+
+  #invoice-form {
+    #invoice-form-fields {
+      display: grid;
+      gap: 1rem;
+
+      .invoice-form-field {
+        display: grid;
+        gap: 0.5rem;
+        font-weight: bold;
+        color: #777;
+        font-size: 0.7rem;
+        place-content: center;
+        text-align: center;
+        #email {
+          padding: 0.5rem;
+          border-radius: 5px;
+          font-size: 0.8rem;
+          width: 13rem;
+          text-align: center;
+        }
+        #name-and-address {
+          padding: 0.5rem;
+          border-radius: 5px;
+          line-height: 2;
+          text-align: center;
+          width: 13rem;
+        }
+        button {
+          display: flex;
+          align-items: center;
+          gap: 0.5rem;
+          padding: 0.5rem;
+          img {
+            height: 1.2rem;
+          }
+        }
+      }
+    }
+    .storage-time {
+      font-size: 0.8rem;
+      text-align: center;
+    }
   }
 }
diff --git a/pass/routes/orders.js b/pass/routes/orders.js
index a8615e9..b7b0360 100644
--- a/pass/routes/orders.js
+++ b/pass/routes/orders.js
@@ -9,7 +9,12 @@ const OrderReceipt = require("../app/pdf/OrderReceipt");
 router.use("/:order_id", param("order_id").isInt(), (req, res, next) => {
   Order.LOAD_ORDER_FROM_ID(req.params.order_id)
     .then((order) => {
-      req.data.order = order;
+      req.data.css.push("/styles/orders.css");
+      req.data.order = { order: order };
+      req.data.order.orders_url = `/key/${req.data.key.key}/orders`;
+      req.data.order.order_url = `/key/${req.data.key.key}/orders/${req.params.order_id}#order`;
+      req.data.order.receipt_url = `/key/${req.data.key.key}/orders/${req.params.order_id}/pdf`;
+      req.data.order.invoice_url = `/key/${req.data.key.key}/orders/${req.params.order_id}/invoice#invoice-form`;
       next("route");
     })
     .catch((reason) => {
@@ -18,17 +23,20 @@ router.use("/:order_id", param("order_id").isInt(), (req, res, next) => {
 });
 
 router.get("/:order_id", (req, res) => {
-  req.data.css.push("/styles/orders.css");
-  req.data.order_receipt_url = `/key/${req.data.key.key}/orders/${req.params.order_id}/pdf`;
   res.render("key", req.data);
 });
 
 router.get("/:order_id/pdf", (req, res) => {
-  let doc = OrderReceipt.CREATE_ORDER_RECEIPT(req.data.order, res);
+  let doc = OrderReceipt.CREATE_ORDER_RECEIPT(req.data.order.order, res);
   res.status(200).header({
     "Content-Type": "application/pdf",
   });
   doc.pipe(res);
 });
 
+router.get("/:order_id/invoice", (req, res) => {
+  req.data.order.invoice = true;
+  res.render("key", req.data);
+});
+
 module.exports = router;
diff --git a/pass/views/orders/order.ejs b/pass/views/orders/order.ejs
index 9ff51b2..bacb85f 100644
--- a/pass/views/orders/order.ejs
+++ b/pass/views/orders/order.ejs
@@ -1,28 +1,65 @@
 <div id="order">
-    <h2>Ihre Bestellung Nr. <%= order.getOrderID() %></h2>
+    <%_ if(!order.invoice) { _%>
+    <h2>Ihre Bestellung Nr. <%= order.order.getOrderID() %></h2>
+    <ul class="breadcrumbs">
+        <li><a href="<%= order.orders_url %>">Bestellungen</a></li>
+        <li><%= order.order.getOrderID() %></li>
+    </ul>
     <div id="order-details">
         <div class="heading item">Bestelldetails</div>
         <div class="heading count">Anzahl</div>
         <div class="heading price">Preis</div>
         <div class="item">MetaGer Schlüssel: Suchanfragen (300x)</div>
-        <div class="count"><%= order.getAmount() / 300 %></div>
-        <div class="price"><%= order.getNettoPrice() %> €</div>
-        <div class="item">MwSt. (<%= order.getVat() %> %)</div>
+        <div class="count"><%= order.order.getAmount() / 300 %></div>
+        <div class="price"><%= order.order.getNettoPrice() %> €</div>
+        <div class="item">MwSt. (<%= order.order.getVat() %> %)</div>
         <div class="count"></div>
-        <div class="price"><%= order.getVatAmount() %> €</div>
+        <div class="price"><%= order.order.getVatAmount() %> €</div>
         <div class="item sum">Gesamtbetrag</div>
         <div class="count"></div>
-        <div class="price"><%= order.getPrice() %> €</div>
+        <div class="price"><%= order.order.getPrice() %> €</div>
     </div>
     <h3>Vielen Dank für Ihren Einkauf!</h3>
     <div id="order-buttons">
-        <a href="<%= order_receipt_url %>" target="_blank" class="button">
+        <a href="<%= order.receipt_url %>" target="_blank" class="button">
             <img src="/images/download.svg" alt="" />
             <span>Auftragsbestätigung herunterladen</span>
         </a>
-        <a href="#" class="button">
+        <a href="<%= order.invoice_url %>" class="button">
             <img src="/images/invoice.svg" alt="" />
             <span>Rechnung beantragen</span>
         </a>
     </div>
+    <%_ } else { _%>
+    <form action="POST" id="invoice-form">
+        <h2>Rechnung</h2>
+        <ul class="breadcrumbs">
+            <li><a href="<%= order.orders_url %>">Bestellungen</a></li>
+            <li><a href="<%= order.order_url %>"><%= order.order.getOrderID() %></a></li>
+            <li>Rechnung</li>
+        </ul>
+        <p>
+            Wenn Sie eine Rechnung benötigen, tragen Sie bitte Ihre Rechnungsdaten in das nachfolgende Formular ein. Wir benötigen von Ihnen dafür Ihren vollständigen Namen, Ihre postalische Anschrift und Ihre E-Mail Adresse um Ihnen die Rechnung zuzustellen.
+        </p>
+        <div id="invoice-form-fields">
+        <div class="invoice-form-field">
+            <label for="email">E-Mail*</label>
+            <input type="email" name="email" id="email" placeholder="test@example.com" required>
+        </div>
+        <div class="invoice-form-field">
+            <label for="name-and-address">Name & Anschrift*</label>
+            <textarea name="name-and-address" id="name-and-address" cols="30" rows="4" placeholder="Max Mustermann&#10;Mustergasse 3&#10;30159 Musterstadt&#10;Deutschland" required></textarea>
+        </div>
+        <div class="invoice-form-field">
+            <button type="submit" class="button">
+                <img src="/images/invoice.svg" alt="" />
+                <span>Rechnung beantragen</span>
+            </button>
+        </div>
+        </div>
+        <p class="storage-time">
+            Wir sind rechtlich dazu verpflichtet einmal ausgestellte Rechnungen <span class="bold">10 Jahre</span> lang aufzubewahren. Da eine Rechnung auf Sie persönlich ausgestellt sein muss, enthält sie zwangsläufig personenbeziehbare Daten (Name, Anschrift, E-Mail).
+        </p>
+    </form>
+    <%_ } _%>
 </div>
\ No newline at end of file
-- 
GitLab