diff --git a/pass/app/Payment.js b/pass/app/Payment.js index 13f48adf87900671c5fe74564cd0220f68d9222d..bb7540faab48eceb48dd0eb622f78d91ee5a7c54 100644 --- a/pass/app/Payment.js +++ b/pass/app/Payment.js @@ -11,7 +11,10 @@ const PaymentProcessor = require("./payment_processor/PaymentProcessor"); * @property {number} PaymentsDB.price * @property {number} PaymentsDB.converted_price * @property {string} PaymentsDB.converted_currency - * @property {number} PaymentsDB.payment_reference + * @property {number} PaymentsDB.payment_reference_id + * @property {number} PaymentsDB.payment_processor_id + * @property {string} PaymentsDB.payment_processor_data + * @property {number} PaymentsDB.receipt_id * @property {string} PaymentsDB.created_at */ /** @returns {Knex.QueryBuilder<PaymentsDB, {}>} */ @@ -47,6 +50,9 @@ class Payment { ); } this.payment_processor_id = payment_data.payment_processor_id; + if (payment_data.payment_processor_data) { + this.payment_processor_data = payment_data.payment_processor_data; + } this.receipt_id = payment_data.receipt_id; this.created_at = dayjs(payment_data.created_at); } diff --git a/pass/lang/de/admin.json b/pass/lang/de/admin.json index 733c20676d6dfb1c0411641a0af719b932c38a21..4483878e38cbae1b9c3c9cfc9d6302de217bf57e 100644 --- a/pass/lang/de/admin.json +++ b/pass/lang/de/admin.json @@ -75,6 +75,9 @@ "label": "Betrag (€)" }, "submit": "Jetzt aufladen!" + }, + "payments": { + "heading": "Zahlungen" } } } diff --git a/pass/public/styles/admin/key-overview.css b/pass/public/styles/admin/key-overview.css index 2fc4a7bae848fcd3176071ad2af2fe0936ac941b..97cd5f6b0bfe5da55808ffdf7f55883183d7708f 100644 --- a/pass/public/styles/admin/key-overview.css +++ b/pass/public/styles/admin/key-overview.css @@ -1 +1 @@ -#admin-container{display:grid;gap:1rem}#admin-container .breadcrumps{margin:0}#admin-container #key-info{display:grid;gap:.5rem}#admin-container #key-info h2{margin:0}#admin-container #key-info .charge-success{color:green}#admin-container #key-info #charges{display:flex;gap:1rem;flex-wrap:wrap}#admin-container #key-info #charges .charge{display:grid;gap:.5rem;place-items:center;border:1px solid #777;width:max-content;padding:1rem;border-radius:5px}#admin-container #key-info #charges .charge .charge-amount{font-size:2rem}#admin-container form#charge-form{display:grid;grid-template-columns:repeat(3, auto);gap:1rem;place-items:center}#admin-container form#charge-form .heading,#admin-container form#charge-form .hint,#admin-container form#charge-form .button,#admin-container form#charge-form #errors{grid-column:span 3}@media (max-width:530px){#admin-container form#charge-form{grid-template-columns:auto}#admin-container form#charge-form .heading,#admin-container form#charge-form .hint,#admin-container form#charge-form .button,#admin-container form#charge-form #errors{grid-column:1}}#admin-container form#charge-form h3{margin:0}#admin-container form#charge-form #errors{list-style-type:none;padding:0;color:red}#admin-container form#charge-form .button{padding:.5rem;cursor:pointer}#admin-container form#charge-form .input-group{display:grid;place-items:center;gap:.5rem}#admin-container form#charge-form .input-group>label{font-weight:bold}#admin-container form#charge-form .input-group input{padding:.25rem .5rem;border-radius:5px} \ No newline at end of file +#admin-container{display:grid;gap:1rem}#admin-container .breadcrumps{margin:0}#admin-container #key-info{display:grid;gap:.5rem}#admin-container #key-info h2{margin:0}#admin-container #key-info .charge-success{color:green}#admin-container #key-info #charges{display:flex;gap:1rem;flex-wrap:wrap}#admin-container #key-info #charges .charge{display:grid;gap:.5rem;place-items:center;border:1px solid #777;width:max-content;padding:1rem;border-radius:5px}#admin-container #key-info #charges .charge .charge-amount{font-size:2rem}#admin-container form#charge-form{display:grid;grid-template-columns:repeat(3, auto);gap:1rem;place-items:center}#admin-container form#charge-form .heading,#admin-container form#charge-form .hint,#admin-container form#charge-form .button,#admin-container form#charge-form #errors{grid-column:span 3}@media (max-width:530px){#admin-container form#charge-form{grid-template-columns:auto}#admin-container form#charge-form .heading,#admin-container form#charge-form .hint,#admin-container form#charge-form .button,#admin-container form#charge-form #errors{grid-column:1}}#admin-container form#charge-form h3{margin:0}#admin-container form#charge-form #errors{list-style-type:none;padding:0;color:red}#admin-container form#charge-form .button{padding:.5rem;cursor:pointer}#admin-container form#charge-form .input-group{display:grid;place-items:center;gap:.5rem}#admin-container form#charge-form .input-group>label{font-weight:bold}#admin-container form#charge-form .input-group input{padding:.25rem .5rem;border-radius:5px}#admin-container div#payments{display:grid;gap:3rem}#admin-container div#payments>h1{margin:0;text-align:center}#admin-container div#payments>div.payment{display:grid;gap:.5rem;grid-template-columns:repeat(5, 1fr)}#admin-container div#payments>div.payment>div{white-space:nowrap}#admin-container div#payments>div.payment>details.payment_processor_data{grid-column:span 5}#admin-container div#payments>div.payment>details.payment_processor_data>summary{text-align:center}#admin-container div#payments>div.payment>details.payment_processor_data>p{white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #777;padding:1rem} \ No newline at end of file diff --git a/pass/public/styles/admin/key-overview.less b/pass/public/styles/admin/key-overview.less index 674bf101bd26c76c4c8f0e91de5f3a28fad7ed36..b688183b4a45b936c84d652ba3b9547eabb88a12 100644 --- a/pass/public/styles/admin/key-overview.less +++ b/pass/public/styles/admin/key-overview.less @@ -77,4 +77,33 @@ } } } + + div#payments { + display: grid; + gap: 3rem; + > h1 { + margin: 0; + text-align: center; + } + > div.payment { + display: grid; + gap: 0.5rem; + grid-template-columns: repeat(5, 1fr); + > div { + white-space: nowrap; + } + > details.payment_processor_data { + grid-column: span 5; + > summary { + text-align: center; + } + > p { + white-space: pre-wrap; + background-color: #f5f5f5; + border: 1px solid #777; + padding: 1rem; + } + } + } + } } diff --git a/pass/routes/admin/index.js b/pass/routes/admin/index.js index 61f375046138d36d96a8cc6f8691e4ced4640542..5f445609b65a2397445f3c2b6857f5345b813829 100644 --- a/pass/routes/admin/index.js +++ b/pass/routes/admin/index.js @@ -17,6 +17,7 @@ const PaymentReference = require("../../app/PaymentReference"); const Receipt = require("../../app/Receipt"); const Cash = require("../../app/payment_processor/Cash"); const Key = require("../../app/Key"); +const Paypal = require("../../app/payment_processor/Paypal"); router.use((req, res, next) => { let cookie_path = new URL(res.locals.baseDir).pathname.replace( @@ -353,8 +354,30 @@ router.use("/key/:key", (req, res, next) => { if (req.query.charge_success) { res.locals.success = true; } - Key.GET_KEY(req.params.key, false).then((key) => { + Key.GET_KEY(req.params.key, false).then(async (key) => { res.locals.key = key; + // Get Payments for this key + res.locals.payments = []; + let charge_orders = key.get_charge_orders(); + for (let i = 0; i < charge_orders.length; i++) { + let keyOrder = charge_orders[i]; + await Payment.LOAD_PAYMENTS_FROM_REFERENCE( + keyOrder.payment_reference_id, + key.get_key() + ).then((payments) => { + for (j = 0; j < payments.length; j++) { + if (payments[j].payment_processor instanceof Paypal) { + payments[j].payment_processor_data = JSON.stringify( + JSON.parse(payments[j].payment_processor_data), + null, + 4 + ); + } + res.locals.payments.push(payments[j]); + } + console.log(payments); + }); + } next(); }); }); diff --git a/pass/views/admin/key/overview.ejs b/pass/views/admin/key/overview.ejs index 3d90d9d3a02bcb893f96b548b18f249bedf93192..be7cd1d0c0b8ad04e8b72adb7852877d26e6b0e1 100644 --- a/pass/views/admin/key/overview.ejs +++ b/pass/views/admin/key/overview.ejs @@ -1,4 +1,7 @@ -<%- include('../../templates/page_header', {css: [`${baseDir}/styles/admin/base.css`, `${baseDir}/styles/admin/key-overview.css`], js: [`${baseDir}/js/admin/key-overview.js`]}); %> +<%- include('../../templates/page_header', {css: +[`${baseDir}/styles/admin/base.css`, +`${baseDir}/styles/admin/key-overview.css`], js: +[`${baseDir}/js/admin/key-overview.js`]}); %> <div id="admin-container"> <ul class="breadcrumps"> <li> @@ -10,26 +13,50 @@ </ul> <div id="key-info"> <h1><%= key.get_key() _%></h1> - <h2><%= req.t("key.key-overview.charge", {ns: "admin", token: key.get_charge()}) _%></h2> + <h2> + <%= req.t("key.key-overview.charge", {ns: "admin", token: + key.get_charge()}) _%> + </h2> <%_ if(typeof success !== "undefined") { %> - <div class="charge-success"><%= req.t("key.key-overview.charge-success", {ns: "admin"}) _%></div> + <div class="charge-success"> + <%= req.t("key.key-overview.charge-success", {ns: "admin"}) _%> + </div> <%_ } _%> <div id="charges"> <%_ for(let i = 0; i < key.get_charge_orders().length; i++) { _%> <div class="charge"> - <div class="charge-amount"><%= key.get_charge_orders()[i].amount _%></div> - <div><%= req.t("key.key-overview.expiration", {ns: "admin", expiration: key.get_charge_orders()[i].expiration.format("DD.MM.YYYY HH:mm:ss")}) _%></div> - <form method="POST" action="<%= `${baseDir}/admin/key/${key.get_key()}/remove-charge`%>"> - <input type="hidden" name="payment_reference" value="<%= key.get_charge_orders()[i].payment_reference_id _%>"> - <button type="submit"><%= req.t("key.key-overview.delete", {ns: "admin"}) _%></button> + <div class="charge-amount"> + <%= key.get_charge_orders()[i].amount _%> + </div> + <div> + <%= req.t("key.key-overview.expiration", {ns: "admin", expiration: + key.get_charge_orders()[i].expiration.format("DD.MM.YYYY HH:mm:ss")}) + _%> + </div> + <form + method="POST" + action="<%= `${baseDir}/admin/key/${key.get_key()}/remove-charge`%>" + > + <input + type="hidden" + name="payment_reference" + value="<%= key.get_charge_orders()[i].payment_reference_id _%>" + /> + <button type="submit"> + <%= req.t("key.key-overview.delete", {ns: "admin"}) _%> + </button> </form> </div> <%_ } _%> </div> </div> <form method="POST" id="charge-form"> - <h3 class="heading"><%= req.t("key.key-overview.charge-form.heading", {ns: "admin"}) _%></h3> - <div class="hint"><%= req.t("key.key-overview.charge-form.hint", {ns: "admin"}) _%></div> + <h3 class="heading"> + <%= req.t("key.key-overview.charge-form.heading", {ns: "admin"}) _%> + </h3> + <div class="hint"> + <%= req.t("key.key-overview.charge-form.hint", {ns: "admin"}) _%> + </div> <%_ if(typeof errors !== "undefined") { _%> <ul id="errors"> <%_ for(let i = 0; i < errors.length; i++) { _%> @@ -38,15 +65,66 @@ </ul> <%_ } _%> <div class="input-group"> - <label for="amount"><%= req.t("key.key-overview.charge-form.amount.label", {ns: "admin"}) _%></label> - <input type="number" name="amount" id="amount" min="0" step="1" placeholder="1000"> + <label for="amount" + ><%= req.t("key.key-overview.charge-form.amount.label", {ns: "admin"}) + _%></label + > + <input + type="number" + name="amount" + id="amount" + min="0" + step="1" + placeholder="1000" + /> </div> <div>oder</div> <div class="input-group"> - <label for="price"><%= req.t("key.key-overview.charge-form.price.label", {ns: "admin"}) _%></label> - <input type="number" name="price" id="price" min="0" step="0.01" placeholder="10.00"> + <label for="price" + ><%= req.t("key.key-overview.charge-form.price.label", {ns: "admin"}) + _%></label + > + <input + type="number" + name="price" + id="price" + min="0" + step="0.01" + placeholder="10.00" + /> </div> - <button class="button" type="submit"><%= req.t("key.key-overview.charge-form.submit", {ns: "admin"}) _%></buton> + <button class="button" type="submit"> + <%= req.t("key.key-overview.charge-form.submit", {ns: "admin"}) _%> + </button> </form> + <%_ if(payments.length > 0) { _%> + <div id="payments"> + <h1 class="heading"> + <%= req.t("key.key-overview.payments.heading", {ns: "admin"}) _%> + </h1> + <%_ for(let i = 0; i < payments.length; i++) { _%> + <div class="payment"> + <div class="payment_id_name">ID</div> + <div class="payment_public_id_name">Public ID</div> + <div class="payment_price_name">Betrag</div> + <div class="payment_processor_id_name">Zahlungsdienstleister ID</div> + <div class="payment_created_at_name">Eingangsdatum</div> + <div class="payment_id"><%= payments[i].id _%></div> + <div class="payment_public_id"><%= payments[i].public_id _%></div> + <div class="payment_price"><%= payments[i].price + "€" _%></div> + <div class="payment_processor_id_id"> + <%= payments[i].payment_processor_id _%> + </div> + <div class="payment_processor_id_id"> + <%= payments[i].created_at.format("DD.MM.YYYY HH:mm:ss") _%> + </div> + <details class="payment_processor_data"> + <summary>Zahlungsdienstleister Antwort</summary> + <p><%= payments[i].payment_processor_data _%></p> + </details> + </div> + <%_ } _%> + </div> + <%_ } _%> </div> -<%- include('../../templates/page_footer'); -%> \ No newline at end of file +<%- include('../../templates/page_footer'); -%>