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

added base interface to process cash payments

parent df10e043
No related branches found
No related tags found
No related merge requests found
...@@ -16,6 +16,12 @@ const mglangdetector = require("./app/Langdetector"); ...@@ -16,6 +16,12 @@ const mglangdetector = require("./app/Langdetector");
const langdetector = new i18nextmiddleware.LanguageDetector(); const langdetector = new i18nextmiddleware.LanguageDetector();
langdetector.addDetector(mglangdetector); langdetector.addDetector(mglangdetector);
let ns = []; let ns = [];
readdirSync(path.join(__dirname, 'lang', "de")).forEach((fileName) => {
const joinedPath = path.join(path.join(__dirname, 'lang', 'de'), fileName)
if (!lstatSync(joinedPath).isDirectory()) {
ns.push(fileName.replace(".json", ""));
}
});
i18next.use(langdetector).use(i18nextfsbackend).init({ i18next.use(langdetector).use(i18nextfsbackend).init({
debug: false, debug: false,
......
const { writeFileSync, readFileSync, existsSync } = require("fs");
const dayjs = require("dayjs");
const config = require("config");
class Exchangerates {
#data_path = "/data/exchangerates.json";
#currencies = [
"USD",
"CAD",
"GBP"
];
#exchangerates = {
};
constructor() {
if (existsSync(this.#data_path)) {
this.#exchangerates = JSON.parse(readFileSync(this.#data_path));
}
}
async update() {
let currentdate = dayjs();
let date_formatted = currentdate.format("YYYY-MM-DD");
if (!(date_formatted in this.#exchangerates)) {
let api_url = new URL(config.get("payments.exchange_api_apilayer.host"));
let exchangerate = {}
for (let i = 0; i < this.#currencies.length; i++) {
let params = new URLSearchParams({
symbols: "EUR",
base: this.#currencies[i]
});
api_url.search = params.toString();
await fetch(api_url).then(result => result.json()).then(result => {
exchangerate[this.#currencies[i]] = result.rates.EUR;
}).catch(reason => {
console.error("reason");
exchangerate = null;
})
if (exchangerate === null) {
break;
}
}
if (exchangerate !== null) {
this.#exchangerates[date_formatted] = exchangerate;
this.save();
}
}
}
save() {
writeFileSync(this.#data_path, JSON.stringify(this.#exchangerates));
}
}
module.exports = Exchangerates;
\ No newline at end of file
...@@ -5,6 +5,7 @@ const config = require("config"); ...@@ -5,6 +5,7 @@ const config = require("config");
const path = require("path"); const path = require("path");
const { writeFileSync } = require("fs"); const { writeFileSync } = require("fs");
const { exec } = require("child_process"); const { exec } = require("child_process");
const Exchangerates = require("../app/Exchangerates");
let redis_client; let redis_client;
/** /**
* Will call every cron script every minute. * Will call every cron script every minute.
...@@ -25,6 +26,12 @@ let cronjobs = async () => { ...@@ -25,6 +26,12 @@ let cronjobs = async () => {
"YYYY-MM-DD HH:mm:ss" "YYYY-MM-DD HH:mm:ss"
)}] Written ${written_logs} key changes.` )}] Written ${written_logs} key changes.`
); );
await fetchExchangerates();
console.log(
`[${now.format(
"YYYY-MM-DD HH:mm:ss"
)}] Fetched exchange rates.`
);
await accentSync(); await accentSync();
await redis_client.quit(); await redis_client.quit();
console.log(`[${now.format("YYYY-MM-DD HH:mm:ss")}] Finish`); console.log(`[${now.format("YYYY-MM-DD HH:mm:ss")}] Finish`);
...@@ -66,6 +73,18 @@ async function accentSync() { ...@@ -66,6 +73,18 @@ async function accentSync() {
} }
async function fetchExchangerates() {
let redis_lock_key = "cron:fetchExchangerates";
let interval_seconds = 60 * 15; // Will execute every 15 minutes
let lock = await tryToGetLock(redis_lock_key, interval_seconds);
if (!lock) {
return 0;
}
let exchagerates = new Exchangerates();
await exchagerates.update();
}
async function writeLogsToOrder() { async function writeLogsToOrder() {
let redis_lock_key = "cron:writeLogsToOrder"; let redis_lock_key = "cron:writeLogsToOrder";
let interval_seconds = 60; // Will execute every minute let interval_seconds = 60; // Will execute every minute
......
...@@ -36,7 +36,14 @@ ...@@ -36,7 +36,14 @@
"price": { "price": {
"per_300": 10, "per_300": 10,
"vat": 7, "vat": 7,
"purchasable": [300, 600, 900, 1200, 1800, 3600] "purchasable": [
300,
600,
900,
1200,
1800,
3600
]
}, },
"redis": { "redis": {
"host": "express_redis", "host": "express_redis",
...@@ -80,6 +87,10 @@ ...@@ -80,6 +87,10 @@
"services": { "services": {
"paysafecard": {} "paysafecard": {}
} }
},
"exchange_api_apilayer": {
"host": "https://api.apilayer.com/exchangerates_data/live",
"api_key": "<APILAYER_API_KEY>"
} }
} }
} }
\ No newline at end of file
{
"breadcrumps": {
"overview": "Übersicht",
"payments-cash": "Barzahlung erfassen"
},
"index": {
"actions": {
"cash-payment": "Bargeldzahlung erfassen",
"heading": "Aktionen:"
},
"heading": "MetaGer Schlüssel Admin"
},
"cash-payment": {
"info": "Erfasse hier eingegangene Barzahlungen um die zugehörigen Bestellungen zu buchen",
"price": {
"placeholder": "10,00",
"label": "Eingegangener Betrag"
},
"orderid": {
"label": "Bestellnummer:",
"placeholder": "123456789"
}
}
}
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
@import "../misc/vars.less";
div#admin-container {
max-width: @max-content-width;
margin: 0 auto;
h1 {
border-bottom: 1px solid @color-main;
text-align: center;
}
h2 {
width: max-content;
}
ul.breadcrumps {
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 1.5rem;
color: lighten(@font-color-on-white, 10%);
> li {
&:first-child {
list-style-type: none;
}
}
}
}
div#admin-container div#action-container{display:flex;flex-wrap:wrap;margin-top:2rem}div#admin-container div#action-container>a{display:flex;gap:.5rem;align-items:center;border:1px solid #ef7700;padding:1rem;border-radius:10px;text-decoration:none;color:inherit;cursor:pointer}div#admin-container div#action-container>a>img{width:2em}
\ No newline at end of file
@import "../misc/vars.less";
div#admin-container {
div#action-container {
display: flex;
flex-wrap: wrap;
margin-top: 2rem;
> a {
display: flex;
gap: 0.5rem;
align-items: center;
border: 1px solid @color-main;
padding: 1rem;
border-radius: 10px;
text-decoration: none;
color: inherit;
cursor: pointer;
> img {
width: 2em;
}
}
}
}
var express = require("express");
var router = express.Router();
const config = require("config");
const { auth, requiresAuth, claimCheck } = require("express-openid-connect");
router.use(requiresAuth());
router.get("/", (req, res) => {
res.render("admin/index");
});
router.get("/payments/cash", (req, res) => {
res.render("admin/payments/cash");
})
module.exports = router;
\ No newline at end of file
...@@ -7,6 +7,7 @@ var browserify = require("browserify-middleware"); ...@@ -7,6 +7,7 @@ var browserify = require("browserify-middleware");
var paypalCheckoutRouter = require("../routes/checkout/paypal.js"); var paypalCheckoutRouter = require("../routes/checkout/paypal.js");
var micropaymentCheckoutRouter = require("../routes/checkout/micropayment"); var micropaymentCheckoutRouter = require("../routes/checkout/micropayment");
var apiRouter = require("./api"); var apiRouter = require("./api");
var adminRouter = require("./admin/index");
var path = require("path"); var path = require("path");
const config = require("config"); const config = require("config");
...@@ -19,6 +20,8 @@ router.use("/api/json", apiRouter); ...@@ -19,6 +20,8 @@ router.use("/api/json", apiRouter);
var authenticationRouter = require("../routes/authentication"); var authenticationRouter = require("../routes/authentication");
router.use("/", authenticationRouter); router.use("/", authenticationRouter);
router.use("/admin", adminRouter);
/* GET home page. */ /* GET home page. */
router.get("/", function (req, res, next) { router.get("/", function (req, res, next) {
req.i18n.setDefaultNamespace("index"); // Default NS for localized Strings req.i18n.setDefaultNamespace("index"); // Default NS for localized Strings
......
<%- include('../templates/page_header', {css: [`${baseDir}/styles/admin/base.css`, `${baseDir}/styles/admin/index.css`], js: []}); %>
<div id="admin-container">
<h1><%= req.t("index.heading", {ns: "admin"}) _%></h1>
<ul class="breadcrumps">
<li><%= req.t("breadcrumps.overview", {ns: "admin"}) _%></li>
</ul>
<h2><%= req.t("index.actions.heading", {ns: "admin"}) _%></h2>
<div id="action-container">
<a id="action-cash-payment" href="<%= baseDir %>/admin/payments/cash">
<img src="<%= baseDir %>/images/money.svg" alt="Geldschein">
<div><%= req.t("index.actions.cash-payment", {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/cash.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>
<li><%= req.t("breadcrumps.payments-cash", {ns: "admin"}) _%></li>
</ul>
<p><%= req.t("cash-payment.info", {ns: "admin"}) _%></p>
<form method="POST">
<div class="input-group">
<label for="orderid"><%= req.t("cash-payment.orderid.label", {ns: "admin"}) _%></label>
<input type=" text" name="orderid" id="orderid" placeholder="<%= req.t("cash-payment.orderid.placeholder", {ns: "admin"}) _%>">
</div>
<div class="input-group">
<label for="price"><%= req.t("cash-payment.price.label", {ns: "admin"}) _%></label>
<input type="number" name="price" id="price" placeholder="<%= req.t("cash-payment.price.placeholder", {ns: "admin"}) _%>" step="0.01">
<select name="currency" id="currency">
<option value="EUR" selected>EUR</option>
<option value="USD">USD</option>
<option value="CAD">CAD</option>
<option value="GBP">GBP</option>
</select>
</div>
</form>
</div>
<%- include('../../templates/page_footer'); -%>
\ 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