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

added order receipt

parent 22ff0358
No related branches found
No related tags found
No related merge requests found
......@@ -94,8 +94,21 @@ class Order {
return this.#amount;
}
getNettoPrice() {
let amount = this.getPrice();
let vat_amount = this.getVatAmount();
return amount - vat_amount;
}
getVat() {
return config.get("price.vat");
}
getVatAmount() {
let vat = config.get("price.vat");
let amount = this.getPrice();
return Number((amount * (vat / 100)).toFixed(2));
}
getPrice() {
return this.#price;
return Number(this.#price).toFixed(2);
}
getPaymentMethodLink() {
......
const Order = require("../Order");
const dayjs = require("dayjs");
class OrderReceipt {
/**
*
* @param {Order} order
*/
static CREATE_ORDER_RECEIPT(order, target) {
let letter_left_margin = OrderReceipt.CM_TO_POINTS(2.5, false);
let letter_right_margin = OrderReceipt.CM_TO_POINTS(2, false);
let PDFDocument = require("pdfkit");
const doc = new PDFDocument({
size: "A4",
info: {
Title: `Bestellung ${order.getOrderID()}`,
Author: "SUMA-EV - Verein für freien Wissenszugang",
Subject: "MetaGer Schlüssel: Suchanfragen (x300)",
},
});
doc
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf")
.fontSize(10);
// The header with logo and line
doc.image("public/images/metager.png", letter_left_margin, 20, {
height: 20,
});
doc.image("public/images/suma-ev.png", 400, 22, {
height: 18,
});
doc
.moveTo(letter_left_margin, 50)
.lineTo(OrderReceipt.CM_TO_POINTS(21, false) - letter_right_margin, 50)
.strokeColor("#515151")
.stroke();
// Our Address Information
/*
doc
.fontSize(8)
.text(
"SUMA-EV | Röselerstraße 3 | 30159 Hannover | Deutschland",
OrderReceipt.CM_TO_POINTS(2, false),
OrderReceipt.CM_TO_POINTS(4.5, true),
{
width: OrderReceipt.CM_TO_POINTS(8.5, false),
}
);
*/
// General Information
doc
.fontSize(10)
.text(
"Bestellnummer: ",
OrderReceipt.CM_TO_POINTS(21 - 8.5, false),
OrderReceipt.CM_TO_POINTS(5, true),
{
width: OrderReceipt.CM_TO_POINTS(7.5, false),
continued: true,
lineGap: 4,
}
)
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(order.getOrderID(), { align: "right" })
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf")
.text("Telefon:", {
width: OrderReceipt.CM_TO_POINTS(7.5, false),
lineGap: 4,
continued: true,
})
.text("+4951134000070", { align: "right" })
.text("E-Mail:", {
width: OrderReceipt.CM_TO_POINTS(7.5, false),
lineGap: 4,
continued: true,
})
.text("support@metager.de", { align: "right" })
.text("Internet:", {
width: OrderReceipt.CM_TO_POINTS(7.5, false),
lineGap: 4,
continued: true,
})
.text("metager.de", { align: "right" })
.moveDown()
.text("Datum:", {
width: OrderReceipt.CM_TO_POINTS(7.5, false),
lineGap: 4,
continued: true,
})
.text(dayjs().format("DD.MM.YYYY"), { align: "right" });
// Actual content of the letter
// Orange Line
doc
.moveTo(
OrderReceipt.CM_TO_POINTS(2.5, false),
OrderReceipt.CM_TO_POINTS(12.5, true)
)
.lineTo(
OrderReceipt.CM_TO_POINTS(21 - 2, false),
OrderReceipt.CM_TO_POINTS(12.5, true)
)
.strokeColor("#ff7f00")
.stroke();
doc
.fontSize(10)
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(
"Auftragsbestätigung " + order.getOrderID(),
OrderReceipt.CM_TO_POINTS(2.5, false),
OrderReceipt.CM_TO_POINTS(9.846, true)
);
doc
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(
"Bestelldetails",
OrderReceipt.CM_TO_POINTS(2.5, false),
OrderReceipt.CM_TO_POINTS(12, true),
{
width: OrderReceipt.CM_TO_POINTS(10, false),
align: "center",
}
)
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf")
.moveDown()
.text("MetaGer Schlüssel: Suchanfragen (300x)", {
width: OrderReceipt.CM_TO_POINTS(10, false),
align: "right",
});
doc
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(
"Anzahl",
OrderReceipt.CM_TO_POINTS(12.5, false),
OrderReceipt.CM_TO_POINTS(12, true),
{
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "center",
}
)
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf")
.moveDown()
.text(order.getAmount() / 300, {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
lineGap: 15,
})
.text("MwSt (7%)", {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
lineGap: 10,
})
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text("Gesamtbetrag", {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
});
doc
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(
"Preis",
OrderReceipt.CM_TO_POINTS(15.75, false),
OrderReceipt.CM_TO_POINTS(12, true),
{
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "center",
}
)
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf")
.moveDown()
.text(order.getNettoPrice() + "", {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
lineGap: 15,
})
.text(order.getVatAmount() + "", {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
lineGap: 10,
})
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text(order.getPrice() + "", {
width: OrderReceipt.CM_TO_POINTS(3.25, false),
align: "right",
})
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf");
// Footer
let textbox_width = doc.widthOfString("Vorstand");
doc.fontSize(8);
textbox_width = Math.max(
doc.widthOfString("Dominik Hebeler", "Manuela Branz", "Carsten Riel")
);
console.log(textbox_width);
doc.fontSize(10);
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), {
lineBreak: false,
})
.fontSize(8)
.moveDown(1.5)
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf");
doc.x = x;
doc
.text("Dominik Hebeler", {
lineBreak: false,
})
.moveDown();
doc.x = x;
doc
.text("Manuela Branz", {
lineBreak: false,
})
.moveDown();
doc.x = x;
doc.text("Carsten Riel", {
lineBreak: false,
});
x = OrderReceipt.CM_TO_POINTS(2.5, false);
doc
.font("public/fonts/liberation-sans/LiberationSans-Bold.ttf")
.text("SUMA-EV", x, OrderReceipt.CM_TO_POINTS(27.2, true), {
lineBreak: false,
})
.fontSize(8)
.moveDown(1.5)
.font("public/fonts/liberation-sans/LiberationSans-Regular.ttf");
doc.x = x;
doc
.text("Röselerstraße 3", {
lineBreak: false,
})
.moveDown();
doc.x = x;
doc
.text("30159 Hannover", {
lineBreak: false,
})
.moveDown();
doc.x = x;
doc.text("Deutschland", {
lineBreak: false,
});
doc.end();
return doc;
}
/**
*
* @param {Number} cm
* @param {boolean} height
* @returns
*/
static CM_TO_POINTS(cm, vertical) {
let width_in_points = 595.28;
let height_in_points = 841.89;
if (vertical) {
return cm * (height_in_points / 29.7);
} else {
return cm * (width_in_points / 21.0);
}
}
}
module.exports = OrderReceipt;
......@@ -3,7 +3,8 @@
"url": "http://localhost:8080"
},
"price": {
"per_300": 5
"per_300": 5,
"vat": 7
},
"redis": {
"host": "redis"
......
This diff is collapsed.
......@@ -23,6 +23,7 @@
"less-middleware": "~2.2.1",
"morgan": "~1.9.1",
"node-forge": "^1.3.1",
"pdfkit": "^0.13.0",
"qrcode": "^1.5.1",
"uuid": "^9.0.0"
},
......
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://inkscape.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:ns1="http://sozi.baierouge.fr"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
id="svg1"
sodipodi:docbase="/home/danny/work/kde/koffice/templates/kspread"
inkscape:export-ydpi="72.000000"
viewBox="0 0 60 60"
inkscape:export-xdpi="72.000000"
version="1.0"
sodipodi:docname="crsc-action-template_invoice.svg"
inkscape:export-filename="/home/danny/work/kde/koffice/templates/kspread/cr48-action-template_invoice.png"
inkscape:version="0.41"
sodipodi:version="0.32"
_SVGFile__filename="oldscale/actions/aobottom.svg"
y="0"
x="0"
>
<sodipodi:namedview
id="base"
bordercolor="#666666"
inkscape:window-x="0"
inkscape:window-y="0"
pagecolor="#ffffff"
inkscape:zoom="6.0612328"
inkscape:pageshadow="2"
borderopacity="1.0"
inkscape:current-layer="svg1"
inkscape:cx="64.719876"
inkscape:cy="29.172597"
inkscape:window-width="1020"
inkscape:pageopacity="0.0000000"
inkscape:window-height="691"
/>
<g
id="g2079"
transform="matrix(1.0513 0 0 1.0513 -1.5376 -1.5376)"
>
<path
id="path2077"
sodipodi:nodetypes="cccccc"
style="stroke-linejoin:round;color:#000000;display:block;stroke:#ffffff;stroke-linecap:round;stroke-width:7.1343;fill:none"
d="m11.75 54.375v-48.75h27.688l8.812 8.813v39.937h-36.5z"
/>
<path
id="rect1089"
sodipodi:nodetypes="cccccc"
style="stroke-linejoin:round;color:#000000;display:block;stroke:#000000;stroke-linecap:round;stroke-width:2.3781;fill:#ffffff"
d="m11.75 54.375v-48.75h27.688l8.812 8.813v39.937h-36.5z"
/>
<path
id="path1713"
sodipodi:nodetypes="cccc"
style="stroke-linejoin:round;color:#000000;display:block;stroke:#000000;stroke-linecap:round;stroke-width:2.3781;fill:#000000"
d="m39.437 14.438v-8.813l8.813 8.813h-8.813z"
/>
</g
>
<path
id="path1326"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m17.052 10.931h8.685"
/>
<path
id="path1334"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 47.316h5.797"
/>
<g
id="g1344"
style="stroke:#000000"
transform="matrix(.39577 0 0 1 10.303 0)"
>
<path
id="path1346"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:3.9739;fill:none"
d="m17.052 22.068h28.899"
/>
<path
id="path1348"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:3.9739;fill:none"
d="m17.052 27.13h20.826"
/>
<path
id="path1350"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:3.9739;fill:none"
d="m17.052 32.192h33.477"
/>
<path
id="path1352"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:3.9739;fill:none"
d="m17.052 42.316h17.797"
/>
<path
id="path1354"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:3.9739;fill:none"
d="m17.052 37.254h30.95"
/>
</g
>
<path
id="path2116"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 42.316h5.797"
/>
<path
id="path2118"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 37.316h5.797"
/>
<path
id="path2120"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 32.316h5.797"
/>
<path
id="path2122"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 27.316h5.797"
/>
<path
id="path2124"
sodipodi:nodetypes="cc"
style="stroke-linejoin:round;stroke:#000000;stroke-linecap:round;stroke-width:2.5;fill:none"
d="m37.151 22.316h5.797"
/>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>
pass/public/images/metager.png

