Bankverbindung (Bank, IBAN, BIC) im Adressbuch, IBAN/BIC über den Rechnungssteller statt Freitext
IBAN-Prüfung (ISO 13616) in eigenen IbanValidator ausgelagert; Käuferreferenz und dev-Testdaten aus der Rechnungsmaske entfernt, Entwurf-Speichern nur bei gefüllten Pflichtfeldern. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,11 @@ public class Address {
|
||||
private String email;
|
||||
private String phone;
|
||||
|
||||
// Bankverbindung (v. a. für Rechnungssteller relevant)
|
||||
private String bankName;
|
||||
private String iban;
|
||||
private String bic;
|
||||
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
@@ -114,6 +119,30 @@ public class Address {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getBankName() {
|
||||
return bankName;
|
||||
}
|
||||
|
||||
public void setBankName(String bankName) {
|
||||
this.bankName = bankName;
|
||||
}
|
||||
|
||||
public String getIban() {
|
||||
return iban;
|
||||
}
|
||||
|
||||
public void setIban(String iban) {
|
||||
this.iban = iban;
|
||||
}
|
||||
|
||||
public String getBic() {
|
||||
return bic;
|
||||
}
|
||||
|
||||
public void setBic(String bic) {
|
||||
this.bic = bic;
|
||||
}
|
||||
|
||||
public LocalDateTime getCreatedAt() {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package de.assecutor.pdftool.invoice;
|
||||
|
||||
/**
|
||||
* Prüft IBANs nach ISO 13616 (MOD 97-10).
|
||||
*/
|
||||
public final class IbanValidator {
|
||||
|
||||
private IbanValidator() {
|
||||
}
|
||||
|
||||
public static boolean isValid(String value) {
|
||||
String normalized = normalize(value);
|
||||
if (!normalized.matches("[A-Z]{2}\\d{2}[A-Z0-9]{11,30}")) {
|
||||
return false;
|
||||
}
|
||||
String rearranged = normalized.substring(4) + normalized.substring(0, 4);
|
||||
int mod = 0;
|
||||
for (char c : rearranged.toCharArray()) {
|
||||
int digit = Character.isDigit(c) ? c - '0' : c - 'A' + 10;
|
||||
mod = digit < 10 ? (mod * 10 + digit) % 97 : (mod * 100 + digit) % 97;
|
||||
}
|
||||
return mod == 1;
|
||||
}
|
||||
|
||||
/** Entfernt Leerzeichen und wandelt in Großbuchstaben um. */
|
||||
public static String normalize(String value) {
|
||||
return value.replaceAll("\\s", "").toUpperCase();
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.vaadin.flow.router.Route;
|
||||
import de.assecutor.pdftool.address.Address;
|
||||
import de.assecutor.pdftool.address.AddressRepository;
|
||||
import de.assecutor.pdftool.address.AddressType;
|
||||
import de.assecutor.pdftool.invoice.IbanValidator;
|
||||
import de.assecutor.pdftool.invoice.VatIdValidator;
|
||||
import org.springframework.data.domain.Sort;
|
||||
|
||||
@@ -122,7 +123,7 @@ public class AddressBookView extends VerticalLayout {
|
||||
Address target = address == null ? new Address() : address;
|
||||
|
||||
Dialog dialog = new Dialog();
|
||||
dialog.setHeaderTitle(isNew ? "Neue Adresse" : "Adresse bearbeiten");
|
||||
dialog.setHeaderTitle(isNew ? "Neues Unternehmen" : "Unternehmen bearbeiten");
|
||||
|
||||
ComboBox<AddressType> type = new ComboBox<>("Typ");
|
||||
type.setItems(AddressType.values());
|
||||
@@ -154,7 +155,17 @@ public class AddressBookView extends VerticalLayout {
|
||||
TextField phone = new TextField("Telefon");
|
||||
phone.setValue(target.getPhone() != null ? target.getPhone() : "");
|
||||
|
||||
FormLayout form = new FormLayout(type, name, street, zip, city, countryCode, vatId, email, phone);
|
||||
// Bankverbindung (optional)
|
||||
TextField bankName = new TextField("Bank");
|
||||
bankName.setValue(target.getBankName() != null ? target.getBankName() : "");
|
||||
TextField iban = new TextField("IBAN");
|
||||
iban.setValue(target.getIban() != null ? target.getIban() : "");
|
||||
iban.setHelperText("z. B. DE02 1203 0000 0000 2020 51");
|
||||
TextField bic = new TextField("BIC");
|
||||
bic.setValue(target.getBic() != null ? target.getBic() : "");
|
||||
|
||||
FormLayout form = new FormLayout(type, name, street, zip, city, countryCode, vatId, email, phone,
|
||||
bankName, iban, bic);
|
||||
form.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1), new FormLayout.ResponsiveStep("500px", 2));
|
||||
form.setWidth("560px");
|
||||
dialog.add(form);
|
||||
@@ -189,6 +200,17 @@ public class AddressBookView extends VerticalLayout {
|
||||
email.setInvalid(true);
|
||||
errors.add("E-Mail-Adresse ist ungültig.");
|
||||
}
|
||||
if (!iban.getValue().isBlank() && !IbanValidator.isValid(iban.getValue())) {
|
||||
iban.setErrorMessage("IBAN ist ungültig (Prüfsumme).");
|
||||
iban.setInvalid(true);
|
||||
errors.add("IBAN ist ungültig (Prüfsumme).");
|
||||
}
|
||||
if (!bic.getValue().isBlank()
|
||||
&& !bic.getValue().trim().matches("[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?")) {
|
||||
bic.setErrorMessage("BIC ist ungültig (8 oder 11 Stellen).");
|
||||
bic.setInvalid(true);
|
||||
errors.add("BIC ist ungültig (8 oder 11 Stellen).");
|
||||
}
|
||||
if (!errors.isEmpty()) {
|
||||
Notification.show(String.join("\n", errors), 5000, Notification.Position.MIDDLE)
|
||||
.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||
@@ -204,6 +226,9 @@ public class AddressBookView extends VerticalLayout {
|
||||
target.setVatId(vatId.getValue().isBlank() ? "" : VatIdValidator.normalize(vatId.getValue()));
|
||||
target.setEmail(email.getValue().trim());
|
||||
target.setPhone(phone.getValue().trim());
|
||||
target.setBankName(bankName.getValue().trim());
|
||||
target.setIban(iban.getValue().isBlank() ? "" : IbanValidator.normalize(iban.getValue()));
|
||||
target.setBic(bic.getValue().trim().toUpperCase());
|
||||
target.touch();
|
||||
repository.save(target);
|
||||
|
||||
|
||||
@@ -27,12 +27,11 @@ import com.vaadin.flow.component.upload.receivers.MemoryBuffer;
|
||||
import com.vaadin.flow.router.PageTitle;
|
||||
import com.vaadin.flow.router.Route;
|
||||
import com.vaadin.flow.server.StreamResource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.Profiles;
|
||||
import de.assecutor.pdftool.address.Address;
|
||||
import de.assecutor.pdftool.address.AddressRepository;
|
||||
import de.assecutor.pdftool.address.AddressType;
|
||||
import de.assecutor.pdftool.invoice.CapturedInvoiceData;
|
||||
import de.assecutor.pdftool.invoice.IbanValidator;
|
||||
import de.assecutor.pdftool.invoice.InvoiceDraft;
|
||||
import de.assecutor.pdftool.invoice.InvoiceDraftService;
|
||||
import de.assecutor.pdftool.invoice.InvoiceMetadata;
|
||||
@@ -107,9 +106,6 @@ public class MainView extends VerticalLayout {
|
||||
private final DatePicker dueDate = new DatePicker("Fälligkeitsdatum");
|
||||
private final TextField currency = new TextField("Währung");
|
||||
private final TextField paymentTerms = new TextField("Zahlungsbedingungen");
|
||||
private final TextField buyerReference = new TextField("Käuferreferenz / Leitweg-ID");
|
||||
private final TextField iban = new TextField("IBAN (Rechnungssteller)");
|
||||
private final TextField bic = new TextField("BIC");
|
||||
|
||||
private final PartyForm sender = new PartyForm(true);
|
||||
private final PartyForm recipient = new PartyForm(false);
|
||||
@@ -128,8 +124,7 @@ public class MainView extends VerticalLayout {
|
||||
|
||||
public MainView(ZugferdService zugferdService, CapturedInvoiceData capturedInvoiceData,
|
||||
InvoiceTemplateService invoiceTemplateService, TemplatePdfService templatePdfService,
|
||||
AddressRepository addressRepository, InvoiceDraftService invoiceDraftService,
|
||||
Environment environment) {
|
||||
AddressRepository addressRepository, InvoiceDraftService invoiceDraftService) {
|
||||
this.zugferdService = zugferdService;
|
||||
this.capturedInvoiceData = capturedInvoiceData;
|
||||
this.invoiceTemplateService = invoiceTemplateService;
|
||||
@@ -209,10 +204,8 @@ public class MainView extends VerticalLayout {
|
||||
currency.setPattern("[A-Za-z]{3}");
|
||||
currency.setErrorMessage("Währung als dreistelliger ISO-Code, z. B. EUR.");
|
||||
currency.setValue("EUR");
|
||||
buyerReference.setHelperText("BT-10 — für Rechnungen an Behörden erforderlich");
|
||||
iban.setHelperText("Für die Zahlungsangaben (BG-16) empfohlen");
|
||||
FormLayout invoiceForm = new FormLayout(invoiceNumber, issueDate, deliveryDate, dueDate, currency,
|
||||
paymentTerms, buyerReference, iban, bic);
|
||||
paymentTerms);
|
||||
invoiceForm.setResponsiveSteps(new FormLayout.ResponsiveStep("0", 1), new FormLayout.ResponsiveStep("600px", 3));
|
||||
add(new H3("2. Rechnungsdaten"), invoiceForm);
|
||||
|
||||
@@ -240,10 +233,6 @@ public class MainView extends VerticalLayout {
|
||||
|
||||
registerDraftDirtyTracking();
|
||||
updateSaveDraftEnabled();
|
||||
|
||||
if (environment.acceptsProfiles(Profiles.of("dev"))) {
|
||||
prefillDevData();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -325,9 +314,9 @@ public class MainView extends VerticalLayout {
|
||||
issueDate.getValue(), deliveryDate.getValue(), dueDate.getValue(),
|
||||
currency.getValue().trim(),
|
||||
paymentTerms.getValue(),
|
||||
buyerReference.getValue().trim(),
|
||||
iban.getValue().trim(),
|
||||
bic.getValue().trim(),
|
||||
"",
|
||||
sender.ibanNormalized(),
|
||||
sender.bicNormalized(),
|
||||
sender.toParty(), recipient.toParty(),
|
||||
List.copyOf(lineItems),
|
||||
LocalDateTime.now());
|
||||
@@ -358,10 +347,8 @@ public class MainView extends VerticalLayout {
|
||||
dueDate.setValue(draft.dueDate());
|
||||
currency.setValue(nullToEmpty(draft.currency()));
|
||||
paymentTerms.setValue(nullToEmpty(draft.paymentTerms()));
|
||||
buyerReference.setValue(nullToEmpty(draft.buyerReference()));
|
||||
iban.setValue(nullToEmpty(draft.iban()));
|
||||
bic.setValue(nullToEmpty(draft.bic()));
|
||||
applyParty(sender, draft.sender());
|
||||
sender.prefillBank(nullToEmpty(draft.iban()), nullToEmpty(draft.bic()));
|
||||
applyParty(recipient, draft.recipient());
|
||||
lineItems.clear();
|
||||
if (draft.items() != null) {
|
||||
@@ -382,7 +369,7 @@ public class MainView extends VerticalLayout {
|
||||
form.prefill(nullToEmpty(party.name()), nullToEmpty(party.street()),
|
||||
nullToEmpty(party.zip()), nullToEmpty(party.city()),
|
||||
nullToEmpty(party.countryCode()), nullToEmpty(party.vatId()),
|
||||
nullToEmpty(party.email()), nullToEmpty(party.phone()));
|
||||
nullToEmpty(party.email()));
|
||||
}
|
||||
|
||||
/** Konfiguriert eine Adressbuch-Auswahl, die bei Auswahl das zugehörige Adressformular vorbelegt. */
|
||||
@@ -397,7 +384,8 @@ public class MainView extends VerticalLayout {
|
||||
form.prefill(nullToEmpty(address.getName()), nullToEmpty(address.getStreet()),
|
||||
nullToEmpty(address.getZip()), nullToEmpty(address.getCity()),
|
||||
nullToEmpty(address.getCountryCode()), nullToEmpty(address.getVatId()),
|
||||
nullToEmpty(address.getEmail()), nullToEmpty(address.getPhone()));
|
||||
nullToEmpty(address.getEmail()));
|
||||
form.prefillBank(nullToEmpty(address.getIban()), nullToEmpty(address.getBic()));
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -415,22 +403,6 @@ public class MainView extends VerticalLayout {
|
||||
return List.copyOf(lineItems);
|
||||
}
|
||||
|
||||
/** Belegt das Formular im dev-Profil mit Testdaten vor, um manuelles Tippen zu sparen. */
|
||||
private void prefillDevData() {
|
||||
invoiceNumber.setValue("11111");
|
||||
deliveryDate.setValue(LocalDate.now());
|
||||
dueDate.setValue(LocalDate.now().plusDays(14));
|
||||
paymentTerms.setValue("14 Tage");
|
||||
buyerReference.setValue("11111");
|
||||
iban.setValue("DE64 6001 0070 0379 0907 00");
|
||||
bic.setValue("PBNKDEFFXXX");
|
||||
// Rechnungssteller und -empfänger bleiben leer und werden über die
|
||||
// Adressbuch-Auswahl befüllt.
|
||||
lineItems.add(new InvoiceMetadata.LineItem("sdf", BigDecimal.ONE, new BigDecimal("100"),
|
||||
new BigDecimal("19")));
|
||||
refreshItemsGrid();
|
||||
}
|
||||
|
||||
/** Tabelle der Rechnungspositionen mit Bearbeiten-/Löschen-Icons pro Zeile. */
|
||||
private void configureItemsGrid() {
|
||||
itemsGrid.addColumn(item -> item.description()).setHeader("Beschreibung").setFlexGrow(1);
|
||||
@@ -471,20 +443,28 @@ public class MainView extends VerticalLayout {
|
||||
dueDate.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
currency.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
paymentTerms.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
buyerReference.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
iban.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
bic.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
templateSelect.addValueChangeListener(event -> updateSaveDraftEnabled());
|
||||
sender.onAnyChange(this::updateSaveDraftEnabled);
|
||||
recipient.onAnyChange(this::updateSaveDraftEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Der Speichern-Button ist nur aktiv, wenn keine Vorbelegung geladen wurde
|
||||
* oder sich die Eingaben seit dem Laden bzw. Speichern geändert haben.
|
||||
* Der Speichern-Button ist nur aktiv, wenn alle Pflichtfelder gefüllt sind
|
||||
* und keine Vorbelegung geladen wurde oder sich die Eingaben seit dem Laden
|
||||
* bzw. Speichern geändert haben.
|
||||
*/
|
||||
private void updateSaveDraftEnabled() {
|
||||
saveDraftButton.setEnabled(loadedDraftState == null || !comparableState().equals(loadedDraftState));
|
||||
boolean changed = loadedDraftState == null || !comparableState().equals(loadedDraftState);
|
||||
saveDraftButton.setEnabled(changed && requiredFieldsFilled());
|
||||
}
|
||||
|
||||
/** @return true, wenn alle Pflichtfelder der Maske gefüllt sind. */
|
||||
private boolean requiredFieldsFilled() {
|
||||
return !invoiceNumber.getValue().isBlank()
|
||||
&& issueDate.getValue() != null
|
||||
&& !currency.getValue().isBlank()
|
||||
&& sender.requiredFieldsFilled()
|
||||
&& recipient.requiredFieldsFilled();
|
||||
}
|
||||
|
||||
/** Der aktuelle Formularstand ohne Name und Zeitstempel, zum Vergleich mit der geladenen Vorbelegung. */
|
||||
@@ -495,9 +475,9 @@ public class MainView extends VerticalLayout {
|
||||
issueDate.getValue(), deliveryDate.getValue(), dueDate.getValue(),
|
||||
currency.getValue().trim(),
|
||||
paymentTerms.getValue(),
|
||||
buyerReference.getValue().trim(),
|
||||
iban.getValue().trim(),
|
||||
bic.getValue().trim(),
|
||||
"",
|
||||
sender.ibanNormalized(),
|
||||
sender.bicNormalized(),
|
||||
sender.toParty(), recipient.toParty(),
|
||||
List.copyOf(lineItems),
|
||||
null);
|
||||
@@ -694,16 +674,6 @@ public class MainView extends VerticalLayout {
|
||||
&& !currency.getValue().trim().matches("[A-Za-z]{3}")) {
|
||||
markInvalid(currency, "Währung als dreistelliger ISO-Code, z. B. EUR.", errors);
|
||||
}
|
||||
if (!iban.isEmpty() && !isValidIban(iban.getValue())) {
|
||||
markInvalid(iban, "IBAN ist ungültig (Prüfsumme).", errors);
|
||||
} else {
|
||||
iban.setInvalid(false);
|
||||
}
|
||||
if (!bic.isEmpty() && !bic.getValue().trim().matches("[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?")) {
|
||||
markInvalid(bic, "BIC muss 8 oder 11 Stellen haben, z. B. NOLADE21RZB.", errors);
|
||||
} else {
|
||||
bic.setInvalid(false);
|
||||
}
|
||||
errors.addAll(sender.validateFields("Rechnungssteller"));
|
||||
errors.addAll(recipient.validateFields("Rechnungsempfänger"));
|
||||
if (lineItems.isEmpty()) {
|
||||
@@ -720,9 +690,9 @@ public class MainView extends VerticalLayout {
|
||||
dueDate.getValue(),
|
||||
currency.getValue().trim().toUpperCase(),
|
||||
paymentTerms.getValue(),
|
||||
buyerReference.getValue().trim(),
|
||||
iban.getValue().replaceAll("\\s", "").toUpperCase(),
|
||||
bic.getValue().trim().toUpperCase(),
|
||||
"",
|
||||
sender.ibanNormalized(),
|
||||
sender.bicNormalized(),
|
||||
sender.toParty(),
|
||||
recipient.toParty(),
|
||||
lineItems
|
||||
@@ -760,21 +730,6 @@ public class MainView extends VerticalLayout {
|
||||
errors.add(message);
|
||||
}
|
||||
|
||||
/** IBAN-Prüfung nach ISO 13616 (MOD 97-10). */
|
||||
private static boolean isValidIban(String value) {
|
||||
String normalized = value.replaceAll("\\s", "").toUpperCase();
|
||||
if (!normalized.matches("[A-Z]{2}\\d{2}[A-Z0-9]{11,30}")) {
|
||||
return false;
|
||||
}
|
||||
String rearranged = normalized.substring(4) + normalized.substring(0, 4);
|
||||
int mod = 0;
|
||||
for (char c : rearranged.toCharArray()) {
|
||||
int digit = Character.isDigit(c) ? c - '0' : c - 'A' + 10;
|
||||
mod = digit < 10 ? (mod * 10 + digit) % 97 : (mod * 100 + digit) % 97;
|
||||
}
|
||||
return mod == 1;
|
||||
}
|
||||
|
||||
private void showErrors(List<String> messages) {
|
||||
Notification notification = new Notification();
|
||||
notification.addThemeVariants(NotificationVariant.LUMO_ERROR);
|
||||
@@ -802,7 +757,10 @@ public class MainView extends VerticalLayout {
|
||||
private final TextField countryCode = new TextField("Land (ISO-Code, z.B. DE)");
|
||||
private final TextField vatId = new TextField("USt-IdNr.");
|
||||
private final EmailField email = new EmailField("E-Mail");
|
||||
private final TextField phone = new TextField("Telefon");
|
||||
|
||||
// Bankverbindung; nur beim Rechnungssteller sichtbar und Pflicht
|
||||
private final TextField iban = new TextField("IBAN");
|
||||
private final TextField bic = new TextField("BIC");
|
||||
|
||||
PartyForm(boolean vatRequired) {
|
||||
this.vatRequired = vatRequired;
|
||||
@@ -824,15 +782,35 @@ public class MainView extends VerticalLayout {
|
||||
email.setErrorMessage("Gültige E-Mail-Adresse angeben.");
|
||||
// E-Mail direkt beim Verlassen des Feldes prüfen
|
||||
email.addValueChangeListener(event -> checkEmail());
|
||||
add(name, street, zip, city, countryCode, vatId, email);
|
||||
if (vatRequired) {
|
||||
phone.setHelperText("Für den Verkäufer-Kontakt (BR-DE-6) empfohlen");
|
||||
iban.setRequired(true);
|
||||
iban.setHelperText("Für die Zahlungsangaben (BG-16)");
|
||||
bic.setRequired(true);
|
||||
bic.setHelperText("8 oder 11 Stellen, z. B. NOLADE21RZB");
|
||||
add(iban, bic);
|
||||
}
|
||||
add(name, street, zip, city, countryCode, vatId, email, phone);
|
||||
setResponsiveSteps(new ResponsiveStep("0", 1), new ResponsiveStep("600px", 3));
|
||||
}
|
||||
|
||||
/** Belegt die Bankverbindung vor, z. B. aus dem Adressbuch. */
|
||||
void prefillBank(String ibanValue, String bicValue) {
|
||||
iban.setValue(ibanValue);
|
||||
bic.setValue(bicValue);
|
||||
}
|
||||
|
||||
/** IBAN ohne Leerzeichen in Großschreibung. */
|
||||
String ibanNormalized() {
|
||||
return iban.getValue().replaceAll("\\s", "").toUpperCase();
|
||||
}
|
||||
|
||||
/** BIC ohne führende/abschließende Leerzeichen in Großschreibung. */
|
||||
String bicNormalized() {
|
||||
return bic.getValue().trim().toUpperCase();
|
||||
}
|
||||
|
||||
void prefill(String nameValue, String streetValue, String zipValue, String cityValue,
|
||||
String countryValue, String vatIdValue, String emailValue, String phoneValue) {
|
||||
String countryValue, String vatIdValue, String emailValue) {
|
||||
name.setValue(nameValue);
|
||||
street.setValue(streetValue);
|
||||
zip.setValue(zipValue);
|
||||
@@ -840,7 +818,18 @@ public class MainView extends VerticalLayout {
|
||||
countryCode.setValue(countryValue);
|
||||
vatId.setValue(vatIdValue);
|
||||
email.setValue(emailValue);
|
||||
phone.setValue(phoneValue);
|
||||
}
|
||||
|
||||
/** @return true, wenn alle Pflichtfelder des Adressformulars gefüllt sind. */
|
||||
boolean requiredFieldsFilled() {
|
||||
return !name.getValue().isBlank()
|
||||
&& !street.getValue().isBlank()
|
||||
&& !zip.getValue().isBlank()
|
||||
&& !city.getValue().isBlank()
|
||||
&& !countryCode.getValue().isBlank()
|
||||
&& (!vatRequired || !vatId.getValue().isBlank())
|
||||
&& !email.getValue().isBlank()
|
||||
&& (!vatRequired || (!iban.getValue().isBlank() && !bic.getValue().isBlank()));
|
||||
}
|
||||
|
||||
/** Meldet jede Wertänderung eines Feldes, z. B. für die Dirty-Erkennung. */
|
||||
@@ -852,12 +841,14 @@ public class MainView extends VerticalLayout {
|
||||
countryCode.addValueChangeListener(event -> listener.run());
|
||||
vatId.addValueChangeListener(event -> listener.run());
|
||||
email.addValueChangeListener(event -> listener.run());
|
||||
phone.addValueChangeListener(event -> listener.run());
|
||||
iban.addValueChangeListener(event -> listener.run());
|
||||
bic.addValueChangeListener(event -> listener.run());
|
||||
}
|
||||
|
||||
/** Leert alle Felder; das Land behält den Standardwert "DE". */
|
||||
void clearFields() {
|
||||
prefill("", "", "", "", "DE", "", "", "");
|
||||
prefill("", "", "", "", "DE", "", "");
|
||||
prefillBank("", "");
|
||||
name.setInvalid(false);
|
||||
street.setInvalid(false);
|
||||
zip.setInvalid(false);
|
||||
@@ -865,6 +856,8 @@ public class MainView extends VerticalLayout {
|
||||
countryCode.setInvalid(false);
|
||||
vatId.setInvalid(false);
|
||||
email.setInvalid(false);
|
||||
iban.setInvalid(false);
|
||||
bic.setInvalid(false);
|
||||
}
|
||||
|
||||
/** @return true, wenn die E-Mail-Adresse gültig (oder leer) ist. */
|
||||
@@ -915,6 +908,16 @@ public class MainView extends VerticalLayout {
|
||||
} else if (!checkEmail()) {
|
||||
errors.add(partyLabel + ": E-Mail-Adresse ist ungültig.");
|
||||
}
|
||||
if (vatRequired) {
|
||||
if (requireFilled(iban, partyLabel + ": IBAN ist ein Pflichtfeld.", errors)
|
||||
&& !IbanValidator.isValid(iban.getValue())) {
|
||||
markInvalid(iban, partyLabel + ": IBAN ist ungültig (Prüfsumme).", errors);
|
||||
}
|
||||
if (requireFilled(bic, partyLabel + ": BIC ist ein Pflichtfeld.", errors)
|
||||
&& !bic.getValue().trim().matches("[A-Za-z]{6}[A-Za-z0-9]{2}([A-Za-z0-9]{3})?")) {
|
||||
markInvalid(bic, partyLabel + ": BIC muss 8 oder 11 Stellen haben, z. B. NOLADE21RZB.", errors);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
@@ -927,7 +930,7 @@ public class MainView extends VerticalLayout {
|
||||
countryCode.getValue().trim().toUpperCase(),
|
||||
vatId.isEmpty() ? "" : VatIdValidator.normalize(vatId.getValue()),
|
||||
email.getValue().trim(),
|
||||
phone.getValue().trim()
|
||||
""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user