fix(sync): Lieferadresse nicht mehr feldweise mischen, Adresszusatz statt Land
- Sync nimmt die Lieferadresse als Ganzes: mit eigener LieferAdressId alle Felder aus ihr, sonst alle aus der Belegadresse. Das bisherige COALESCE je Feld hat leere Felder mit Werten des Bestellers gefüllt (z. B. dessen Ortsteil an eine fremde Anschrift gehängt). - ERP-Freitext `Adressen.Land` (praktisch Ortsteil/Etage/Hinweis) wird zum Adresszusatz `Address.addition`; `country` kommt jetzt aus dem Länderstamm (`LandID` → `Laender.Land`). Deutschland-Kürzel und reine Landnamen sind kein Zusatz. - Migration 0034: `customers.address_addition`, `deliveries.snap_addition`; Bestandstext aus `country` wandert in den Zusatz. - Lieferbericht und Beleg-Ansicht: Land nur außerhalb Deutschlands, Zusatz als eigene Zeile „Zusatz: …". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@ -16,5 +16,74 @@ pub struct Address {
|
||||
pub house_number: String,
|
||||
pub postal_code: String,
|
||||
pub city: String,
|
||||
/// Land laut ERP-Länderstamm (`Adressen.LandID` → `Laender.Land`), z. B.
|
||||
/// „Deutschland" oder „Belgien". Leer, wenn im ERP kein Land verknüpft ist.
|
||||
pub country: String,
|
||||
/// Freier Adresszusatz. Kommt aus dem ERP-Textfeld `Adressen.Land`, das
|
||||
/// die Sachbearbeitung praktisch für Ortsteil, Etage oder Hinweise nutzt
|
||||
/// (z. B. „Holzheim", „3. Etage", „Parterre"). `None`, wenn leer.
|
||||
#[serde(default)]
|
||||
pub addition: Option<String>,
|
||||
}
|
||||
|
||||
impl Address {
|
||||
/// Einzeilige Anschrift „Straße Nr, PLZ Ort" — das Land nur, wenn es
|
||||
/// nicht Deutschland ist. Der Adresszusatz gehört nicht dazu (eigene
|
||||
/// Zeile in der Anzeige).
|
||||
pub fn one_line(&self) -> String {
|
||||
let line1 = join_non_empty(&[&self.street, &self.house_number], " ");
|
||||
let line2 = join_non_empty(&[&self.postal_code, &self.city], " ");
|
||||
let country = self.foreign_country().unwrap_or_default();
|
||||
join_non_empty(&[&line1, &line2, country], ", ")
|
||||
}
|
||||
|
||||
/// Land für die Anzeige: `None` für Deutschland (Heimatmarkt) oder leer.
|
||||
pub fn foreign_country(&self) -> Option<&str> {
|
||||
let c = self.country.trim();
|
||||
(!c.is_empty() && !is_germany(c)).then_some(c)
|
||||
}
|
||||
}
|
||||
|
||||
/// `true` für die im ERP vorkommenden Schreibweisen von Deutschland.
|
||||
pub fn is_germany(value: &str) -> bool {
|
||||
matches!(
|
||||
value.trim().to_lowercase().as_str(),
|
||||
"d" | "de" | "deu" | "deutschland" | "germany" | "brd"
|
||||
)
|
||||
}
|
||||
|
||||
fn join_non_empty(parts: &[&str], sep: &str) -> String {
|
||||
parts
|
||||
.iter()
|
||||
.map(|p| p.trim())
|
||||
.filter(|p| !p.is_empty())
|
||||
.collect::<Vec<_>>()
|
||||
.join(sep)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod address_tests {
|
||||
use super::*;
|
||||
|
||||
fn address(country: &str) -> Address {
|
||||
Address {
|
||||
street: "Am Sandberg".into(),
|
||||
house_number: "15".into(),
|
||||
postal_code: "41472".into(),
|
||||
city: "Neuss".into(),
|
||||
country: country.into(),
|
||||
addition: Some("Holzheim".into()),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deutschland_und_zusatz_stehen_nicht_in_der_zeile() {
|
||||
assert_eq!(address("Deutschland").one_line(), "Am Sandberg 15, 41472 Neuss");
|
||||
assert_eq!(address("").one_line(), "Am Sandberg 15, 41472 Neuss");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ausland_wird_angehaengt() {
|
||||
assert_eq!(address("Belgien").one_line(), "Am Sandberg 15, 41472 Neuss, Belgien");
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ pub use account::Account;
|
||||
pub use article::Article;
|
||||
pub use audit::{AuditAction, ScanAuditEntry};
|
||||
pub use car::Car;
|
||||
pub use common::Address;
|
||||
pub use common::{is_germany, Address};
|
||||
pub use contact::{ContactChannel, ContactKind, ContactRole, ContactSource};
|
||||
pub use customer::{Customer, CustomerContact};
|
||||
pub use delivery::{
|
||||
|
||||
Reference in New Issue
Block a user