This commit is contained in:
seb
2026-07-31 05:54:13 +02:00
parent 6db7d4d75c
commit db8b192094
32 changed files with 100 additions and 2048 deletions

View File

@@ -1,46 +0,0 @@
import Database from 'better-sqlite3';
import { mkdirSync } from 'fs';
import { dirname, resolve } from 'path';
import { fileURLToPath } from 'url';
import env from '../config/env.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
const defaultPath = resolve(__dirname, '../../data/dashback.db');
let db;
function getDbPath() {
return env.sqlitePath || defaultPath;
}
function initSchema(database) {
database.exec(`
CREATE TABLE IF NOT EXISTS google_auth (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE COLLATE NOCASE,
created_at TEXT NOT NULL DEFAULT (datetime('now'))
)
`);
}
export function getDb() {
if (!db) {
const dbPath = getDbPath();
mkdirSync(dirname(dbPath), { recursive: true });
db = new Database(dbPath);
db.pragma('journal_mode = WAL');
initSchema(db);
}
return db;
}
export function ensureConnection() {
getDb().prepare('SELECT 1').get();
}
export function closeDb() {
if (db) {
db.close();
db = undefined;
}
}

View File

@@ -1,34 +1,27 @@
import { getDb } from './client.js';
import { getStore } from './store.js';
export function listAllowedEmails() {
return getDb()
.prepare('SELECT id, email, created_at FROM google_auth ORDER BY email COLLATE NOCASE')
.all();
export async function listAllowedEmails() {
const store = await getStore();
return store.google_auth.list();
}
export function getAllowedEmail(email) {
return getDb()
.prepare('SELECT id, email, created_at FROM google_auth WHERE email = ? COLLATE NOCASE')
.get(email);
}
export function getAllowedEmailById(id) {
return getDb()
.prepare('SELECT id, email, created_at FROM google_auth WHERE id = ?')
.get(id);
}
export function addAllowedEmail(email) {
export async function getAllowedEmail(email) {
const normalized = email.trim().toLowerCase();
const result = getDb()
.prepare('INSERT INTO google_auth (email) VALUES (?)')
.run(normalized);
return getAllowedEmailById(result.lastInsertRowid);
const store = await getStore();
return (await store.google_auth.getByEmail(normalized)) ?? null;
}
export function removeAllowedEmail(email) {
export async function addAllowedEmail(email) {
const normalized = email.trim().toLowerCase();
return getDb()
.prepare('DELETE FROM google_auth WHERE email = ? COLLATE NOCASE')
.run(normalized).changes > 0;
const store = await getStore();
const id = await store.google_auth.add(normalized);
return { id, email: normalized };
}
export async function removeAllowedEmail(email) {
const row = await getAllowedEmail(email);
if (!row) return false;
const store = await getStore();
await store.google_auth.del(row.id);
return true;
}

View File

@@ -1,28 +0,0 @@
export const LOAD_KAT_MAP = `
SELECT kKategorie, kOberKategorie
FROM dbo.tkategorie
`;
export const LOAD_CATEGORIES = `
SELECT
kKategorie,
kOberKategorie,
nSort,
(
SELECT cName
FROM dbo.tKategorieSprache
WHERE kSprache = 1
AND kPlattform = 1
AND kShop = 0
AND dbo.tkategorie.kKategorie = dbo.tKategorieSprache.kKategorie
) AS cName
FROM dbo.tkategorie
ORDER BY nSort, cName
`;
export const CATEGORY_ARTICLE_COUNTS = `
SELECT ka.kKategorie, COUNT(*) AS count
FROM tkategorieartikel ka
INNER JOIN tArtikel a ON a.kArtikel = ka.kArtikel AND a.cAktiv = 'Y'
GROUP BY ka.kKategorie
`;

View File

@@ -1,248 +0,0 @@
export const FIND_ARTICLE = `
SELECT TOP 1
tArtikelBeschreibung.cBeschreibung,
tArtikelBeschreibung.cKurzBeschreibung,
b.kVersandklasse,
(SELECT cName FROM dbo.tVersandklasse WHERE tVersandklasse.kVersandklasse = b.kVersandklasse) AS tVersandklassecName,
nIstVater,
kStueckliste,
kVaterArtikel,
b.kEigenschaftKombi,
b.kArtikel,
fUVP,
fGewicht,
tHersteller.cName AS cHersteller,
cBarcode,
fBestand,
b.cArtNr,
b.cAktiv,
tArtikelBeschreibung.cName,
b.fVKNEtto,
b.kSteuerklasse,
nVPE,
kMassEinheit,
fMassMenge,
kGrundPreisEinheit,
cAnmerkung,
tEigenschaftSprache.kEigenschaft,
tEigenschaftSprache.cName AS cEigenschaftName,
tEigenschaftWertSprache.kEigenschaftWert,
tEigenschaftWertSprache.cName AS cEigenschaftWertName,
(
SELECT c.cArtNr
FROM tArtikel c
WHERE c.kArtikel = (
SELECT tArtikel_kArtikel
FROM tliefartikel
WHERE cLiefArtNr = b.cArtNr AND tlieferant_klieferant = 96
)
) AS cLiefArtNr96
FROM tArtikelBeschreibung
INNER JOIN tArtikel b ON b.kArtikel = tArtikelBeschreibung.kArtikel
LEFT JOIN dbo.vLagerbestandProLager ON (
dbo.vLagerbestandProLager.kArtikel = b.kArtikel
AND vLagerbestandProLager.kWarenlager = 1
)
LEFT JOIN tGebinde ON b.kArtikel = tGebinde.kArtikel
LEFT JOIN tHersteller ON b.kHersteller = tHersteller.kHersteller
LEFT JOIN tEigenschaftKombiWert ON b.kEigenschaftKombi = tEigenschaftKombiWert.kEigenschaftKombi
LEFT JOIN tEigenschaftSprache ON (
tEigenschaftKombiWert.kEigenschaft = tEigenschaftSprache.kEigenschaft
AND tEigenschaftSprache.kSprache = 1
)
LEFT JOIN tEigenschaftWertSprache ON (
tEigenschaftWertSprache.kEigenschaftWert = tEigenschaftKombiWert.kEigenschaftWert
AND tEigenschaftWertSprache.kSprache = 1
)
WHERE b.cArtNr = @target OR tGebinde.cEAN = @target OR b.cBarcode = @target
`;
export const CHILDREN_BY_VATER = `
SELECT
tArtikel.cArtNr,
tArtikelBeschreibung.cName,
tArtikel.kEigenschaftKombi,
tEigenschaftSprache.kEigenschaft,
tEigenschaftSprache.cName AS cEigenschaftName,
tEigenschaftWertSprache.kEigenschaftWert,
tEigenschaftWertSprache.cName AS cEigenschaftWertName
FROM tArtikelBeschreibung
INNER JOIN tArtikel ON tArtikel.kArtikel = tArtikelBeschreibung.kArtikel
LEFT JOIN tEigenschaftKombiWert ON tArtikel.kEigenschaftKombi = tEigenschaftKombiWert.kEigenschaftKombi
LEFT JOIN tEigenschaftSprache ON (
tEigenschaftKombiWert.kEigenschaft = tEigenschaftSprache.kEigenschaft
AND tEigenschaftSprache.kSprache = 1
)
LEFT JOIN tEigenschaftWertSprache ON (
tEigenschaftWertSprache.kEigenschaftWert = tEigenschaftKombiWert.kEigenschaftWert
AND tEigenschaftWertSprache.kSprache = 1
)
WHERE tArtikel.kVaterArtikel = @kArtikel
`;
export const VATER_BY_ID = `
SELECT tArtikel.cArtNr
FROM tArtikelBeschreibung
INNER JOIN tArtikel ON tArtikel.kArtikel = tArtikelBeschreibung.kArtikel
WHERE tArtikel.kArtikel = @kArtikel
`;
export const STUECKLISTE = `
SELECT
tArtikelBeschreibung.cName,
tArtikel.cArtNr,
tStueckliste.fAnzahl,
tArtikel.fVKNEtto,
tArtikel.kSteuerklasse,
vLagerbestandProLager.fBestand
FROM dbo.tStueckliste
INNER JOIN dbo.tArtikelBeschreibung ON tArtikelBeschreibung.kArtikel = tStueckliste.kArtikel
LEFT JOIN dbo.vLagerbestandProLager ON (
vLagerbestandProLager.kArtikel = tStueckliste.kArtikel
AND vLagerbestandProLager.kWarenlager = 1
)
INNER JOIN dbo.tArtikel ON tArtikel.kArtikel = tStueckliste.kArtikel
WHERE tStueckliste.kStueckliste = @kStueckliste
ORDER BY tStueckliste.nSort
`;
export const ANDERE_LAGER = `
SELECT SUM(fBestand) AS fSumme
FROM dbo.vLagerbestandProLager
WHERE dbo.vLagerbestandProLager.kArtikel = @kArtikel
AND vLagerbestandProLager.kWarenlager != 1
GROUP BY dbo.vLagerbestandProLager.kArtikel
`;
export const EANS = `
SELECT cEAN
FROM tGebinde
WHERE kArtikel = @kArtikel
`;
export function categoriesQuery(katSkipClause, katLists) {
return `
SELECT kKategorie
FROM dbo.tkategorieartikel
WHERE kArtikel = @kArtikel
AND ${katSkipClause}kKategorie NOT IN (
SELECT kKategorie
FROM tKategorie
WHERE kOberKategorie = ${katLists}
)
`;
}
export const SUPPLIERS = `
SELECT
tlieferant.kLieferant,
cFirma,
tliefartikel.cLiefArtNr,
nStandard,
fLagerbestand,
cVPEEinheit,
nVPEMenge,
fMwSt,
fEKNetto,
tShopKorb.nMenge,
tlieferant.cEmail,
tlieferant.cAnmerkung
FROM tliefartikel
INNER JOIN tlieferant ON tlieferant.kLieferant = tliefartikel.tLieferant_kLieferant
LEFT JOIN tShopKorb ON (
tShopKorb.kLieferant = tlieferant.kLieferant
AND tliefartikel.cLiefArtNr = tShopKorb.cLiefArtNr
)
WHERE tArtikel_kArtikel = @kArtikel
ORDER BY nStandard DESC, tlieferant.kLieferant
`;
export const INCOMING_ORDERS = `
SELECT
tLieferantenBestellung.kLieferant,
tLieferantenBestellungPos.kLieferantenBestellungPos,
tLieferantenBestellungPos.kLieferantenBestellung,
cEigeneBestellnummer,
tLieferantenBestellungPos.kLieferantenBestellung + 1 AS kLieferantenBestellung2,
cFirma,
tLieferantenBestellungPos.dLieferdatum,
cFremdbelegnummer,
cInternerKommentar,
fAnzahlOffen
FROM tLieferantenBestellung
INNER JOIN tlieferant ON tlieferant.kLieferant = tLieferantenBestellung.kLieferant
INNER JOIN tLieferantenBestellungPos ON (
tLieferantenBestellungPos.kLieferantenBestellung = tLieferantenBestellung.kLieferantenBestellung
)
WHERE fAnzahlOffen > 0 AND kArtikel = @kArtikel
ORDER BY tLieferantenBestellungPos.kLieferantenBestellung
`;
export const OPEN_INCIDENTS = `
SELECT cType, cNote, kIncident, cEmployeeIssuer, cEmployeeMap
FROM dbo.tIncident
WHERE kRef1 = @kArtikel
AND cState = 'new'
AND cType IN ('order_count', 'order_label', 'order_free')
`;
export const MERKMALE = `
SELECT
tArtikelMerkmal.kMerkmal,
tArtikelMerkmal.kMerkmalWert,
tMerkmalSprache.cName,
tMerkmalWertSprache.cWert
FROM dbo.tArtikelMerkmal
INNER JOIN dbo.tMerkmalSprache ON tMerkmalSprache.kMerkmal = tArtikelMerkmal.kMerkmal
INNER JOIN dbo.tMerkmalWertSprache ON tMerkmalWertSprache.kMerkmalWert = tArtikelMerkmal.kMerkmalWert
WHERE tArtikelMerkmal.kArtikel = @kArtikel
ORDER BY tArtikelMerkmal.kMerkmal
`;
export const ATTRIBUTES = `
SELECT
tArtikelAttribut.kAttribut,
tArtikelAttributSprache.cWertVarchar,
tArtikelAttributSprache.nWertInt,
tArtikelAttributSprache.fWertDecimal
FROM dbo.tArtikelAttribut
INNER JOIN dbo.tArtikelAttributSprache ON (
tArtikelAttributSprache.kArtikelAttribut = tArtikelAttribut.kArtikelAttribut
AND kSprache = 0
)
WHERE kShop = 0 AND tArtikelAttribut.kArtikel = @kArtikel
`;
export const STAFFEL = `
SELECT nAnzahlAb, fNEttoPreis
FROM tPreis
INNER JOIN tPreisDetail ON tPreisDetail.kPreis = tPreis.kPreis
WHERE kArtikel = @kArtikel AND kKundenGruppe = 2 AND kShop = 0
`;
export const EXTRA_LAGER = `
SELECT nMenge
FROM tExtraLager
WHERE kArtikel = @kArtikel AND nLager = @nLager
`;
export const SHOP_SUM = `
SELECT SUM(kShop) AS kShop
FROM tArtikelShop
WHERE kArtikel = @kArtikel
`;
export const HERSTELLER_GPSR = `
SELECT
tHersteller.cBeschreibung AS cHerstellerGPSR,
b.bVorschauBild AS herstellerBild
FROM tArtikel
INNER JOIN tHersteller ON tArtikel.kHersteller = tHersteller.kHersteller
LEFT JOIN tHerstellerBildPlattform hbp ON (
hbp.kHersteller = tHersteller.kHersteller
AND hbp.kPlattform = 1
AND hbp.kShop = 0
)
LEFT JOIN tBild b ON b.kBild = hbp.kBild
WHERE tArtikel.kArtikel = @kArtikel
`;

View File

@@ -1,37 +0,0 @@
export const SELECT_COLUMNS = `
(SELECT STRING_AGG(tk1.kKategorie, ',')
FROM dbo.tkategorieartikel AS tk1
WHERE tk1.kArtikel = tArtikel.kArtikel
GROUP BY tk1.kArtikel) AS katList,
MIN(fVerfuegbar) AS fVerfuegbar,
tArtikel.kArtikel,
MIN(fBestand) AS fBestand,
MIN(tArtikel.cArtNr) AS cArtNr,
MIN(tArtikelBeschreibung.cName) AS cName,
MIN(tArtikel.fVKNEtto) AS fVKNEtto,
MIN(tArtikel.kSteuerklasse) AS kSteuerklasse
`;
export const FROM_JOINS = `
FROM tArtikelBeschreibung
INNER JOIN tArtikel ON tArtikel.kArtikel = tArtikelBeschreibung.kArtikel
LEFT JOIN tLiefArtikel ON tArtikel.kArtikel = tLiefArtikel.tArtikel_kArtikel
LEFT JOIN tGebinde ON tArtikel.kArtikel = tGebinde.kArtikel
LEFT JOIN dbo.tlagerbestand ON dbo.tlagerbestand.kArtikel = tArtikel.kArtikel
LEFT JOIN dbo.vLagerbestandProLager ON (
dbo.vLagerbestandProLager.kArtikel = tArtikel.kArtikel
AND vLagerbestandProLager.kWarenlager = 1
)
`;
export const GROUP_ORDER = `
GROUP BY tArtikel.kArtikel
ORDER BY MIN(tArtikelBeschreibung.cName)
`;
export const CATEGORY_JOIN = `
INNER JOIN dbo.tkategorieartikel ON (
tkategorieartikel.kArtikel = tArtikel.kArtikel
AND ({categoryFilter})
)
`;

View File

@@ -1,24 +0,0 @@
export const LOAD_STEUERSATZ = `
SELECT
kSteuerklasse,
fSteuersatz
FROM dbo.tSteuersatz
WHERE kSteuerzone IN (
SELECT kSteuerzone FROM dbo.tSteuerzone WHERE cName = @steuerZone
)
ORDER BY kSteuerklasse
`;
export const LOAD_STEUERKLASSEN = `
SELECT
sk.kSteuerklasse,
sk.cName,
sk.nStandard,
sz.fSteuersatz
FROM dbo.tSteuerklasse sk
INNER JOIN dbo.tSteuersatz sz ON sz.kSteuerklasse = sk.kSteuerklasse
WHERE sz.kSteuerzone IN (
SELECT kSteuerzone FROM dbo.tSteuerzone WHERE cName = @steuerZone
)
ORDER BY sk.kSteuerklasse
`;

View File

@@ -1,7 +1,9 @@
import sql from 'mssql';
import LibDashStore from 'libdashstore';
import env from '../config/env.js';
let pool;
let store;
let connecting;
function getMssqlConfig() {
@@ -29,36 +31,36 @@ function getMssqlConfig() {
};
}
export async function getPool() {
if (pool) {
return pool;
/**
* Returns the initialized LibDashStore singleton.
* @returns {Promise<InstanceType<typeof LibDashStore>>}
*/
export async function getStore() {
if (store) {
return store;
}
if (!connecting) {
connecting = new sql.ConnectionPool(getMssqlConfig())
.connect()
.then((connectedPool) => {
pool = connectedPool;
return pool;
})
.finally(() => {
connecting = undefined;
});
connecting = (async () => {
pool = await new sql.ConnectionPool(getMssqlConfig()).connect();
store = await new LibDashStore(pool);
return store;
})().finally(() => {
connecting = undefined;
});
}
return connecting;
}
export async function ensureConnection() {
const activePool = await getPool();
await activePool.request().query('SELECT 1 AS ok');
await getStore();
}
export async function closePool() {
export async function closeStore() {
if (pool) {
await pool.close();
pool = undefined;
store = undefined;
}
}
export { sql };