feat(agrarmonitor): fehlende Lieferantennummern vergeben
Build and Push Multi-Platform Images / build-and-push (push) Successful in 1m1s
Build and Push Multi-Platform Images / build-and-push (push) Successful in 1m1s
Neuer Bereich „Lieferantennummern überprüfen“ in den Agrarmonitor- Einstellungen. Er vergibt allen aktiven Lieferanten ohne Lieferantennummer eine fortlaufende Nummer im Schema 1555xxxx, ab der höchsten vergebenen Nummer (Inaktive zählen mit, Altlasten werden ignoriert). - Vorschau „Lieferant → neue Nummer“, geschrieben wird erst nach Bestätigung; Einzelmodus zum Testen an einem Lieferanten - formData wird wie in der Weboberfläche aus #form_detail aufgebaut, nur die Lieferantennummer ändert sich - Dublettencheck über vorhanden.php, Erfolgskontrolle durch Neuladen des Details, Abbruch beim ersten Fehler - Lauf im Hintergrund mit Status-Abfrage (wegen Proxy-Timeouts), Listenfilter werden danach zurückgesetzt - HTML-Parsing mit cheerio, Unit-Tests für Parser und Vergabe-Ablauf Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
029009182a
commit
3d4125b29a
11 files changed
+1507
-3
No files matched your search
@@ -0,0 +1,151 @@
|
||||
import type { AxiosInstance } from 'axios';
|
||||
import type { AgrarmonitorService } from './agrarmonitor.service';
|
||||
import {
|
||||
LieferantennummernService,
|
||||
type LieferantennummerLaufErgebnis,
|
||||
} from './lieferantennummern.service';
|
||||
import type { ListenLieferant } from './lieferantennummern.parser';
|
||||
|
||||
// Der echte Connector lädt jsdom (ESM), das Jest nicht verarbeiten kann – hier wird er nicht gebraucht.
|
||||
jest.mock('agrarmonitor-connector', () => ({}));
|
||||
|
||||
interface UpdateBody {
|
||||
kundeID: number;
|
||||
formData: Record<string, unknown>;
|
||||
}
|
||||
|
||||
function detail(nummer: string): string {
|
||||
return (
|
||||
'<form id="form_detail">' +
|
||||
'<input type="text" name="kundennummer" id="kundennummer" value="21207">' +
|
||||
`<input type="text" name="lieferantennummer" id="lieferantennummer" value="${nummer}">` +
|
||||
'<input type="text" name="firma" value="Firma">' +
|
||||
'<input type="checkbox" name="ist_kunde" value="1">' +
|
||||
'<input type="checkbox" name="ist_lieferant" value="1" checked>' +
|
||||
'</form>'
|
||||
);
|
||||
}
|
||||
|
||||
function kandidat(kundeId: number, firma: string): ListenLieferant {
|
||||
return { kundeId, lieferantennummer: '', firma, name: '', aktiv: true };
|
||||
}
|
||||
|
||||
function neuerLauf(gesamt: number): LieferantennummerLaufErgebnis {
|
||||
return {
|
||||
modus: 'alle',
|
||||
gestartetAm: '',
|
||||
beendetAm: null,
|
||||
gesamt,
|
||||
vergeben: 0,
|
||||
uebersprungen: 0,
|
||||
zuPruefen: 0,
|
||||
fehler: 0,
|
||||
abgebrochen: false,
|
||||
eintraege: [],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Simuliert Agrarmonitor: speichert Nummern aus updateKunde.php pro Kunde,
|
||||
* vorhanden.php meldet für die Ids in `dubletten` ähnliche Kontakte.
|
||||
*/
|
||||
function fakeHttp(opts: {
|
||||
nummern: Record<number, string>;
|
||||
dubletten?: number[];
|
||||
speichernIgnorieren?: number[];
|
||||
}) {
|
||||
const aufrufe: string[] = [];
|
||||
const updates: UpdateBody[] = [];
|
||||
const http = {
|
||||
get: jest.fn((url: string) => {
|
||||
aufrufe.push(`GET ${url}`);
|
||||
const m = /\/kunden\/detail\/(\d+)/.exec(url);
|
||||
if (m) {
|
||||
return Promise.resolve({
|
||||
data: detail(opts.nummern[Number(m[1])] ?? ''),
|
||||
});
|
||||
}
|
||||
return Promise.resolve({ data: '' });
|
||||
}),
|
||||
post: jest.fn((url: string, body: string | UpdateBody) => {
|
||||
aufrufe.push(`POST ${url}`);
|
||||
if (typeof body === 'string') {
|
||||
const id = Number(new URLSearchParams(body).get('customerID'));
|
||||
return Promise.resolve({
|
||||
data: opts.dubletten?.includes(id) ? '<div>Ähnlich</div>' : '',
|
||||
});
|
||||
}
|
||||
updates.push(body);
|
||||
if (!opts.speichernIgnorieren?.includes(body.kundeID)) {
|
||||
opts.nummern[body.kundeID] = String(body.formData.lieferantennummer);
|
||||
}
|
||||
return Promise.resolve({ data: '/kunden/detail/' + body.kundeID });
|
||||
}),
|
||||
};
|
||||
return { http: http as unknown as AxiosInstance, aufrufe, updates };
|
||||
}
|
||||
|
||||
function service() {
|
||||
const agrarmonitor = { clearClient: jest.fn() };
|
||||
return new LieferantennummernService(
|
||||
agrarmonitor as unknown as AgrarmonitorService,
|
||||
);
|
||||
}
|
||||
|
||||
describe('LieferantennummernService.vergeben', () => {
|
||||
it('vergibt fortlaufend, überspringt Vorhandene und verbraucht bei Dubletten keine Nummer', async () => {
|
||||
const { http, updates, aufrufe } = fakeHttp({
|
||||
nummern: { 2: '15550010' },
|
||||
dubletten: [3],
|
||||
});
|
||||
const lauf = neuerLauf(4);
|
||||
await service().vergeben(
|
||||
http,
|
||||
[kandidat(1, 'A'), kandidat(2, 'B'), kandidat(3, 'C'), kandidat(4, 'D')],
|
||||
15550706,
|
||||
lauf,
|
||||
);
|
||||
|
||||
expect(lauf.eintraege.map((e) => [e.kundeId, e.status, e.nummer])).toEqual([
|
||||
[1, 'vergeben', '15550706'],
|
||||
[2, 'uebersprungen', undefined],
|
||||
[3, 'pruefen', undefined],
|
||||
[4, 'vergeben', '15550707'],
|
||||
]);
|
||||
expect(lauf).toMatchObject({
|
||||
vergeben: 2,
|
||||
uebersprungen: 1,
|
||||
zuPruefen: 1,
|
||||
fehler: 0,
|
||||
abgebrochen: false,
|
||||
});
|
||||
expect(updates[0].kundeID).toBe(1);
|
||||
expect(updates[0].formData).toMatchObject({
|
||||
kundennummer: '21207',
|
||||
lieferantennummer: '15550706',
|
||||
ist_kunde: '',
|
||||
ist_lieferant: '1',
|
||||
});
|
||||
expect(aufrufe[aufrufe.length - 1]).toContain('itemsperpage=25');
|
||||
expect(lauf.beendetAm).not.toBeNull();
|
||||
});
|
||||
|
||||
it('bricht ab, wenn die Nummer nach dem Speichern nicht übernommen wurde', async () => {
|
||||
const { http, updates, aufrufe } = fakeHttp({
|
||||
nummern: {},
|
||||
speichernIgnorieren: [1],
|
||||
});
|
||||
const lauf = neuerLauf(2);
|
||||
await service().vergeben(
|
||||
http,
|
||||
[kandidat(1, 'A'), kandidat(2, 'B')],
|
||||
15550706,
|
||||
lauf,
|
||||
);
|
||||
|
||||
expect(updates).toHaveLength(1);
|
||||
expect(lauf).toMatchObject({ vergeben: 0, fehler: 1, abgebrochen: true });
|
||||
expect(lauf.eintraege[0].hinweis).toContain('15550706');
|
||||
expect(aufrufe[aufrufe.length - 1]).toContain('itemsperpage=25');
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user