package bnn import ( "bufio" "io" "os" "strconv" "strings" "golang.org/x/text/encoding/charmap" ) // Info Structure of headline type Info struct { Kennung string //BNN als Kennung des Dateityps Version int //3 als Versionsnummer der Schnittstelle Zeichensatz int //0=AscII 1=Ansi Versenderadresse string //Name, Ort ... des Händlers Umfang string //V=vollständige Preisliste, T=Teilliste, S=Sonderliste Inhalt string //Text, der die Preisliste näher beschreibt Preiswaehrung string //Währung banküblich (DEM=DM, ATS=österr.Schilling, EUR=Euro) DatumAb string //Preise gültig ab JJJJMMTT DatumBis string //gültig bis, 0=unbestimmt Abgabedatum string //Datum der Datei-Erstellung JJJJMMTT Abgabezeit string //Uhrzeit der Datei-Erstellung SSMM Dateizaehler int //Angabe der Dateinummer, Datei/Diskette1 } // Item Structure of each Item type Item struct { ArtikelNr string //hausinterne Artikelnummer, mit der bestellt werden soll Aenderungskennung string //N=neu, A=Änderung, X=ausgelistet, R=Restbestand, V=vorübergehend ausgelistet, W=wiedergelistet AenderungsDatum int //letztes Artikel-Änderungsdatum JJJJMMTT AenderungsZeit int //Uhrzeit letzte Artikel-Änderung SSMM EANladen int //EAN-Nummer Ladeneinheit (1) EANbestell int //EAN-Nummer Bestelleinheit (1) Bezeichnung string //Artikelbezeichnung Bezeichnung2 string //Zusatz-Artikelbezeichnung Bezeichnung3 string //Bezeichnung für Etiketten- bzw. Kassentext Handelsklasse string //Handelsklasse (in römischen Zahlen: I, II, III, IV ...) HerstellerInverkehrbringer string //Herstellerkürzel (nach BNN-Liste) des Herstellers lt. Deklaration auf der Verpackung Hersteller string //Herstellerkürzel (nach BNN-Liste) falls abweichend von der Verpackung Herkunft string //Qualitätsland (Auto-Länderkennzeichen) Qualitaet string //Qualitätskennung (nach BNN-IK-Liste) Kontrollstelle string //EG-Kontrollstellen-Kennung MHDRestlaufzeit int //übliche Restlaufzeit in Tagen WGBNN int //Warengruppe BNNEH (nach BNN-Liste) WGIfH int //Warengruppe Institut für Handelsforschung (Liste beim BNN erhältlich) WGGH int //Warengruppe des jeweiligen Großhändlers ErsatzArtikelNr string //Ersatz-Artikelnummer Ersatzartikel wird geliefert, falls sonst nicht lieferbar MinBestellMenge float64 //Mindestbestellmenge in Bestelleinheit (1) Bestelleinheit string //Bestelleinheit (1) = Verkaufseinheit des Lieferanten BestelleinheitsMenge float64 //Anzahl Ladeneinheiten je Bestelleinheit (1) Ladeneinheit string //Ladeneinheit (1) = Verkaufseinheit im Laden Mengenfaktor float64 //Faktor zur Menge-Preis-Relation Ladeneinheit (2) Gewichtsartikel bool //J=Ja, N=Nein Ja, wenn der Artikel nur abgewogen verkauft wird PfandNrLadeneinheit string //hausinterne PfandNr für Ladeneinheit (1) PfandNrBestelleinheit string //hausinterne PfandNr für Bestelleinheit (1) GewichtLadeneinheit float64 //Bruttogewicht einer Ladeneinheit (1) in kg GewichtBestelleinheit float64 //Bruttogewicht einer Bestelleinheit (1) in kg Breite int //Packungsbreite der Ladeneinheit in cm Hoehe int //Packungshöhe der Ladeneinheit in cm Tiefe int //Packungstiefe der Ladeneinheit in cm MwstKennung int //Mehrwertsteuer 1=reduziert 2=voll 3=LandwirtsSatz VkFestpreis float64 //Festpreis Endkunde incl. MWSt. lt. Hersteller (Bücher) EmpfVk float64 //empf.VK des Herstellers incl. MWSt. je Ladeneinheit EmpfVkGH float64 //VK-Vorschlag des Lieferanten incl. MWSt. je Ladeneinheit Preis float64 //Einzelpreis o. MWSt je Ladeneinheit Mengenfaktor beachten! rabattfaehig bool //J=Ja, N=Nein skontierfaehig bool //J=Ja, N=Nein StaffelMenge1 float64 //Staffelmenge in Ladeneinheit (1) StaffelPreis1 float64 //Staffelpreis je Ladeneinheit (1) o. MWSt. rabattfaehig1 bool //J=Ja, N=Nein skontierfaehig1 bool //J=Ja, N=Nein StaffelMenge2 float64 //Staffelmenge in Ladeneinheit (1) StaffelPreis2 float64 //Staffelpreis je Ladeneinheit (1) o. MWSt. rabattfaehig2 bool //J=Ja, N=Nein skontierfaehig2 bool //J=Ja, N=Nein StaffelMenge3 float64 //Staffelmenge in Ladeneinheit (1) StaffelPreis3 float64 //Staffelpreis je Ladeneinheit (1) o. MWSt. rabattfaehig3 bool //J=Ja, N=Nein skontierfaehig3 bool //J=Ja, N=Nein StaffelMenge4 float64 //Staffelmenge in Ladeneinheit (1) StaffelPreis4 float64 //Staffelpreis je Ladeneinheit (1) o. MWSt. rabattfaehig4 bool //J=Ja, N=Nein skontierfaehig4 bool //J=Ja, N=Nein StaffelMenge5 float64 //Staffelmenge in Ladeneinheit (1) StaffelPreis5 float64 //Staffelpreis je Ladeneinheit (1) o. MWSt. rabattfaehig5 bool //J=Ja, N=Nein skontierfaehig5 bool //J=Ja, N=Nein Artikelart string //F=Frische (mit Tagespreisen), T=Trocken, W=NaturWaren, P=Pfand (dieser Artikel ist das Pfand selbst!), A=Artikel aus FrischePreisliste (aktuelles Angebot) Aktionspreis string //A=Aktionspreis AktionspreisGueltigAb string //Datum JJJJMMTT, 0 bzw. leer = ab sofort AktionspreisGueltigBis string //Datum JJJJMMTT, 0 bzw. leer = unbestimmt empfVkAktion float64 //Aktions-VK-Vorschlag incl. MWSt. GrundpreisEinheit string //Einheit der Grundpreisauszeichnung (kg, l) GrundpreisFaktor float64 //Mengen-Faktor der Grundpreiseinheit zur Ladeneinheit LieferbarAb string //Datum JJJJMMTT LieferbarBis string //Datum JJJJMMTT } // Bnn Information of file type Bnn struct { Info Info Items []Item } func convertBnnBool(s string) bool { if s == "J" { return true } return false } func convertStringToInt(s string) int { ret, _ := strconv.Atoi(s) return ret } func convertStringToFloat(s string) float64 { ret, _ := strconv.ParseFloat(strings.ReplaceAll(s, ",", "."), 64) return ret } // ReadBnnFile Reads file and returns object with all containing information func ReadBnnFile(path string) (Bnn, error) { file, err := os.Open(path) if err != nil { return Bnn{}, err } defer file.Close() content, err := ReadBnn(file) if err != nil { return Bnn{}, err } return content, nil } // ReadBnn Reads from reader and returns object with all containing information func ReadBnn(r io.Reader) (Bnn, error) { //dr := charmap.CodePage850.NewDecoder().Reader(r) scanner := bufio.NewScanner(r) var lines []string for scanner.Scan() { lines = append(lines, scanner.Text()) } var content Bnn var encoding string for i, line := range lines { var item Item // How to decode file? Use header info for encoding information. if i == 0 && strings.Split(line, ";")[2] == "0" { encoding = "ascii" } // Example file for ASCII was provided by Paxan // Extended ASCII has been used -> ä 132 \u0084 if encoding == "ascii" { line, _ = charmap.CodePage850.NewDecoder().String(line) } col := strings.Split(line, ";") // Headline contains infos if i == 0 { content.Info.Kennung = col[0] content.Info.Version = convertStringToInt(col[1]) content.Info.Zeichensatz = convertStringToInt(col[2]) content.Info.Versenderadresse = col[3] content.Info.Umfang = col[4] content.Info.Inhalt = col[5] content.Info.Preiswaehrung = col[6] content.Info.DatumAb = col[7] content.Info.DatumBis = col[8] content.Info.Abgabedatum = col[9] content.Info.Abgabezeit = col[10] content.Info.Dateizaehler = convertStringToInt(col[11]) continue } // Jump over last line and exit if len(col) == 3 { break } item.ArtikelNr = col[0] item.Aenderungskennung = col[1] item.AenderungsDatum = convertStringToInt(col[2]) item.AenderungsZeit = convertStringToInt(col[3]) item.EANladen = convertStringToInt(col[4]) item.EANbestell = convertStringToInt(col[5]) item.Bezeichnung = col[6] item.Bezeichnung2 = col[7] item.Bezeichnung3 = col[8] item.Handelsklasse = col[9] item.HerstellerInverkehrbringer = col[10] item.Hersteller = col[11] item.Herkunft = col[12] item.Qualitaet = col[13] item.Kontrollstelle = col[14] item.MHDRestlaufzeit = convertStringToInt(col[15]) item.WGBNN = convertStringToInt(col[16]) item.WGIfH = convertStringToInt(col[17]) item.WGGH = convertStringToInt(col[18]) item.ErsatzArtikelNr = col[19] item.MinBestellMenge = convertStringToFloat(col[20]) item.Bestelleinheit = col[21] item.BestelleinheitsMenge = convertStringToFloat(col[22]) item.Ladeneinheit = col[23] item.Mengenfaktor = convertStringToFloat(col[24]) item.Gewichtsartikel = convertBnnBool(col[25]) item.PfandNrLadeneinheit = col[26] item.PfandNrBestelleinheit = col[27] item.GewichtLadeneinheit = convertStringToFloat(col[28]) item.GewichtBestelleinheit = convertStringToFloat(col[29]) item.Breite = convertStringToInt(col[30]) item.Hoehe = convertStringToInt(col[31]) item.Tiefe = convertStringToInt(col[32]) item.MwstKennung = convertStringToInt(col[33]) item.VkFestpreis = convertStringToFloat(col[34]) item.EmpfVk = convertStringToFloat(col[35]) item.EmpfVkGH = convertStringToFloat(col[36]) item.Preis = convertStringToFloat(col[37]) item.rabattfaehig = convertBnnBool(col[38]) item.skontierfaehig = convertBnnBool(col[39]) item.StaffelMenge1 = convertStringToFloat(col[40]) item.StaffelPreis1 = convertStringToFloat(col[41]) item.rabattfaehig1 = convertBnnBool(col[42]) item.skontierfaehig1 = convertBnnBool(col[43]) item.StaffelMenge2 = convertStringToFloat(col[44]) item.StaffelPreis2 = convertStringToFloat(col[45]) item.rabattfaehig2 = convertBnnBool(col[46]) item.skontierfaehig2 = convertBnnBool(col[47]) item.StaffelMenge3 = convertStringToFloat(col[48]) item.StaffelPreis3 = convertStringToFloat(col[49]) item.rabattfaehig3 = convertBnnBool(col[50]) item.skontierfaehig3 = convertBnnBool(col[51]) item.StaffelMenge4 = convertStringToFloat(col[52]) item.StaffelPreis4 = convertStringToFloat(col[53]) item.rabattfaehig4 = convertBnnBool(col[54]) item.skontierfaehig4 = convertBnnBool(col[55]) item.StaffelMenge5 = convertStringToFloat(col[56]) item.StaffelPreis5 = convertStringToFloat(col[57]) item.rabattfaehig5 = convertBnnBool(col[58]) item.skontierfaehig5 = convertBnnBool(col[59]) item.Artikelart = col[60] item.Aktionspreis = col[61] item.AktionspreisGueltigAb = col[62] item.AktionspreisGueltigBis = col[63] item.empfVkAktion = convertStringToFloat(col[64]) item.GrundpreisEinheit = col[65] item.GrundpreisFaktor = convertStringToFloat(col[66]) item.LieferbarAb = col[67] item.LieferbarBis = col[68] content.Items = append(content.Items, item) } return content, nil }