Skip to content
Snippets Groups Projects
Commit 1f48cd19 authored by Dominik Hebeler's avatar Dominik Hebeler
Browse files

added admin path to create receipts

parent 76f8ae3f
No related branches found
No related tags found
No related merge requests found
......@@ -642,6 +642,10 @@ class Order {
});
}
getOrderDate() {
return this.#order_date;
}
/**
*
* @param {number} price
......
{
"breadcrumps": {
"overview": "Übersicht",
"payments-cash": "Barzahlung erfassen"
"payments-cash": "Barzahlung erfassen",
"receipt": "Rechnung erstellen"
},
"index": {
"actions": {
"cash-payment": "Bargeldzahlung erfassen",
"receipt": "Rechnung erstellen",
"heading": "Aktionen:"
},
"heading": "MetaGer Schlüssel Admin"
......@@ -26,5 +28,22 @@
},
"submit": "Bestellung buchen",
"success": "Die Bestellung mit der Nummer {{orderid}} wurde erfolgreich gebucht!"
},
"receipt": {
"orderid": {
"label": "Bestellnummer ({{orderdate}}):",
"placeholder": "Bestellnummer eingeben...",
"submit": "Bestellung laden"
},
"name": {
"label": "Vollständiger Name:"
},
"email": {
"label": "E-Mail"
},
"address": {
"label": "Anschrift"
},
"submit-userdata": "Rechnungsdaten übernehmen"
}
}
}
\ No newline at end of file
div#admin-container{max-width:980px;margin:0 auto}div#admin-container h1{border-bottom:1px solid #ef7700;text-align:center}div#admin-container h2{width:max-content}div#admin-container ul.breadcrumps{padding:0;display:flex;flex-wrap:wrap;gap:1.5rem;color:#6a6a6a}div#admin-container ul.breadcrumps>li:first-child{list-style-type:none}
\ No newline at end of file
div#admin-container{max-width:980px;margin:0 auto;padding:1rem}div#admin-container h1{border-bottom:1px solid #ef7700;text-align:center}div#admin-container h2{width:max-content}div#admin-container ul.breadcrumps{padding:0;display:flex;flex-wrap:wrap;gap:1.5rem;color:#6a6a6a}div#admin-container ul.breadcrumps>li:first-child{list-style-type:none}
\ No newline at end of file
......@@ -3,6 +3,7 @@
div#admin-container {
max-width: @max-content-width;
margin: 0 auto;
padding: 1rem;
h1 {
border-bottom: 1px solid @color-main;
......
#admin-container #content-container{display:flex;flex-direction:row-reverse;justify-content:space-between;gap:1rem}@media (max-width:630px){#admin-container #content-container{flex-direction:column;align-items:center}#admin-container #content-container>*{width:100%}}#admin-container #content-container form{width:max-content;display:grid;gap:1rem}#admin-container #content-container form>.input-group{display:grid}#admin-container #content-container form>.input-group>label{font-weight:bold;font-size:.8rem;margin-bottom:.5rem}#admin-container #content-container form>.input-group input{padding:.5rem;border-radius:5px}#admin-container #content-container form>.input-group textarea{padding:.5rem;line-height:1.5}#admin-container #content-container form button{width:100%;padding:.5rem 1rem}#admin-container #content-container>div#order{padding:0;flex-grow:1}#admin-container #content-container>div#order>div#order-details{padding:0}#admin-container #content-container>div#order>iframe{width:100%;height:100%}
\ No newline at end of file
#admin-container {
#content-container {
display: flex;
flex-direction: row-reverse;
justify-content: space-between;
gap: 1rem;
@media (max-width: 630px) {
flex-direction: column;
align-items: center;
> * {
width: 100%;
}
}
form {
width: max-content;
display: grid;
gap: 1rem;
> .input-group {
display: grid;
> label {
font-weight: bold;
font-size: 0.8rem;
margin-bottom: 0.5rem;
}
input {
padding: 0.5rem;
border-radius: 5px;
}
textarea {
padding: 0.5rem;
line-height: 1.5;
}
}
button {
width: 100%;
padding: 0.5rem 1rem;
}
}
> div#order {
padding: 0;
flex-grow: 1;
> div#order-details {
padding: 0;
}
> iframe {
width: 100%;
height: 100%;
}
}
}
}
......@@ -3,7 +3,8 @@ var router = express.Router();
const config = require("config");
const Order = require("../../app/Order");
const { auth, requiresAuth, claimCheck } = require("express-openid-connect");
const { validationResult, matchedData, body } = require("express-validator");
const { validationResult, matchedData, body, query } = require("express-validator");
const OrderReceipt = require("../../app/pdf/OrderReceipt");
router.use(requiresAuth());
......@@ -11,6 +12,51 @@ router.get("/", (req, res) => {
res.render("admin/index");
});
router.get("/payments/receipt",
query("order").isNumeric({ gt: 0 }).customSanitizer(async orderid => await Order.LOAD_ORDER_FROM_ID(orderid).catch(reason => null)),
query("email").isEmail({ domain_specific_validation: true }),
query("address").isLength({ max: 1000 }),
query("name").isLength({ max: 500, min: 5 }),
async (req, res) => {
const reqData = matchedData(req, { locations: ["query"] });
let data_complete = true;
if ("order" in reqData) {
res.locals.order = reqData.order;
} else {
data_complete = false;
}
if ("email" in reqData) {
res.locals.email = reqData.email;
} else {
data_complete = false;
}
if ("address" in reqData) {
res.locals.address = reqData.address;
} else {
data_complete = false;
}
if ("name" in reqData) {
res.locals.name = reqData.name;
} else {
data_complete = false;
}
if (data_complete) {
// Create Invoice for preview
let receipt_pdf = await OrderReceipt.CREATE_ORDER_RECEIPT(
reqData.order,
{
name: res.locals.name,
email: res.locals.email,
address: res.locals.address
}
);
receipt_pdf = Buffer.concat(receipt_pdf).toString("base64");
res.locals.receiptb64 = receipt_pdf;
}
res.render("admin/payments/receipt");
});
router.use("/payments/cash", (req, res, next) => {
res.locals.allowed_currencies = config.get("price.allowed_currencies");
next();
......
......@@ -65,16 +65,15 @@ router.post(
},
(req, res) => {
let moderation_params = {
moderation: true,
order: req.data.order.order.getOrderID(),
name: req.data.order.invoice.params.name,
email: req.data.order.invoice.params.email,
address: req.data.order.invoice.params.address,
};
req.data.order.invoice.moderation_url = `${res.locals.baseDir}/key/${req.data.key.key.get_key()
}/orders/${req.data.order.order.getOrderID()}/invoice?${new URLSearchParams(
moderation_params
).toString()}#invoice-form`;
req.data.order.invoice.moderation_url = `${res.locals.baseDir}/admin/payments/receipt?${new URLSearchParams(
moderation_params
).toString()}`;
// Render the message
let ejs = require("ejs"),
......@@ -95,7 +94,7 @@ router.post(
},
body: JSON.stringify({
alert: true,
autorespond: true,
autorespond: false,
source: "API",
name: req.data.order.invoice.params.name,
email: req.data.order.invoice.params.email,
......
......@@ -10,6 +10,10 @@
<img src="<%= baseDir %>/images/money.svg" alt="Geldschein">
<div><%= req.t("index.actions.cash-payment", {ns: "admin"}) _%></div>
</a>
<a id="action-receipt" href="<%= baseDir %>/admin/payments/receipt">
<img src="<%= baseDir %>/images/invoice.svg" alt="Geldschein">
<div><%= req.t("index.actions.receipt", {ns: "admin"}) _%></div>
</a>
</div>
</div>
<%- include('../templates/page_footer'); -%>
\ No newline at end of file
<%- include('../../templates/page_header', {css: [`${baseDir}/styles/admin/base.css`, `${baseDir}/styles/admin/payments/receipt.css`, `${baseDir}/styles/orders/order.css`], js: []}); %>
<div id="admin-container">
<h1><%= req.t("index.heading", {ns: "admin"}) _%></h1>
<ul class="breadcrumps">
<li>
<a href="<%= baseDir _%>/admin/">
<%= req.t("breadcrumps.overview", {ns: "admin"}) _%>
</a>
</li>
<%_ if(typeof order === "undefined") { _%>
<li><%= req.t("breadcrumps.receipt", {ns: "admin"}) _%></li>
<%_ }else { _%>
<li>
<a href="<%= baseDir _%>/admin/payments/receipt">
<%= req.t("breadcrumps.receipt", {ns: "admin"}) _%>
</a>
</li>
</a>
<li><%= order.getOrderID() _%></li>
<%_ } _%>
</ul>
<h2><%= req.t("breadcrumps.receipt", {ns: "admin"}) _%></h2>
<div id="content-container">
<%_ if(typeof order === "undefined") { _%>
<form>
<input type="text" name="order" id="order" placeholder="<%= req.t("receipt.orderid.placeholder", {ns: "admin"}) _%>">
<button class="button" type="submit"><%= req.t("receipt.orderid.submit", {ns: "admin"}) _%></button>
</form>
<%_ } else { _%>
<div id="order">
<%_ if(typeof receiptb64 === "undefined") { _%>
<%- include("../../orders/order_details", {order: {order: order}}) %>
<%_ } else { _%>
<iframe src="data:application/pdf;base64,<%= receiptb64 _%>" frameborder="0"></iframe>
<%_ } _%>
</div>
<form method="GET">
<div class="input-group">
<label for="orderid"><%= req.t("receipt.orderid.label", {ns: "admin", orderdate: order.getOrderDate().format("DD.MM.YYYY")}) _%></label>
<input type="text" name="order" id="orderid" value="<%= order.getOrderID() _%>" readonly />
</div>
<div class="input-group">
<label for="name"><%= req.t("receipt.name.label", {ns: "admin"}) _%></label>
<input type="text" name="name" id="name" value="<%= typeof name === "undefined" ? "" : name _%>" placeholder="Max Mustermann">
</div>
<div class="input-group">
<label for="email"><%= req.t("receipt.email.label", {ns: "admin"}) _%></label>
<input type="email" name="email" id="email" value="<%= typeof email === "undefined" ? "" : email _%>" placeholder="max@mustermann.de">
</div>
<div class="input-group">
<label for="address"><%= req.t("receipt.address.label", {ns: "admin"}) _%></label>
<textarea name="address" id="address" cols="30" rows="3" placeholder="Mustergasse 3&#10;30159 Musterstadt&#10;Deutschland"><%= typeof address === "undefined" ? "" : address _%></textarea>
</div>
<button class="button"><%= req.t("receipt.submit-userdata", {ns: "admin"}) _%></button>
</form>
<%_ } _%>
</div>
</div>
<%- include('../../templates/page_footer'); -%>
\ No newline at end of file
......@@ -7,7 +7,7 @@
</ul>
<%- include("order_details") %>
<form <% if(admin) { %>action="<%= order.invoice.create_invoice_url %>" <%_ } _%> method="POST" id="invoice-form">
<form method="POST" id="invoice-form">
<%_ if(!order.invoice.success) { _%>
<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.
......@@ -25,22 +25,12 @@
<label for="address" <%_ if(order.invoice.errors["address"]) { _%>class="error" <%_ } _%>>Anschrift*</label>
<textarea name="address" id="address" cols="30" rows="4" placeholder="Mustergasse 3&#10;30159 Musterstadt&#10;Deutschland" required><%= order.invoice.params["address"] %></textarea>
</div>
<% if (admin) { %>
<input type="hidden" name="admin" value="true">
<div class="invoice-form-field">
<button type="submit" class="button">
<img src="<%= baseDir _%>/images/invoice.svg" alt="" />
<span>Rechnung erstellen</span>
</button>
</div>
<%_ } else { _%>
<div class="invoice-form-field">
<button type="submit" class="button">
<img src="<%= baseDir _%>/images/invoice.svg" alt="" />
<span>Rechnung anfragen</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).
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment