725 lines
30 KiB
JavaScript
725 lines
30 KiB
JavaScript
"use strict";
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.AgrarmonitorConnector = void 0;
|
|
const axios_1 = __importDefault(require("axios"));
|
|
const axios_cookiejar_support_1 = require("axios-cookiejar-support");
|
|
const jsdom_1 = require("jsdom");
|
|
const tough_cookie_1 = require("tough-cookie");
|
|
class AgrarmonitorConnector {
|
|
options;
|
|
http;
|
|
static s3DateienBaseUrl = 'https://s3-eu-central-1.amazonaws.com/dateien.agrarmonitor.de/07';
|
|
baseUrl;
|
|
apiBaseUrl;
|
|
timeoutMs;
|
|
autoLogin;
|
|
autoRetry;
|
|
loginStrategy;
|
|
logger;
|
|
cookieJar;
|
|
apiHttp;
|
|
loginInProgress = null;
|
|
constructor(options) {
|
|
this.options = options;
|
|
this.baseUrl = options.baseUrl ?? 'https://admin7.agrarmonitor.de';
|
|
this.apiBaseUrl = this.normalizeApiBaseUrl(options.apiBaseUrl ?? 'https://api.agrarmonitor.de/v1');
|
|
this.timeoutMs = options.timeoutMs ?? 15000;
|
|
this.autoLogin = options.autoLogin ?? true;
|
|
this.autoRetry = options.autoRetry ?? true;
|
|
this.loginStrategy = options.loginStrategy ?? 'redirect';
|
|
this.logger = options.logger;
|
|
}
|
|
async init() {
|
|
this.cookieJar = await this.options.cookieStore.load();
|
|
this.http = this.createHttpClient();
|
|
this.apiHttp = this.createApiHttpClient();
|
|
if (this.autoLogin) {
|
|
const valid = await this.isSessionValid();
|
|
if (!valid) {
|
|
await this.login();
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
async login() {
|
|
if (this.loginInProgress) {
|
|
return this.loginInProgress;
|
|
}
|
|
this.loginInProgress = this.performLogin().finally(() => {
|
|
this.loginInProgress = null;
|
|
});
|
|
return this.loginInProgress;
|
|
}
|
|
async clearSession() {
|
|
this.cookieJar = new tough_cookie_1.CookieJar();
|
|
await this.options.cookieStore.clear();
|
|
this.http = this.createHttpClient();
|
|
this.apiHttp = this.createApiHttpClient();
|
|
}
|
|
async saveSession() {
|
|
await this.options.cookieStore.save(this.cookieJar);
|
|
}
|
|
async getCookieCount(url = this.baseUrl) {
|
|
return this.cookieJar.getCookiesSync(url).length;
|
|
}
|
|
async checkFreigeschaltet() {
|
|
const response = await this.http.get('/', {
|
|
maxRedirects: 0,
|
|
validateStatus: status => status >= 200 && status < 400,
|
|
});
|
|
await this.saveSession();
|
|
const redirectLocation = this.getHeader(response, 'location');
|
|
const redirected = response.status >= 300 && response.status < 400 && this.isFreischaltungUrl(redirectLocation);
|
|
return {
|
|
freigeschaltet: !redirected,
|
|
status: response.status,
|
|
redirected,
|
|
redirectLocation,
|
|
timestamp: new Date().toISOString(),
|
|
cookies: await this.getCookieCount(),
|
|
};
|
|
}
|
|
async checkRegistriert() {
|
|
const response = await this.http.get('/', {
|
|
maxRedirects: 5,
|
|
validateStatus: status => status >= 200 && status < 500,
|
|
});
|
|
await this.saveSession();
|
|
const pageContent = typeof response.data === 'string' ? response.data : '';
|
|
const hasRegistrationText = pageContent.includes('Neues Gerät registrieren');
|
|
return {
|
|
registriert: !hasRegistrationText,
|
|
status: response.status,
|
|
hasRegistrationText,
|
|
timestamp: new Date().toISOString(),
|
|
cookies: await this.getCookieCount(),
|
|
};
|
|
}
|
|
async registerDevice(registration) {
|
|
const agrarmonitorId = registration.agrarmonitorId.trim();
|
|
const pcName = registration.pcName.trim();
|
|
if (!agrarmonitorId || !pcName) {
|
|
throw new Error('AgrarmonitorID und PC-Name sind erforderlich');
|
|
}
|
|
const freischaltungResponse = await this.http.get('/freischaltung/');
|
|
const responseContent = typeof freischaltungResponse.data === 'string' ? freischaltungResponse.data : '';
|
|
const nonce = this.extractNonce(responseContent, '#nonce, input[name="nonce"]');
|
|
const registerResponse = await this.http.post('/freischaltung/api/register.php', {
|
|
firma: agrarmonitorId,
|
|
name: pcName,
|
|
nonce,
|
|
}, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
validateStatus: status => status >= 200 && status < 500,
|
|
});
|
|
await this.saveSession();
|
|
const success = registerResponse.status >= 200 && registerResponse.status < 300;
|
|
return {
|
|
success,
|
|
status: registerResponse.status,
|
|
message: success ? 'Registrierung erfolgreich' : 'Registrierung fehlgeschlagen',
|
|
data: {
|
|
agrarmonitorId,
|
|
pcName,
|
|
nonce: this.maskNonce(nonce),
|
|
},
|
|
timestamp: new Date().toISOString(),
|
|
cookies: await this.getCookieCount(),
|
|
};
|
|
}
|
|
async fetchCustomers(options = {}) {
|
|
const response = await this.apiRequest('/kunden', {
|
|
params: {
|
|
per_page: options.perPage ?? 99999,
|
|
},
|
|
apiToken: options.apiToken,
|
|
});
|
|
const responseData = response.data;
|
|
if (!responseData || !Array.isArray(responseData.data)) {
|
|
throw new Error('Ungueltige Agrarmonitor API-Antwort');
|
|
}
|
|
return responseData.data;
|
|
}
|
|
async getKunden2(options = {}) {
|
|
const customers = await this.fetchAllCustomers(options);
|
|
return customers.map(customer => this.mapKunde2(customer));
|
|
}
|
|
async eingangsrechnungenLivesearch(suchstring) {
|
|
const response = await this.http.get('/module/dateien/livesearch.php', {
|
|
params: this.createDateienLivesearchParams(suchstring),
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#dateien tbody tr'));
|
|
const results = [];
|
|
for (const row of rows) {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
const typText = cells[3]?.textContent?.trim() ?? '';
|
|
if (!typText.startsWith('Eingangsrechnungen')) {
|
|
continue;
|
|
}
|
|
const dokumentId = this.parseNumber(row.getAttribute('data-file_id'));
|
|
const dataFile = row.getAttribute('data-file') ?? '';
|
|
const dokumentName = cells[2]?.querySelector('b > a')?.textContent?.trim() ?? '';
|
|
const dateiName = cells[2]?.querySelector('span')?.textContent?.trim() ?? '';
|
|
const belegLink = cells[3]?.querySelector('a');
|
|
const belegTextParts = (belegLink?.textContent ?? '').split(',').map(part => part.trim()).filter(Boolean);
|
|
const belegNummer = belegTextParts[0] ?? '';
|
|
const belegDatum = this.parseGermanShortDateFromText(belegTextParts.at(-1) ?? '');
|
|
const eingangId = this.parseNumber(this.lastPathSegment(belegLink?.getAttribute('href') ?? ''));
|
|
const { interneBelegNummer, kundenId, betriebId, dokumentTyp } = await this.getEingangsrechnungEditMeta(eingangId);
|
|
const { eingangsDatum, buchungsDatum } = await this.getEingangsrechnungDetailMeta(eingangId);
|
|
results.push({
|
|
dokumentId,
|
|
vorschauUrl: `${AgrarmonitorConnector.s3DateienBaseUrl}/v_${this.fileBasename(dataFile)}.png`,
|
|
dokumentUrl: `${AgrarmonitorConnector.s3DateienBaseUrl}/${dataFile}`,
|
|
dokumentName,
|
|
dateiName,
|
|
belegNummer,
|
|
interneBelegNummer,
|
|
belegDatum,
|
|
buchungsDatum,
|
|
eingangsDatum,
|
|
eingangId,
|
|
kundenId,
|
|
betriebId,
|
|
dokumentTyp,
|
|
});
|
|
}
|
|
return results;
|
|
}
|
|
async eingangsrechnungVorhanden(suchstring) {
|
|
const response = await this.http.get('/module/dateien/livesearch.php', {
|
|
params: this.createDateienLivesearchParams(suchstring),
|
|
});
|
|
await this.saveSession();
|
|
return this.hasTableRows(response.data, 'table#dateien tbody tr');
|
|
}
|
|
async eingangsrechnungImDateieingangVorhanden(suchstring) {
|
|
const response = await this.http.get('/module/dateien/eingang/livesearch.php', {
|
|
params: {
|
|
suchstring,
|
|
seite: 1,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
return this.hasTableRows(response.data, 'table#dateien_eingang tbody tr');
|
|
}
|
|
async getRechnungsdaten(rechnungId) {
|
|
const response = await this.http.get('/module/eingangsrechnungen/api/eingangsrechnungen.php', {
|
|
params: {
|
|
id: 'edit',
|
|
rechnungId,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
return {
|
|
lieferschein: this.inputValue(document, 'lieferscheinnummer'),
|
|
rechnung: this.inputValue(document, 'rechnungsnummer'),
|
|
datum: this.requireDate(this.parseGermanShortDate(this.inputValue(document, 'rechnungsdatum')), 'rechnungsdatum'),
|
|
kundenId: this.selectedNumberValue(document, 'rgempf'),
|
|
adresstext: this.inputValue(document, 'addressName'),
|
|
};
|
|
}
|
|
async setRechnungsdaten(rechnungId, daten) {
|
|
const response = await this.http.post(`/module/eingangsrechnungen/api/eingangsrechnungen.php?id=update&rechnungId=${encodeURIComponent(rechnungId)}`, new URLSearchParams({
|
|
lieferscheinnummer: daten.lieferschein,
|
|
rechnungsnummer: daten.rechnung,
|
|
rechnungsdatum: this.formatGermanShortDate(daten.datum),
|
|
rgempf: String(daten.kundenId),
|
|
adresstext: daten.adresstext,
|
|
}), this.formPostConfig(`/eingangsrechnungen/detail/${rechnungId}`));
|
|
await this.saveSession();
|
|
return response.status >= 200 && response.status < 300;
|
|
}
|
|
async setLieferscheinNummer(rechnungId, nummer) {
|
|
const rechnungsdaten = await this.getRechnungsdaten(rechnungId);
|
|
const success = await this.setRechnungsdaten(rechnungId, {
|
|
...rechnungsdaten,
|
|
lieferschein: nummer,
|
|
});
|
|
if (!success) {
|
|
throw new Error('Lieferscheinnummer konnte nicht gespeichert werden');
|
|
}
|
|
}
|
|
async setEingangsdatum(rechnungId, datum) {
|
|
const response = await this.http.post('/module/eingangsrechnungen/api/updateReceived.php', new URLSearchParams({
|
|
datum: this.formatGermanShortDate(datum),
|
|
receiptID: String(rechnungId),
|
|
}), this.formPostConfig(`/eingangsrechnungen/detail/${rechnungId}`));
|
|
await this.saveSession();
|
|
return response.status >= 200 && response.status < 300;
|
|
}
|
|
async getCustomerById(id) {
|
|
const response = await this.apiRequest(`/kunden/${id}`);
|
|
this.logDebug('Agrarmonitor customer API raw response', response.data);
|
|
if (this.isWrappedApiCustomer(response.data)) {
|
|
return response.data.data;
|
|
}
|
|
if (this.isApiCustomer(response.data)) {
|
|
return response.data;
|
|
}
|
|
throw new Error('Ungueltige Agrarmonitor Kunden-API-Antwort');
|
|
}
|
|
async getMaschinenKategorien() {
|
|
const response = await this.http.get('/maschinen/kategorien');
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#kategorien tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.id),
|
|
name: cells[0]?.textContent?.trim() ?? '',
|
|
zugmaschine: this.parseJaNein(cells[2]?.textContent ?? ''),
|
|
mobilSichtbar: Boolean(cells[4]?.querySelector('input[type="checkbox"]')?.checked),
|
|
};
|
|
});
|
|
}
|
|
async getMaschinen(gruppenId, suchstring = '') {
|
|
const response = await this.http.get('/module/maschinen/livesearch.php', {
|
|
params: {
|
|
suchstring,
|
|
maschinen_aktiv: 1,
|
|
maschinengruppe: gruppenId,
|
|
seite: 1,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table.maschinen_table tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.getAttribute('data-id') ?? row.id),
|
|
nummer: cells[0]?.textContent?.trim() ?? '',
|
|
name: cells[1]?.textContent?.trim() ?? '',
|
|
kennzeichen: cells[2]?.textContent?.trim() ?? '',
|
|
aktiv: Boolean(cells[4]?.querySelector('.fa-check, .text-green')),
|
|
};
|
|
});
|
|
}
|
|
async getFirmen() {
|
|
const response = await this.http.get('/einstellungen');
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#firmen_table tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.getAttribute('data-firma_id') ?? row.id),
|
|
bezeichnung: cells[0]?.textContent?.trim() ?? '',
|
|
};
|
|
});
|
|
}
|
|
async getArtikelEinheiten() {
|
|
const response = await this.http.get('/artikel/einheiten');
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#einheiten tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.getAttribute('data-id') ?? row.id),
|
|
bezeichnung: cells[0]?.textContent?.trim() ?? '',
|
|
kurz: cells[1]?.textContent?.trim() ?? '',
|
|
};
|
|
});
|
|
}
|
|
async getArtikelKategorien() {
|
|
const response = await this.http.get('/artikel/kategorien');
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#kategorien tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.id),
|
|
name: cells[1]?.textContent?.trim() ?? '',
|
|
};
|
|
});
|
|
}
|
|
async getArtikel(artikelGruppe, suchstring = '') {
|
|
const response = await this.http.get('/module/artikel/livesearch.php', {
|
|
params: {
|
|
suchstring,
|
|
artikel_aktiv: 0,
|
|
warengruppe: artikelGruppe,
|
|
lagerplatz: 0,
|
|
bestand: 0,
|
|
itemsperpage: 100000,
|
|
seite: 1,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#artikel_table tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.getAttribute('data-id') ?? row.id),
|
|
nummer: cells[0]?.textContent?.trim() ?? '',
|
|
bezeichnung: cells[1]?.textContent?.trim() ?? '',
|
|
};
|
|
});
|
|
}
|
|
async getMitarbeiter(suchstring = '', mitarbeitergruppe = 0) {
|
|
const response = await this.http.get('/module/mitarbeiter/livesearch.php', {
|
|
params: {
|
|
suchstring,
|
|
mitarbeiter_aktiv: 1,
|
|
mitarbeitergruppe,
|
|
itemsperpage: 100000,
|
|
seite: 1,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const rows = Array.from(document.querySelectorAll('table#mitarbeiter_table tbody tr, table.mitarbeiter_table tbody tr'));
|
|
return rows.map(row => {
|
|
const cells = Array.from(row.querySelectorAll('td'));
|
|
return {
|
|
id: this.parseNumber(row.getAttribute('data-id') ?? row.id),
|
|
nummer: cells[0]?.textContent?.trim() ?? '',
|
|
nachname: cells[1]?.textContent?.trim() ?? '',
|
|
vorname: cells[2]?.textContent?.trim() ?? '',
|
|
};
|
|
});
|
|
}
|
|
createHttpClient() {
|
|
const client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({
|
|
baseURL: this.baseUrl,
|
|
jar: this.cookieJar,
|
|
withCredentials: true,
|
|
timeout: this.timeoutMs,
|
|
headers: {
|
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
|
|
},
|
|
maxRedirects: 5,
|
|
validateStatus: status => status >= 200 && status < 400,
|
|
}));
|
|
client.interceptors.response.use(async (response) => {
|
|
await this.options.cookieStore.save(this.cookieJar);
|
|
if (this.autoRetry && this.isLoginRequiredResponse(response)) {
|
|
return this.retryAfterLogin(response.config);
|
|
}
|
|
return response;
|
|
}, async (error) => {
|
|
const response = error.response;
|
|
if (this.autoRetry && response && this.isLoginRequiredResponse(response)) {
|
|
return this.retryAfterLogin(error.config);
|
|
}
|
|
throw error;
|
|
});
|
|
return client;
|
|
}
|
|
createApiHttpClient(apiToken = this.options.apiToken) {
|
|
return axios_1.default.create({
|
|
baseURL: this.apiBaseUrl,
|
|
timeout: this.timeoutMs,
|
|
headers: {
|
|
Accept: 'application/json',
|
|
...(apiToken ? { Authorization: `Bearer ${apiToken}` } : {}),
|
|
},
|
|
validateStatus: status => status >= 200 && status < 500,
|
|
});
|
|
}
|
|
async apiRequest(url, config = {}) {
|
|
const apiToken = config.apiToken ?? this.options.apiToken;
|
|
if (!apiToken) {
|
|
throw new Error('Agrarmonitor API-Token nicht konfiguriert');
|
|
}
|
|
const { apiToken: _apiToken, ...axiosConfig } = config;
|
|
const client = apiToken === this.options.apiToken ? this.apiHttp : this.createApiHttpClient(apiToken);
|
|
return client.get(url, axiosConfig);
|
|
}
|
|
async fetchAllCustomers(options) {
|
|
const customers = [];
|
|
let page = 1;
|
|
let lastPage = 1;
|
|
do {
|
|
const response = await this.apiRequest('/kunden', {
|
|
params: {
|
|
per_page: options.perPage ?? 99999,
|
|
page,
|
|
},
|
|
apiToken: options.apiToken,
|
|
});
|
|
if (!response.data || !Array.isArray(response.data.data)) {
|
|
throw new Error('Ungueltige Agrarmonitor API-Antwort');
|
|
}
|
|
customers.push(...response.data.data);
|
|
lastPage = this.parsePositiveNumber(response.data.meta?.last_page, page);
|
|
page++;
|
|
} while (page <= lastPage);
|
|
return customers;
|
|
}
|
|
mapKunde2(customer) {
|
|
return {
|
|
ID: this.parseNumber(customer.id),
|
|
ist_Kunde: this.toBoolean(customer.ist_kunde),
|
|
Kundennummer: this.toStringValue(customer.kundennummer),
|
|
ist_Lieferant: this.toBoolean(customer.ist_lieferant),
|
|
Lieferantennummer: this.toStringValue(customer.lieferantennummer),
|
|
Firma: this.toStringValue(customer.firma),
|
|
Anrede: this.toStringValue(customer.anrede),
|
|
Vorname: this.toStringValue(customer.vorname),
|
|
Nachname: this.toStringValue(customer.nachname),
|
|
Strasse: this.toStringValue(customer.strasse),
|
|
Plz: this.toStringValue(customer.plz),
|
|
Ort: this.toStringValue(customer.ort),
|
|
Land: this.toStringValue(customer.land_iso_3166),
|
|
ist_aktiv: this.toBoolean(customer.ist_aktiv),
|
|
};
|
|
}
|
|
async performLogin() {
|
|
if (!this.options.username || !this.options.password) {
|
|
throw new Error('Agrarmonitor-Credentials nicht konfiguriert');
|
|
}
|
|
this.logger?.info?.('Fuehre Agrarmonitor-Login durch');
|
|
if (this.loginStrategy === 'auto') {
|
|
this.logger?.warn?.('loginStrategy "auto" ist veraltet; verwende Redirect-Login');
|
|
}
|
|
await this.performRedirectLogin();
|
|
await this.options.cookieStore.save(this.cookieJar);
|
|
this.logger?.info?.('Agrarmonitor-Login erfolgreich');
|
|
}
|
|
async performRedirectLogin() {
|
|
const loginPageResponse = await this.http.get('/');
|
|
const loginPageText = typeof loginPageResponse.data === 'string' ? loginPageResponse.data : '';
|
|
if (!this.isLoginPageText(loginPageText)) {
|
|
return;
|
|
}
|
|
const nonce = this.extractNonce(loginPageText, 'input[name="nonce"]');
|
|
const loginData = {
|
|
username: this.options.username,
|
|
passwort: this.options.password,
|
|
nonce,
|
|
ssoAction: "",
|
|
ssoReturn: "",
|
|
};
|
|
const response = await this.http.post('/login/api/login.php', loginData, {
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
});
|
|
const responseText = typeof response.data === 'string' ? response.data : '';
|
|
if (this.isLoginPageText(responseText)) {
|
|
throw new Error('Agrarmonitor-Redirect-Login fehlgeschlagen');
|
|
}
|
|
}
|
|
async isSessionValid() {
|
|
try {
|
|
const response = await this.http.get('/');
|
|
return !this.isLoginRequiredResponse(response);
|
|
}
|
|
catch {
|
|
return false;
|
|
}
|
|
}
|
|
isLoginRequiredResponse(response) {
|
|
const responseUrl = this.getResponseUrl(response);
|
|
const responseText = typeof response.data === 'string' ? response.data : '';
|
|
return (response.status === 401 ||
|
|
response.status === 403 ||
|
|
this.isLoginPageText(responseText) ||
|
|
responseText.includes('Anmeldung') ||
|
|
responseText.includes('Einloggen'));
|
|
}
|
|
async retryAfterLogin(config) {
|
|
if (config._agrarmonitorRetry) {
|
|
throw new Error('Agrarmonitor-Request nach erneutem Login weiterhin nicht autorisiert');
|
|
}
|
|
config._agrarmonitorRetry = true;
|
|
this.logger?.info?.('Agrarmonitor-Session abgelaufen, erneuter Login wird ausgefuehrt');
|
|
await this.login();
|
|
return this.http.request(config);
|
|
}
|
|
createDateienLivesearchParams(suchstring) {
|
|
return {
|
|
suchstring,
|
|
stammdatum_typ: -1,
|
|
mobil: -1,
|
|
sensibel: -1,
|
|
firma: 0,
|
|
itemsperpage: 100000,
|
|
seite: 1,
|
|
};
|
|
}
|
|
async getEingangsrechnungEditMeta(rechnungId) {
|
|
const response = await this.http.get('/module/eingangsrechnungen/api/eingangsrechnungen.php', {
|
|
params: {
|
|
id: 'edit',
|
|
rechnungId,
|
|
},
|
|
});
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
return {
|
|
interneBelegNummer: this.inputValue(document, 'lieferscheinnummer'),
|
|
kundenId: this.selectedNumberValue(document, 'rgempf'),
|
|
betriebId: this.selectedNumberValue(document, 'firma_id'),
|
|
dokumentTyp: this.selectedNumberValue(document, 'typ'),
|
|
};
|
|
}
|
|
async getEingangsrechnungDetailMeta(rechnungId) {
|
|
const response = await this.http.get(`/eingangsrechnungen/detail/${rechnungId}`);
|
|
await this.saveSession();
|
|
const document = this.parseHtmlDocument(response.data);
|
|
const receivedStatus = document.querySelector('#receivedStatus');
|
|
const receivedText = receivedStatus?.textContent?.trim() ?? '';
|
|
const parentParts = (receivedStatus?.parentElement?.textContent ?? '').split('-');
|
|
const bookingText = parentParts.at(-1)?.trim() ?? '';
|
|
return {
|
|
eingangsDatum: !receivedText || receivedText === 'Nicht empfangen'
|
|
? null
|
|
: this.parseGermanShortDateFromText(receivedText.slice(13).trim()),
|
|
buchungsDatum: !bookingText || bookingText === 'Nicht gebucht'
|
|
? null
|
|
: this.parseGermanShortDateFromText(bookingText.slice(11).trim()),
|
|
};
|
|
}
|
|
formPostConfig(refererPath) {
|
|
return {
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
Referer: `${this.baseUrl}${refererPath}`,
|
|
Origin: this.baseUrl,
|
|
},
|
|
validateStatus: status => status >= 200 && status < 400,
|
|
};
|
|
}
|
|
parseHtmlDocument(data) {
|
|
return new jsdom_1.JSDOM(typeof data === 'string' ? data : String(data ?? '')).window.document;
|
|
}
|
|
hasTableRows(data, selector) {
|
|
return this.parseHtmlDocument(data).querySelectorAll(selector).length > 0;
|
|
}
|
|
inputValue(document, name) {
|
|
return document.querySelector(`input[name="${name}"]`)?.value.trim() ?? '';
|
|
}
|
|
selectedNumberValue(document, name) {
|
|
return this.parseNumber(document.querySelector(`select[name="${name}"] option:checked`)?.value);
|
|
}
|
|
parseNumber(value) {
|
|
const numberValue = Number(String(value ?? '').trim());
|
|
return Number.isFinite(numberValue) ? numberValue : 0;
|
|
}
|
|
parsePositiveNumber(value, fallback) {
|
|
const numberValue = this.parseNumber(value);
|
|
return numberValue > 0 ? numberValue : fallback;
|
|
}
|
|
toStringValue(value) {
|
|
return value === null || typeof value === 'undefined' ? '' : String(value);
|
|
}
|
|
toBoolean(value) {
|
|
if (typeof value === 'boolean') {
|
|
return value;
|
|
}
|
|
if (typeof value === 'number') {
|
|
return value === 1;
|
|
}
|
|
const normalized = String(value ?? '').trim().toLowerCase();
|
|
return normalized === '1' || normalized === 'true' || normalized === 'ja';
|
|
}
|
|
parseJaNein(value) {
|
|
return value.trim().toLowerCase() === 'ja';
|
|
}
|
|
parseGermanShortDate(value) {
|
|
const match = value.trim().match(/^(\d{2})\.(\d{2})\.(\d{2})$/);
|
|
if (!match) {
|
|
return null;
|
|
}
|
|
const [, day, month, year] = match;
|
|
const parsed = new Date(Number(`20${year}`), Number(month) - 1, Number(day));
|
|
if (parsed.getFullYear() !== Number(`20${year}`) ||
|
|
parsed.getMonth() !== Number(month) - 1 ||
|
|
parsed.getDate() !== Number(day)) {
|
|
return null;
|
|
}
|
|
return parsed;
|
|
}
|
|
requireDate(value, fieldName) {
|
|
if (!value) {
|
|
throw new Error(`Ungueltiges Datumsformat fuer ${fieldName}`);
|
|
}
|
|
return value;
|
|
}
|
|
formatGermanShortDate(date) {
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const year = String(date.getFullYear()).slice(-2);
|
|
return `${day}.${month}.${year}`;
|
|
}
|
|
lastPathSegment(value) {
|
|
return value.split('?')[0]?.split('/').filter(Boolean).at(-1) ?? '';
|
|
}
|
|
fileBasename(fileName) {
|
|
const lastDotIndex = fileName.lastIndexOf('.');
|
|
return lastDotIndex === -1 ? fileName : fileName.slice(0, lastDotIndex);
|
|
}
|
|
normalizeApiBaseUrl(value) {
|
|
const withoutTrailingSlash = value.replace(/\/+$/, '');
|
|
return withoutTrailingSlash.endsWith('/v1') ? withoutTrailingSlash : `${withoutTrailingSlash}/v1`;
|
|
}
|
|
isWrappedApiCustomer(value) {
|
|
return (typeof value === 'object' &&
|
|
value !== null &&
|
|
'data' in value &&
|
|
this.isApiCustomer(value.data));
|
|
}
|
|
isApiCustomer(value) {
|
|
return (typeof value === 'object' &&
|
|
value !== null &&
|
|
'id' in value &&
|
|
(typeof value.id === 'string' || typeof value.id === 'number'));
|
|
}
|
|
parseGermanShortDateFromText(value) {
|
|
const match = value.match(/(\d{2}\.\d{2}\.\d{2})/);
|
|
return match ? this.parseGermanShortDate(match[1]) : null;
|
|
}
|
|
logDebug(message, meta) {
|
|
if (this.logger?.debug) {
|
|
this.logger.debug(message, meta);
|
|
return;
|
|
}
|
|
this.logger?.info?.(message, meta);
|
|
}
|
|
getResponseUrl(response) {
|
|
const request = response.request;
|
|
return request?.res?.responseUrl ?? '';
|
|
}
|
|
getHeader(response, header) {
|
|
const value = response.headers[header.toLowerCase()];
|
|
if (Array.isArray(value)) {
|
|
return value[0] ?? null;
|
|
}
|
|
return typeof value === 'string' ? value : null;
|
|
}
|
|
isFreischaltungUrl(value) {
|
|
return Boolean(value?.includes('freischaltung'));
|
|
}
|
|
isLoginPageText(responseText) {
|
|
return responseText.includes('Anmeldung - AGRARMONITOR');
|
|
}
|
|
extractNonce(html, selector) {
|
|
const dom = new jsdom_1.JSDOM(html);
|
|
const element = dom.window.document.querySelector(selector);
|
|
const nonce = element?.getAttribute('value') ?? element?.value ?? '';
|
|
if (!nonce) {
|
|
throw new Error('Nonce-Element nicht gefunden oder leer');
|
|
}
|
|
return nonce;
|
|
}
|
|
maskNonce(nonce) {
|
|
return nonce.length <= 10 ? nonce : `${nonce.slice(0, 10)}...`;
|
|
}
|
|
}
|
|
exports.AgrarmonitorConnector = AgrarmonitorConnector;
|
|
//# sourceMappingURL=AgrarmonitorConnector.js.map
|