This commit is contained in:
seb
2026-06-24 09:50:08 +02:00
parent 185b68fe52
commit 9b11a8a24c
18 changed files with 716 additions and 34 deletions

View File

@@ -5,7 +5,7 @@ import chalk from 'chalk';
import { getArticle } from '../src/services/article/getArticle.js';
import { searchArticles } from '../src/services/article/searchArticles.js';
import { closePool } from '../src/db/mssqlClient.js';
import { getBrutto } from '../src/utils/tax.js';
import { bruttoFromNetto, loadSteuerklassen } from '../src/services/misc/steuerklassen.js';
import '../src/config/env.js';
@@ -28,11 +28,12 @@ const eur = (value) => {
return new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' }).format(value);
};
function formatPrice(row) {
function formatPrice(row, steuerklassen) {
if (row.fVKNEtto == null) {
return '—';
}
return eur(getBrutto(row.fVKNEtto, row.kSteuerklasse));
const brutto = bruttoFromNetto(row.fVKNEtto, row.kSteuerklasse, steuerklassen);
return brutto == null ? '—' : eur(brutto);
}
function hasValue(value) {
@@ -67,10 +68,8 @@ function Section({ title, children }) {
);
}
function ArticleDetail({ article }) {
const brutto = article.fVKNEtto != null
? getBrutto(article.fVKNEtto, article.kSteuerklasse)
: null;
function ArticleDetail({ article, steuerklassen }) {
const brutto = bruttoFromNetto(article.fVKNEtto, article.kSteuerklasse, steuerklassen);
const aktiv = article.cAktiv === 'Y'
? chalk.green('active')
: article.cAktiv === 'N'
@@ -194,14 +193,14 @@ function truncateForDisplay(value, max = 80) {
return `${value.slice(0, max)}… (${value.length} chars)`;
}
function formatListRow(row) {
function formatListRow(row, steuerklassen) {
const stock = row.fBestand ?? '—';
const price = formatPrice(row);
const price = formatPrice(row, steuerklassen);
const name = row.cName ?? '—';
return `${row.cArtNr ?? '—'} ${stock} ${price} ${name}`;
}
const ResultList = ({ rows, onSelect, onBack }) => {
const ResultList = ({ rows, onSelect, onBack, steuerklassen }) => {
const [selected, setSelected] = useState(0);
const windowStart = Math.max(0, Math.min(selected - Math.floor(VISIBLE_ROWS / 2), rows.length - VISIBLE_ROWS));
const visible = rows.slice(windowStart, windowStart + VISIBLE_ROWS);
@@ -228,8 +227,8 @@ const ResultList = ({ rows, onSelect, onBack }) => {
const absoluteIndex = windowStart + index;
const prefix = absoluteIndex === selected ? chalk.cyan('> ') : ' ';
const label = absoluteIndex === selected
? chalk.cyan.bold(formatListRow(row))
: formatListRow(row);
? chalk.cyan.bold(formatListRow(row, steuerklassen))
: formatListRow(row, steuerklassen);
return e(Text, { key: row.kArtikel ?? absoluteIndex }, prefix, label);
}),
rows.length > VISIBLE_ROWS
@@ -238,7 +237,7 @@ const ResultList = ({ rows, onSelect, onBack }) => {
);
};
const App = () => {
const App = ({ steuerklassen }) => {
const { exit } = useApp();
const [mode, setMode] = useState(MODES.SEARCH);
const [target, setTarget] = useState('');
@@ -337,6 +336,7 @@ const App = () => {
rows,
onSelect: (row) => loadArticle(row.cArtNr),
onBack: backToSearch,
steuerklassen,
});
}
@@ -352,7 +352,7 @@ const App = () => {
: 'Enter = new search, q = quit';
return e(Box, { flexDirection: 'column' },
e(ArticleDetail, { article }),
e(ArticleDetail, { article, steuerklassen }),
e(Box, { marginTop: 1 }, e(Text, null, chalk.gray(footer))),
e(ResultInput, {
onAgain: resetSearch,
@@ -398,4 +398,5 @@ const ExitOnKey = ({ onExit }) => {
return null;
};
render(e(App));
const steuerklassen = await loadSteuerklassen();
render(e(App, { steuerklassen }));