import { Component, ElementRef, inject, OnInit, signal, viewChild } from '@angular/core'; import { ActivatedRoute, Router } from '@angular/router'; import { FormsModule } from '@angular/forms'; import { SelectableRow, TableModule, TableRowSelectEvent } from 'primeng/table'; import { ButtonDirective } from 'primeng/button'; import { InputTextModule } from 'primeng/inputtext'; import { DialogModule } from 'primeng/dialog'; import { TransactionModel, WzHeaderDto, WzRowMeyleDto } from '../../core/models'; import { WarehouseService } from '../../core/services/warehouse.service'; import { findCombinations, isValidMeyleScannedValue, } from '../../shared/utils/business-logic'; import { PageShellComponent } from '../../shared/components/page-shell/page-shell.component'; import { ContentSectionComponent } from '../../shared/components/content-section/content-section.component'; @Component({ selector: 'app-meyle-pack-list', standalone: true, imports: [TableModule, SelectableRow, ButtonDirective, InputTextModule, DialogModule, FormsModule, PageShellComponent, ContentSectionComponent], template: `
Numer Zamówienia Meyle Numer Indeksu FA Numer Indeksu Meyle Ilość w Dostawie Nr Palety Nr Partii SL Nr Partii Meyle {{ row.orderNumber }} {{ row.faIndex }} {{ row.itemNumber }} {{ row.quantity }}
@if (exportValid()) {

Packing List został wygenerowany i wysłany!

} @else if (!emailAddresses?.trim()) {

Błąd: Proszę wprowadzić przynajmniej jeden ADRES EMAIL do wysyłki raportu!

} @else {

Błąd: Nie Wszystkie linie mają wypełniony NUMER PALETY.
Packing List nie zostanie wygenerowany!

}

Błąd skanowania! Wystąpił jeden z wyjątków (Zeskanowana wartość '{{ lastScannedValue }}'):

Błąd skanowania! Wybierz NUMER PALETY większy niż 0 (Aktualnie '{{ palletNumber }}'):

`, }) export class MeylePackListComponent implements OnInit { private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); private readonly warehouseService = inject(WarehouseService); readonly scanner = viewChild>('scanner'); wzHeaderId = ''; emailAddresses = ''; wzNumber = ''; palletNumber = '0'; scannedValue = ''; lastScannedValue = ''; newQuantity = '0'; readonly rows = signal([]); readonly selectedRow = signal(null); selectedRowsList: WzRowMeyleDto[] = []; changedRecords: WzRowMeyleDto[] = []; transactionModels: Record = {}; showInfoDialog = false; showValidationDialog = false; showPalletDialog = false; readonly showSplitDialog = signal(false); readonly exportValid = signal(false); get yearPrefix(): number { return new Date().getFullYear() - 2000; } async ngOnInit(): Promise { this.wzHeaderId = this.route.snapshot.paramMap.get('WzHeader') ?? ''; const header = await this.warehouseService.getWzHeaderById(this.wzHeaderId); this.rows.set(await this.warehouseService.getWzRowsMeyleByWzHeaderId(this.wzHeaderId)); this.transactionModels = await this.warehouseService.getTransactionsModels(); this.emailAddresses = header.emailAddresses ?? ''; this.wzNumber = header.wzNumbers ?? ''; setTimeout(() => this.scanner()?.nativeElement.focus()); } changeView(): void { this.router.navigate(['/Warehouse/Meyle/PackList', this.wzHeaderId, 'Simple']); } onRowSelect(event: TableRowSelectEvent): void { const data = event.data; if (data && !Array.isArray(data)) this.selectedRow.set(data); } markChanged(row: WzRowMeyleDto): void { if (!this.changedRecords.includes(row)) this.changedRecords.push(row); } hideModal(): void { this.showInfoDialog = false; this.showValidationDialog = false; this.showPalletDialog = false; this.showSplitDialog.set(false); this.lastScannedValue = this.scannedValue; this.scannedValue = ''; setTimeout(() => this.scanner()?.nativeElement.focus()); } async saveChanges(): Promise { if (this.emailAddresses?.trim()) { await this.warehouseService.addEmailsToWzHeader(this.wzHeaderId, this.emailAddresses); } if (this.changedRecords.length) { await this.updateRows(this.changedRecords); this.changedRecords = []; } } async exportXls(): Promise { const missingPallet = this.rows().some((x) => x.palletNumber == null); const valid = !missingPallet && !!this.emailAddresses?.trim(); this.exportValid.set(valid); if (valid) { await this.warehouseService.addEmailsToWzHeader(this.wzHeaderId, this.emailAddresses); await this.warehouseService.generateXlsForMeyle(this.wzHeaderId); } this.showInfoDialog = true; } async scanValue(): Promise { const value = this.scannedValue.trim(); if (!value) return; if (parseInt(this.palletNumber, 10) <= 0) { this.showPalletDialog = true; return; } this.transactionModels[value]?.[0]; const materialTransaction = this.transactionModels[value]?.[0]; if (!materialTransaction && isValidMeyleScannedValue(value)) { await this.fillMeylePartNumber(value); this.lastScannedValue = value; this.scannedValue = ''; return; } if (materialTransaction) { this.selectedRowsList = []; await this.fillFaPartNumberAndPalletNumber(materialTransaction, value); } else { this.showValidationDialog = true; this.changedRecords = []; return; } this.lastScannedValue = value; this.scannedValue = ''; setTimeout(() => this.scanner()?.nativeElement.focus()); } private async fillMeylePartNumber(scanned: string): Promise { const selected = this.selectedRow(); if (selected && !this.selectedRowsList.length) { selected.partNumber = scanned; this.changedRecords.push(selected); } for (const row of this.selectedRowsList) { row.partNumber = scanned; this.changedRecords.push(row); } await this.saveChanges(); this.changedRecords = []; this.selectedRowsList = []; setTimeout(() => this.scanner()?.nativeElement.focus()); } private async fillFaPartNumberAndPalletNumber(material: TransactionModel, scanned: string): Promise { const palletNum = parseInt(this.palletNumber, 10); const currentRows = this.rows(); let rowIndex = currentRows.findIndex((x) => x.faIndex === material.itemNumber && x.quantity === material.quantity); if (rowIndex === -1) { const candidates = currentRows.filter((x) => x.faIndex === material.itemNumber); if (!candidates.length) { this.showValidationDialog = true; return; } rowIndex = currentRows.findIndex((x) => x.faIndex === candidates[0].faIndex && x.quantity === candidates[0].quantity); const validCombinations = findCombinations(candidates, material.quantity ?? 0); for (const combination of validCombinations) { for (const record of combination) { record.partNumberSl = scanned; record.palletNumber = palletNum; this.changedRecords.push(record); } } this.selectedRowsList = [...this.changedRecords]; this.selectedRow.set(this.selectedRowsList[0] ?? null); } else { const row = currentRows[rowIndex]; this.selectedRow.set(row); row.partNumberSl = scanned; row.palletNumber = palletNum; if (!this.changedRecords.some((x) => x.transactionNumber === row.transactionNumber)) { this.changedRecords.push(row); } } await this.saveChanges(); this.changedRecords = []; setTimeout(() => this.scanner()?.nativeElement.focus()); } async splitLine(): Promise { const qty = parseInt(this.newQuantity, 10); const selected = this.selectedRow(); if (qty <= 0 || !selected) return; const splitRow: WzRowMeyleDto = { id: crypto.randomUUID(), fk_Header: selected.fk_Header, quantity: qty, faIndex: selected.faIndex, itemNumber: selected.itemNumber, orderNumber: selected.orderNumber, palletNumber: selected.palletNumber, wzNumber: selected.wzNumber, transactionNumber: (selected.transactionNumber ?? 0) + 10000, partNumberSl: selected.partNumberSl, partNumber: selected.partNumber, }; selected.quantity = (selected.quantity ?? 0) - qty; await this.warehouseService.createWzRowsMeyle([splitRow]); await this.updateRows([selected]); this.showSplitDialog.set(false); } private async updateRows(changed: WzRowMeyleDto[]): Promise { await this.warehouseService.updateWzRowsMeyle(changed); this.rows.set(await this.warehouseService.getWzRowsMeyleByWzHeaderId(this.wzHeaderId)); } }