10.9 KiB

pass/public/images/suma-ev.png

11.5 KiB

......@@ -70,12 +70,12 @@ button {
.button.share,
.button.download {
display: none;
justify-content: center;
align-content: center;
&.download {
display: flex;
img {
height: 2em;
height: 1.5em;
}
}
......
#checkout-amount-template{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#checkout-amount-template>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#checkout-amount-template>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#checkout-amount-template>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}#checkout #checkout-amount{display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;justify-items:center;align-items:center}#checkout #checkout-amount.single{grid-template-columns:1fr}#checkout #checkout-amount>a{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#checkout #checkout-amount>a>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#checkout #checkout-amount>a>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#checkout #checkout-amount>a>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}@media (max-width:800px){#checkout #checkout-amount{grid-template-columns:1fr 1fr}#checkout #checkout-amount.single{grid-template-columns:1fr}}@media (max-width:470px){#checkout #checkout-amount{grid-template-columns:1fr}#checkout #checkout-amount>a{width:100%;grid-template-columns:1fr 3em}}#payment{margin-bottom:1rem}#payment>h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#payment>label[for="payment-group-paypal"]{border:1px solid #777;display:block;padding:.5rem;border-top-left-radius:5px;border-top-right-radius:5px;background-color:#f0f0f0;border-bottom-color:#ff7f00;border-bottom-width:2px}#payment>#payment-group-paypal{display:none}#payment>.payment-group{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:center;justify-items:center;gap:1rem;border:1px solid #777;padding:1rem;border-top:0;place-items:stretch}#payment>.payment-group>div{width:14em}@media (max-width:930px){#payment>.payment-group{grid-template-columns:1fr 1fr}}@media (max-width:470px){#payment>.payment-group{grid-template-columns:1fr}}#payment>.payment-group>div{min-width:10em}#payment>.payment-group#paypal-payments>.funding_source{display:flex;border:1px solid #777;padding:1rem;align-items:center;justify-content:center;height:2em;border-radius:5px;gap:.5rem;color:inherit;text-decoration:none}#payment>.payment-group#paypal-payments>.funding_source img{max-width:100%;max-height:100%}#paypal-checkout>h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#paypal-checkout>#loading_paypal_funding_source{display:flex;align-items:center;justify-content:center;gap:1rem;color:#777;padding:2rem 0}#paypal-checkout>#loading_paypal_funding_source img{width:2rem}#paypal-checkout #paypal-payment-card #paypal-card-form{display:grid;grid-template-columns:1fr 5em;grid-template-rows:1fr auto auto;place-items:stretch;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>div{display:flex;flex-direction:column;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label{font-weight:bold;font-size:.8rem;white-space:nowrap}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label.error{color:red;line-height:1}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label.error::before{font-size:initial}#paypal-checkout #paypal-payment-card #paypal-card-form>div>div{height:2.3rem;border:1px solid #777;border-radius:5px}#paypal-checkout #paypal-payment-card #paypal-card-form>div.card-holder-name{grid-column:span 2}#paypal-checkout #paypal-payment-card #paypal-card-form>div.card-holder-name input{padding:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card{grid-column:span 2;padding:.5rem;justify-self:center;display:flex;white-space:nowrap;align-items:center;line-height:1;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card>img{display:none}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card.loading>img{display:block}@media (max-width:920px){#paypal-checkout #paypal-payment-card #paypal-card-form{grid-template-columns:1fr}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card{grid-column:auto}}main{max-width:980px;margin:0 auto;display:grid;row-gap:1rem;padding-right:1rem;grid-template-columns:auto 1fr;grid-template-rows:auto 1fr auto auto;grid-template-areas:"qr key " "qr setting-url" "qr buttons" "amount charge"}main>#qr{grid-area:qr;justify-self:center}main #key{grid-area:key;font-size:clamp(.9rem, 4.8vw, 1.5rem);font-weight:bold;width:max-content;margin-top:11px;margin-right:1rem}main #setting-url{grid-area:setting-url;align-self:start;display:flex;padding:.5rem 1rem;border-radius:5px}main #setting-url>input{line-height:1.5;padding:.1rem .5rem;border-radius:5px;flex-grow:1}main>#buttons{grid-area:buttons;display:flex;gap:1rem;margin-bottom:17px;justify-content:flex-end}@media (max-width:435px){main>#buttons{display:grid;grid-template-columns:1fr}main>#buttons .button{width:auto}main>#buttons>*{display:grid;justify-items:center;text-align:center}}main>#amount{grid-area:amount;max-width:200px;justify-self:center;display:flex;flex-direction:column;align-items:center}main>#amount>h3{font-size:1.5rem;margin:0}main>#amount>div.amount{font-size:3rem}main>#charge{grid-area:charge}main>#charge>#store>p{line-height:1.5}@media (max-width:770px){main{padding:0 1rem;grid-template-rows:auto auto auto auto auto;grid-template-columns:auto auto;grid-template-areas:"amount qr " "key key" "setting-url setting-url" "buttons buttons " "charge charge "}main>#key{margin:0;justify-self:center}main>#setting-url{text-align:center}main>#buttons{justify-content:center;margin-bottom:0}main>#amount{align-self:center}main>#charge>#store{display:flex;flex-direction:column;align-items:center}}@media (max-width:430px){main{grid-template-rows:auto auto auto auto auto auto;grid-template-columns:auto;grid-template-areas:"qr" "key" "setting-url" "buttons" "amount" "charge"}}h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#summary{display:flex;align-items:center;gap:1rem;justify-content:center;margin-bottom:3rem}#summary>.checkout-amount{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#summary>.checkout-amount>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#summary>.checkout-amount>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#summary>.checkout-amount>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}#summary>.funding_source{height:4.5rem;width:11rem;display:grid;place-content:center;place-items:center;border:1px solid #777;border-radius:10px;color:inherit;text-decoration:none;gap:.5rem}#summary>.funding_source img{max-width:70%;max-height:100%}@media (max-width:430px){#summary{flex-direction:column}}
\ No newline at end of file
#checkout-amount-template{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#checkout-amount-template>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#checkout-amount-template>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#checkout-amount-template>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}#checkout #checkout-amount{display:grid;grid-template-columns:1fr 1fr 1fr;gap:1rem;justify-items:center;align-items:center}#checkout #checkout-amount.single{grid-template-columns:1fr}#checkout #checkout-amount>a{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#checkout #checkout-amount>a>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#checkout #checkout-amount>a>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#checkout #checkout-amount>a>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}@media (max-width:800px){#checkout #checkout-amount{grid-template-columns:1fr 1fr}#checkout #checkout-amount.single{grid-template-columns:1fr}}@media (max-width:470px){#checkout #checkout-amount{grid-template-columns:1fr}#checkout #checkout-amount>a{width:100%;grid-template-columns:1fr 3em}}#payment{margin-bottom:1rem}#payment>h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#payment>label[for="payment-group-paypal"]{border:1px solid #777;display:block;padding:.5rem;border-top-left-radius:5px;border-top-right-radius:5px;background-color:#f0f0f0;border-bottom-color:#ff7f00;border-bottom-width:2px}#payment>#payment-group-paypal{display:none}#payment>.payment-group{display:grid;grid-template-columns:1fr 1fr 1fr;align-items:center;justify-items:center;gap:1rem;border:1px solid #777;padding:1rem;border-top:0;place-items:stretch}#payment>.payment-group>div{width:14em}@media (max-width:930px){#payment>.payment-group{grid-template-columns:1fr 1fr}}@media (max-width:470px){#payment>.payment-group{grid-template-columns:1fr}}#payment>.payment-group>div{min-width:10em}#payment>.payment-group#paypal-payments>.funding_source{display:flex;border:1px solid #777;padding:1rem;align-items:center;justify-content:center;height:2em;border-radius:5px;gap:.5rem;color:inherit;text-decoration:none}#payment>.payment-group#paypal-payments>.funding_source img{max-width:100%;max-height:100%}#paypal-checkout>h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#paypal-checkout>#loading_paypal_funding_source{display:flex;align-items:center;justify-content:center;gap:1rem;color:#777;padding:2rem 0}#paypal-checkout>#loading_paypal_funding_source img{width:2rem}#paypal-checkout #paypal-payment-card #paypal-card-form{display:grid;grid-template-columns:1fr 5em;grid-template-rows:1fr auto auto;place-items:stretch;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>div{display:flex;flex-direction:column;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label{font-weight:bold;font-size:.8rem;white-space:nowrap}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label.error{color:red;line-height:1}#paypal-checkout #paypal-payment-card #paypal-card-form>div>label.error::before{font-size:initial}#paypal-checkout #paypal-payment-card #paypal-card-form>div>div{height:2.3rem;border:1px solid #777;border-radius:5px}#paypal-checkout #paypal-payment-card #paypal-card-form>div.card-holder-name{grid-column:span 2}#paypal-checkout #paypal-payment-card #paypal-card-form>div.card-holder-name input{padding:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card{grid-column:span 2;padding:.5rem;justify-self:center;display:flex;white-space:nowrap;align-items:center;line-height:1;gap:.5rem}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card>img{display:none}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card.loading>img{display:block}@media (max-width:920px){#paypal-checkout #paypal-payment-card #paypal-card-form{grid-template-columns:1fr}#paypal-checkout #paypal-payment-card #paypal-card-form>button#submit-credit-card{grid-column:auto}}main{max-width:980px;margin:0 auto;display:grid;row-gap:1rem;padding-right:1rem;grid-template-columns:auto 1fr;grid-template-rows:auto 1fr auto auto;grid-template-areas:"qr key " "qr setting-url" "qr buttons" "amount content"}main>#qr{grid-area:qr;justify-self:center}main #key{grid-area:key;font-size:clamp(.9rem, 4.8vw, 1.5rem);font-weight:bold;width:max-content;margin-top:11px;margin-right:1rem}main #setting-url{grid-area:setting-url;align-self:start;display:flex;padding:.5rem 1rem;border-radius:5px}main #setting-url>input{line-height:1.5;padding:.1rem .5rem;border-radius:5px;flex-grow:1}main>#buttons{grid-area:buttons;display:flex;gap:1rem;margin-bottom:17px;justify-content:flex-end}@media (max-width:450px){main>#buttons{display:grid;grid-template-columns:1fr}main>#buttons .button{width:auto}}main>#amount{grid-area:amount;max-width:200px;justify-self:center;display:flex;flex-direction:column;align-items:center}main>#amount>h3{font-size:1.5rem;margin:0}main>#amount>div.amount{font-size:3rem}main>#charge{grid-area:content}main>#charge>#store>p{line-height:1.5}@media (max-width:770px){main{padding:0 1rem;grid-template-rows:auto auto auto auto auto;grid-template-columns:auto auto;grid-template-areas:"amount qr " "key key" "setting-url setting-url" "buttons buttons " "content content "}main>#key{margin:0;justify-self:center}main>#setting-url{text-align:center}main>#buttons{justify-content:center;margin-bottom:0}main>#amount{align-self:center}main>#charge>#store{display:flex;flex-direction:column;align-items:center}}@media (max-width:430px){main{grid-template-rows:auto auto auto auto auto auto;grid-template-columns:auto;grid-template-areas:"qr" "key" "setting-url" "buttons" "amount" "content"}}h2{margin:0 0 1rem;text-align:center;border-bottom:1px solid #ff7f00}#summary{display:flex;align-items:center;gap:1rem;justify-content:center;margin-bottom:3rem}#summary>.checkout-amount{text-decoration:none;color:inherit;display:grid;grid-template-columns:7em 3.5em;grid-template-rows:2.5em 2em;place-items:stretch}#summary>.checkout-amount>.checkout-amount{font-size:2rem;font-weight:bold;line-height:1;display:flex;align-items:center;justify-content:center;border-top-left-radius:10px;border:1px solid #ff7f00;border-bottom:0;border-right:0}#summary>.checkout-amount>.checkout-duration{border-bottom-left-radius:10px;display:flex;align-items:center;justify-content:center;border:1px solid #ff7f00;border-top:0;border-right:0}#summary>.checkout-amount>.checkout-cost{grid-row:span 2;justify-content:center;background-color:#ff7f00;color:white;font-size:1.7rem;align-items:center;border-top-right-radius:10px;border-bottom-right-radius:10px;border:1px solid #ff7f00;border-left:0;display:flex}#summary>.funding_source{height:4.5rem;width:11rem;display:grid;place-content:center;place-items:center;border:1px solid #777;border-radius:10px;color:inherit;text-decoration:none;gap:.5rem}#summary>.funding_source img{max-width:70%;max-height:100%}@media (max-width:430px){#summary{flex-direction:column}}
\ No newline at end of file
......@@ -14,7 +14,7 @@ main {
padding-right: 1rem;
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr auto auto;
grid-template-areas: "qr key " "qr setting-url" "qr buttons" "amount charge";
grid-template-areas: "qr key " "qr setting-url" "qr buttons" "amount content";
> #qr {
grid-area: qr;
......@@ -52,19 +52,13 @@ main {
margin-bottom: 17px;
justify-content: flex-end;
@media (max-width: 435px) {
@media (max-width: 450px) {
display: grid;
grid-template-columns: 1fr;
.button {
width: auto;
}
> * {
display: grid;
justify-items: center;
text-align: center;
}
}
}
......@@ -87,7 +81,7 @@ main {
}
> #charge {
grid-area: charge;
grid-area: content;
> #store {
> p {
......@@ -100,7 +94,7 @@ main {
padding: 0 1rem;
grid-template-rows: auto auto auto auto auto;
grid-template-columns: auto auto;
grid-template-areas: "amount qr " "key key" "setting-url setting-url" "buttons buttons " "charge charge ";
grid-template-areas: "amount qr " "key key" "setting-url setting-url" "buttons buttons " "content content ";
> #key {
margin: 0;
......@@ -132,7 +126,7 @@ main {
@media (max-width: @key-breakpoint-2) {
grid-template-rows: auto auto auto auto auto auto;
grid-template-columns: auto;
grid-template-areas: "qr" "key" "setting-url" "buttons" "amount" "charge";
grid-template-areas: "qr" "key" "setting-url" "buttons" "amount" "content";
}
}
......
@import "./misc/vars.less";
#order {
grid-area: content;
#order-details {
display: grid;
grid-template-columns: 1fr 4rem 4rem;
text-align: right;
> div {
&.heading {
text-align: left;
border-bottom: 1px solid @color-main;
font-weight: bold;
padding-bottom: 0.2rem;
}
&:not(.heading) {
padding: 0.5rem 0;
}
&.sum {
font-weight: bold;
}
}
}
> h3 {
text-align: center;
}
#order-buttons {
display: flex;
justify-content: flex-end;
gap: 0.5rem;
.button {
font-size: 0.8rem;
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
gap: 0.5rem;
padding: 0.5rem;
img {
height: 1rem;
filter: brightness(0) invert(1);
}
}
}
}
......@@ -37,6 +37,7 @@ router.use("/:key", param("key").isUUID(4), async (req, res, next) => {
qr: qr_data_uri,
},
js: [],
css: ["/styles/key/key.css"],
};
next("route");
});
......
......@@ -3,17 +3,32 @@ var router = express.Router({ mergeParams: true });
const { param, validationResult } = require("express-validator");
const Order = require("../app/Order");
router.use("/", (req, res, next) => {
Order.LOAD_ORDERS_FROM_KEY(req.data.key.key).then(
/** @param {Order} order */ (orders) => {
req.data.orders = orders;
res.status(200).json(req.data);
}
);
const dayjs = require("dayjs");
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;
next("route");
})
.catch((reason) => {
res.status(404).json({ errors: [{ msg: "Order could not be found" }] });
});
});
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);
res.status(200).header({
"Content-Type": "application/pdf",
});
doc.pipe(res);
});
module.exports = router;
<%- include('templates/page_header', {css: ["/styles/key/key.css"], js: js}); %>
<%- include('templates/page_header', {css: css, js: js}); %>
<img id="qr" src="<%= key.qr %> "></img>
<div id="key">
......
<div id="order">
<h1><%= order.getAmount() %></h1>
<h2>Ihre Bestellung Nr. <%= order.getOrderID() %></h2>
<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"></div>
<div class="price"><%= order.getVatAmount() %> €</div>
<div class="item sum">Gesamtbetrag</div>
<div class="count"></div>
<div class="price"><%= 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">
<img src="/images/download.svg" alt="" />
<span>Auftragsbestätigung herunterladen</span>
</a>
<a href="#" class="button">
<img src="/images/invoice.svg" alt="" />
<span>Rechnung beantragen</span>
</a>
</div>
</div>
\ No newline at end of file
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