diff --git a/check_for_new_stores.py b/check_for_new_stores.py new file mode 100644 index 0000000..8de24a3 --- /dev/null +++ b/check_for_new_stores.py @@ -0,0 +1,46 @@ +import os +from datetime import datetime, timedelta +from localconfig import STORESFILE, SORTED_PATH, log +import tempfile +import csv + +stores_to_invoice = {} + +def list_of_stores_on(YYYY, MM, DD): + list_of_stores_in_folder = [] + folder = os.path.join(SORTED_PATH, YYYY, MM, DD) + for root, dirs, files in os.walk(folder): + for dir in dirs: + if len(dir) == 4: + list_of_stores_in_folder.append(dir) + + return list_of_stores_in_folder + + +def get_new_stores(stores_in_sorted): + # open the csv file and crosslink it with the found stores in the folder + new_stores = '' + with open(STORESFILE, newline="", encoding="utf-8") as f_in: + reader = csv.DictReader(f_in) + for row in reader: + if row["store"] in stores_in_sorted: + stores_in_sorted.remove(row["store"]) + # now we are left with stores_in_sorted only holding stores not in our storesfile + if len(stores_in_sorted) > 0: + for s in stores_in_sorted: + new_stores += f"{s},,,,,1\n" + log(f"Found new store {s}. You can find it in {STORESFILE}",1) + return new_stores + + + +if __name__ == '__main__': + today = datetime.today().date() + yesterday = today - timedelta(days=1) + stores_poslogged = list_of_stores_on(yesterday.strftime('%Y'), yesterday.strftime('%m'), yesterday.strftime('%d')) + csv_lines = get_new_stores(stores_poslogged) + if len(csv_lines) > 1: + with open(STORESFILE, "a", encoding="utf-8") as f: + f.write(csv_lines) + + diff --git a/data/buyersdata_broken.csv b/data/buyersdata_broken.csv new file mode 100644 index 0000000..226b6ea --- /dev/null +++ b/data/buyersdata_broken.csv @@ -0,0 +1,4 @@ +Office,Invoice,Receipt,OrgId,TaxId,Organization,City,Street,Zip,Country +PL,A282_T000_260110_1,A28220260110102114,0,0,-customer not found-,,,,EU +HR,A100_T000_260126_1,A10020260126101017,,,Test,Zagreb,Test 12,10000,HR +BE,AN19_T000_260209_2,AN1920260104105115,,,,Heppen,Leopoldsburgsesteenweg 58,3971,BE diff --git a/data/buyersdata_repaired.csv b/data/buyersdata_repaired.csv new file mode 100644 index 0000000..a247324 --- /dev/null +++ b/data/buyersdata_repaired.csv @@ -0,0 +1,17 @@ +Office,Invoice,Receipt,OrgId,TaxId,Organization,City,Street,Zip,Country +HR,A100_T000_260129_1,A10020260129101012,123456789,123456789,Max ,Zagreb,Teststreet 12,10000,XX +BE,AN02_T000_260203_1,AN0220251231101117,XX,XX,First Name,Brug,Streetnumber 2,28394,XX +BE,AN03_T000_260206_1,AN0320260106101110,673369743,673369743,House of Bouillon,Bouillon,Quai du rempart 36,6830,BE +BE,A1E0_T000_260206_1,A1E020260112102152,787736010,787736010,R-FIK COMPANY,Neufchâteau,Avenue de la Gare 147,6840,BE +BE,AN09_T000_260209_1,AN0920260119103083,633579459,633579459,Codrigis BV,Zwevegem,Beekstraat  58,8550,BE +BE,AN09_T000_260209_2,AN0920260118101087,819258040,819258040,DJ KRISTOF,Izegem,Voetbalstraat  21,8870,BE +BE,AN09_T000_260209_3,AN0920260205101029,1016600679,1016600679,Mama Etna,Oostende,Alfonspieterslaan  41,8400,BE +BE,AN09_T000_260209_4,AN0920260205101030,1016600679,1016600679,Mama Etna,Oostende,Alfonspieterslaan 41,8400,BE +BE,AN09_T000_260209_5,AN0920260201101027,700748388,700748388,Legally Speaking,Schoten,Botermelkbaan 51,2900,BE +BE,AN09_T000_260209_6,AN0920260111103015,793416943,793416943,AL MAJMAIE LAYTH,Bredene,Duinenstraat 293,8450,BE +BE,AN09_T000_260209_7,AN0920260208101022,769935223,769935223,GJ CONSULTING BV,De Haan,Platanenlaan-oost 35,8420,BE +BE,AN09_T000_260209_8,AN0920260125101011,809707795,809707795,VTELLIGENCE BV,Roeselare,Gruyaertshof  11,8800,BE +BE,AN03_T000_260209_2,AN0320260110101033,476123411,476123411,EVIMAGE SRL,LASNE,chemin de bas-ransbeck 51,1380,BE +BE,AN20_T000_260210_30,AN2020260115103197,,,PARISSE Manon,Perle Rambrouch,Rue de la poste 34c3,L-8824,XX +BE,AN20_T000_260210_31,AN2020260124103074,,,NTEMO PERRAUT Cecile,Esch sur Alzette,Rue Ada Lovelace 45,4211,XX +BE,AN14_T000_260211_1,AN1420260124101276,1017649368,1017649368,Tia Global Refinepro Solutions BV,Antwerpen,Floralienlaan 4,2600,BE diff --git a/data/dontprocessbefore.txt b/data/dontprocessbefore.txt new file mode 100644 index 0000000..087ab06 --- /dev/null +++ b/data/dontprocessbefore.txt @@ -0,0 +1 @@ +20260201 \ No newline at end of file diff --git a/data/offices.csv b/data/offices.csv new file mode 100644 index 0000000..d3a3691 --- /dev/null +++ b/data/offices.csv @@ -0,0 +1,4 @@ +PartyScheme,PartyId,Name,Street1,Street2,City,Zip,Country,TaxId,LegalId,VRBL,MinimumAmount,orgidlength,taxidlength,roundingAllowed +9925,BE0475871409,PVH Brands Belgium,Van Breestraat 2,,Antwerpen,2018,BE,BE0475871409,BE0475871409,GENERIC_PEPPOL_BIS3p0_BE,0,10,10,0 +9934,90656275879,PVH Brands Croatia d.o.o.,Vrankovec 1 49223,Sveti Kriz Zacretje,Krapinsko,,HR,HR90656275879,HR90656275879,GENERIC_AS4_HR,0,11,11,0 +VRBL:PL:TAX,525-231-23-80,PVH Brands Poland Sp. z o.o.,Ul. Emilii Plater 53 ,,Warsaw,00-113,PL,PL5252312380,5252312380,GENERIC_PL_KSeF-FA_3p0,450,10,10,0 diff --git a/data/stores_to_invoice.csv b/data/stores_to_invoice.csv new file mode 100644 index 0000000..c67ceef --- /dev/null +++ b/data/stores_to_invoice.csv @@ -0,0 +1,647 @@ +store,name,country,invoice,found,new +A200,Tommy Hilfiger Graz,AT,,0, +A205,Tommy Hilfiger Vienna,AT,,0, +A201,Tommy Hilfiger Innsbruck,AT,,0, +A204,Tommy Hilfiger Salzburg,AT,,0, +A203,Tommy Hilfiger Klagenfurt,AT,,0, +A206,Tommy Hilfiger Parndorf Outlet,AT,,0, +A207,Tommy Hilfiger Parndorf Outlet Childrenswear,AT,,0, +A142,Calvin Klein Salzburg Outlet,AT,,0, +A141,Calvin Klein Underwear Parndorf Outlet,AT,,0, +A143,Calvin Klein Underwear Innsbruck (DEZ Mall),AT,,0, +A140,Calvin Klein Jeans Parndorf Outlet,AT,,0, +A942,Tommy Hilfiger Vosendorf (SCS),AT,,0, +A179,Calvin Klein Jeans Vienn(Donauzentrum),AT,,0, +A180,Calvin Klein Underwear Vosendorf (SCS Mall),AT,,0, +A949,Tommy Hilfiger Vienna (Donauzentrum),AT,,0, +A966,Tommy Hilfiger Parndorf Outlet Temp II,AT,,0, +F00E,Tommy Hilfiger Vienna (Dorotheergasse),AT,,0, +F00M,Tommy Hilfiger Footwear Parndorf Designer Outlet TEMP,AT,,0, +AN16,Tommy Hilfiger Roeselare,BE,1,0, +AN07,Tommy Hilfiger Leuven Jeans,BE,1,0, +AN02,Tommy Hilfiger Brugge,BE,1,0, +AN05,Tommy Hilfiger Knokke,BE,1,0, +AN11,Tommy Hilfiger Antwerp (Schuttershof),BE,1,0, +AN08,Tommy Hilfiger Wijnegem Jeans,BE,1,0, +AN06,Tommy Hilfiger Knokke,BE,1,0, +AN12,Tommy Hilfiger Namur Jeans,BE,1,0, +AN14,Tommy Hilfiger Wijnegem,BE,1,0, +AN09,Tommy Hilfiger Oostende,BE,1,0, +AN03,Tommy Hilfiger Brussels,BE,1,0, +AN20,Tommy Hilfiger Outlet Messancy,BE,1,0, +AN19,Tommy Hilfiger Maasmechelen Outlet,BE,1,0, +A011,Calvin Klein Jeans Messancy Outlet,BE,1,0, +A009,Calvin Klein Jeans Maasmechelen Outlet,BE,1,0, +A008,Calvin Klein Outlet Maasmechelen,BE,1,0, +AN17,Tommy Hilfiger Liege Jeans,BE,1,0, +A066,Calvin Klein Underwear Wijnegem,BE,1,0, +A067,Calvin Klein Underwear Antwerp (Lombardenvest),BE,1,0, +AN22,Tommy Hilfiger Maasmechelen Outlet Childrenswear,BE,1,0, +A069,Calvin Klein Underwear Gent (Kouterdreef),BE,1,0, +A071,Calvin Klein Underwear Charleroi (Rive Gauche shopping mall),BE,1,0, +AN23,Tommy Hilfiger Gent (Kouterdreef),BE,1,0, +AN24,Tommy Hilfiger Antwerp Jeans,BE,1,0, +AN25,Tommy Hilfiger Gent Jeans,BE,1,0, +A1E0,Calvin Klein Messancy Outlet,BE,1,0, +AN26,Tommy Hilfiger Brugge Jeans,BE,1,0, +AN27,Tommy Hilfiger Knokke,BE,1,0, +F00O,Calvin Klein Maasmechelen Village Outlet Kids TEMP,BE,1,0, +F00U,Calvin Klein Maasmechelen Village Outlet,BE,1,0, +F02G,Tommy Hilfiger Underwear Kids Galleria Inno Oostende,BE,1,0, +F02L,Tommy Hilfiger Underwear Kids Galleria Inno Sint Niklaas (Waasland),BE,1,0, +F02M,Tommy Hilfiger Underwear Kids Galleria Inno Brussels (Rue Neuve),BE,1,0, +F02O,Tommy Hilfiger Underwear Kids Galleria Inno Charleroi,BE,1,0, +F02F,Tommy Hilfiger Underwear Kids Galleria Inno Schoten,BE,1,0, +F02H,Tommy Hilfiger Underwear Kids Galleria Inno Mechelen,BE,1,0, +F02K,Tommy Hilfiger Underwear Kids Galleria Inno Antwerp,BE,1,0, +F02I,Tommy Hilfiger Underwear Kids Galleria Inno Leuven,BE,1,0, +F02J,Tommy Hilfiger Underwear Kids Galleria Inno Gent,BE,1,0, +F02N,Tommy Hilfiger Underwear Kids Galleria Inno Brussels (Louise),BE,1,0, +F02P,Tommy Hilfiger Underwear Kids Galleria Inno Brugge,BE,1,0, +F05E,Tommy Hilfiger Underwear Kids Galleria Inno Luik,BE,1,0, +A211,Tommy Hilfiger Zurich,CH,,0, +A208,Tommy Hilfiger Geneva,CH,,0, +A209,Tommy Hilfiger Luzern,CH,,0, +A210,Tommy Hilfiger St. Moritz,CH,,0, +AA03,Tommy Hilfiger Outlet Mendrisio,CH,,0, +A212,Tommy Hilfiger Alpenrhein Outlet,CH,,0, +A139,Calvin Klein Alpenrhein Outlet,CH,,0, +A153,Calvin Klein Aubonne Outlet,CH,,0, +A170,Calvin Klein Mendrisio Outlet,CH,,0, +A960,Tommy Hilfiger Aubonne Outlet,CH,,0, +A965,Tommy Hilfiger Landquart Outlet Temp,CH,,0, +A970,Tommy Hilfiger Mendrisio Outlet Temp,CH,,0, +A215,Tommy Hilfiger Prague (Na Prikope),CZ,,0, +A218,Tommy Hilfiger Prague (Fashion Arena) Outlet,CZ,,0, +A217,Tommy Hilfiger Znojmo (Freeport Mall) Outlet,CZ,,0, +A216,Tommy Hilfiger Znojmo (Freeport Mall) Outlet Clearance,CZ,,0, +A977,Tommy Hilfiger Ostrava Outlet (Arena Moravia),CZ,,0, +A229,Tommy Hilfiger Hannover Jeans,DE,,0, +A226,Tommy Hilfiger Bremen (Waterfront),DE,,0, +A244,Tommy Hilfiger Cologne (Weiden),DE,,0, +A232,Tommy Hilfiger Dortmund,DE,,0, +A225,Tommy Hilfiger Braunschweig,DE,,0, +A242,Tommy Hilfiger Kempten,DE,,0, +A252,Tommy Hilfiger Oberhausen,DE,,0, +A220,Tommy Hilfiger Berlin (KuDamm),DE,,0, +A227,Tommy Hilfiger Braunschweig Jeans,DE,,0, +A239,Tommy Hilfiger Hamburg (EEZ),DE,,0, +A228,Tommy Hilfiger Hamburg Jeans,DE,,0, +A222,Tommy Hilfiger Berlin (Potsdamer Platz),DE,,0, +A233,Tommy Hilfiger Duesseldorf,DE,,0, +A256,Tommy Hilfiger Siegen,DE,,0, +A240,Tommy Hilfiger Hamburg (Alte Post),DE,,0, +A247,Tommy Hilfiger Mainz,DE,,0, +A250,Tommy Hilfiger Muenster,DE,,0, +A234,Tommy Hilfiger Essen,DE,,0, +A238,Tommy Hilfiger Hamburg (AEZ),DE,,0, +A237,Tommy Hilfiger Guenthersdorf,DE,,0, +A230,Tommy Hilfiger Muenster Jeans,DE,,0, +A236,Tommy Hilfiger Freiburg,DE,,0, +A221,Tommy Hilfiger Berlin (Muenzstrasse),DE,,0, +A224,Tommy Hilfiger Bochum,DE,,0, +A254,Tommy Hilfiger Regensburg,DE,,0, +A257,Tommy Hilfiger Sindelfingen,DE,,0, +A258,Tommy Hilfiger Sulzbach MTZ,DE,,0, +A251,Tommy Hilfiger Nuremberg,DE,,0, +A223,Tommy Hilfiger Berlin (Steglitz),DE,,0, +A219,Tommy Hilfiger Bayreuth,DE,,0, +A243,Tommy Hilfiger Cologne (Schildergasse),DE,,0, +A246,Tommy Hilfiger Magdeburg,DE,,0, +A235,Tommy Hilfiger Frankfurt,DE,,0, +A259,Tommy Hilfiger Timmendorf,DE,,0, +A245,Tommy Hilfiger Ludwigsburg,DE,,0, +A231,Tommy Hilfiger Oberhausen Jeans,DE,,0, +A255,Tommy Hilfiger Saarbrucken (Europa Mall),DE,,0, +A248,Tommy Hilfiger Munich,DE,,0, +A249,Tommy Hilfiger Munich (Riem Arcaden),DE,,0, +A270,Tommy Hilfiger Radolfzell Outlet,DE,,0, +A274,Tommy Hilfiger Outlet Zweibruecken,DE,,0, +A263,Tommy Hilfiger Outlet Ingolstadt,DE,,0, +A261,Tommy Hilfiger Outlet Berlin B5,DE,,0, +A268,Tommy Hilfiger Muelheim-Kaerlich Outlet,DE,,0, +A262,Tommy Hilfiger Outlet Bremen,DE,,0, +A271,Tommy Hilfiger Wertheim Outlet,DE,,0, +A264,Tommy Hilfiger Ingolstadt Outlet Childrenswear,DE,,0, +A265,Tommy Hilfiger Metzingen Outlet,DE,,0, +A272,Tommy Hilfiger Wertheim Outlet Childrenswear,DE,,0, +AA30,Calvin Klein Underwear Munich,DE,,0, +A137,Calvin Klein Neumuenster Outlet,DE,,0, +A131,Calvin Klein Underwear Berlin B5 Outlet,DE,,0, +A130,Calvin Klein Jeans Wertheim Outlet,DE,,0, +A128,Calvin Klein Underwear Zweibruecken Outlet,DE,,0, +A127,Calvin Klein Underwear Ingolstadt Outlet,DE,,0, +A132,Calvin Klein Jeans Berlin B5 Outlet,DE,,0, +A126,Calvin Klein Underwear Wertheim Outlet,DE,,0, +A129,Calvin Klein Jeans Ingolstadt Outlet,DE,,0, +A133,Calvin Klein Jeans Zweibrucken Outlet,DE,,0, +A135,Calvin Klein Metzingen Outlet,DE,,0, +A136,Calvin Klein Wolfsburg Outlet,DE,,0, +A267,Tommy Hilfiger Montabaur (Fashion) Outlet,DE,,0, +A926,Tommy Hilfiger Stuttgart (Milaneo Mall) Jeans,DE,,0, +A253,Tommy Hilfiger Osnabrueck,DE,,0, +A117,Calvin Klein Underwear Hamburg (Europa Passage Mall),DE,,0, +A118,Calvin Klein Underwear Sulzbach (Main-Taunus-Zentrum Mall),DE,,0, +A122,Calvin Klein Underwear Duesseldorf,DE,,0, +A119,Calvin Klein Underwear Cologne (Weiden),DE,,0, +A120,Calvin Klein Underwear Kassel (City-Point Mall),DE,,0, +A148,Calvin Klein Underwear Hannover (Ernst-August-Galerie Mall),DE,,0, +A124,Calvin Klein Underwear Hamburg (Alstertal-Einkaufszentrum Mall),DE,,0, +A165,Calvin Klein Jeans Berlin (Berlin Mall),DE,,0, +A154,Calvin Klein Underwear Ludwigsburg (Breuningerland Mall),DE,,0, +A155,Calvin Klein Underwear Mannheim (Q6Q7),DE,,0, +A158,Calvin Klein Jeans Oberhausen,DE,,0, +A161,Calvin Klein Underwear Stuttgart (Milaneo Mall),DE,,0, +A160,Calvin Klein Underwear Braunschweig (Schloss Arkaden Mall),DE,,0, +A159,Calvin Klein Underwear Berlin (Das Schloss Mall),DE,,0, +A167,Calvin Klein Duesseldorf,DE,,0, +A174,Calvin Klein Jeans Essen (Limbecker Platz Mall),DE,,0, +A178,Calvin Klein Stuhr-Brinkum (Ochtum Park) Outlet,DE,,0, +A157,Calvin Klein Jeans Hannover (Ernst-August-Galerie Mall),DE,,0, +A923,Tommy Hilfiger Wurzburg,DE,,0, +A163,Calvin Klein Jeans Munster,DE,,0, +A164,Calvin Klein Jeans Hamburg (Europa Passage Mall),DE,,0, +A166,Calvin Klein Underwear Magdeburg (Allee-Center),DE,,0, +A150,Calvin Klein Underwear Oberhausen (Centro Mall),DE,,0, +A175,Calvin Klein Underwear Rostock (Galeria Rostocker Hof),DE,,0, +A176,Calvin Klein Wertheim Outlet Temp,DE,,0, +A939,Tommy Hilfiger Hannover (Karmarschstr.),DE,,0, +A941,Tommy Hilfiger Dortmund Underwear,DE,,0, +A181,Calvin Klein Cologne,DE,,0, +A273,Tommy Hilfiger Wolfsburg Outlet,DE,,0, +A951,Tommy Hilfiger Wolfsburg Outlet Temp,DE,,0, +A952,Tommy Hilfiger Neumuenster Outlet Temp,DE,,0, +A185,Calvin Klein Ochtrup (McArthurGlen Designer Outlet) Outlet,DE,,0, +A186,Calvin Klein Wustermark Outlet (Berlin B5),DE,,0, +A188,Calvin Klein Zweibruecken Outlet (Londoner Bogen),DE,,0, +A0K0,Izod Montabaur Outlet,DE,,0, +A956,Tommy Hilfiger Wustermark Outlet Temp,DE,,0, +A957,Tommy Hilfiger Ingolstadt Outlet Temp IV,DE,,0, +A198,Calvin Klein Underwear Berlin (Alexa Center),DE,,0, +A197,Calvin Klein Jeans Berlin (Alexa Center),DE,,0, +A196,Calvin Klein Jeans Dresden (Altmarkt-Galerie),DE,,0, +A269,Tommy Hilfiger Neumunster Outlet,DE,,0, +AJ00,Calvin Klein Montabaur Outlet Temp,DE,,0, +AJ02,Calvin Klein Radolfzell Outlet Temp,DE,,0, +A971,Tommy Hilfiger Zweibruecken Outlet Temp,DE,,0, +A950,Tommy Hilfiger Ochtrup Outlet,DE,,0, +AJ06,Calvin Klein Radolfzell Outlet,DE,,0, +AJ05,Calvin Klein Montabaur Outlet,DE,,0, +F001,Tommy Jeans Munich,DE,,0, +F002,Calvin Klein Jeans Munich Pasing Arcaden,DE,,0, +F005,Tommy Hilfiger Bonn,DE,,0, +F00L,Tommy Hilfiger Kids Neumunster Designer Outlet,DE,,0, +F00K,Tommy Hilfiger Kids Wustermark Designer Outlet Berlin,DE,,0, +F060,Tommy Hilfiger Soltau Designer Outlet,DE,,0, +F06Q,Calvin Klein Lifestyle Hamburg (Überseequartier Süd),DE,,0, +F06R,Tommy Hilfiger Hamburg (Überseequartier Süd),DE,,0, +F07K,Calvin Klein Lifestyle Duesseldorf (Kö-Bogen Königsallee),DE,,0, +F0D6,Calvin Klein Cologne Ehrenstraße,DE,,0, +F0EY,Tommy Hilfiger Sankt Augustin HUMA Shopping & Outlet,DE,,0, +F0F7,Calvin Klein Sankt Augustin HUMA Shopping & Outlet,DE,,0, +AS02,Tommy Hilfiger Odense (Rosengaardcentret Mall),DK,,0, +AA02,Tommy Hilfiger Copenhagen,DK,,0, +AS01,Tommy Hilfiger Aarhus Jeans,DK,,0, +A049,Calvin Klein Ringsted Outlet,DK,,0, +A056,Calvin Klein Underwear Copenhagen (Fisketorvet Shopping Center),DK,,0, +A055,Calvin Klein Underwear Copenhagen (Fields),DK,,0, +AS83,Tommy Hilfiger Ringsted Outlet,DK,,0, +A026,Calvin Klein Jeans Madrid (Fuencarral St.),ES,,0, +A039,Calvin Klein Palma de Mallorca (Festival Park) Outlet,ES,,0, +A036,Calvin Klein Underwear Sevilla Outlet,ES,,0, +A032,Calvin Klein Jeans Barcelona (La Roca Outlet Mall) Outlet,ES,,0, +A031,Calvin Klein Jeans Madrid (Las Rozas Village) Outlet,ES,,0, +A029,Calvin Klein Underwear Barcelona (La Roca Outlet Mall) Outlet,ES,,0, +A033,Calvin Klein Underwear Bilbao Outlet,ES,,0, +A034,Calvin Klein Underwear Gran Canaria Outlet,ES,,0, +A044,Calvin Klein Underwear Madrid (Las Rozas Village) Outlet,ES,,0, +A074,Calvin Klein Underwear Marbella (Canada Mall),ES,,0, +A075,Calvin Klein Malaga Outlet,ES,,0, +B745,Calvin Klein Jeans Women El Corte Ingles Burgos,ES,,0, +B746,Calvin Klein Jeans Women El Corte Ingles Princesa Madrid,ES,,0, +B747,Calvin Klein Accessories El Corte Ingles Valderas Alcorcón,ES,,0, +AA15,Calvin Klein Jeans Helsinki (Kamppi Mall),FI,,0, +A046,Calvin Klein Underwear Helsinki (Kamppi Mall),FI,,0, +AS53,Tommy Hilfiger Helsinki (Kamppi Shopping Center Mall),FI,,0, +AS75,Tommy Hilfiger Helsinki (Vantaa) Outlet,FI,,0, +A077,Calvin Klein Helsinki (Vantaa) Outlet,FI,,0, +AS81,Tommy Hilfiger Helsinki Outlet Pop-Up,FI,,0, +AP03,Tommy Hilfiger Paris (Beaugrenelle Mall),FR,,0, +AP07,Tommy Hilfiger Lille Jeans,FR,,0, +AP05,Tommy Hilfiger Montpellier (Odysseum),FR,,0, +AP00,Tommy Hilfiger Paris (Parly 2),FR,,0, +AP01,Tommy Hilfiger Cannes,FR,,0, +AP02,Tommy Hilfiger Tours,FR,,0, +AP04,Tommy Hilfiger Saint-Laurent du Var (CAP 3000),FR,,0, +AP06,Tommy Hilfiger Paris (Capucines),FR,,0, +AP14,Tommy Hilfiger Talange Outlet,FR,,0, +AP13,Tommy Hilfiger Troyes Outlet,FR,,0, +AP12,Tommy Hilfiger Outlet Coquelles,FR,,0, +AP15,Tommy Hilfiger Serris (La Vallee) Outlet,FR,,0, +A012,Calvin Klein Underwear Paris (Les Halles Mall),FR,,0, +A023,Calvin Klein Troyes Outlet,FR,,0, +A018,Calvin Klein Underwear Roubaix Outlet,FR,,0, +A022,Calvin Klein Roppenheim Outlet,FR,,0, +AP16,Tommy Hilfiger Roppenheim (The Style Outlets) Outlet,FR,,0, +AP17,Tommy Hilfiger Miramas Provence Outlet,FR,,0, +AP08,Tommy Hilfiger Saint-Tropez,FR,,0, +A024,Calvin Klein Coquelles (Channel Outlet Store) Outlet,FR,,0, +A025,Calvin Klein Miramas (Provence) Outlet,FR,,0, +A016,Calvin Klein Underwear Cagnes-sur-Mer,FR,,0, +A010,Calvin Klein Underwear Rennes,FR,,0, +AP09,Tommy Hilfiger La Baule,FR,,0, +AP18,Tommy Hilfiger Paris,FR,,0, +AP10,Tommy Hilfiger Lille (Rue de la Grande Chaussee),FR,,0, +AP19,Tommy Hilfiger Boulogne-Billancourt (Les Passages Mall),FR,,0, +A017,Calvin Klein Jeans Lyon (Rue Ferrandiere),FR,,0, +A014,Calvin Klein Jeans Paris (Les Halles Mall),FR,,0, +A076,Calvin Klein Jeans Montpellier (Odysseum Mall),FR,,0, +A078,Calvin Klein Paris (Bourgeois),FR,,0, +AP23,Tommy Hilfiger Roubaix (McArthurGlen Mall) Outlet,FR,,0, +AP24,Tommy Hilfiger Cannes (No.100),FR,,0, +A082,Calvin Klein Serris (La Vallee) Outlet,FR,,0, +A0J0,Izod Roppenheim Outlet,FR,,0, +AP25,Tommy Hilfiger Bordeaux,FR,,0, +F00C,Calvin Klein Giverny Paris Giverny Designer Outlet,FR,,0, +F00D,Tommy Hilfiger Giverny Paris Giverny Designer Outlet,FR,,0, +F05V,Tommy Hilfiger The Village Villefontaine Outlet,FR,,0, +F07M,Calvin Klein Paris (Avenue des Champs Elysées),FR,,0, +F08Q,Calvin Klein The Village Villefontaine Outlet,FR,,0, +F0DM,Tommy Hilfiger Angers (Rue Voltaire),FR,,0, +F0EV,Tommy Hilfiger Orléans Rue Ducerceau,FR,,0, +F0EX,Tommy Hilfiger Vannes Rue Billault,FR,,0, +F0EW,Tommy Hilfiger Brest Rue de Siam,FR,,0, +AQ01,Tommy Hilfiger Birmingham (Bullring Mall),GB,,0, +AQ00,Tommy Hilfiger London (Regent St.),GB,,0, +AQ02,Tommy Hilfiger Kingston,GB,,0, +AQ03,Tommy Hilfiger Bath,GB,,0, +AQ05,Tommy Hilfiger London (Westfield Stratford Mall),GB,,0, +AQ07,Tommy Hilfiger Greenhithe (Bluewater Mall),GB,,0, +AQ08,Tommy Hilfiger Edinburgh,GB,,0, +AQ04,Tommy Hilfiger London (Brompton Rd),GB,,0, +AQ11,Tommy Hilfiger London (Westfield White City Mall),GB,,0, +AQ10,Tommy Hilfiger Birmingham (The Mailbox Mall),GB,,0, +AQ23,Tommy Hilfiger Outlet Cheshire Oaks,GB,,0, +AA08,Tommy Hilfiger Outlet Bicester,GB,,0, +AQ25,Tommy Hilfiger Outlet Ashford,GB,,0, +AQ28,Tommy Hilfiger Outlet Bridgend,GB,,0, +AQ29,Tommy Hilfiger Portsmouth Outlet,GB,,0, +AQ30,Tommy Hilfiger Livingston Outlet,GB,,0, +AQ31,Tommy Hilfiger York Outlet,GB,,0, +AQ32,Tommy Hilfiger South Normanton (Mansfield) Outlet,GB,,0, +AQ26,Tommy Hilfiger Braintree Outlet,GB,,0, +AQ27,Tommy Hilfiger Swindon Outlet,GB,,0, +A301,Calvin Klein Underwear London (Covent Garden),GB,,0, +A305,Calvin Klein Underwear London (One New Change),GB,,0, +AA14,Calvin Klein London (Regent Street),GB,,0, +A306,Calvin Klein Underwear London (Westfield Stratford),GB,,0, +A304,Calvin Klein Underwear London (Westfield White City),GB,,0, +A309,Calvin Klein Underwear Birmingham (The Mailbox Mall),GB,,0, +A300,Calvin Klein Underwear London (Kings Rd.),GB,,0, +A302,Calvin Klein Manchester (Trafford Centre),GB,,0, +A303,Calvin Klein Underwear Belfast (Victoria Square Mall),GB,,0, +A314,Calvin Klein Jeans Cheshire (Cheshire Oaks) Outlet,GB,,0, +AA12,Calvin Klein Underwear Bicester Outlet,GB,,0, +A315,Calvin Klein Underwear Cheshire (Cheshire Oaks) Outlet,GB,,0, +A311,Calvin Klein Underwear Portsmouth Outlet,GB,,0, +A312,Calvin Klein Underwear Banbridge Outlet,GB,,0, +A318,Calvin Klein Underwear Hatfield (The Galleria) Outlet,GB,,0, +A321,Calvin Klein York Outlet,GB,,0, +A319,Calvin Klein Gloucester (Gloucester Quays) Outlet,GB,,0, +A313,Calvin Klein Swindon Outlet,GB,,0, +A320,Calvin Klein Ashford Outlet,GB,,0, +A316,Calvin Klein Bridgend Outlet,GB,,0, +A317,Calvin Klein South Normanton (Mansfield) Outlet,GB,,0, +AQ09,Tommy Hilfiger Leeds (Victoria Gate Mall),GB,,0, +A307,Calvin Klein Underwear Leeds (Victoria Gate Mall),GB,,0, +A308,Calvin Klein Underwear London (Canary Wharf Mall),GB,,0, +A340,Calvin Klein Underwear Greenhithe (Bluewater),GB,,0, +A339,Calvin Klein Underwear Grays (Lakeside),GB,,0, +A349,Calvin Klein Underwear Oxford (Westgate Shopping Centre),GB,,0, +AQ12,Tommy Hilfiger Oxford (Westgate Shopping Mall),GB,,0, +A348,Calvin Klein Underwear London (St. Pancras),GB,,0, +A346,Calvin Klein Underwear Cardiff (St. David's),GB,,0, +A350,Calvin Klein Underwear Cambridge (Grand Arcade Mall),GB,,0, +A351,Calvin Klein London Outlet (O2 Arena Mall),GB,,0, +A355,Calvin Klein Birmingham (Bullring Mall),GB,,0, +A352,Calvin Klein Livingston Outlet,GB,,0, +A353,Calvin Klein Jeans Bicester Outlet,GB,,0, +A354,Calvin Klein Cheshire Outlet (Cheshire Oaks),GB,,0, +AQ37,Tommy Hilfiger Southampton (WestQuay),GB,,0, +AQ38,Tommy Hilfiger London (The O2 Arena) Outlet,GB,,0, +AQ41,Tommy Hilfiger Hull Outlet Temp,GB,,0, +A358,Calvin Klein Lifestyle London (White City) Temp,GB,,0, +A362,Calvin Klein Portsmouth Outlet,GB,,0, +A363,Calvin Klein Richmond Scotch Corner Outlet,GB,,0, +A364,Calvin Klein Cannock Outlet,GB,,0, +A361,Calvin Klein Jeans Portsmouth Outlet Temp,GB,,0, +AQ43,Tommy Hilfiger Cannock Outlet,GB,,0, +AQ44,Tommy Hilfiger London (Liverpool Street),GB,,0, +AQ45,Tommy Hilfiger London Kids Outlet Temp,GB,,0, +AQ46,Tommy Hilfiger Edinburgh (St James Centre),GB,,0, +A386,Calvin Klein Jeans Edinburgh (St James Centre),GB,,0, +AQ47,Tommy Hilfiger Bicester Outlet Temp,GB,,0, +AQ48,Tommy Hilfiger Wembley Outlet Temp,GB,,0, +A387,Calvin Klein Outlet Wembley Temp,GB,,0, +AQ49,Tommy Hilfiger London (The O2 Arena) Outlet Kids Temp,GB,,0, +A388,Calvin Klein Outlet Braintree Temp,GB,,0, +A389,Calvin Klein Jeans Outlet Street Temp,GB,,0, +AQ50,Tommy Hilfiger Street Outlet Temp,GB,,0, +AQ51,Tommy Hilfiger Gloucester Outlet Temp,GB,,0, +A390,Calvin Klein Outlet Colne (Boundary Outlet),GB,,0, +AQ53,Tommy Hilfiger Sheffield (Meadowhall),GB,,0, +AQ54,Tommy Hilfiger Manchester (Trafford),GB,,0, +AQ55,Tommy Hilfiger Bicester Kids/Womenswear Outlet,GB,,0, +AQ56,Tommy Hilfiger London (Battersea),GB,,0, +A391,Calvin Klein Lifestyle London (Battersea),GB,,0, +AQ57,Tommy Hilfiger Manchester (Arndale) Temp,GB,,0, +AQ58,Tommy Hilfiger Thurrock Lakeside Temp,GB,,0, +AQ59,Tommy Hilfiger Glasgow Silverburn Temp,GB,,0, +AQ60,Tommy Hilfiger London Wembley Outlet,GB,,0, +A393,Calvin Klein London Wembley Outlet,GB,,0, +AQ61,Tommy Hilfiger Aberdeen Temp,GB,,0, +AQ62,Tommy Hilfiger Derby,GB,,0, +AQ63,Tommy Hilfiger Plymouth,GB,,0, +AQ64,Tommy Hilfiger Bristol Temp,GB,,0, +AQ65,Tommy Hilfiger Milton Keynes Temp,GB,,0, +A394,Calvin Klein Underwear Vending London Heathrow,GB,,0, +F007,Calvin Klein Jeans (Braintree Village) Outlet,GB,,0, +F00A,Calvin Klein Jeans Clarks Village Street Outlet,GB,,0, +F00B,Calvin Klein Greenhithe Bluewater,GB,,0, +F00G,Calvin Klein London Westfield Stratford City,GB,,0, +F00H,Calvin Klein London Westfield White City,GB,,0, +F05Y,Calvin Klein Lifestyle Grays (Lakeside),GB,,0, +F064,Calvin Klein Gretna (Caledonia Park Outlet),GB,,0, +F06S,Tommy Hilfiger Gretna Caledonia Park Outlet,GB,,0, +F076,Tommy Jeans Fenwick Colchester,GB,,0, +F07F,Calvin Klein Seaham Dalton Park Outlet TEMP,GB,,0, +F07G,Tommy Hilfiger Seaham Dalton Park Outlet TEMP,GB,,0, +F0D3,Calvin Klein Bicester Bicester Village Outlet,GB,,0, +F0D5,Tommy Hilfiger Street Clarks Village Outlet,GB,,0, +F0EB,Tommy Hilfiger tewksbury cotswolds designer outlet,GB,,0, +F0ED,Calvin Klein tewksbury Cotswolds Designer Outlet,GB,,0, +A275,Tommy Hilfiger Sv. Kriz Zacretje (Roses) Outlet,HR,1,0, +A100,Calvin Klein Sv. Kriz Zacretje (Roses) Outlet,HR,1,0, +A944,Tommy Hilfiger Zagreb (Designer Outlet) Outlet,HR,1,0, +A182,Calvin Klein Zagreb Outlet,HR,1,0, +AQ16,Tommy Hilfiger Limerick,IE,,0, +AQ19,Tommy Hilfiger Cork (Mahon Mall),IE,,0, +AQ15,Tommy Hilfiger Dublin (Liffey Valley),IE,,0, +AQ18,Tommy Hilfiger Swords (Pavilions Mall),IE,,0, +AQ14,Tommy Hilfiger Cork (Opera),IE,,0, +AQ20,Tommy Hilfiger Galway,IE,,0, +AQ21,Tommy Hilfiger Waterford,IE,,0, +AQ17,Tommy Hilfiger Athlone,IE,,0, +AQ22,Tommy Hilfiger Dublin (Dundrum Mall),IE,,0, +AQ33,Tommy Hilfiger Outlet Kildare,IE,,0, +AA29,Calvin Klein Lifestyle Dublin (Dundrum Mall),IE,,0, +A322,Calvin Klein Underwear Kildare Outlet,IE,,0, +A323,Calvin Klein Jeans Kildare Outlet,IE,,0, +A392,Calvin Klein Kildare Outlet,IE,,0, +AQ66,Tommy Hilfiger Kildare Outlet Kids,IE,,0, +F05X,Calvin Klein Jeans Dublin Clondalkin Liffey Valley,IE,,0, +F06T,Tommy Hilfiger Blanchardstown,IE,,0, +F06U,Calvin Klein Jeans Blanchardstown,IE,,0, +F0DU,Calvin Klein Kildare Outlet TEMP,IE,,0, +AU43,Tommy Hilfiger Milan,IT,,0, +AU44,Tommy Hilfiger Florence,IT,,0, +AU45,Tommy Hilfiger Rome (Porta Di Roma),IT,,0, +AU46,Tommy Hilfiger Padua,IT,,0, +AU47,Tommy Hilfiger Lonato del Garda,IT,,0, +AU48,Tommy Hilfiger Turin Jeans,IT,,0, +AU49,Tommy Hilfiger Alba,IT,,0, +AU50,Tommy Hilfiger Aosta,IT,,0, +AU51,Tommy Hilfiger Turin (Le Gru),IT,,0, +AU52,Tommy Hilfiger Carugate,IT,,0, +AU53,Tommy Hilfiger Orio al Serio (Bergamo) Jeans,IT,,0, +AU54,Tommy Hilfiger Rome (Euroma 2 Mall),IT,,0, +AU57,Tommy Hilfiger Chieti,IT,,0, +AU70,Tommy Hilfiger Vicolungo (The Style) Outlet,IT,,0, +AU58,Tommy Hilfiger Outlet Noventa di Piave,IT,,0, +AU59,Tommy Hilfiger Marcianise (La Reggia) Outlet,IT,,0, +AU60,Tommy Hilfiger Barberino di Mugello Outlet,IT,,0, +AU61,Tommy Hilfiger Foiano Outlet,IT,,0, +AU62,Tommy Hilfiger Rodengo Saiano (Franciacorta) Outlet,IT,,0, +AU63,Tommy Hilfiger Fidenza Outlet,IT,,0, +AU64,Tommy Hilfiger Serravalle Outlet,IT,,0, +AU65,Tommy Hilfiger Castel Romano Outlet,IT,,0, +AU71,Tommy Hilfiger Castel Romano Outlet Childrenswear,IT,,0, +AU66,Tommy Hilfiger Palmanova Outlet,IT,,0, +A400,Calvin Klein Jeans Venice,IT,,0, +A402,Calvin Klein Jeans Rome (Galleria),IT,,0, +A403,Calvin Klein Jeans Orio al Serio (Bergamo),IT,,0, +A406,Calvin Klein Jeans Rimini,IT,,0, +A407,Calvin Klein Jeans Milan (Vulcano),IT,,0, +A408,Calvin Klein Jeans Salerno,IT,,0, +A409,Calvin Klein Jeans Rome (Est Mall),IT,,0, +A410,Calvin Klein Jeans Rome (Porta Di Roma),IT,,0, +A411,Calvin Klein Jeans Milan (Carugate),IT,,0, +A412,Calvin Klein Jeans Florence,IT,,0, +A413,Calvin Klein Jeans Milan (Buenos Aires),IT,,0, +A414,Calvin Klein Jeans Rome (Euroma 2 Mall),IT,,0, +A417,Calvin Klein Jeans Catanzaro,IT,,0, +A419,Calvin Klein Turin (Roma St. 12),IT,,0, +A401,Calvin Klein Lifestyle Rome (Cola Di Rienzo),IT,,0, +A405,Calvin Klein Jeans Chieti,IT,,0, +A420,Calvin Klein Jeans Milan (Milano Centrale Mall),IT,,0, +A422,Calvin Klein Jeans Serravalle Outlet,IT,,0, +A423,Calvin Klein Jeans Rome (Castel Romano) Outlet,IT,,0, +A424,Calvin Klein Underwear Fidenza Outlet,IT,,0, +A425,Calvin Klein Underwear Rome (Castel Romano) Outlet,IT,,0, +A426,Calvin Klein Jeans Molfetta Outlet,IT,,0, +A428,Calvin Klein Underwear Serravalle Outlet,IT,,0, +A429,Calvin Klein Barberino di Mugello Outlet,IT,,0, +A431,Calvin Klein Jeans Fidenza Outlet,IT,,0, +A433,Calvin Klein Castel Guelfo di Bologna Outlet,IT,,0, +A436,Calvin Klein Foiano della Chiana (Valdichiana) Outlet,IT,,0, +A438,Calvin Klein Noventa di Piave Outlet,IT,,0, +A439,Calvin Klein Palmanova Outlet,IT,,0, +A440,Calvin Klein Rodengo Saiano (Franciacorta) Outlet,IT,,0, +A437,Calvin Klein Valmontone Outlet,IT,,0, +A427,Calvin Klein Vicolungo Outlet,IT,,0, +AU30,Tommy Hilfiger Rimini (Le Befane),IT,,0, +AU29,Tommy Hilfiger Limbiate (Carrefour Mall),IT,,0, +AU31,Tommy Hilfiger Milan (Galleria Borromea),IT,,0, +AU33,Tommy Hilfiger Novate Milanese (Metropoli Mall) Jeans,IT,,0, +AU32,Tommy Hilfiger Rome (Via Cola),IT,,0, +A441,Calvin Klein Agira (Sicilia) Outlet -CLOSED-,IT,,0, +AU36,Tommy Hilfiger Marcianise (Campania Mall),IT,,0, +AU55,Tommy Hilfiger Arese (Arese Mall) Jeans,IT,,0, +A421,Calvin Klein Jeans Arese (Il Centro),IT,,0, +AU34,Tommy Hilfiger Marghera (Nave de Vero Mall),IT,,0, +A446,Calvin Klein Marcianise (La Reggia) Outlet,IT,,0, +A447,Calvin Klein Underwear Rome (Termini),IT,,0, +A448,Calvin Klein Underwear Rome (Via del Corso),IT,,0, +AU35,Tommy Hilfiger Roncadelle (Ikea Mall),IT,,0, +A453,Calvin Klein Jeans Roncadelle (Ikea),IT,,0, +A450,Calvin Klein Brenner Outlet,IT,,0, +A449,Calvin Klein Settimo Torinese Outlet,IT,,0, +AU67,Tommy Hilfiger Brenner Outlet,IT,,0, +AU68,Tommy Hilfiger Settimo Torinese Outlet,IT,,0, +AU69,Tommy Hilfiger Locate di Triulzi Outlet,IT,,0, +A451,Calvin Klein Locate di Triulzi (Scalo Milano City Style) Outlet,IT,,0, +AU56,Tommy Hilfiger Verona (Adigeo Mall),IT,,0, +A452,Calvin Klein Jeans Verona (Adigeo Mall),IT,,0, +AU72,Tommy Hilfiger Campi Bisenzio (I Gigli Mall),IT,,0, +A454,Calvin Klein Underwear Florence (Via Calimala),IT,,0, +AU73,Tommy Hilfiger Milan (CityLife),IT,,0, +A457,Calvin Klein Underwear Naples (Via Toledo),IT,,0, +A455,Calvin Klein Underwear Marcianise (Campania Mall),IT,,0, +A456,Calvin Klein Jeans Milan (Citylife),IT,,0, +A458,Calvin Klein Underwear Pavia,IT,,0, +A481,Calvin Klein Underwear Bari (Sparano),IT,,0, +A482,Calvin Klein Underwear Como,IT,,0, +A498,Calvin Klein Underwear Bolzano,IT,,0, +AU97,Tommy Hilfiger Milan (Orefici),IT,,0, +AF01,Calvin Klein Underwear Turin (Le Gru Mall),IT,,0, +AU98,Tommy Hilfiger Modena (Grandemilia Mall),IT,,0, +AZ10,Tommy Hilfiger Catanzaro (CC Le Fontane),IT,,0, +AU99,Tommy Hilfiger Busnago (Il Globo Mall),IT,,0, +AZ11,Tommy Hilfiger Valmontone Outlet,IT,,0, +AI50,Izod Valmontone Outlet,IT,,0, +AI51,Izod Vicolungo Outlet,IT,,0, +AZ50,Tommy Hilfiger Assago,IT,,0, +AZ97,Tommy Hilfiger Bolzano,IT,,0, +AZ99,Tommy Hilfiger Bologna,IT,,0, +AG00,Calvin Klein Jeans Assago (Milanofiori Mall),IT,,0, +AG01,Calvin Klein Jeans Milano Vulcano,IT,,0, +AY12,Tommy Hilfiger Pontecagnano (CC Maximall),IT,,0, +AG02,Calvin Klein Jeans Marcianise (Campania Mall),IT,,0, +AG03,Calvin Klein Jeans Marghera (Nave de Vero Mall),IT,,0, +AY13,Tommy Hilfiger Cagliari (Le Vele Mall),IT,,0, +F000,Calvin Klein Collestrada CKJ Perugia (Collestrada Mall),IT,,0, +F003,Calvin Klein Jeans Busnago (Il Globo Mall),IT,,0, +F004,Tommy Hilfiger Bologna (Shopville Gran Reno),IT,,0, +F006,Calvin Klein Jeans Bologna (Shopville Gran Reno),IT,,0, +F00F,Tommy Hilfiger Rome ROMAEST,IT,,0, +F00R,Tommy Hilfiger Rome Via del Corso,IT,,0, +F00Q,Calvin Klein Jeans Milan Via Dante,IT,,0, +F00J,Tommy Jeans Pompei (La Cartiera Mall),IT,,0, +F00I,Calvin Klein Jeans Pompei (La Cartiera Mall),IT,,0, +F05U,Calvin Klein Milan Piazza San Babila,IT,,0, +F065,Tommy Hilfiger Milan (Merlata Bloom),IT,,0, +F066,Calvin Klein Jeans Milan (Merlata Bloom),IT,,0, +F063,Tommy Hilfiger Castel Guelfo di Bologna (The Style Outlets),IT,,0, +F07D,Calvin Klein Jeans Rome (Piazza Colonna),IT,,0, +F08Z,Calvin Klein Jeans Bolzano,IT,,0, +F0D0,Tommy Hilfiger Pompei (Maximall),IT,,0, +F0D1,Calvin Klein Jeans Pompei (Maximall),IT,,0, +F0DX,Calvin Klein Turin (Le Gru),IT,,0, +F0EN,Tommy Hilfiger Molfetta Puglia Village Outlet,IT,,0, +AN21,Tommy Hilfiger Luxembourg,LU,,0, +AL18,Tommy Hilfiger Breda,NL,,0, +AL16,Tommy Hilfiger Maastricht Jeans,NL,,0, +AL06,Tommy Hilfiger Den Haag,NL,,0, +AL17,Tommy Hilfiger Rotterdam (Kruiskade),NL,,0, +AL02,Tommy Hilfiger Haarlem Jeans,NL,,0, +AL15,Tommy Hilfiger Eindhoven,NL,,0, +AL08,Tommy Hilfiger Den Bosch Jeans,NL,,0, +AL13,Tommy Hilfiger Hillegersberg,NL,,0, +AL11,Tommy Hilfiger Amersfoort Jeans,NL,,0, +AL07,Tommy Hilfiger Arnhem (Roggestraat) Jeans,NL,,0, +AA01,Tommy Hilfiger Amsterdam (Kalverstraat) Jeans,NL,,0, +AL04,Tommy Hilfiger Rotterdam (Lijnbaan) Jeans,NL,,0, +AL14,Tommy Hilfiger Groningen,NL,,0, +AL09,Tommy Hilfiger Utrecht,NL,,0, +AL05,Tommy Hilfiger Maastricht,NL,,0, +AL10,Tommy Hilfiger Apeldoorn Jeans,NL,,0, +AL12,Tommy Hilfiger Arnhem (Bakkerstraat),NL,,0, +AL00,Tommy Hilfiger Amsterdam (PC 125) Jeans,NL,,0, +AL22,Tommy Hilfiger Lelystad (Batavia Stad) Outlet,NL,,0, +AL21,Tommy Hilfiger Roermond Outlet Childrenswear,NL,,0, +AA07,Tommy Hilfiger Roermond Outlet,NL,,0, +A041,Calvin Klein Amsterdam (PC 105),NL,,0, +A042,Calvin Klein Underwear Roermond Outlet,NL,,0, +AA10,Calvin Klein Jeans Roermond Outlet,NL,,0, +A005,Calvin Klein Lelystad (Batavia Stad) Outlet,NL,,0, +A006,Calvin Klein Roosendaal (Rosada) Outlet,NL,,0, +A068,Calvin Klein Underwear Amsterdam,NL,,0, +A073,Calvin Klein Underwear Rotterdam,NL,,0, +AL03,Tommy Hilfiger Roermond Outlet Temp X,NL,,0, +AW54,Tommy Hilfiger Zandvoort Swimwear Pop Up,NL,,0, +AW56,Tommy Hilfiger Lelystad (Batavia Stad) Childrenswear Outlet,NL,,0, +A079,Calvin Klein Underwear Maastricht,NL,,0, +AX32,Tommy Hilfiger Roosendaal (Rosada Designer Outlet) Outlet,NL,,0, +AW98,Tommy Hilfiger Amsterdam Campus,NL,,0, +A081,Calvin Klein Amsterdam Campus,NL,,0, +AX52,Tommy Hilfiger Roosendaal Kids Outlet,NL,,0, +AX54,Tommy Hilfiger Roermond Outlet Temp Clearance,NL,,0, +AD99,Calvin Klein Jeans Leidschendam,NL,,0, +AP28,Tommy Hilfiger Leidschendam Mall of the Netherlands,NL,,0, +F0DP,Calvin Klein Halfweg Sugar City Outlet TEMP,NL,,0, +F0DO,Tommy Hilfiger Halfweg Sugar City Outlet TEMP,NL,,0, +AS06,Tommy Hilfiger Oslo (Vestby) Outlet,NO,,0, +A058,Calvin Klein Vestby (Norwegian) Outlet,NO,,0, +A289,Tommy Hilfiger Poznan,PL,1,0, +A291,Tommy Hilfiger Warsaw (Arkadia),PL,1,0, +A279,Tommy Hilfiger Gdansk,PL,1,0, +A280,Tommy Hilfiger Gdynia,PL,1,0, +A284,Tommy Hilfiger Lodz,PL,1,0, +A281,Tommy Hilfiger Gdynia (Riviera Mall),PL,1,0, +A285,Tommy Hilfiger Lublin (Atrium Felicity Mall),PL,1,0, +A282,Tommy Hilfiger Katowice,PL,1,0, +A290,Tommy Hilfiger Szczecin (Galaxy Mall),PL,1,0, +A277,Tommy Hilfiger Poznan Jeans,PL,1,0, +A278,Tommy Hilfiger Warsaw (Galeria Mokotow),PL,1,0, +A294,Tommy Hilfiger Wroclaw (Magnolia Mall),PL,1,0, +A276,Tommy Hilfiger Bydgoszcz (Zielone Arkady Mall),PL,1,0, +A297,Tommy Hilfiger Rzgow (Ptak) Outlet,PL,1,0, +A296,Tommy Hilfiger Krakow Outlet,PL,1,0, +A902,Tommy Hilfiger Warsaw (Ursus) Outlet,PL,1,0, +A901,Tommy Hilfiger Warsaw (Piaseczno) Outlet Accessories,PL,1,0, +A299,Tommy Hilfiger Warsaw (Annopol) Outlet,PL,1,0, +A903,Tommy Hilfiger Wroclaw (Factory) Outlet,PL,1,0, +A900,Tommy Hilfiger Warsaw (Piaseczno) Outlet,PL,1,0, +A298,Tommy Hilfiger Szczecin (Park) Outlet,PL,1,0, +A104,Calvin Klein Jeans Poznan (Stary Browar Mall),PL,1,0, +A102,Calvin Klein Jeans Katowice,PL,1,0, +A106,Calvin Klein Jeans Krakow (Krakowska Mall),PL,1,0, +A108,Calvin Klein Warsaw (Ursus) Outlet,PL,1,0, +A109,Calvin Klein Wroclaw (Factory) Outlet,PL,1,0, +A110,Calvin Klein Warsaw (Piaseczno) Outlet,PL,1,0, +A111,Calvin Klein Warsaw (Annopol) Outlet,PL,1,0, +A149,Calvin Klein Szczecin (Park) Outlet,PL,1,0, +A113,Calvin Klein Sosnowiec (Fashion House) Outlet,PL,1,0, +A114,Calvin Klein Gdansk (Fashion House) Outlet,PL,1,0, +A115,Calvin Klein Rzgow (Ptak) Outlet,PL,1,1, +A112,Calvin Klein Modlniczka (Factory Krakow) Outlet,PL,1,0, +A287,Tommy Hilfiger Poznan (Posnania Shopping Mall) Jeans,PL,1,0, +A168,Calvin Klein Jeans Wroclaw (Wroclavia Shopping Center),PL,1,0, +A286,Tommy Hilfiger Krakow (Krakowska Mall),PL,1,0, +A162,Calvin Klein Jeans Gdansk (Galeria Baltycka),PL,1,0, +A925,Tommy Hilfiger Wroclaw (Wroclavia Mall),PL,1,0, +A924,Tommy Hilfiger Warsaw (Atrium Promenada Mall),PL,1,0, +A173,Calvin Klein Jeans Warsaw (Promenada Mall),PL,1,0, +A177,Calvin Klein Jeans Bydgoszcz (Zielone Arkady Mall),PL,1,0, +A943,Tommy Hilfiger Gdansk (Designer Outlet) Outlet,PL,1,0, +A947,Tommy Hilfiger Lubon (Factory Poznan Mall) Outlet,PL,1,0, +A183,Calvin Klein Lubon (Poznan) Outlet,PL,1,0, +AJ01,Calvin Klein Modlniczka (Factory Krakow) Outlet Temp,PL,1,0, +A967,Tommy Hilfiger Gdansk (Designer Outlet) Outlet Temp,PL,1,0, +A968,Tommy Hilfiger Warsaw (Piaseczno) Outlet Temp,PL,1,0, +F05Z,Tommy Hilfiger Sosnowiec Designer Outlet,PL,1,0, +F061,Tommy Hilfiger Krakow (Designer Outlet),PL,1,1, +F062,Calvin Klein Krakow (Designer Outlet),PL,1,0, +A040,Calvin Klein Porto Outlet,PT,1,0, +A053,Calvin Klein Underwear Alcabideche (Cascai Shopping Mall),PT,1,0, +A059,Calvin Klein Underwear Lisbon (Vasco de Gama Mall),PT,1,0, +A065,Calvin Klein Jeans Alcochete (Freeport) Outlet,PT,1,0, +A064,Calvin Klein Underwear Alcochete (Freeport) Outlet,PT,1,0, +A063,Calvin Klein Jeans Loule (Algarve) Outlet,PT,1,0, +A1C1,Calvin Klein Porto (Norteshopping),PT,1,0, +AS04,Tommy Hilfiger Taby,SE,,0, +AA26,Tommy Hilfiger Stockholm (Bibliotek),SE,,0, +AS07,Tommy Hilfiger Jarfalla (Barkarby) Outlet,SE,,0, +A048,Calvin Klein Barkarby (Stockholm Quality Outlet Barkarby) Outlet,SE,,0, +AS08,Tommy Hilfiger Kungsbacka (Freeport) Outlet,SE,,0, +AS05,Tommy Hilfiger Solna (Mall of Scandinavia),SE,,0, +A051,Calvin Klein Underwear Malmo (Emporia Mall),SE,,0, +AS57,Tommy Hilfiger Gothenburg (Arkaden Mall),SE,,0, +A080,Calvin Klein Kungsbacka Outlet Pop Up,SE,,0, +A1G0,Calvin Klein Kungsbacka (Hede Fashion Outlet) Outlet,SE,,0, +AS79,Tommy Hilfiger Kungsbacka Outlet Pop-Up,SE,,0, +AS80,Tommy Hilfiger Barkarby Outlet Pop-Up,SE,,0, +F068,Tommy Hilfiger MIX NK Gothenburg,SE,,0, +F067,Tommy Hilfiger MIX NK Stockholm,SE,,0, +CU80,Calvin Klein Womenswear NK Gothenburg,SE,,0, +AXXX,,,,,1 diff --git a/data/translations.csv b/data/translations.csv new file mode 100644 index 0000000..93cf501 --- /dev/null +++ b/data/translations.csv @@ -0,0 +1,167 @@ +type,country,from,to +tender,PL,PTCS,VRBL:PL:01 +tender,PL,PTEU,VRBL:PL:01 +tender,PL,PTMA,VRBL:PL:02 +tender,PL,PTAM,VRBL:PL:02 +tender,PL,PTMC,VRBL:PL:02 +tender,PL,PTVI,VRBL:PL:02 +tender,PL,PTDC,VRBL:PL:02 +tender,PL,PTCU,VRBL:PL:02 +tender,PL,PTJC,VRBL:PL:02 +tender,PL,PTOC,VRBL:PL:02 +tender,PL,PTVO,VRBL:PL:03 +tender,PL,PTCA,VRBL:PL:03 +tender,PL,PTCN, +tender,PL,POMA,VRBL:PL:02 +tender,PL,POAM,VRBL:PL:02 +tender,PL,POMC,VRBL:PL:02 +tender,PL,POVI,VRBL:PL:02 +tender,PL,PODC,VRBL:PL:02 +tender,PL,POJC,VRBL:PL:02 +tender,PL,POCU,VRBL:PL:02 +tender,PL,PTAL,VRBL:PL:02 +tender,PL,PTWE,VRBL:PL:02 +tender,PL,POAL,VRBL:PL:02 +tender,PL,ZORV,VRBL:PL:03 +tender,PL,POWE,VRBL:PL:02 +tender,PL,POPF, +tender,PL,PTTW,VRBL:PL:02 +tender,PL,POTW,VRBL:PL:02 +tender,PL,PTZE,VRBL:PL:02 +tender,PL,PTCV,VRBL:PL:03 +tender,PL,POCV,VRBL:PL:03 +tender,PL,PTGC,VRBL:PL:02 +tender,PL,POGC,VRBL:PL:02 +tender,PL,PTEU,VRBL:PL:01 +tender,PL,PTUS,VRBL:PL:01 +tender,PL,PTDK,VRBL:PL:02 +tender,PL,PODK,VRBL:PL:02 +tender,PL,PTHR,VRBL:PL:01 +tender,PL,POEM,VRBL:PL:02 +tender,PL,POEV,VRBL:PL:02 +tender,PL,POED,VRBL:PL:02 +tender,PL,POZM,VRBL:PL:02 +tender,PL,POZN,VRBL:PL:02 +tender,PL,POZV,VRBL:PL:02 +tender,PL,PTVA,VRBL:PL:03 +tender,PL,POVA,VRBL:PL:03 +tender,PL,PTCN, +tender,PL,PONK,VRBL:PL:03 +tender,PL,POBA, +tender,PL,POPA,VRBL:PL:02 +tender,PL,POSA,VRBL:PL:02 +tax,PL,6B,VRBL:PL:02 +tax,PL,A0,VRBL:PL:07 +tax,PL,BO,VRBL:PL:03 +tax,PL,PA,VRBL:PL:01 +tax,HR,A3,VRBL:HR:HR:PDV25 +tax,BE,67,AA +tax,BE,A0,E +tax,BE,A6,S +tender,HR,PTCS,10 +tender,HR,PTEU,10 +tender,HR,PTMA,55 +tender,HR,PTAM,54 +tender,HR,PTMC,54 +tender,HR,PTVI,54 +tender,HR,PTDC,54 +tender,HR,PTCU,54 +tender,HR,PTJC,54 +tender,HR,PTOC,54 +tender,HR,PTVO,10 +tender,HR,PTCA,10 +tender,HR,PTCN,60 +tender,HR,POMA,55 +tender,HR,POAM,54 +tender,HR,POMC,54 +tender,HR,POVI,54 +tender,HR,PODC,54 +tender,HR,POJC,54 +tender,HR,POCU,54 +tender,HR,PTAL,54 +tender,HR,PTWE,54 +tender,HR,POAL,54 +tender,HR,ZORV,10 +tender,HR,POWE,54 +tender,HR,POPF,ZZZ +tender,HR,PTTW,54 +tender,HR,POTW,54 +tender,HR,PTZE,54 +tender,HR,PTCV,10 +tender,HR,POCV,10 +tender,HR,PTGC,56 +tender,HR,POGC,56 +tender,HR,PTEU,10 +tender,HR,PTUS,10 +tender,HR,PTDK,54 +tender,HR,PODK,54 +tender,HR,PTHR,10 +tender,HR,POEM,54 +tender,HR,POEV,54 +tender,HR,POED,54 +tender,HR,POZM,54 +tender,HR,POZN,54 +tender,HR,POZV,54 +tender,HR,PTVA,10 +tender,HR,POVA,10 +tender,HR,PTCN,20 +tender,HR,PONK,10 +tender,HR,POBA,ZZZ +tender,HR,POPA,54 +tender,HR,POSA,54 +tender,BE,PTCS,10 +tender,BE,PTEU,10 +tender,BE,PTMA,55 +tender,BE,PTAM,54 +tender,BE,PTMC,54 +tender,BE,PTVI,54 +tender,BE,PTDC,54 +tender,BE,PTCU,54 +tender,BE,PTJC,54 +tender,BE,PTOC,54 +tender,BE,PTVO,10 +tender,BE,PTCA,10 +tender,BE,PTCN,60 +tender,BE,POMA,55 +tender,BE,POAM,54 +tender,BE,POMC,54 +tender,BE,POVI,54 +tender,BE,PODC,54 +tender,BE,POJC,54 +tender,BE,POCU,54 +tender,BE,PTAL,54 +tender,BE,PTWE,54 +tender,BE,POAL,54 +tender,BE,ZORV,10 +tender,BE,POWE,54 +tender,BE,POPF,ZZZ +tender,BE,PTTW,54 +tender,BE,POTW,54 +tender,BE,PTZE,54 +tender,BE,PTCV,10 +tender,BE,POCV,10 +tender,BE,PTGC,56 +tender,BE,POGC,56 +tender,BE,PTEU,10 +tender,BE,PTUS,10 +tender,BE,PTDK,54 +tender,BE,PODK,54 +tender,BE,PTHR,10 +tender,BE,POEM,54 +tender,BE,POEV,54 +tender,BE,POED,54 +tender,BE,POZM,54 +tender,BE,POZN,54 +tender,BE,POZV,54 +tender,BE,PTVA,10 +tender,BE,POVA,10 +tender,BE,PTCN,20 +tender,BE,PONK,10 +tender,BE,POBA,ZZZ +tender,BE,POPA,54 +tender,BE,POSA,54 +scheme,BE,endpoint,0208 +scheme,BE,party,0208 +scheme,HR,endpoint,9934 +scheme,HR,party,VRBL:HR:TAX +scheme,PL,party,VRBL:PL:TAX diff --git a/flask_invoicing.py b/flask_invoicing.py new file mode 100644 index 0000000..d05e6cb --- /dev/null +++ b/flask_invoicing.py @@ -0,0 +1,608 @@ +from flask import Flask, request, render_template, send_file, render_template_string,abort, Response, redirect, url_for +from werkzeug.middleware.proxy_fix import ProxyFix +# from waitress import serve +import os +import json +import io +import re +import base64 +import lzma +from io import BytesIO +from barcode import Code39 as BarCodeObj +from barcode.writer import ImageWriter +import qrcode +from datetime import date, timedelta, datetime +from xhtml2pdf import pisa +import zipfile +import datetime +from localconfig import * +import csv +from lib_poslog import process_invoice_request, etree_to_dict, get_trxlink_from_dict +import xml.etree.ElementTree as ET +from models import db, StateOfDate, StateOfInvoice +from pprint import pprint +from lib_poslog import process_invoice_request, etree_to_dict +from collections import deque + + +MAXZIPSIZE = 100 # max number of files in a zipfile to download + + +app = Flask(__name__) +app.config["SECRET_KEY"] = "lkjasfuhf83749yow8urehfkuresa" +app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///state.db" + +db.init_app(app) + +with app.app_context(): + db.create_all() + + +@app.route('/invoice', methods=['GET']) +def home(): + return render_template('home.html') + + +@app.route('/invoice/download', methods=['GET']) +def download(): + # when all is done, read the ecosio folder and show all downloadable files, by country + xmlfiles = {} # structure: downloads[date][country]=filename + dir_list = os.listdir(ECOSIO_PATH) + for f in dir_list: + if f.endswith('.xml'): # PL_A282_T000_260110_1.xml + country = f[0:2] # first two chars + date = f"20{f[13:19]}" + if date not in xmlfiles: + xmlfiles[date] = 0 + xmlfiles[date] += 1 + + states = {} + # r = StateOfDate.query.filter(system_issues=0, data_issues>0).all() + date_states = StateOfDate.query.all() + for d in date_states: + if d.system_issues > 0 or d.data_issues > 0: + files = 0 + if d.date in xmlfiles: + files = xmlfiles[d.date] + states[d.date] = [files, d.system_issues, d.data_issues] + + for yyyymmdd in xmlfiles.keys(): + if yyyymmdd not in states: + states[yyyymmdd] = [xmlfiles[yyyymmdd],0,0] + + return render_template('ecosio_service.html', downloads=states) + + +@app.route('/invoice/downloadaszip', methods=['GET']) +def downloadaszip(): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + try: + filenames = [ + f for f in os.listdir(ECOSIO_PATH) + if f.endswith(".xml") + ] + except FileNotFoundError: + abort(404, description="Files directory not found") + + if not filenames: + abort(404, description="No xml files found") + + # Create in-memory ZIP file + memory_file = io.BytesIO() + + with zipfile.ZipFile(memory_file, mode="w", compression=zipfile.ZIP_DEFLATED) as zf: + for filename in filenames: # PL_A282_T000_260110_1.xml + file_path = os.path.join(ECOSIO_PATH, filename) + zf.write(file_path, arcname=filename) + # move the file to the archive + os.replace(file_path, os.path.join(DONE_PATH, filename)) + # update db with file status TODO + invoiceIsEcosiod(filename[3:].replace('.xml',''),0) # parameter like A282_T000_260110_1 + + memory_file.seek(0) + + return send_file( + memory_file, + mimetype="application/zip", + as_attachment=True, + download_name="bundle_for_ecosio.zip" + ) + +def file_has_invoice(filename): + is_invoice = False + sto = dat = til = seq = '' + transactiontytpe = '' + with open(filename, 'r', encoding='utf-8') as f: + while line := f.readline(): + if transactiontytpe in line: + is_invoice = True + if is_invoice: + e = ET.parse(filename) + root = e.getroot() + tree = etree_to_dict(root) + trx = tree['POSLog']['Transaction']['RetailTransaction'] + if 'InvoiceNumber' in trx: + trx_link = get_trxlink_from_dict(trx) + if len(trx_link) > 1: + return f"{trx_link['store']}_T{trx_link['till']}_{trx_link['year']}{trx_link['month']}{trx_link['day']}_{trx_link['seq']}" + return 0 + + +@app.route('/invoice/requests', methods=['GET','POST']) +def get_invoices(): + ''' + this url takes a store and a date + then shows all found invoice-requests for that date + clicking on one of these will show the invoice in message format + ''' + xml_files = [] + store = "" + date = "" + + if request.method == "POST": + store = request.form.get("store") + date = request.form.get("date") + + folder = os.path.join(SORTED_PATH, date, store) + + if folder and os.path.isdir(folder): + for f in os.listdir(folder): + if '_T000_' in f and f.endswith(".xml"): + filepath = os.path.join(folder, f) + i = file_has_invoice(filepath) + if i: + xml_files.append([f, i]) + + else: + xml_files = [] + + return render_template( + "requests.html", + xml_files=xml_files, + store=store, + date=date + ) + + +@app.route("/invoice/invoice", methods=['GET']) +def view_invoice(): + ''' + this endpoint will show one invoice in message format + ''' + date = request.args.get("date") + store = request.args.get("store") + filename = request.args.get("filename") + + if not date or not store or not filename: + print("wrong url") + abort(400) + + y,m,d = date.split('/') + # req, sales = filename.split(':') + filepath = os.path.join(SORTED_PATH, y, m, d, store, filename) + + # Basic safety check + if not os.path.isfile(filepath) or not filepath.lower().endswith(".xml"): + abort(404) + + invoice = process_invoice_request(filepath) + return str(invoice) + + + + +def read_cust_csv(): + with open(BUYERS_BROKEN, newline="", encoding="utf-8") as f: + reader = csv.reader(f) + rows = list(reader) + return rows[0], rows[1:] # header, data + + +def write_repaired_csv(rows): + with open(BUYERS_REPAIRED, "a", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + # writer.writerow(header) + writer.writerows(rows) + +def write_broken_csv(header, rows): + with open(BUYERS_BROKEN, "w", newline="", encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(header) + writer.writerows(rows) + +EDITABLECOLS = 7 + +@app.route("/invoice/buyers", methods=["GET", "POST"]) +def broken_buyers(): + ''' + this endpoint will show all data from the broken-buyers csv file + after upodating any line, if its approved as good data, the buyer will move from broken to repaired csv + ''' + header, rows = read_cust_csv() + + if request.method == "POST": + updated_rows = [] + not_updated_rows = [] + + for i, row in enumerate(rows): + updated = row[:-EDITABLECOLS] # untouched columns + dataOk = True + for j in range(EDITABLECOLS): + field_name = f"row_{i}_col_{j}" + value = request.form[field_name] + if len(value) < 2: + dataOk = False + updated.append(value) + if dataOk: + updated_rows.append(updated) + else: + not_updated_rows.append(updated) + + write_broken_csv(header, not_updated_rows) + write_repaired_csv(updated_rows) + return redirect(url_for("table")) + + return render_template( + "buyers.html", + header=header, + rows=rows, + editable_cols=EDITABLECOLS, + ) + +@app.route('/invoice/api/getStatusOfDate///
', methods=['GET']) +def getStatusOfDate(YYYY, MM, DD): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + result = {} + result['status'] = 'pending' + if YYYY and MM and DD: + d=f"{YYYY}{MM}{DD}" + r = StateOfDate.query.filter_by(date=d).first() + if r: + result['data'] = str(r) + if r.isDone(): + result['status'] = 'done' + return json.dumps(result), 200 + + +@app.route('/invoice/api/setStatusOfDate///
//', methods=['GET']) +def setStatusOfDate(YYYY, MM, DD, systemerrors, dataerrors): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + result = {} + if YYYY and MM and DD: + d=f"{YYYY}{MM}{DD}" + r = StateOfDate.query.filter_by(date=d).first() + if r: + r.system_issues = systemerrors + r.data_issues = dataerrors + db.session.commit() + result['status'] = 'Ok' + result['data'] = str(r) + else: + r = StateOfDate(date=f"{YYYY}{MM}{DD}", system_issues=systemerrors, data_issues=dataerrors) + db.session.add(r) + db.session.commit() + result['status'] = 'Ok' + result['data'] = str(r) + + return json.dumps(result), 200 + + +@app.route('/invoice/api/getNextProcessDate/', methods=['GET']) +def getNextProcessDate(YYYYMMDD): + result = {} + latest_date = datetime.datetime.today().date() + date = latest_date + earliest_date = datetime.datetime.strptime(YYYYMMDD, "%Y%m%d").date() + for sod in StateOfDate.query.all(): + if sod.system_issues > 0 or sod.data_issues > 0: + date = datetime.datetime.strptime(sod.date, "%Y%m%d").date() + if date >= earliest_date and date < latest_date: + latest_date = date + result['status'] = 'Ok' + result['data'] = str(date.strftime('%Y%m%d')) + + return json.dumps(result), 200 + + +def setInvoiceState(poslogid=None, receiptid=None, country='XX', state=-1): + result = {} + if poslogid: + r = StateOfInvoice.query.filter_by(poslogid=poslogid).first() + if r: + r.state = state + db.session.commit() + result['status'] = 'Ok' + result['data'] = str(r) + else: + YYYYMM=receiptid[4:10] + print(f">->->{YYYYMM}") + r = StateOfInvoice(poslogid=poslogid, receiptid=receiptid, receiptmonth=YYYYMM, country=country, state=state) + db.session.add(r) + db.session.commit() + result['status'] = 'Ok' + result['data'] = str(r) + return json.dumps(result), 200 + + +def getInvoiceState(poslogid=None): + if poslogid: + r = StateOfInvoice.query.filter_by(poslogid=poslogid).first() + if r: + return r.state + return -1 + +@app.route('/invoice/api/poslog/isConverted///', methods=['GET']) +def poslogIsConverted(poslogid, receiptid, country): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + return setInvoiceState(poslogid=poslogid, receiptid=receiptid, country=country, state=1) + +@app.route('/invoice/api/poslog/hasIssues///', methods=['GET']) +def poslogHasIssues(poslogid, receiptid, country): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + return setInvoiceState(poslogid=poslogid, receiptid=receiptid, country=country, state=0) + +@app.route('/invoice/api/invoice/isEcosiod/', methods=['GET']) +def invoiceIsEcosiod(poslogid, receiptid): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + return setInvoiceState(poslogid=poslogid, state=2) + +@app.route('/invoice/api/invoice/isMonthlied/', methods=['GET']) +def isMonthlied(poslogid, receiptid): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + return setInvoiceState(poslogid=poslogid, state=3) + +@app.route('/invoice/api/poslog/canBeConverted/', methods=['GET']) +def isOkToCreateXML(poslogid): + result = {} + result['status'] = 'NotOk' + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + r = getInvoiceState(poslogid=poslogid) + if r<2: + result['status'] = 'Ok' + return result + +@app.route('/invoice/showtables/', methods=['GET']) +def showPoslogs(status): + # if there is a filename someone wants a download + # if the filename is "all", then zip up all the avalable files and send the zip + result = 'poslogs:
' + if status: + poslogs = StateOfInvoice.query.all() + if poslogs: + for p in poslogs: + result += f"{p}
" + + result += '
date-states:
' + states = StateOfDate.query.all() + if states: + for p in states: + result += f"{p}
" + + return result + +def file_has_invoicenr(filename, nrs): + with open(filename, 'r', encoding='utf-8') as f: + while line := f.readline(): + for nr in nrs: + if nr in line: + return True + return False + + +@app.route('/invoice/find_rejectedids', methods=['GET','POST']) +def find_rejectedids(): + rows=[] + if request.method == "POST": + if len(request.form['date']) == 6 and len(request.form['countrycode']) == 2 and len(request.form['invoices']) > 10: + # scroll though the ecosio/downloaded folder in search for , later than , then open them to see if they match an invoicenr + invoices = [] + files = [] + for i in request.form['invoices'].split("\n"): + if len(i) > 10: + invoices.append(i.strip()) + + YY = request.form['date'][0:2] + MM = request.form['date'][2:4] + DD = request.form['date'][4:] + + for f in os.listdir(DONE_PATH): + if f.startswith(f"{request.form['countrycode']}_") and f.endswith(".xml"): + country,store,till,filename_datestr,dummy = f.split('_') + file_date = datetime.datetime.strptime(filename_datestr, "%y%m%d").date() + ref_date = datetime.datetime.strptime(request.form['date'], "%y%m%d").date() + if file_date >= ref_date: + filepath = os.path.join(DONE_PATH, f) + if file_has_invoicenr(filepath, invoices): + # get the original sorted poslog file + filepath = os.path.join(SORTED_PATH, file_date.strftime("%Y"),file_date.strftime("%m"),file_date.strftime("%d"),store,f"{f[3:]}" ) + inv = process_invoice_request(filepath) + row = [inv.country(), inv.nr, inv.receipt_id(), inv.poslogid, inv.buyer.name, inv.buyer.orgid, inv.buyer.taxID] + rows.append(row) + + if len(rows) > 0: + return render_template("repair_rejectedids.html", rows=rows) + return render_template("find_rejectedids.html") + + +@app.route('/invoice/repair_rejectedids', methods=['POST']) +def repair_rejectedids(): + files = {} + download = [] + + for f in request.form.keys(): + store, till, date, seq, field = f.split("_") + filename = f"{store}_{till}_{date}_{seq}.xml" + if not filename in files: + files[filename] = {} + files[filename][field] = request.form[f] + + # we now have a nice dict with filenames and their new orgid and taxid + for f in files.keys(): + # make the sorted filename of the invoice: + store, till, date, dummy = f.split("_") + inv_filepath = os.path.join(SORTED_PATH, f"20{date[0:2]}", date[2:4], date[4:], store, f) + inv = process_invoice_request(inv_filepath) + # update the orgid and taxid + inv.buyer.orgid = files[f]['orgid'] + inv.buyer.taxID = files[f]['taxid'] + # overwrite the file in the downloaded folder + fname = f"{inv.country()}_{inv.poslogid}.xml" + with open(os.path.join(DONE_PATH, fname), "w", encoding="utf-8") as lfile: + lfile.write(str(inv)) + download.append(fname) + + # now zipo up and download the new files + # Create in-memory ZIP file + memory_file = io.BytesIO() + + with zipfile.ZipFile(memory_file, mode="w", compression=zipfile.ZIP_DEFLATED) as zf: + for filename in download: # PL_A282_T000_260110_1.xml + file_path = os.path.join(DONE_PATH, filename) + zf.write(file_path, arcname=filename) + + memory_file.seek(0) + + return send_file( + memory_file, + mimetype="application/zip", + as_attachment=True, + download_name="repairs_for_ecosio.zip" + ) + +@app.route('/invoice/monthlyreport', methods=['GET','POST']) +def monthlyreport(): + csv = '' + month = '202601' + include = False + if request.method == "POST": + today = datetime.datetime.today().strftime('%Y-%m-%d') + if len(request.form['countrycode']) == 2 and len(request.form['month']) == 6: + country = request.form['countrycode'] + month = request.form['month'] + include = 'include_older' in request.form + csv = 'ReportDate,InvoiceNr,InvoiceSentdate,oibSeller,oibBuyer,PaymentDate,PaymentAmount,PaymentMethod\n' + if country == 'HR': + csv = 'datumVrijemeSlanja,brojDokumenta,datumIzdavanja,oibPorezniBrojIzdavatelja,oibPorezniBrojPrimatelja,datumNaplate,naplaceniIznos,nacinPlacanja\n' + # get the invoices from the database + unreported = StateOfInvoice.query.filter_by(country=country, state=2).all() + for inv in unreported: + # get info from all + if (include and inv.receiptmonth <= month) or (inv.receiptmonth==month): + # load the ecosio file + filepath = os.path.join(DONE_PATH, f"{inv.country}_{inv.poslogid}.xml") + downloaddate = inv.updated_at.strftime('%Y-%m-%d') + if os.path.exists(filepath): + e = ET.parse(filepath) + root = e.getroot() + tree = etree_to_dict(root) + line = f"{today};{tree['Invoice']['ID']};{downloaddate};{tree['Invoice']['AccountingSupplierParty']['Party']['PartyLegalEntity']['CompanyID']};{tree['Invoice']['AccountingCustomerParty']['Party']['PartyLegalEntity']['CompanyID']};{tree['Invoice']['DueDate']};{tree['Invoice']['LegalMonetaryTotal']['PayableAmount']['#text']};T\n" + csv += line + isMonthlied(inv.poslogid, 0) + # download to csv file + buffer = io.BytesIO() + buffer.write(csv.encode("utf-8")) + buffer.seek(0) + + return send_file( + buffer, + mimetype="text/csv", + as_attachment=True, + download_name=f"monthly_report_{country}_{month}.csv" + ) + + return render_template("monthlyreport.html", ) + return render_template("monthlyreport.html") + + +def read_csv(csv_file): + with open(csv_file, newline='', encoding="utf-8") as f: + reader = list(csv.reader(f)) + header = reader[0] + rows = reader[1:] + return header, rows + + +def write_csv(csv_file, header, rows): + with open(csv_file, "w", newline='', encoding="utf-8") as f: + writer = csv.writer(f) + writer.writerow(header) + writer.writerows(rows) + + +@app.route("/invoice/maintain_csv/", methods=["GET", "POST"]) +def maintain_csv(csv_file): + csv_path = os.path.join(DATADIR, f"{csv_file}.csv") + + header, rows = read_csv(csv_path) + + if request.method == "POST": + new_rows = [] + num_columns = len(header) + + # Collect form data + row_index = 0 + while True: + row = [] + for col_index in range(num_columns): + field_name = f"row-{row_index}-col-{col_index}" + if field_name not in request.form: + break + row.append(request.form.get(field_name).strip()) + + if len(row) != num_columns: + break + + # Skip completely empty rows + if any(cell != "" for cell in row): + new_rows.append(row) + + row_index += 1 + + write_csv(csv_path, header, new_rows) + return redirect(url_for("home")) + return render_template("edit_csv.html", header=header, rows=rows, csv=csv_file) + + +def tail(filename, n=500, loglevel=1): + lines = [] + with open(filename, 'r', encoding='utf-8') as f: + lines = list(deque(f, maxlen=n)) + if loglevel==0: + return ''.join(lines) + if loglevel==1: + return ''.join( [ l for l in lines if LOGLEVELS[0] not in l ] ) + if loglevel>1: + return ''.join( [ l for l in lines if LOGLEVELS[2] in l or LOGLEVELS[3] in l ] ) + + +@app.route("/invoice/log/") +def show_log(loglevel): + return render_template("show_log.html", txt=tail('log.txt', loglevel=int(loglevel))) + +@app.route("/invoice/earliestdate", methods=["GET", "POST"]) +def earliestdate(): + if request.method == "POST": + earliestdate = request.form['earliestdate'] + with open(EARLIEST_DATE_FILE, 'w') as file: + file.write(earliestdate) + else: + earliestdate = '20260101' + if os.path.exists(EARLIEST_DATE_FILE): + with open(EARLIEST_DATE_FILE, 'r') as f: + earliestdate = f.readline() + + return render_template("update_earliest_date.html", earliestdate=earliestdate) + + +if __name__ == '__main__': + # as native flask + app.run(debug=True, host='0.0.0.0', port=9666) + diff --git a/invoice_all_stores.py b/invoice_all_stores.py new file mode 100644 index 0000000..e9252e7 --- /dev/null +++ b/invoice_all_stores.py @@ -0,0 +1,137 @@ +import os +from datetime import datetime, timedelta +import csv +import time +from lib_poslog import find_invoices_in_storeday +from localconfig import * +from stores import Stores +import io +import zipfile +from pprint import pprint +import urllib.request +import json +import tempfile +import models + +SORTED_PATH = os.path.join(BASEPATH, "Sorted") +ECOSIO_PATH = os.path.join(BASEPATH, "Ecosio") + +stores = Stores() + +def save_edate(yyyymmdd): + if not TEST: + with open(EARLIEST_DATE_FILE, 'w') as file: + file.write(yyyymmdd) + +def load_edate(): + yyyymmdd = '20260201' + if os.path.exists(EARLIEST_DATE_FILE): + with open(EARLIEST_DATE_FILE, 'r') as f: + yyyymmdd = f.readline() + return yyyymmdd + + +def remove_duplicates_inplace(file_path): + seen = set() + + # Create temporary file in same directory + dir_name = os.path.dirname(file_path) + with tempfile.NamedTemporaryFile( + mode='w', + newline='', + encoding='utf-8', + delete=False, + dir=dir_name + ) as temp_file: + + temp_path = temp_file.name + + with open(file_path, mode='r', newline='', encoding='utf-8') as infile: + reader = csv.reader(infile) + writer = csv.writer(temp_file) + + for row in reader: + if not row: + continue + + key = row[0] + + if key not in seen: + seen.add(key) + writer.writerow(row) + + # Replace original file with cleaned file + os.replace(temp_path, file_path) + +def invoice_all_stores_for(YYYY, MM, DD, update_store_file=False): + """ + + from CSV file "stores_to_invoice" (global: stores) Get all the stores who creates archive files for + check for if processing is done/not + if not: for all stores check if a invoice found is already processed/not + if not: process invoice and write to the processing service: invoicenr, system-isues, data-issues + processing results on a list of invoices, they should be save to the ecosio folder - a service will pick themn up + if a date has completely been processed, write to the processing service: date, poslogged, ecosiod + + + If there is any file in the folder-structure NOT in the csv file, add it to the csv and issue a warning + Pick up all the stores from the csv files who are tagged to create-invoices + ...and have those invoices created + :param YYYY: year + :param MM: month + :param DD: date + """ + global process_results + name_prexif = 'TST_' if TEST else '' + + # open the results file + buyer_issues = 0 + system_issues = 0 + date = f"{YYYY}-{MM}-{DD}" + # contents = json.loads(urllib.request.urlopen(INVOICE_SERVICE + f"getStatusOfDate/{YYYY}/{MM}/{DD}").read()) + # if contents['status'] == 'pending': + print(f"Invoicing for {YYYY} {MM} {DD}") + for country in stores.all_countries(): + for store in stores.stores_for(country): + # try: + # get the invoices that are good to sent, and the number of data-fails + invoices, invoices_with_data_issues = find_invoices_in_storeday(store, YYYY, MM, DD) + for invoice in invoices: + contents = json.loads(urllib.request.urlopen(INVOICE_SERVICE + f"poslog/canBeConverted/{invoice.poslogid}").read()) + if (contents['status'] == 'Ok') or TEST: + with open(os.path.join(ECOSIO_PATH, f"{name_prexif}{country}_{invoice.poslogid}.xml"), "w", encoding="utf-8") as lfile: + lfile.write(str(invoice)) + if not TEST: + contents = urllib.request.urlopen(INVOICE_SERVICE + f"poslog/isConverted/{invoice.poslogid}/{invoice.receipt_id()}/{invoice.country()}").read() + # save status to service + for invoice in invoices_with_data_issues: + if not TEST: + contents = urllib.request.urlopen(INVOICE_SERVICE + f"poslog/hasIssues/{invoice.poslogid}/{invoice.receipt_id()}/{invoice.country()}").read() + buyer_issues += 1 + # except: + # log(f"Programming error while processing {store} {YYYY}-{MM}-{DD}", 3) + # # something went dreadfully wrong: send state to service + # system_issues += 1 + + if not TEST: + contents = urllib.request.urlopen(INVOICE_SERVICE + f"setStatusOfDate/{YYYY}/{MM}/{DD}/{system_issues}/{buyer_issues}").read() + +if __name__ == '__main__': + today = datetime.datetime.today().date() + earliest_date_str = load_edate() + earliest_date = datetime.datetime.strptime(earliest_date_str, "%Y%m%d").date() + process_date = earliest_date + while process_date <= today: + year4 = process_date.strftime('%Y') # 4-digit year + month = process_date.strftime('%m') # 2-digit month + day = process_date.strftime('%d') # 2-digit day + d = f"{year4}-{month}-{day}" + invoice_all_stores_for(year4,month,day) + process_date = process_date + timedelta(days=1) + + # in the broken buyers csv files, remove any duplicates that may have caused it with multiple runs + remove_duplicates_inplace(BUYERS_BROKEN) + + contents = json.loads(urllib.request.urlopen(INVOICE_SERVICE + f"getNextProcessDate/{earliest_date_str}").read()) + save_edate(contents['data']) + diff --git a/invoice_as_html.py b/invoice_as_html.py new file mode 100644 index 0000000..84b2b43 --- /dev/null +++ b/invoice_as_html.py @@ -0,0 +1,147 @@ +from invoice_base import * +import xml.etree.ElementTree as ET + +class Invoice(BaseInvoice): + + def filter_elements_by_country(self, xml_string): + root = ET.fromstring(xml_string) + + for parent in root.iter(): + for child in list(parent): + include = child.attrib.get("include") + + # No include attribute → keep element as-is + if include is None: + continue + + values = [v.strip() for v in include.split(",")] + print(f" {self.country()} {values}") + + # Remove element if include does not contains the country + if self.country() not in values: + parent.remove(child) + else: + # Otherwise, remove only the include attribute + del child.attrib["include"] + + return ET.tostring(root, encoding="unicode") + + def __str__(self): + taxestotal = '' + for x in self.taxes: + taxestotal += str(x) + allarticles = '' + for a in self.articles: + allarticles += str(a) + alltenders = '' + for t in self.tenders: + alltenders += str(t) + + xml = f''' + + + + + + + + + + + {allarticles} + + + + + + +
BuyerSeller
{self.buyer}{self.seller}


+ Invoice: {self.nr}
+ Receipt: {self.receipt.store}{self.receipt.year}{self.receipt.month}{self.receipt.day}{self.receipt.till}{self.receipt.seq.zfill(6)}
+ Date: {self.receipt.year}-{self.receipt.month}-{self.receipt.day}
+



Item Description Price {self.currency()}


Totals:
{self.totals}
Taxes:
{taxestotal}
Settled:
{alltenders}

+ + +''' + + # return self.filter_elements_by_country(xml) + return xml + +class Discount(BaseDiscount): + def __str__(self): + return f'''{self.promotionID}: {self.currency()} {self.net_amount():.2f}
''' + +class Tax(BaseTax): + spaces = 'tax' + + def __str__(self): + return f"{self.translated_group()} {self.percentage}% of {self.taxableamount:.2f}: {self.amount:.2f}
" + +class TotalTax(Tax): + def __str__(self): + return f"{self.translated_group()} {self.percentage}% of {self.currency()} {self.taxableamount:.2f}: {self.amount:.2f}
" + + +class Header(BaseHeader): + pass + + +class Totals(BaseTotals): + def __str__(self): + return f'''in {self.currency()}
+Nett: {self.currency()} {self.netAmount:.2f}
+Gross: {self.currency()} {self.grandAmount:.2f}
''' + + + + +class Receipt(BaseReceipt): + pass + + + +class Buyer(BaseBuyer): + def __str__(self): + return f'''{self.scheme}: {self.orgid}
+ {self.name}
+ {self.street1}, {self.street2}
+ {self.zip} {self.city}
+ {self.phone} {self.email}
+ {self.country}
+ VAT: {self.taxID}
''' + +class Delivery(): + pass + +class Seller(BaseSeller): + def __str__(self): + return f'''{self.scheme}: {self.orgid}, {self.legalid}
+ {self.name}
+ {self.street1}, {self.street2}
+ {self.zip} {self.city}
+ {self.phone} {self.email}
+ {self.country}
+ VAT: {self.taxID}
''' + +class Tender(BaseTender): + + def translate(self, code): + return '54' # credit card + + def __str__(self): + return f'''{self.description} {self.translated_type()} {self.my_currency} {self.amount}
''' + +class Article(BaseArticle): + def __str__(self): + discounts = '' + for d in self.discounts: + discounts += str(d) + + return f''' + {self.sequence} {self.itemid} {self.description} {'-' if self.returnflag else ''}{self.quantity} {'-' if self.returnflag else ''}{self.netBasePrice():.2f} + {self.upc} + + {discounts} + Line total: {'-' if self.returnflag else ''}{self.netSalesPrice():.2f} + {self.tax.translated_group()} {self.tax.percentage}%: {self.tax.amount:.2f}
+''' diff --git a/invoice_as_peppol.py b/invoice_as_peppol.py new file mode 100644 index 0000000..626b923 --- /dev/null +++ b/invoice_as_peppol.py @@ -0,0 +1,273 @@ +from invoice_base import * + +class Invoice(BaseInvoice): + def __str__(self): + taxestotal = '' + for x in self.taxes: + taxestotal += str(x) + allarticles = '' + for a in self.articles: + allarticles += str(a) + alltenders = '' + for t in self.tenders: + alltenders += str(t) + + xml = f''' + + urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0 + urn:fdc:peppol.eu:2017:poacc:billing:01:1.0 + {self.nr} + {self.receipt.year}-{self.receipt.month}-{self.receipt.day} + {self.receipt.year}-{self.receipt.month}-{self.receipt.day} + 388 + {self.currency()} + + {self.receipt.store}{self.receipt.year}{self.receipt.month}{self.receipt.day}{self.receipt.till}{self.receipt.seq.zfill(6)} + + {self.seller} + + {self.buyer} + + {alltenders} + + + {self.receipt.year}-{self.receipt.month}-{self.receipt.day} + + + {self.totals} + + + {self.total_taxes():.2f} + {taxestotal} + + {allarticles} + +''' + result = "" + + + result += xml + # if self.seller: + # result += str(self.seller) + # else: + # result += "[ == no country / PVH-ofice found ==]\n" + # if self.buyer: + # result += str(self.buyer) + # for a in self.articles: + # result += str(a) + # for t in self.tenders: + # result += str(t) + + return result + +class Discount(BaseDiscount): + def __str__(self): + return f''' + + false + 95 + {self.promotionID} + {self.net_amount():.2f} + +''' + +class Tax(BaseTax): + spaces = 'tax' + + #### TODO translation pls note self.country is always XX + def translated_group(self): + result = 'S' # peppol: S: standard + p = float(self.percentage) + if p < 18.0: + result = 'AA' # lower rate + if p <0.01: + result = 'E' # zero rate + return result + + def __str__(self): + return f"{self.spaces},{self.typesubtype},{self.code},{self.amount},{self.percentage}%,{self.translated_group()},{self.taxableamount}\n" + +class TotalTax(Tax): + def __str__(self): + return f''' + + {self.taxableamount:.2f} + {self.amount:.2f} + + {self.translated_group()} + {self.percentage} + + VAT + + + + ''' + +class Header(BaseHeader): + pass + + +class Totals(BaseTotals): + def __str__(self): + return f''' + + {self.netAmount:.2f} + {self.netAmount:.2f} + {self.grandAmount:.2f} + + {self.grandAmount:.2f} + +''' + + + + +class Receipt(BaseReceipt): + pass + + + +class Buyer(BaseBuyer): + def __str__(self): + return f''' + + + {self.orgid} + + + {self.name} + + + {self.street1} + {self.street2} + {self.city} + {self.zip} + + {self.country} + + + + {self.taxID} + + tax + + + + {self.name} + {self.orgid} + + + {self.name} + {self.phone} + {self.email} + + + +''' + +class Delivery(): + pass + +class Seller(BaseSeller): + def __str__(self): + return f''' + + + {self.orgid} + + + {self.name} + + + {self.street1} + {self.street2} + {self.city} + {self.zip} + + {self.country} + + + + {self.taxID} + + tax + + + + {self.name} + {self.orgid} + + + +''' + +class Tender(BaseTender): + + def translate(self, code): + return '54' # credit card + + def __str__(self): + return f''' + + {self.type} + + +''' + +class Article(BaseArticle): + def __str__(self): + discounts = '' + for d in self.discounts: + discounts += str(d) + + return f''' + + {self.sequence} + {'-' if self.returnflag else ''}{self.quantity} + {'-' if self.returnflag else ''}{self.netSalesPrice():.2f} + + + {discounts} + + {self.description} + {self.description} + + {self.itemid} + + + + + {self.upc} + + + {self.tax.translated_group()} + {self.tax.percentage} + + VAT + + + + + {self.netBasePrice():.2f} + + +''' diff --git a/invoice_as_text.py b/invoice_as_text.py new file mode 100644 index 0000000..2963eb0 --- /dev/null +++ b/invoice_as_text.py @@ -0,0 +1,66 @@ +from invoice_base import * + +class Invoice(BaseInvoice): + def __str__(self): + result = ">>>>>>\n" + result += f"inv,{'CREDTNOTE' if self.debit else 'SALE'},{self.nr}\n" + result += f"str,{self.storename}\n" + result += f"{self.sales}" + if self.seller: + result += str(self.seller) + else: + result += "[ == no country / PVH-ofice found ==]\n" + if self.buyer: + result += str(self.buyer) + for a in self.articles: + result += str(a) + for t in self.tenders: + result += str(t) + for x in self.taxes: + result += str(x) + result += "<<<<<<<\n" + return result + +class Discount(BaseDiscount): + def __str__(self): + return(f"prm,{self.promotionID},{self.action},{self.amount},{self.reasoncode}\n") + +class Tax(BaseTax): + spaces = 'tax' + + def __str__(self): + return f"{self.spaces},{self.typesubtype},{self.code},{self.amount},{self.percentage}%,{self.translated_group()},{self.taxableamount}\n" + +class TotalTax(BaseTotalTax): + ''' + Docstring for TotalTax + ''' + spaces = 'tax,' + +class Sales(BaseSales): + def __str__(self): + result = f"sal,{self.store},{self.year}{self.month}{self.day},{self.till},{self.seq}\n" + result += f"tot,{self.grandAmount},{self.netAmount},{self.taxAmount}\n" + return result + +class Buyer(BaseBuyer): + def __str__(self): + return f"buy,{self.orgid},{self.name},{self.city},{self.taxID}\n" + +class Seller(BaseSeller): + def __str__(self): + return f"sel,{self.orgid},{self.name},{self.city},{self.taxID}\n" + +class Tender(BaseTender): + def __str__(self): + return(f"tdr,{self.description},{self.amount},{self.type},{self.code} \n") + +class Article(BaseArticle): + + def __str__(self): + result = f"itm,{self.itemid},{self.description},{self.quantity},{self.unit},{self.salesPrice},{self.basePrice}\n" + for d in self.discounts: + result += str(d) + for t in self.taxes: + result += str(t) + return result \ No newline at end of file diff --git a/invoice_as_vrbl.py b/invoice_as_vrbl.py new file mode 100644 index 0000000..d6f5705 --- /dev/null +++ b/invoice_as_vrbl.py @@ -0,0 +1,361 @@ +from invoice_base import * +import xml.etree.ElementTree as ET +import re + + +class Invoice(BaseInvoice): + + def filter_elements_by_country(self, xml_string): + root = ET.fromstring(xml_string) + ET.register_namespace("ubl", "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2") + ET.register_namespace("cac", "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2") + ET.register_namespace("cbc", "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2") + ET.register_namespace("cec", "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2") + ET.register_namespace("vrbl", "urn:vertexinc:vrbl:ExtensionComponent:1") + + for parent in root.iter(): + for child in list(parent): + countries = child.attrib.get("countries") + + # No include attribute → keep element as-is + if countries is None: + continue + + values = [v.strip() for v in countries.split(",")] + + # Remove element if include does not contains the country + if 'not' in values: + if self.country() in values: + parent.remove(child) + else: + # Otherwise, remove only the include attribute + del child.attrib["countries"] + else: + if self.country() not in values: + parent.remove(child) + else: + # Otherwise, remove only the include attribute + del child.attrib["countries"] + + return ET.tostring(root, encoding="unicode", xml_declaration=True) + + def __str__(self): + self.totals.get_total_lines_netsalesprice() + taxestotal = '' + for x in self.taxes: + taxestotal += str(x) + allarticles = '' + for a in self.articles: + allarticles += str(a) + alltenders = '' + paymentTermText = '' + if ONLY_ONE_TENDER: + if len(self.tenders)>1: + paymentTermText = 'with ' + for t in self.tenders: + paymentTermText += f"{t.description}:{t.amount:.2f} " + alltenders += str(self.tenders[0]) + else: + for t in self.tenders: + alltenders += str(t) + + xml = f''' + + + + + VRBL:HR:{'P1' if self.totals.grandAmount>0 else 'P9'} + + {self.seller.taxID} + {self.seller.vrbl_receiver} + + true + + + + + urn:vertexinc:vrbl:billing:1 + urn:vertexinc:vrbl:billing:1#Invoice#VRBL-Invoice-HR-CIUS-1p0 + urn:vertexinc:vrbl:billing:1 + {self.nr} + false + {self.receipt.year}-{self.receipt.month}-{self.receipt.day} + {self.receipt.time_str} + {self.receipt.year}-{self.receipt.month}-{self.receipt.day} + 380 + {self.currency()} + + {self.receipt.store}{self.receipt.year}{self.receipt.month}{self.receipt.day}{self.receipt.till}{self.receipt.seq.zfill(6)} + + + { self.header.fiscalseq } + + + { self.header.get_taxref('JIR') } + JIR + + + { self.header.get_taxref('ZKI') } + ZKI + + + {self.seller} + + {self.buyer} + + {alltenders} + + + {self.receipt.year}-{self.receipt.month}-{self.receipt.day}. Settled in full {paymentTermText} + + + {taxestotal} + + + + {self.totals} + + {allarticles} + +''' + + return self.filter_elements_by_country(xml) + return xml + +class Discount(BaseDiscount): + def __str__(self): + return f''' + + false + 95 + {self.promotionID} + {self.net_amount():.2f} + +''' + +class Tax(BaseTax): + spaces = 'tax' + + def __str__(self): + return f"{self.spaces},{self.typesubtype},{self.code},{self.amount},{self.percentage}%,{self.translated_group()},{self.taxableamount}\n" + +class TotalTax(Tax): + def __str__(self): + zerovat = '' + if abs(self.amount)<0.001: + zerovat = "Not subject to VAT" + return f''' + + {self.amount:.2f} + + {self.taxableamount:.2f} + {self.amount:.2f} + + {self.translated_group()} + {self.percentage} + {zerovat} + + VAT + + + + + ''' + +class Header(BaseHeader): + pass + + +class Totals(BaseTotals): + def __str__(self): + return f''' + + + {self.totalLinesAmount:.2f} + {self.netAmount:.2f} + {(self.grandAmount - self.roundingAmount):.2f} + + {self.grandAmount:.2f} + {self.roundingAmount:.2f} + {self.grandAmount:.2f} + 0.00 + +''' + +class Receipt(BaseReceipt): + pass + + + +class Buyer(BaseBuyer): + + def id_schema(self, element): + return vrbl.translate(element, type='scheme', country=self._country()) + + def __str__(self): + phone = f'{self.phone}\n' if len(self.phone)>0 else '' + email = f'{self.email}\n' if len(self.email)>0 else '' + return f''' + + + {self.orgid} + + {self.orgid} + + + {self.name} + + + {self.street1} + {self.street2} + {self.city} + {self.zip} + + {self.country} + + + + {self.country}{self.taxID} + + VAT + + + + {self.name} + {self.orgid} + + + {self.name} + {phone} + {email} + + + +''' + +class Delivery(): + pass + +class Seller(BaseSeller): + def __str__(self): + return f''' + + {self.orgid} + {self.orgid} + + {self.orgid} + + {self.orgid} + + + {self.name} + + + {self.street1} + {self.street2} + {self.city} + {self.zip} + + {self.country} + + + + {self.taxID} + + VAT + + + + {self.name} + {self.legalid} + + + Customer service + + + +''' + +class Tender(BaseTender): + + def translate(self, code): + return '54' # credit card + + def __str__(self): + return f''' + + {self.translated_type()} + +''' + +class Article(BaseArticle): + def __str__(self): + discounts = '' + for d in self.discounts: + discounts += str(d) + + return f''' + + {int(self.sequence) + 1} + {self.line_uuid()} + {self.description} + {'-' if self.returnflag else ''}{self.quantity} + + {self.netSalesPrice():.2f} + + {self.tax.amount:.2f} + + + + {discounts} + + {self.description} + {self.description} + + {self.itemid} + + + {self.upc} + + + {self.upc} + + + 47.71.00 + + + {self.tax.translated_group()} + {self.tax.percentage} + + VAT + + + + + {self.netBasePrice():.2f} + {self.quantity} + + + + + + + + {self.netBasePrice():.2f} + + + + + {self.netSalesPrice():.2f} + + +''' diff --git a/invoice_base.py b/invoice_base.py new file mode 100644 index 0000000..519c000 --- /dev/null +++ b/invoice_base.py @@ -0,0 +1,427 @@ +from pprint import pprint +from translations import Translations +from localconfig import * +import re +import itertools + +vrbl = Translations() + +def before_tax(grossAmount, taxPercentage): + return round(grossAmount / (100.0 + taxPercentage) * 100.0, 2) + +class BaseInvoice(): + def __init__(self, nr, country): + self.nr = nr + self.process_country = country + self.buyer = None + self.seller = None + self.receipt = None + self.header = None + self.totals = None + self.tenders = [] + self.articles = [] + self.taxes = [] + self.poslogid = '' + + def add_receipt(self, receipt): + self.receipt = receipt + + def add_header(self, header): + self.header = header + + def add_totals(self, totals): + totals.set_parent(self) + self.totals = totals + + def add_buyer(self, organization, source): + if organization is not None: + organization.set_source(source) + organization.set_parent(self) + self.buyer = organization + + def add_seller(self, organization): + self.seller = organization + + def add_tax(self, tax): + tax.set_parent(self) + self.taxes.append(tax) + + def total_taxes(self): + total = 0.0 + for t in self.taxes: + total += t.amount + return total + + def add_article(self, article): + article.set_parent(self) + self.articles.append(article) + + def add_tender(self, tender): + tender.set_parent(self) + self.tenders.append(tender) + + def get_total_lines_netsalesprice(self): + total = 0.0 + for a in self.articles: + total += a.netSalesPrice() + return total + + def roundingAllowed(self): + if self.seller: + return self.seller.roundingAllowed + return 0 + + def fuck_prices_of_first_item_to_avoid_rounding(self, roundingamount): + log(f"Receipt {self.receipt.id()}: Avoid rounding of {roundingamount:.2f} by updating max {len(self.articles)} articles.") + article_cycle = itertools.cycle(self.articles) + cents_to_round = int(round((roundingamount * 100),0)) + number_of_tries = cents_to_round + len(self.articles) + for a in article_cycle: + # print(f" === {cents_to_round} {number_of_tries}") + cents_to_round -= a.increasePrices((cents_to_round / abs(cents_to_round))) + number_of_tries -= 1 + if cents_to_round == 0 or number_of_tries == 0: + break + + + + def currency(self): + return self.header.currency + + def country(self): + return self.header.country + + def receipt_id(self): + return self.receipt.id() + + + # def update_currency(self, newcurrency): + # self.currency = newcurrency + # # if self.sales: + # # self.sales.update_currency(newcurrency) + + def __str__(self): + result = f"==={'CREDITNOTE ' if self.debit else 'SALE'}=================================================\n" + result += f"{self.nr} '{self.storename}' {self.sales}\n" + if self.seller: + result += str(self.seller) + else: + result += "[ == no country / PVH-ofice found ==]\n" + if self.buyer: + result += str(self.buyer) + for a in self.articles: + result += str(a) + for t in self.tenders: + result += str(t) + for x in self.taxes: + result += str(x) + return result + +class BaseDiscount(): + """ + Docstring for Discount + """ + def __init__(self, idtext, action, amount, reasoncode): + self.promotionID = idtext + self.action = action #substract or add + self.amount = float(amount) + self.reasoncode = reasoncode + self.sales = None + self.parent = None + + def set_parent(self, parent): + self.parent = parent + + def currency(self): + return self.parent.currency() + + def net_amount(self): + return before_tax(self.amount, self.parent.taxpercentage()) + + def __str__(self): + return(f" {self.promotionID} {self.action} {self.amount} {self.reasoncode}\n") + +class BaseTax(): + """ + Docstring for tax + """ + spaces = ' ' + + def __init__(self, typesubtype, code, amount, percentage, group, taxincludedamount): + self.typesubtype = typesubtype + self.code = code + self.amount = float(amount) + self.percentage = float(percentage) + self.group = group # GK / SAP taxcodes + self.taxincludedamount = float(taxincludedamount) + self.taxableamount = self.taxincludedamount - self.amount # net price + self.parent = None + + def translated_group(self): + return vrbl.translate(self.group, type='tax', country=self.country()) + + def set_parent(self, parent): + self.parent = parent + + def currency(self): + return self.parent.currency() + + def country(self): + return self.parent.country() + + def __str__(self): + return f"{self.spaces}{self.typesubtype} {self.code} {self.amount} {self.percentage}% {self.translated_group()} {self.taxableamount}\n" + + +class BaseTotalTax(BaseTax): + ''' + Docstring for Totaltax + ''' +pass + +class BaseHeader(): + """ + will hold the invoice header info + """ + + def __init__(self, country, brand, curreny, is_debit, is_return, is_postvoided, loyalty_nr, fiscalseq, is_fiscal, fiscalprinter): + self.country = country + self.brand = brand + self.currency = curreny + self.is_debit = is_debit + self.is_return = is_return + self.is_voided = is_postvoided + self.loyalty = loyalty_nr + self.fiscalseq = fiscalseq + self.is_fiscal = is_fiscal + self.fiscalprinter = fiscalprinter + self.taxref = {} + + def add_taxref(self, key, value): + self.taxref[key] = value + + def get_taxref(self, key): + if key in self.taxref: + return self.taxref[key] + return '' + + def __str__(self): + return f"{self.country} {self.brand} {self.currency} " + + +class BaseReceipt(): + """ + will hold the receipt identification + """ + + + def __init__(self, store, year, month, day, till, seq): + self.store = store + self.year = year + self.month = month + self.day = day + self.till = till + self.seq = seq + self.time_str = '' + + + + def id(self): + return f"{self.store}{self.year}{self.month}{self.day}{self.till}{self.seq.zfill(3)}" + + def __str__(self): + return f"{self.id()}\n" + + def add_time(self, hhmmss_with_colons): + self.time_str = hhmmss_with_colons + +class BaseTotals(): + """ + will hold the finiancial totals + """ + + + def __init__(self, grand, net, tax): + self.grandAmount = float(grand) + self.netAmount = float(net) + self.taxAmount = float(tax) + self.totalLinesAmount = self.netAmount + self.roundingAmount = 0.0 + self.parent = None + + def set_parent(self, parent): + self.parent = parent + + def currency(self): + return self.parent.currency() + + def get_total_lines_netsalesprice(self): + self.totalLinesAmount = self.parent.get_total_lines_netsalesprice() + # print(f" ---- {self.parent.country()} {self.parent.roundingAllowed()} {type(self.parent.roundingAllowed())}") + if self.parent.roundingAllowed(): + self.roundingAmount = self.netAmount - self.totalLinesAmount + else: + roundingamount = self.netAmount - self.totalLinesAmount + if abs(roundingamount) > 0.001: + self.parent.fuck_prices_of_first_item_to_avoid_rounding(roundingamount) + self.totalLinesAmount += roundingamount + + def __str__(self): + return f"{self.grandAmount} {self.netAmount}{self.taxAmount}\n" + +class BaseOrganization(): + ''' + will hold the organizations detail, can be buyer or seller(PVH) + ''' + def __init__(self, orgid, name, city, name2='', street1='', street2='', zip='', country='EU', taxid='0', scheme=DEFAULTCUSTSCHEME, phone='', email='', legalid='', vrbl_receiver='BASE_VRBL', minimum=0.0, orgidlength=0, taxidlength=0, roundingAllowed=1): + self.orgid = orgid + self.scheme = scheme + self.name = name + self.name2 = name2 + self.street1 = street1 + self.street2 = street2 + self.zip = zip + self.city = city + self.country = country + self.taxID = taxid + self.legalid = legalid + self.phone = phone + self.email = email + self.vrbl_receiver = vrbl_receiver + self.source = '' + self.minimum = float(minimum) + self.orgidlength = int(orgidlength) + self.taxidlength = int(taxidlength) + self.roundingAllowed = int(roundingAllowed) # 0: distribute rounding diffs over the items + self.parent = None + + def set_source(self, source): + self.source = source + + def set_parent(self, parent): + self.parent = parent + + def __str__(self): + return f" {self.orgid} {self.name} {self.city} {self.taxID}\n" + +class BaseBuyer(BaseOrganization): + def update(self, buyerdata): + self.orgid = buyerdata['OrgId'] + self.name = buyerdata['Organization'] + self.zip = buyerdata['Zip'] + self.city = buyerdata['City'] + self.country = buyerdata['Country'] + self.taxID = buyerdata['TaxId'] + self.street1 = buyerdata['Street'] + + def _country(self): + return self.country if len(self.country)>1 else self.parent.country() + + def shorttxt(self): + return f"{self.orgid}, {self.name}, {self.zip}, {self.country}, {self.taxID}, {self.email}, {self._country()}" + + def repair_and_check_if_data_is_broken(self): + orgid_as_number = re.sub(r"\D", "", self.orgid) + if len(orgid_as_number)<=2 and len(self.orgid)>=6 and len(self.name)<=1: + self.name = self.orgid + self.orgid = '' + else: + self.orgid = orgid_as_number + self.taxID = re.sub(r"\D", "", self.taxID) + if self.orgid == '0' or self.orgid== '1' or self.orgid == '': + self.orgid = self.taxID + if len(self.country)==0: + self.country = self._country() + # print(f"{len(self.name)<2} or {len(self.city)<2} or {len(self.zip)<2} or {(self.country not in EU_COUNTRIES)} or {len(self.orgid)!=self.parent.seller.orgidlength} or {len(self.taxID)!=self.parent.seller.taxidlength}") + return (len(self.name)<2 or len(self.city)<2 or len(self.zip)<2 or (self.country not in EU_COUNTRIES) or len(self.orgid)!=self.parent.seller.orgidlength or len(self.taxID)!=self.parent.seller.taxidlength) + +class BaseSeller(BaseOrganization): + pass + +class BaseTender(): + ''' + payment-line + ''' + def __init__(self, description, amount, type, code, currency=None): + self.description = description + self.type = type + self.code = code + self.amount = float(amount) + self.my_currency = currency + self.parent = None + + def set_parent(self, parent): + self.parent = parent + + def translated_type(self): + return vrbl.translate(self.type, type='tender', country=self.country()) + + def country(self): + return self.parent.country() + + def __str__(self): + return(f" {self.description} {self.amount} {self.translated_type} {self.code} \n") + +class BaseArticle(): + ''' + article info + ''' + + def __init__(self, sequence, returnflag, itemid, upc, description, quantity, unit, basePrice, salesPrice): + self.sequence = sequence + self.returnflag = returnflag + self.itemid = itemid + self.upc = upc + self.description = description + self.quantity = quantity + self.unit = unit + self.basePrice = float(basePrice) # incl tax, before discounts + self.salesPrice = float(salesPrice) # incl tax, after discounts + self.discounts = [] + self.tax = None + self.parent = None + self.priceIncreaseForRounding = 0.0 + + def set_parent(self, parent): + self.parent = parent + + def add_discount(self, discount): + discount.set_parent(self) + self.discounts.append(discount) + + def add_tax(self, tax): + tax.set_parent(self) + self.tax = tax + + def currency(self): + return self.parent.currency() + + def country(self): + return self.parent.country() + + def taxpercentage(self): + return self.tax.percentage + + def netBasePrice(self): + return before_tax(self.basePrice, self.tax.percentage) + self.priceIncreaseForRounding + + def netSalesPrice(self): + return before_tax(self.salesPrice, self.tax.percentage) + self.priceIncreaseForRounding + + + def line_uuid(self): + return f"{self.parent.receipt_id()}{self.sequence.zfill(5)}" + + def increasePrices(self, roundingamount): + if self.netSalesPrice() - self.priceIncreaseForRounding - (roundingamount / 100) > 0.0: + self.priceIncreaseForRounding += (roundingamount / 100) + return roundingamount + return 0 + + def __str__(self): + result = f" {self.itemid} {self.description} {self.quantity} {self.unit} {self.salesPrice} [{self.basePrice}]\n" + for d in self.discounts: + result += str(d) + for t in self.taxes: + result += str(t) + return result \ No newline at end of file diff --git a/lib_poslog.py b/lib_poslog.py new file mode 100644 index 0000000..fe21ff3 --- /dev/null +++ b/lib_poslog.py @@ -0,0 +1,358 @@ +from collections import defaultdict +import xml.etree.ElementTree as ET +import os, re +from pprint import pprint +from localconfig import * +from invoice_as_vrbl import * # lib offices also has a reference to Seller +from stores import Stores +from offices import Offices +from repairedbuyers import RepairedBuyers +from datetime import datetime +import base64 + +SORTED_PATH = os.path.join(BASEPATH, "Sorted") + +till_seq_from_filename = r'^[^_]+_T([^_]+)_[^_]+_([^_.]+)' +storenames = Stores() +offices = Offices() +repairedbuyers = RepairedBuyers() + + +def etree_to_dict(t): + t_tag = t.tag + if '}' in t_tag: + t_tag = t_tag.split('}',1)[1] + d = {t_tag: {} if t.attrib else None} + children = list(t) + if children: + dd = defaultdict(list) + for dc in map(etree_to_dict, children): + for k, v in dc.items(): + dd[k].append(v) + d = {t_tag: {k:v[0] if len(v) == 1 else v for k, v in dd.items()}} + if t.attrib: + d[t_tag].update(('@' + k, v) for k, v in t.attrib.items()) + if t.text: + text = t.text.strip() + if children or t.attrib: + if text: + d[t_tag]['#text'] = text + else: + d[t_tag] = text + return d + +def search_dictlist(d, k, v): + return next((sub for sub in d if sub[k] == v), None) + +def escape_quotes(txt): + if txt and '"' in txt: + return f'"{txt.replace('"','\'')}"' + return txt + +def get_value_from_addon(treex, key): + result = 'XX' + for ao in treex['Addon']: + if ao['Key']==key: + result = ao['Value'] + + return result + +def get_value_from_binary_data(treex, key): + result = '' + for ao in treex['BinaryData']: + if ao['Name']==key: + result = ao['Content'] + if len(result)>1: + result = base64.b64decode(result).decode("utf-8") + return result + +def escape(xmlcontent): + if xmlcontent: + return xmlcontent.replace('&','&').replace('>','>').replace('<','<') + return '' + +def get_elm_value(tree, name, default=''): + names = name.split('/') + if names[0] in tree: + if len(names) > 1: + return get_elm_value(tree[names[0]], '/'.join(names[1:]), default) + return escape(tree[name]) + return default + +def dump_buyer_info(buyer, invoice_ref, receipt_ref, p_country): + if buyer: + message = f"{p_country},{invoice_ref},{receipt_ref},{buyer.orgid},{buyer.taxID},{buyer.name},{buyer.city},{buyer.street1},{buyer.zip},{buyer.country}\n" + with open(BUYERS_BROKEN, "a", encoding="utf-8") as lfile: + lfile.write(message) + +def get_seller_from_country(countrycode): + row = offices.get_office_details(countrycode) + return Seller(row['PartyId'], row['Name'], row['City'], taxid=row['TaxId'], + street1=row['Street1'], street2=row['Street2'], zip=row['Zip'], + country=row['Country'], scheme=row['PartyScheme'], + legalid=row['LegalId'], vrbl_receiver=row['VRBL'],minimum=row['MinimumAmount'], + orgidlength=row['orgidlength'], taxidlength=row['taxidlength'], roundingAllowed=row['roundingAllowed']) + + +def get_customer_from_dict(trx): + cID = cfullname = ccity = ctaxID = cstreet1 = czip = ccountry = cphone = cemail = '' + cFound = False + if 'Customer' in trx: + cID = get_elm_value(trx['Customer'],'CustomerID') + cfullname = get_elm_value(trx['Customer'],'CustomerName/FullName') + ccity = get_elm_value(trx['Customer'],'Address/City') + cstreet1 = get_elm_value(trx['Customer'],'Address/AddressLine/#text') + czip = get_elm_value(trx['Customer'],'Address/PostalCode') + ccountry = get_elm_value(trx['Customer'],'Address/Country') + ctaxID = get_elm_value(trx['Customer'],'CustomerTaxID') + cphone = get_elm_value(trx['Customer'],'Telephone/FullTelephoneNumber') + if not cphone: + cphone = get_elm_value(trx['Customer'],'Telephone/0/FullTelephoneNumber') + cemail = get_elm_value(trx['Customer'],'EMail/EMailAddress') + + # if a @ in the companyname, then the taxid has to come from the fulname + if len(ctaxID)<1 and '@' in cfullname: + cfullname, ctaxID = cfullname.split('@', 1) + + cust = Buyer(cID, cfullname, ccity, taxid=ctaxID, street1=cstreet1, zip=czip, country=ccountry, phone=cphone, email=cemail) + + return cust + return None + +def get_trxlink_from_dict(trx): + link = {} + if 'TransactionLink' in trx: + if 'RetailStoreID' in trx['TransactionLink']: + link['store'] = trx['TransactionLink']['RetailStoreID'] + if 'WorkstationID' in trx['TransactionLink']: + link['till'] = trx['TransactionLink']['WorkstationID'] + if 'SequenceNumber' in trx['TransactionLink']: + link['seq'] = trx['TransactionLink']['SequenceNumber'] + if 'BusinessDayDate' in trx['TransactionLink']: + link['date'] = trx['TransactionLink']['BusinessDayDate'] + if len(link) == 4: + link['year'], link['month'], link['day'], dummy = link['date'].replace('-','_').replace('+','_').split('_') + + return link + + +def process_receipt(invoice): + receipt_filename = f"{invoice.receipt.store}_T{invoice.receipt.till}_{invoice.receipt.year[2:]}{invoice.receipt.month}{invoice.receipt.day}_{invoice.receipt.seq}.xml" + p = os.path.join(SORTED_PATH, invoice.receipt.year, invoice.receipt.month, invoice.receipt.day, invoice.receipt.store, receipt_filename) + if os.path.exists(p): + e = ET.parse(p) + root = e.getroot() + tree = etree_to_dict(root) + trx = tree['POSLog']['Transaction']['RetailTransaction'] + + # 2026-01-10T15:03:18.594+01:00" + dt_iso = get_elm_value(trx, 'ReceiptDateTime') + dt = datetime.fromisoformat(dt_iso) # timezone-aware datetime + invoice.receipt.add_time(dt.astimezone().strftime("%H:%M:%S")) + + # add header brand, store, currency, debitnote + country = get_value_from_addon(tree['POSLog']['Transaction']['ReceiptHeaderAddonList'], 'PVHCountry') + brand = get_value_from_addon(tree['POSLog']['Transaction']['ReceiptHeaderAddonList'], 'PVHBrand') + curr = get_elm_value(tree['POSLog']['Transaction'],'CurrencyCode') + isreturn = get_elm_value(tree['POSLog']['Transaction'],'ReceiptReturnedFlag') + postvoided = get_elm_value(tree['POSLog']['Transaction'],'PostVoidedFlag') + loyalty = get_elm_value(tree['POSLog']['Transaction'],'LoyaltyAccount/CustomerID') + fiscalseq = get_elm_value(tree['POSLog']['Transaction'],'FiscalSequenceNumber') + isfiscal = get_elm_value(tree['POSLog']['Transaction'],'FiscalFlag') + fiscalprinter = get_elm_value(tree['POSLog']['Transaction'],'FiscalPrinterID') + is_debit = False + if 'NegativeTotalFlag' in trx: + if trx['NegativeTotalFlag'] == 'true': + is_debit = True + invoice.add_header(Header(country, brand, curr, is_debit, isreturn, postvoided, loyalty, fiscalseq, isfiscal, fiscalprinter)) + + # for some countries you may need to add tax-references + if country == 'HR': + invoice.header.add_taxref('ZKI',get_value_from_binary_data(tree['POSLog']['Transaction']['TransactionBinaryDataList'], 'FISCALIZATION_RECEIPT_SECURITY')) + invoice.header.add_taxref('JIR',get_value_from_binary_data(tree['POSLog']['Transaction']['TransactionBinaryDataList'], 'FISCALIZATION_RECEIPT_FISCAL_CODE')) + + # add totals + if 'Total' in trx: + grand = net = vat = 0.0 + for e in trx['Total']: + if e['@TotalType'] == 'TransactionGrandAmount': + grand = e['#text'] + elif e['@TotalType'] == 'TransactionNetAmount': + net = e['#text'] + elif e['@TotalType'] == 'TransactionTaxAmount': + vat = e['#text'] + if 'NegativeTotalFlag' in trx and trx['NegativeTotalFlag'] == 'true': + grand = '-' + grand + net = '-' + net + vat = '-' + vat + invoice.add_totals(Totals(grand, net, vat)) + + # add buyer, if noit there yet + if not invoice.buyer: + invoice.add_buyer(get_customer_from_dict(trx), 'receipt') + + # add seller + invoice.add_seller(get_seller_from_country(invoice.process_country)) + + # add salesitesm, tenders and totalstaxes + if 'LineItem' in trx: + for i in trx['LineItem']: + sequence = 0 + if 'SequenceNumber' in i: + sequence = i['SequenceNumber'] + + if i['@VoidFlag']=='false': + if 'Sale' in i or 'Return' in i: + returnflag = False + if 'Sale' in i: + s = i['Sale'] + else: + s = i['Return'] + returnflag = True + + positemid = '' + if type(s['POSIdentity']) is list: + positemid = s['POSIdentity'][-1]['POSItemID'] + else: + positemid = s['POSIdentity']['POSItemID'] + + itemidtext = '' + if '#text' in s['ItemID']: + itemidtext = s['ItemID']['#text'] + elif 'SpecialOrderNumber' in s: + itemidtext = 'Order ' + s['SpecialOrderNumber'] + + article = Article(sequence, returnflag, itemidtext, positemid, escape(s['Description']), s['Quantity']['#text'], s['Quantity']['@UnitOfMeasureCode'], s['RegularSalesUnitPrice']['#text'], s['ExtendedAmount']) + # discount + if 'RetailPriceModifier' in s: + discElm = s['RetailPriceModifier'] + if type(discElm) is list: + for d in discElm: + article.add_discount(Discount(get_elm_value(d,'PromotionID'),d['Amount']['@Action'],d['Amount']['#text'],d['ReasonCode'])) + else: + article.add_discount(Discount(get_elm_value(discElm, 'PromotionID'),discElm['Amount']['@Action'],discElm['Amount']['#text'],discElm['ReasonCode'])) + if 'Tax' in s: + t = s['Tax'] + article.add_tax(Tax(f"{t['@TaxSubType']}.{t['@TaxType']}",t['@TypeCode'],t['Amount'],t['Percent'],t['TaxGroupID'],t['TaxableAmount'])) + invoice.add_article(article) + elif 'Tender' in i: + t = i['Tender'] + invoice.add_tender(Tender(escape(t['@TenderDescription']), t['Amount'], t['@TenderType'], t['@TypeCode'])) + elif 'Tax' in i: + t = i['Tax'] + invoice.add_tax(TotalTax(f"{t['@TaxSubType']}.{t['@TaxType']}",t['@TypeCode'],t['Amount'],t['Percent'],t['TaxGroupID'],t['TaxableAmount'])) + + else: + log(f"No linked receipt file found for {receipt_filename}",2) + return None + return invoice + + +def process_invoice_request(filepath): # csv-line(str) + invoice = None + customer = {} + receipt = {} + invoiceNumber = '' + e = ET.parse(filepath) + root = e.getroot() + tree = etree_to_dict(root) + trx = tree['POSLog']['Transaction']['RetailTransaction'] + + # this incoice request can have a customer or not (if not , the customer info comes from the receipt) + # get the receipt-id + store = date = till = seq = '' + + if 'InvoiceNumber' in trx: + trx_link = get_trxlink_from_dict(trx) + if len(trx_link) > 1: + country = storenames.country_for(trx_link['store']) + + invoice = Invoice(trx['InvoiceNumber'], country) + invoice.poslogid = os.path.basename(filepath).replace('.xml', '') + invoice.add_receipt(Receipt(trx_link['store'], trx_link['year'], trx_link['month'], trx_link['day'], trx_link['till'], trx_link['seq'])) + invoice.add_buyer(get_customer_from_dict(trx), 'invoice') + invoice = process_receipt(invoice) + + if invoice is not None: + # repair the buyerdata + repairedBuyerData = repairedbuyers.get_buyer_for(invoice.poslogid) + if repairedBuyerData: + invoice.buyer.update(repairedBuyerData) + else: + log(f"Invoice reuest {filepath} does not have a related sales",2) + else: + log(f"Invoice Request {filepath} doen NOT have an invoice number",2) + return invoice + + +def file_has_invoice(filename): + transactiontytpe = '' + with open(filename, 'r', encoding='utf-8') as f: + while line := f.readline(): + if transactiontytpe in line: + return True + return False + +def file_has_sales(filename): + transactiontytpe = '' + with open(filename, 'r', encoding='utf-8') as f: + while line := f.readline(): + if transactiontytpe in line: + return True + return False + +def find_invoices_in_storeday(store, year, month, day): + invoices_fine = [] + invoices_broken = [] + broken_buyer = 0 + invoices_found = False + # find files existing in NEW, but not in PRD + folder = os.path.join(SORTED_PATH, year, month, day, store) + for root, dirs, files in os.walk(folder): + for file in files: + if (store in file) and '_T000_' in file and file.endswith(".xml"): + filepath = os.path.join(root, file) + if file_has_invoice(filepath): + # print(f"found file {root} {file}") + m = re.search(till_seq_from_filename, file) + if m: + till, seq = m.groups() + invoices_found = True + invoice = process_invoice_request(filepath) + # ok we have an invoice, now lets check if we should/can send it to ecosio + if invoice is not None: + if invoice.buyer is not None: + if abs(invoice.totals.grandAmount) > invoice.seller.minimum: + # only invoice if seller and buyer are fron the same country. also try to invoice if there is an non-recognized country + if invoice.buyer.country == invoice.country() or invoice.buyer.country not in EU_COUNTRIES: + if invoice.buyer.repair_and_check_if_data_is_broken(): + # add to broken buyerdata + broken_buyer += 1 + log(f"receipt {invoice.receipt.id()}: buyer has insufficient details - repair before export",2) + dump_buyer_info(invoice.buyer, invoice.poslogid, invoice.receipt.id(), invoice.country()) + invoices_broken.append(invoice) + else: + invoices_fine.append(invoice) + else: + log(f"Invoice {invoice.poslogid}: Buyer country {invoice.buyer.country} does not match company country {invoice.country()}",1) + else: + log(f"Invoice {invoice.poslogid}: grandTotal {invoice.totals.grandAmount} not enough for invoicing.") + else: + log(f"Invoice {invoice.poslogid} has not a valid buyer - cannot export",2) + + + # if not invoices_found: + # log(f"No invoices found for {store}, {year}-{month}-{day}") + + return invoices_fine, invoices_broken + + +if __name__ == '__main__': + # several_i, broken_i = find_invoices_in_storeday("AN03","2026","02","06") + # several_i, broken_i = find_invoices_in_storeday("A100","2026","02","06") + several_i, broken_i = find_invoices_in_storeday("AN19","2026","02","10") + for i in several_i: + # print(str(i)) + a = str(i) + # for i in broken_i: + # print(str(i)) \ No newline at end of file diff --git a/localconfig.py b/localconfig.py new file mode 100644 index 0000000..9a34ace --- /dev/null +++ b/localconfig.py @@ -0,0 +1,47 @@ +import os +import datetime + +DEBUG = True +TEST = True + +INVOICE_SERVICE = "http://127.0.0.1:9666/invoice/api/" +# INVOICE_SERVICE = "http://127.0.0.1:11122/invoice/api/" + +BASEPATH = os.path.join('C:\\','Users','isuy','LocalDocs','WatcherArchive') +# BASEPATH = os.path.join('D:\\','WatcherArchive') + +ONLY_ONE_TENDER = True +AVOID_ROUNDING = True + +COLUMNS_REQUEST = ['Filename','InvoiceNumber'] +COLUMNS_CUSTOMER = ['CustomerID','CustomerName','City','CustomerTaxID','Street'] +COLUMNS_SALES = ['TransactionNetAmount','TransactionTaxAmount','TransactionGrandAmount','payment','tender','goods'] +COLUMNS_ALL = COLUMNS_REQUEST + COLUMNS_CUSTOMER + COLUMNS_SALES + +DEFAULTCUSTSCHEME = 'VRBL:PL:TAX' + +DATADIR = 'data' +STORESFILE = os.path.join(DATADIR,"stores_to_invoice.csv") +OFFICESFILE = os.path.join(DATADIR,"offices.csv") +LOGFILE = "log.txt" +TRANSLATIONSFILE = os.path.join(DATADIR,"translations.csv") +BUYERS_REPAIRED = os.path.join(DATADIR,'buyersdata_repaired.csv') +BUYERS_BROKEN = os.path.join(DATADIR,'buyersdata_broken.csv') +EARLIEST_DATE_FILE = os.path.join(DATADIR,'dontprocessbefore.txt') + +ECOSIO_PATH = os.path.join(BASEPATH, "Ecosio") +SORTED_PATH = os.path.join(BASEPATH, "Sorted") +DONE_PATH = os.path.join(ECOSIO_PATH, "downloaded") + +EU_COUNTRIES = ['AD','AL','AT','BA','BE','BG','BY','CH','CY','CZ','DE','DK','EE','ES','FI','FR','GB','GR','HR','HU','IE','IS','IT','LI','LT','LU','LV','MC','MD','ME','MK','MT','NL','NO','PL','PT','RO','RS','RU','SE','SI','SK','SM','TR','UA','VA','XX'] + +LOGLEVELS = ['INFO','WARNING','ERROR','FATAL'] + +def log(txt, loglevel=0): + now = datetime.datetime.now() + message = f"{now} - {LOGLEVELS[loglevel]} {txt}\n" + with open(LOGFILE, "a") as lfile: + lfile.write(message) + if DEBUG: + print(message) + diff --git a/log.txt b/log.txt new file mode 100644 index 0000000..0f332bf --- /dev/null +++ b/log.txt @@ -0,0 +1,983 @@ +2026-02-16 09:02:32.547618 - INFO - Invoice A296_T000_260202_7: grandTotal -120.0 not enough for invoicing. +2026-02-16 09:02:32.564203 - INFO - Invoice A299_T000_260202_1: grandTotal 149.0 not enough for invoicing. +2026-02-16 09:02:32.788109 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-16 09:02:33.075665 - ERROR - receipt A17720260203101048: buyer has insufficient details - repair before export +2026-02-16 09:02:33.496669 - ERROR - receipt A11520260203101038: buyer has insufficient details - repair before export +2026-02-16 09:02:33.717272 - ERROR - receipt A27520260110101225: buyer has insufficient details - repair before export +2026-02-16 09:02:33.729982 - ERROR - receipt A27520260128101030: buyer has insufficient details - repair before export +2026-02-16 09:02:33.893134 - WARNING - Invoice A944_T000_260205_19: Buyer country SI does not match company country HR +2026-02-16 09:02:34.540336 - INFO - Invoice A279_T000_260205_1: grandTotal -296.0 not enough for invoicing. +2026-02-16 09:02:34.654865 - INFO - Invoice A900_T000_260205_1: grandTotal 356.0 not enough for invoicing. +2026-02-16 09:02:34.664892 - INFO - Invoice A900_T000_260205_2: grandTotal 205.0 not enough for invoicing. +2026-02-16 09:02:34.675414 - INFO - Invoice A900_T000_260205_5: grandTotal 276.0 not enough for invoicing. +2026-02-16 09:02:34.956256 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 09:02:35.014710 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 09:02:35.124100 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 09:02:35.152307 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 09:02:35.707588 - INFO - Invoice A111_T000_260206_1: grandTotal -150.3 not enough for invoicing. +2026-02-16 09:02:35.724416 - INFO - Invoice A149_T000_260206_1: grandTotal 375.9 not enough for invoicing. +2026-02-16 09:02:35.787845 - ERROR - receipt A94720260206102152: buyer has insufficient details - repair before export +2026-02-16 09:02:36.162698 - INFO - Invoice A108_T000_260207_1: grandTotal 192.8 not enough for invoicing. +2026-02-16 09:02:36.185982 - INFO - Invoice A110_T000_260207_1: grandTotal 159.0 not enough for invoicing. +2026-02-16 09:02:36.433282 - INFO - Avoid rounding of 0.02 by updating max 5 articles. +2026-02-16 09:02:36.639987 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:36.707507 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:36.731484 - INFO - Avoid rounding of -0.01 by updating max 7 articles. +2026-02-16 09:02:36.776702 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:36.862515 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:36.887122 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 09:02:36.908310 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 09:02:36.933075 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:37.007118 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:37.030630 - INFO - Avoid rounding of -0.01 by updating max 6 articles. +2026-02-16 09:02:37.052199 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 09:02:37.172132 - ERROR - receipt AN0320260104101097: buyer has insufficient details - repair before export +2026-02-16 09:02:37.210779 - INFO - Avoid rounding of 0.03 by updating max 11 articles. +2026-02-16 09:02:37.352841 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-16 09:02:37.435441 - INFO - Avoid rounding of 0.01 by updating max 5 articles. +2026-02-16 09:02:37.460804 - INFO - Avoid rounding of -0.02 by updating max 9 articles. +2026-02-16 09:02:37.524666 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 09:02:37.573306 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:37.603480 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 09:02:37.653745 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:37.678669 - INFO - Avoid rounding of 0.01 by updating max 10 articles. +2026-02-16 09:02:37.911070 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 09:02:38.111868 - ERROR - receipt A90020260207101020: buyer has insufficient details - repair before export +2026-02-16 09:02:38.178737 - INFO - Invoice A102_T000_260209_1: grandTotal -129.0 not enough for invoicing. +2026-02-16 09:02:38.187313 - INFO - Invoice A102_T000_260209_2: grandTotal -129.0 not enough for invoicing. +2026-02-16 09:02:38.431752 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 09:02:38.500246 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 09:02:38.565964 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:38.762526 - INFO - Avoid rounding of 0.03 by updating max 12 articles. +2026-02-16 09:02:38.840592 - WARNING - Invoice AN20_T000_260210_30: Buyer country XX does not match company country BE +2026-02-16 09:02:38.846673 - WARNING - Invoice AN20_T000_260210_31: Buyer country XX does not match company country BE +2026-02-16 09:02:38.922827 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:39.122224 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-16 09:02:39.165704 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-16 09:02:39.359131 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:39.420426 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-16 09:02:39.468471 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 09:02:39.583824 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 09:02:39.608866 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 09:02:39.671985 - INFO - Avoid rounding of 0.02 by updating max 23 articles. +2026-02-16 09:02:39.842933 - INFO - Invoice A902_T000_260210_1: grandTotal -142.4 not enough for invoicing. +2026-02-16 09:02:39.869466 - ERROR - receipt A90020260209102177: buyer has insufficient details - repair before export +2026-02-16 09:02:39.877839 - INFO - Invoice A900_T000_260210_2: grandTotal 419.0 not enough for invoicing. +2026-02-16 09:02:39.884914 - INFO - Invoice A900_T000_260210_3: grandTotal 265.6 not enough for invoicing. +2026-02-16 09:02:39.890831 - ERROR - receipt A90020260207101116: buyer has insufficient details - repair before export +2026-02-16 09:02:39.957991 - INFO - Invoice A109_T000_260210_1: grandTotal 139.0 not enough for invoicing. +2026-02-16 09:02:40.190174 - INFO - Avoid rounding of 0.01 by updating max 4 articles. +2026-02-16 09:02:40.216610 - INFO - Avoid rounding of -0.02 by updating max 16 articles. +2026-02-16 09:02:40.634082 - ERROR - receipt A11120260124102125: buyer has insufficient details - repair before export +2026-02-16 09:02:41.000218 - ERROR - receipt A29420260212102022: buyer has insufficient details - repair before export +2026-02-16 09:02:41.046666 - INFO - Invoice A902_T000_260212_1: grandTotal 376.0 not enough for invoicing. +2026-02-16 09:02:41.217929 - INFO - Invoice A112_T000_260212_1: grandTotal 164.0 not enough for invoicing. +2026-02-16 09:02:41.845358 - ERROR - receipt AN2320260214101024: buyer has insufficient details - repair before export +2026-02-16 09:02:41.905619 - ERROR - receipt F00U20260214101194: buyer has insufficient details - repair before export +2026-02-16 09:02:41.922402 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 09:02:42.202894 - INFO - Invoice A149_T000_260214_1: grandTotal 238.0 not enough for invoicing. +2026-02-16 11:47:55.537047 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-16 11:47:55.824230 - ERROR - receipt A17720260203101048: buyer has insufficient details - repair before export +2026-02-16 11:47:56.246583 - ERROR - receipt A11520260203101038: buyer has insufficient details - repair before export +2026-02-16 11:47:56.429146 - ERROR - receipt A27520260110101225: buyer has insufficient details - repair before export +2026-02-16 11:47:56.441620 - ERROR - receipt A27520260128101030: buyer has insufficient details - repair before export +2026-02-16 11:47:56.537532 - WARNING - Invoice A944_T000_260205_19: Buyer country SI does not match company country HR +2026-02-16 11:47:56.883963 - INFO - Invoice A279_T000_260205_1: grandTotal -296.0 not enough for invoicing. +2026-02-16 11:47:57.000354 - INFO - Invoice A900_T000_260205_1: grandTotal 356.0 not enough for invoicing. +2026-02-16 11:47:57.045980 - INFO - Invoice A900_T000_260205_2: grandTotal 205.0 not enough for invoicing. +2026-02-16 11:47:57.082303 - INFO - Invoice A900_T000_260205_5: grandTotal 276.0 not enough for invoicing. +2026-02-16 11:47:57.381176 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 11:47:57.420664 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 11:47:57.489784 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 11:47:57.508492 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 11:47:57.891084 - INFO - Invoice A111_T000_260206_1: grandTotal -150.3 not enough for invoicing. +2026-02-16 11:47:57.908795 - INFO - Invoice A149_T000_260206_1: grandTotal 375.9 not enough for invoicing. +2026-02-16 11:47:57.969716 - ERROR - receipt A94720260206102152: buyer has insufficient details - repair before export +2026-02-16 11:47:58.168079 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:47:58.205895 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:47:58.221809 - INFO - Avoid rounding of -0.01 by updating max 7 articles. +2026-02-16 11:47:58.248015 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:47:58.296223 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:47:58.312388 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 11:47:58.325506 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 11:47:58.340078 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:47:58.405227 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:47:58.422830 - INFO - Avoid rounding of -0.01 by updating max 6 articles. +2026-02-16 11:47:58.441902 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 11:47:58.525602 - ERROR - receipt AN0320260104101097: buyer has insufficient details - repair before export +2026-02-16 11:47:58.553795 - INFO - Avoid rounding of 0.03 by updating max 11 articles. +2026-02-16 11:47:58.647572 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-16 11:47:58.713980 - INFO - Avoid rounding of 0.01 by updating max 5 articles. +2026-02-16 11:47:58.730760 - INFO - Avoid rounding of -0.02 by updating max 9 articles. +2026-02-16 11:47:58.774332 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 11:47:58.804513 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:47:58.820697 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 11:47:58.845833 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:47:58.861901 - INFO - Avoid rounding of 0.01 by updating max 10 articles. +2026-02-16 11:47:59.011642 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 11:47:59.197788 - ERROR - receipt A90020260207101020: buyer has insufficient details - repair before export +2026-02-16 11:47:59.246649 - INFO - Invoice A102_T000_260209_1: grandTotal -129.0 not enough for invoicing. +2026-02-16 11:47:59.255987 - INFO - Invoice A102_T000_260209_2: grandTotal -129.0 not enough for invoicing. +2026-02-16 11:47:59.504775 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 11:47:59.551220 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 11:47:59.673693 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:47:59.826789 - INFO - Avoid rounding of 0.03 by updating max 12 articles. +2026-02-16 11:47:59.891936 - WARNING - Invoice AN20_T000_260210_30: Buyer country XX does not match company country BE +2026-02-16 11:47:59.913872 - WARNING - Invoice AN20_T000_260210_31: Buyer country XX does not match company country BE +2026-02-16 11:47:59.978208 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:48:00.208225 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-16 11:48:00.249236 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-16 11:48:00.386569 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:48:00.446342 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-16 11:48:00.483391 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 11:48:00.550634 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 11:48:00.566591 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 11:48:00.600640 - INFO - Avoid rounding of 0.02 by updating max 23 articles. +2026-02-16 11:48:00.759887 - INFO - Invoice A902_T000_260210_1: grandTotal -142.4 not enough for invoicing. +2026-02-16 11:48:00.798686 - ERROR - receipt A90020260209102177: buyer has insufficient details - repair before export +2026-02-16 11:48:00.825343 - INFO - Invoice A900_T000_260210_2: grandTotal 419.0 not enough for invoicing. +2026-02-16 11:48:00.834957 - INFO - Invoice A900_T000_260210_3: grandTotal 265.6 not enough for invoicing. +2026-02-16 11:48:00.847404 - ERROR - receipt A90020260207101116: buyer has insufficient details - repair before export +2026-02-16 11:48:00.920193 - INFO - Invoice A109_T000_260210_1: grandTotal 139.0 not enough for invoicing. +2026-02-16 11:48:01.183861 - INFO - Avoid rounding of 0.01 by updating max 4 articles. +2026-02-16 11:48:01.201296 - INFO - Avoid rounding of -0.02 by updating max 16 articles. +2026-02-16 11:48:01.542765 - ERROR - receipt A11120260124102125: buyer has insufficient details - repair before export +2026-02-16 11:48:01.922791 - ERROR - receipt A29420260212102022: buyer has insufficient details - repair before export +2026-02-16 11:48:01.967814 - INFO - Invoice A902_T000_260212_1: grandTotal 376.0 not enough for invoicing. +2026-02-16 11:48:02.163655 - INFO - Invoice A112_T000_260212_1: grandTotal 164.0 not enough for invoicing. +2026-02-16 11:48:02.345376 - ERROR - receipt AN2320260214101024: buyer has insufficient details - repair before export +2026-02-16 11:48:02.377975 - ERROR - receipt F00U20260214101194: buyer has insufficient details - repair before export +2026-02-16 11:48:02.394146 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 11:48:02.648526 - INFO - Invoice A149_T000_260214_1: grandTotal 238.0 not enough for invoicing. +2026-02-16 13:43:46.122667 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-16 13:43:46.428401 - ERROR - receipt A17720260203101048: buyer has insufficient details - repair before export +2026-02-16 13:43:46.848181 - ERROR - receipt A11520260203101038: buyer has insufficient details - repair before export +2026-02-16 13:43:47.018957 - ERROR - receipt A27520260110101225: buyer has insufficient details - repair before export +2026-02-16 13:43:47.032628 - ERROR - receipt A27520260128101030: buyer has insufficient details - repair before export +2026-02-16 13:43:47.152729 - WARNING - Invoice A944_T000_260205_19: Buyer country SI does not match company country HR +2026-02-16 13:43:47.584557 - INFO - Invoice A279_T000_260205_1: grandTotal -296.0 not enough for invoicing. +2026-02-16 13:43:47.692931 - INFO - Invoice A900_T000_260205_1: grandTotal 356.0 not enough for invoicing. +2026-02-16 13:43:47.702885 - INFO - Invoice A900_T000_260205_2: grandTotal 205.0 not enough for invoicing. +2026-02-16 13:43:47.715425 - INFO - Invoice A900_T000_260205_5: grandTotal 276.0 not enough for invoicing. +2026-02-16 13:43:47.964711 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 13:43:48.001553 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 13:43:48.078171 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 13:43:48.095390 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 13:43:48.524415 - INFO - Invoice A111_T000_260206_1: grandTotal -150.3 not enough for invoicing. +2026-02-16 13:43:48.543561 - INFO - Invoice A149_T000_260206_1: grandTotal 375.9 not enough for invoicing. +2026-02-16 13:43:48.610700 - ERROR - receipt A94720260206102152: buyer has insufficient details - repair before export +2026-02-16 13:43:48.771788 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:48.810815 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:48.826952 - INFO - Avoid rounding of -0.01 by updating max 7 articles. +2026-02-16 13:43:48.853834 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:48.905150 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:48.922493 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 13:43:48.936328 - INFO - Avoid rounding of 0.01 by updating max 6 articles. +2026-02-16 13:43:48.951150 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:49.009839 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:49.026361 - INFO - Avoid rounding of -0.01 by updating max 6 articles. +2026-02-16 13:43:49.041343 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 13:43:49.119914 - ERROR - receipt AN0320260104101097: buyer has insufficient details - repair before export +2026-02-16 13:43:49.154693 - INFO - Avoid rounding of 0.03 by updating max 11 articles. +2026-02-16 13:43:49.247364 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-16 13:43:49.323800 - INFO - Avoid rounding of 0.01 by updating max 5 articles. +2026-02-16 13:43:49.343760 - INFO - Avoid rounding of -0.02 by updating max 9 articles. +2026-02-16 13:43:49.388613 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 13:43:49.422940 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:49.439211 - INFO - Avoid rounding of -0.01 by updating max 5 articles. +2026-02-16 13:43:49.467575 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:49.487953 - INFO - Avoid rounding of 0.01 by updating max 10 articles. +2026-02-16 13:43:49.700051 - INFO - Avoid rounding of -0.01 by updating max 3 articles. +2026-02-16 13:43:49.898479 - ERROR - receipt A90020260207101020: buyer has insufficient details - repair before export +2026-02-16 13:43:49.950150 - INFO - Invoice A102_T000_260209_1: grandTotal -129.0 not enough for invoicing. +2026-02-16 13:43:49.958257 - INFO - Invoice A102_T000_260209_2: grandTotal -129.0 not enough for invoicing. +2026-02-16 13:43:50.203743 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 13:43:50.244781 - INFO - Avoid rounding of 0.01 by updating max 2 articles. +2026-02-16 13:43:50.284774 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:50.415116 - INFO - Avoid rounding of 0.03 by updating max 12 articles. +2026-02-16 13:43:50.491857 - WARNING - Invoice AN20_T000_260210_30: Buyer country XX does not match company country BE +2026-02-16 13:43:50.504596 - WARNING - Invoice AN20_T000_260210_31: Buyer country XX does not match company country BE +2026-02-16 13:43:50.555713 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:50.745339 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-16 13:43:50.782086 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-16 13:43:50.905104 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:50.935115 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-16 13:43:50.966699 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 13:43:51.038639 - INFO - Avoid rounding of -0.01 by updating max 4 articles. +2026-02-16 13:43:51.058210 - INFO - Avoid rounding of -0.01 by updating max 2 articles. +2026-02-16 13:43:51.100610 - INFO - Avoid rounding of 0.02 by updating max 23 articles. +2026-02-16 13:43:51.257980 - INFO - Invoice A902_T000_260210_1: grandTotal -142.4 not enough for invoicing. +2026-02-16 13:43:51.289719 - ERROR - receipt A90020260209102177: buyer has insufficient details - repair before export +2026-02-16 13:43:51.299694 - INFO - Invoice A900_T000_260210_2: grandTotal 419.0 not enough for invoicing. +2026-02-16 13:43:51.308293 - INFO - Invoice A900_T000_260210_3: grandTotal 265.6 not enough for invoicing. +2026-02-16 13:43:51.315501 - ERROR - receipt A90020260207101116: buyer has insufficient details - repair before export +2026-02-16 13:43:51.365740 - INFO - Invoice A109_T000_260210_1: grandTotal 139.0 not enough for invoicing. +2026-02-16 13:43:51.616158 - INFO - Avoid rounding of 0.01 by updating max 4 articles. +2026-02-16 13:43:51.633373 - INFO - Avoid rounding of -0.02 by updating max 16 articles. +2026-02-16 13:43:51.951579 - ERROR - receipt A11120260124102125: buyer has insufficient details - repair before export +2026-02-16 13:43:52.287200 - ERROR - receipt A29420260212102022: buyer has insufficient details - repair before export +2026-02-16 13:43:52.329386 - INFO - Invoice A902_T000_260212_1: grandTotal 376.0 not enough for invoicing. +2026-02-16 13:43:52.516356 - INFO - Invoice A112_T000_260212_1: grandTotal 164.0 not enough for invoicing. +2026-02-16 13:43:52.664920 - ERROR - receipt AN2320260214101024: buyer has insufficient details - repair before export +2026-02-16 13:43:52.697134 - ERROR - receipt F00U20260214101194: buyer has insufficient details - repair before export +2026-02-16 13:43:52.710984 - INFO - Avoid rounding of 0.01 by updating max 3 articles. +2026-02-16 13:43:52.969923 - INFO - Invoice A149_T000_260214_1: grandTotal 238.0 not enough for invoicing. +2026-02-17 10:14:38.871789 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-17 10:14:38.884739 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-17 10:14:38.889511 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-17 10:14:38.895766 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-17 10:14:38.900756 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-17 10:14:38.905785 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-17 10:14:38.911264 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-17 10:14:38.917421 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-17 10:14:38.923845 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-17 10:14:38.931329 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-17 10:14:38.937162 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-17 10:14:38.942657 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-17 10:14:38.949072 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-17 10:14:38.954314 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-17 10:14:38.964565 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-17 16:30:48.787709 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-17 16:32:10.610647 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-17 16:36:45.991105 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-18 11:47:40.988635 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-18 11:47:41.180680 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 11:47:41.201161 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 11:47:41.207904 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 11:47:41.213668 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 11:47:41.219579 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 11:47:41.225024 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 11:47:41.230387 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 11:47:41.236645 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 11:47:41.243124 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 11:47:41.249871 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 11:47:41.255617 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 11:47:41.261197 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 11:47:41.267069 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 11:47:41.272584 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 11:47:41.282951 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 12:26:42.791175 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:26:42.810308 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 12:26:42.815290 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 12:26:42.821209 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 12:26:42.827820 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 12:26:42.833248 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 12:26:42.838986 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 12:26:42.844961 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 12:26:42.852683 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:26:42.860765 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 12:26:42.865734 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 12:26:42.871652 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 12:26:42.877062 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 12:26:42.882036 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 12:26:42.891433 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 12:26:43.078885 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-18 12:26:43.123105 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-18 12:26:43.165106 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-18 12:30:00.171192 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:30:00.180229 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 12:30:00.184349 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 12:30:00.188327 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 12:30:00.191829 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 12:30:00.195623 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 12:30:00.203421 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 12:30:00.211622 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 12:30:00.220991 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:30:00.231103 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 12:30:00.238659 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 12:30:00.244029 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 12:30:00.250264 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 12:30:00.258137 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 12:30:00.265509 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 12:30:31.725953 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-18 12:30:31.881641 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:30:31.892265 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 12:30:31.897076 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 12:30:31.902165 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 12:30:31.907372 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 12:30:31.911937 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 12:30:31.916181 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 12:30:31.921230 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 12:30:31.927533 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 12:30:31.934149 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 12:30:31.938393 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 12:30:31.942502 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 12:30:31.947398 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 12:30:31.951743 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 12:30:31.958236 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 12:30:32.097506 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-18 12:30:32.139501 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-18 12:30:32.177936 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-18 13:08:36.578263 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-18 13:08:36.765406 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 13:08:36.780158 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 13:08:36.785814 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 13:08:36.792319 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 13:08:36.798502 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 13:08:36.804831 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 13:08:36.810106 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 13:08:36.815435 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 13:08:36.823614 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 13:08:36.830935 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 13:08:36.837502 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 13:08:36.843113 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 13:08:36.848888 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 13:08:36.855730 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 13:08:36.866642 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 13:08:37.043723 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-18 13:08:37.084434 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-18 13:08:37.125689 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-18 14:15:58.839206 - WARNING - Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-18 14:15:59.019335 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 14:15:59.034064 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 14:15:59.038906 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 14:15:59.044479 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 14:15:59.049316 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 14:15:59.054967 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 14:15:59.060338 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 14:15:59.065564 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 14:15:59.072311 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 14:15:59.079369 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 14:15:59.084324 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 14:15:59.089554 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 14:15:59.094304 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 14:15:59.099169 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 14:15:59.108450 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 14:16:34.997672 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 14:16:35.008520 - ERROR - No linked receipt file found for AN19_T102_260111_101.xml +2026-02-18 14:16:35.012092 - ERROR - No linked receipt file found for AN19_T102_260111_122.xml +2026-02-18 14:16:35.015065 - ERROR - No linked receipt file found for AN19_T102_260111_117.xml +2026-02-18 14:16:35.017696 - ERROR - No linked receipt file found for AN19_T103_260111_98.xml +2026-02-18 14:16:35.021845 - ERROR - No linked receipt file found for AN19_T103_260111_123.xml +2026-02-18 14:16:35.025378 - ERROR - No linked receipt file found for AN19_T102_260113_87.xml +2026-02-18 14:16:35.028433 - ERROR - No linked receipt file found for AN19_T101_260115_80.xml +2026-02-18 14:16:35.032278 - ERROR - receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-18 14:16:35.038563 - ERROR - No linked receipt file found for AN19_T101_260104_148.xml +2026-02-18 14:16:35.042605 - ERROR - No linked receipt file found for AN19_T104_260103_188.xml +2026-02-18 14:16:35.045686 - ERROR - No linked receipt file found for AN19_T101_260103_105.xml +2026-02-18 14:16:35.048303 - ERROR - No linked receipt file found for AN19_T103_260102_255.xml +2026-02-18 14:16:35.052389 - ERROR - No linked receipt file found for AN19_T102_260108_110.xml +2026-02-18 14:16:35.058218 - ERROR - No linked receipt file found for AN19_T104_260110_78.xml +2026-02-18 14:16:35.205587 - INFO - Avoid rounding of -0.14 by updating max 88 articles. +2026-02-18 14:16:35.244595 - INFO - Avoid rounding of -0.08 by updating max 85 articles. +2026-02-18 14:16:35.285312 - INFO - Avoid rounding of 0.02 by updating max 8 articles. +2026-02-19 11:50:52.441656 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-19 11:50:52.672883 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 11:50:52.690067 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 11:50:52.695358 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 11:50:52.700129 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 11:50:52.704882 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 11:50:52.709844 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 11:50:52.714642 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 11:50:52.720608 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 11:50:52.727254 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 11:50:52.734772 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 11:50:52.739691 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 11:50:52.744820 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 11:50:52.749701 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 11:50:52.755003 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 11:50:52.764897 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 11:50:52.990480 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-19 11:50:53.030194 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-19 11:50:53.073821 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-19 12:22:31.749952 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:22:31.759797 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 12:22:31.766976 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 12:22:31.770602 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 12:22:31.774743 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 12:22:31.778791 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 12:22:31.782204 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 12:22:31.785355 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 12:22:31.790318 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:22:31.796362 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 12:22:31.799547 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 12:22:31.802966 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 12:22:31.806344 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 12:22:31.809522 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 12:22:31.815587 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 12:24:19.155909 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-19 12:24:19.307838 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-19 12:24:19.372543 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-19 12:24:19.417380 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-19 12:24:19.675836 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:24:19.687088 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 12:24:19.693959 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 12:24:19.700207 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 12:24:19.705418 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 12:24:19.711732 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 12:24:19.717036 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 12:24:19.722153 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 12:24:19.730479 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:24:19.741421 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 12:24:19.745060 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 12:24:19.749130 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 12:24:19.753580 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 12:24:19.757873 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 12:24:19.763945 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 12:24:19.926164 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-19 12:24:19.963541 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-19 12:24:20.008093 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-19 12:25:57.726040 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-19 12:25:57.839606 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-19 12:27:27.414817 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-19 12:27:27.532389 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-19 12:27:27.587134 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-19 12:27:27.622122 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-19 12:27:27.820697 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:27:27.831937 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 12:27:27.834895 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 12:27:27.838671 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 12:27:27.842696 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 12:27:27.845626 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 12:27:27.848609 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 12:27:27.851646 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 12:27:27.857884 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:27:27.866283 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 12:27:27.870175 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 12:27:27.873986 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 12:27:27.877079 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 12:27:27.880083 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 12:27:27.884930 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 12:30:11.098646 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:30:11.111431 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 12:30:11.114333 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 12:30:11.116748 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 12:30:11.119788 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 12:30:11.123130 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 12:30:11.126202 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 12:30:11.128509 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 12:30:11.132378 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:30:11.136600 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 12:30:11.138776 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 12:30:11.141684 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 12:30:11.145993 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 12:30:11.148542 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 12:30:11.153391 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 12:30:11.336452 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-19 12:30:11.378558 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-19 12:30:11.417774 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-19 12:30:54.688257 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-19 12:30:54.787486 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-19 12:30:54.836376 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-19 12:30:54.867321 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-19 12:30:55.103269 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:30:55.115296 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-19 12:30:55.118341 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-19 12:30:55.121352 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-19 12:30:55.124963 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-19 12:30:55.128568 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-19 12:30:55.131479 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-19 12:30:55.133963 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-19 12:30:55.137356 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-19 12:30:55.141889 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-19 12:30:55.145613 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-19 12:30:55.148418 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-19 12:30:55.150864 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-19 12:30:55.153360 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-19 12:30:55.159222 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-19 12:30:55.310511 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-19 12:30:55.355103 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-19 12:30:55.398294 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-20 10:55:46.617080 - WARNING Found new store AXXX. You can find it in data\stores_to_invoice.csv +2026-02-23 11:10:11.837070 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:10:11.856896 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:10:11.862237 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:10:11.868261 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:10:11.874892 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:10:11.880654 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:10:11.885624 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:10:11.891170 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:10:11.899875 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:10:11.907429 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:10:11.913326 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:10:11.919527 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:10:11.926211 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:10:11.932201 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:10:11.945419 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:10:55.724673 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 11:10:55.863277 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 11:10:55.920883 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 11:10:55.960412 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 11:10:56.170318 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:10:56.183207 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:10:56.188104 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:10:56.192936 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:10:56.198108 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:10:56.202615 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:10:56.207470 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:10:56.212568 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:10:56.219171 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:10:56.226354 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:10:56.231695 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:10:56.236634 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:10:56.241438 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:10:56.246243 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:10:56.252566 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:10:56.475516 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 11:10:56.531045 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 11:10:56.580871 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 11:12:18.211567 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 11:12:18.332041 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 11:12:18.460565 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 11:12:18.561847 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 11:12:18.598141 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 11:12:18.628262 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 11:12:18.786304 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:12:18.796236 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:12:18.799578 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:12:18.803116 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:12:18.806491 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:12:18.809671 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:12:18.812885 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:12:18.815685 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:12:18.819915 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:12:18.824716 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:12:18.828521 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:12:18.831803 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:12:18.835523 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:12:18.838714 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:12:18.845117 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:12:18.995916 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 11:12:19.038242 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 11:12:19.077933 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 11:13:45.018113 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 11:13:45.065380 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 11:13:45.085752 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 11:13:45.115813 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 11:13:45.170873 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 11:13:45.729167 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 11:13:45.844871 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 11:13:46.003572 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 11:13:46.099050 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 11:13:46.137055 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 11:13:46.165440 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 11:13:46.317879 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:13:46.326743 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:13:46.330006 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:13:46.333754 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:13:46.336529 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:13:46.339480 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:13:46.343139 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:13:46.346564 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:13:46.351673 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:13:46.356557 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:13:46.360692 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:13:46.364400 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:13:46.368963 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:13:46.372642 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:13:46.378181 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:13:46.531653 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 11:13:46.567870 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 11:13:46.611647 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 11:22:16.118468 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 11:22:16.130788 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 11:22:16.142054 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 11:22:16.151983 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 11:22:16.179922 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 11:22:16.608968 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 11:22:17.057551 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:22:17.073452 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:22:17.080362 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:22:17.087460 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:22:17.091715 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:22:17.096111 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:22:17.100050 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:22:17.103839 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:22:17.108448 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:22:17.113295 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:22:17.117475 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:22:17.121557 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:22:17.124903 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:22:17.128113 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:22:17.133892 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:33:51.383208 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 11:33:51.403319 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 11:33:51.421673 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 11:33:51.432810 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 11:33:51.460256 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 11:33:51.990668 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 11:33:52.382262 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:33:52.391952 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:33:52.395680 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:33:52.399625 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:33:52.404348 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:33:52.407895 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:33:52.411275 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:33:52.414746 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:33:52.421982 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:33:52.430162 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:33:52.434574 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:33:52.438579 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:33:52.441956 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:33:52.445551 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:33:52.453570 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 11:35:05.938101 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 11:35:05.969961 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 11:35:05.982432 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 11:35:05.989327 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 11:35:06.013970 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 11:35:06.726320 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 11:35:07.149881 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:35:07.158262 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 11:35:07.162091 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 11:35:07.165763 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 11:35:07.169870 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 11:35:07.172890 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 11:35:07.176438 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 11:35:07.180239 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 11:35:07.186580 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 11:35:07.191369 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 11:35:07.195425 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 11:35:07.199468 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 11:35:07.202475 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 11:35:07.205546 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 11:35:07.212169 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:29:53.738218 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:29:53.812549 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:29:53.835749 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:29:53.870727 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:29:53.908509 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:29:54.372126 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:29:54.488684 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:29:54.615522 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:29:54.706513 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:29:54.734407 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:29:54.756606 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:29:54.864966 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:29:54.876735 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:29:54.881383 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:29:54.885738 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:29:54.889765 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:29:54.894296 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:29:54.898266 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:29:54.902226 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:29:54.907528 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:29:54.911932 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:29:54.915632 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:29:54.918662 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:29:54.921701 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:29:54.925155 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:29:54.931834 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:29:55.041019 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:29:55.067612 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:29:55.095495 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:30:54.813933 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:30:54.827153 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:30:54.837428 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:30:54.845911 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:30:54.871284 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:30:55.387017 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:30:55.513984 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:30:55.671221 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:30:55.797231 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:30:55.826844 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:30:55.847021 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:30:55.958006 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:30:55.966595 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:30:55.970233 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:30:55.974591 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:30:55.978586 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:30:55.982547 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:30:55.986740 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:30:55.992036 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:30:55.997756 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:30:56.003649 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:30:56.007560 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:30:56.010904 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:30:56.016249 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:30:56.019779 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:30:56.028432 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:30:56.163107 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:30:56.191801 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:30:56.217754 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:31:19.639863 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:31:19.656434 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:31:19.667425 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:31:19.675212 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:31:19.699859 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:31:20.223331 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:31:20.352574 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:31:20.512270 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:31:20.638078 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:31:20.667651 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:31:20.687709 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:31:20.818798 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:31:20.826904 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:31:20.830944 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:31:20.835301 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:31:20.839177 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:31:20.843250 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:31:20.846941 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:31:20.850259 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:31:20.856135 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:31:20.861358 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:31:20.864453 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:31:20.868954 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:31:20.872446 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:31:20.875291 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:31:20.881105 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:31:21.001119 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:31:21.027337 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:31:21.055113 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:31:45.074086 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:31:45.087649 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:31:45.098417 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:31:45.106607 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:31:45.130386 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:31:45.690462 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:31:45.808572 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:31:45.983643 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:31:46.084459 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:31:46.115398 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:31:46.138064 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:31:46.261735 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:31:46.272739 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:31:46.278881 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:31:46.285804 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:31:46.289458 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:31:46.294026 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:31:46.298140 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:31:46.301658 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:31:46.306456 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:31:46.311913 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:31:46.315351 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:31:46.319409 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:31:46.323183 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:31:46.326730 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:31:46.333421 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:31:46.442350 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:31:46.471771 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:31:46.507893 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:34:19.770038 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:34:19.783014 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:34:19.792079 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:34:19.799792 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:34:19.826694 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:34:20.398156 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:34:20.517567 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:34:20.726545 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:34:20.867997 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:34:20.897865 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:34:20.917585 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:34:21.042576 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:34:21.051669 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:34:21.056573 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:34:21.062025 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:34:21.067388 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:34:21.071678 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:34:21.075277 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:34:21.079865 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:34:21.085720 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:34:21.091342 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:34:21.095506 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:34:21.098834 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:34:21.101819 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:34:21.105342 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:34:21.112053 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:34:21.252040 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:34:21.282311 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:34:21.315423 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:35:33.321547 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:35:33.334105 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:35:33.343553 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:35:33.351814 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:35:33.372979 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:35:33.923617 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:35:34.029950 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:35:34.201405 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:35:34.329012 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:35:34.362924 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:35:34.388654 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:35:34.508769 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:35:34.517284 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:35:34.520262 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:35:34.522896 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:35:34.525727 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:35:34.528792 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:35:34.532628 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:35:34.535932 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:35:34.540453 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:35:34.544430 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:35:34.546757 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:35:34.550139 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:35:34.554127 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:35:34.558564 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:35:34.564097 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:35:34.686582 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:35:34.715382 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:35:34.748624 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:39:45.379723 - WARNING Invoice A282_T000_260110_1: Buyer country BE does not match company country PL +2026-02-23 16:39:45.402849 - INFO Invoice A115_T000_260110_1: grandTotal 244.0 not enough for invoicing. +2026-02-23 16:39:45.423650 - INFO Invoice A115_T000_260110_3: grandTotal -122.0 not enough for invoicing. +2026-02-23 16:39:45.436061 - ERROR receipt F06120260110101045: buyer has insufficient details - repair before export +2026-02-23 16:39:45.483416 - INFO Receipt F06120260110101077: Avoid rounding of -0.01 by updating max 2 articles. +2026-02-23 16:39:46.098436 - ERROR receipt A10020260126101017: buyer has insufficient details - repair before export +2026-02-23 16:39:46.230805 - WARNING Invoice A100_T000_260129_1: Buyer country XX does not match company country HR +2026-02-23 16:39:46.446672 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-23 16:39:46.545506 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-23 16:39:46.578286 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-23 16:39:46.599073 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-23 16:39:46.723728 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:39:46.734280 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:39:46.737043 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:39:46.740867 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:39:46.745665 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:39:46.749420 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:39:46.753218 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:39:46.757493 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:39:46.762856 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:39:46.768001 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:39:46.775831 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:39:46.779454 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:39:46.783403 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:39:46.787113 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:39:46.795521 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:39:46.922453 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:39:46.966073 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:39:46.997858 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-23 16:40:23.704335 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:40:23.711107 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-23 16:40:23.713780 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-23 16:40:23.716764 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-23 16:40:23.720225 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-23 16:40:23.723046 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-23 16:40:23.726025 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-23 16:40:23.729788 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-23 16:40:23.734710 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-23 16:40:23.740092 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-23 16:40:23.743725 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-23 16:40:23.748849 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-23 16:40:23.752346 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-23 16:40:23.756723 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-23 16:40:23.762853 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-23 16:40:23.946555 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-23 16:40:23.978741 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-23 16:40:24.010865 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:07:59.794977 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-24 11:07:59.887027 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-24 11:07:59.924373 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-24 11:07:59.945168 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-24 11:08:00.096166 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:08:00.113682 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:08:00.119309 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:08:00.124396 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:08:00.129763 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:08:00.135564 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:08:00.140880 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:08:00.147269 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:08:00.153629 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:08:00.161572 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:08:00.166028 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:08:00.169641 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:08:00.173761 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:08:00.179019 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:08:00.188357 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:08:00.331190 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:08:00.361823 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:08:00.398469 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:23:24.138563 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:23:24.145444 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:23:24.148010 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:23:24.151242 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:23:24.154585 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:23:24.158232 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:23:24.161204 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:23:24.163625 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:23:24.167963 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:23:24.172827 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:23:24.176471 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:23:24.179547 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:23:24.182315 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:23:24.185117 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:23:24.190012 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:23:26.845374 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:23:26.863596 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:23:26.882029 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:24:10.790293 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-24 11:24:10.815479 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-24 11:24:10.923648 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-24 11:24:10.934058 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-24 11:24:10.975120 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:24:10.983305 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:24:10.985934 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:24:10.989396 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:24:10.992437 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:24:10.996168 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:24:11.000207 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:24:11.003482 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:24:11.008076 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:24:11.014174 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:24:11.017055 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:24:11.021219 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:24:11.024525 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:24:11.028584 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:24:11.033988 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:24:11.096436 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:24:11.117719 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:24:11.143755 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:24:33.355186 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-24 11:24:33.382159 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-24 11:24:33.457320 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-24 11:24:33.467147 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-24 11:24:33.503421 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:24:33.510383 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:24:33.513085 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:24:33.516067 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:24:33.519171 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:24:33.521903 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:24:33.524755 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:24:33.527228 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:24:33.531447 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:24:33.535783 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:24:33.538409 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:24:33.541208 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:24:33.544145 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:24:33.547636 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:24:33.552129 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:24:33.612418 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:24:33.631221 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:24:33.649507 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:26:12.217162 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-24 11:26:12.245086 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-24 11:26:12.332364 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-24 11:26:12.343154 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-24 11:26:12.384050 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:26:12.392819 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:26:12.396812 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:26:12.401156 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:26:12.404528 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:26:12.408050 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:26:12.411984 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:26:12.415729 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:26:12.420007 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:26:12.428162 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:26:12.431716 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:26:12.435566 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:26:12.438936 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:26:12.442086 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:26:12.449369 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:26:12.513322 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:26:12.534105 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:26:12.553289 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. +2026-02-24 11:28:50.010877 - WARNING Invoice AN02_T000_260203_1: Buyer country XX does not match company country BE +2026-02-24 11:28:50.038226 - ERROR No linked receipt file found for A100_T101_260121_30.xml +2026-02-24 11:28:50.121223 - INFO Receipt A10020260103101188: Avoid rounding of -0.01 by updating max 3 articles. +2026-02-24 11:28:50.130855 - INFO Receipt A10020260115101212: Avoid rounding of -0.01 by updating max 4 articles. +2026-02-24 11:28:50.165598 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:28:50.172617 - ERROR No linked receipt file found for AN19_T102_260111_101.xml +2026-02-24 11:28:50.176345 - ERROR No linked receipt file found for AN19_T102_260111_122.xml +2026-02-24 11:28:50.179743 - ERROR No linked receipt file found for AN19_T102_260111_117.xml +2026-02-24 11:28:50.182583 - ERROR No linked receipt file found for AN19_T103_260111_98.xml +2026-02-24 11:28:50.185642 - ERROR No linked receipt file found for AN19_T103_260111_123.xml +2026-02-24 11:28:50.188170 - ERROR No linked receipt file found for AN19_T102_260113_87.xml +2026-02-24 11:28:50.191646 - ERROR No linked receipt file found for AN19_T101_260115_80.xml +2026-02-24 11:28:50.195631 - ERROR receipt AN1920260104105115: buyer has insufficient details - repair before export +2026-02-24 11:28:50.199666 - ERROR No linked receipt file found for AN19_T101_260104_148.xml +2026-02-24 11:28:50.202292 - ERROR No linked receipt file found for AN19_T104_260103_188.xml +2026-02-24 11:28:50.205420 - ERROR No linked receipt file found for AN19_T101_260103_105.xml +2026-02-24 11:28:50.208038 - ERROR No linked receipt file found for AN19_T103_260102_255.xml +2026-02-24 11:28:50.210277 - ERROR No linked receipt file found for AN19_T102_260108_110.xml +2026-02-24 11:28:50.214960 - ERROR No linked receipt file found for AN19_T104_260110_78.xml +2026-02-24 11:28:50.270849 - INFO Receipt AN1920260120103075: Avoid rounding of -0.14 by updating max 88 articles. +2026-02-24 11:28:50.289230 - INFO Receipt AN1920260120103074: Avoid rounding of -0.08 by updating max 85 articles. +2026-02-24 11:28:50.308309 - INFO Receipt AN1920260201102083: Avoid rounding of 0.02 by updating max 8 articles. diff --git a/models.py b/models.py new file mode 100644 index 0000000..5a0a7e2 --- /dev/null +++ b/models.py @@ -0,0 +1,31 @@ +from flask_sqlalchemy import SQLAlchemy +from datetime import datetime + + +db = SQLAlchemy() + +class StateOfDate(db.Model): + id = db.Column(db.Integer, primary_key=True) + updated_at = db.Column(db.TIMESTAMP, default=datetime.now(), onupdate=datetime.now(), nullable=False) + date = db.Column(db.String(8), unique=True, nullable=False) # YYYYMMDD + system_issues = db.Column(db.Integer, default=0) + data_issues = db.Column(db.Integer, default=0) + + def __repr__(self): + return f"{self.date}: {self.system_issues} {self.data_issues}" + + def isDone(self): + return self.system_issues==0 and self.data_issues==0 + +class StateOfInvoice(db.Model): + id = db.Column(db.Integer, primary_key=True) + country = db.Column(db.String(2), nullable=False) # XX + poslogid = db.Column(db.String(16), unique=True, nullable=False) + receiptid = db.Column(db.String(16), unique=True, nullable=False) + receiptmonth = db.Column(db.String(6), nullable=False) # YYYYMM + updated_at = db.Column(db.TIMESTAMP, default=datetime.now(), onupdate=datetime.now(), nullable=False) + state = db.Column(db.Integer, default=-1) # -1: unprocessed, 0: has issues, 1: processed to xml file, 2: sent to ecosio 3: monthly-reported + + def __repr__(self): + return f"{self.country} {self.poslogid} {self.receiptid} {self.receiptmonth} {self.updated_at} {self.state}" + diff --git a/offices.py b/offices.py new file mode 100644 index 0000000..0c745af --- /dev/null +++ b/offices.py @@ -0,0 +1,20 @@ +from pprint import pprint +import csv +from localconfig import OFFICESFILE + +class Offices(): + def __init__(self): + ''' + Get the country - office detail from disk + + ''' + self.offices = {} + with open(OFFICESFILE, newline="", encoding="utf-8") as f_in: + reader = csv.DictReader(f_in) + for row in reader: + self.offices[row['Country']] = row + + def get_office_details(self, country): + if country in self.offices.keys(): + return self.offices[country] + return {'Name': '?', 'PartyId':'?', 'City': '?'} \ No newline at end of file diff --git a/repairedbuyers.py b/repairedbuyers.py new file mode 100644 index 0000000..212b52e --- /dev/null +++ b/repairedbuyers.py @@ -0,0 +1,19 @@ +from pprint import pprint +import csv +from localconfig import BUYERS_REPAIRED + +class RepairedBuyers(): + def __init__(self): + ''' + Get the repaired buyers detail from disk + + ''' + self.buyers = {} + with open(BUYERS_REPAIRED, newline="", encoding="utf-8") as f_in: + reader = csv.DictReader(f_in) + for row in reader: + self.buyers[row['Invoice']] = row + + def get_buyer_for(self, invoiceid): + if invoiceid in self.buyers.keys(): + return self.buyers[invoiceid] \ No newline at end of file diff --git a/static/download.png b/static/download.png new file mode 100644 index 0000000..c4337db Binary files /dev/null and b/static/download.png differ diff --git a/static/no-download.png b/static/no-download.png new file mode 100644 index 0000000..b952331 Binary files /dev/null and b/static/no-download.png differ diff --git a/stores.py b/stores.py new file mode 100644 index 0000000..a538a9d --- /dev/null +++ b/stores.py @@ -0,0 +1,61 @@ +from localconfig import STORESFILE +import csv + +class Stores(): + def __init__(self): + ''' + Download the business unit CSV from the GK reporting server or pick it up from disk + + :param self: Description + ''' + # open csv file to read in all the stores to invoice + self.stores = {} + with open(STORESFILE, newline="", encoding="utf-8") as f_in: + reader = csv.DictReader(f_in) + for row in reader: + if row["invoice"] == "1": + if row['country'] not in self.stores: + self.stores[row["country"]] = [] + self.stores[row["country"]].append([row["store"], row['name']]) + # self.stores = {} + # filename = 'businessunitdetails.csv' + # with open(filename, 'r', encoding='utf-8') as f: + # while line := f.readline(): + # store, name, dummy = line.split(',',2) + # self.stores[store] = name + # print(f" STORES {len(self.stores.keys())}") + + def all_countries(self): + return self.stores.keys() + + def stores_for(self, country): + result = [] + if country in self.stores.keys(): + for stores in self.stores[country]: + result.append(stores[0]) + return result + + def get_store_name(self, store): + result = '[ store name ]' + for country in self.stores.keys(): + for s in self.stores[country]: + if store == s[0]: + result = s[1] + return result + + def report_stores(self): + result = '' + for country in self.stores.keys(): + ss = '' + for s in self.stores[country]: + ss += ' ' + s[0] + result += f"{country}:{ss}\n" + return result + + def country_for(self, store): + result = 'XX' + for country in self.stores.keys(): + for s in self.stores[country]: + if store == s[0]: + result = country + return result \ No newline at end of file diff --git a/templates/buyers.html b/templates/buyers.html new file mode 100644 index 0000000..5c69eb4 --- /dev/null +++ b/templates/buyers.html @@ -0,0 +1,55 @@ + + + + Buyers Editor + + + + +

Buyers Incomplete


+The below list shows buyer-data found incomplete and cannot be sent to the tax-office.
+Add or correct the data and press save.
+If data is found good enough, it will disappear from this list and upon the NEXT interface-run evaluated again.
+This form will NOT show buyer data that has been rejected by the tax office


+ + +
+ + + + {% for col in header %} + + {% endfor %} + + + + {% for row in rows %} + + {% for cell in row[:-editable_cols] %} + + {% endfor %} + + {% for i in range(editable_cols) %} + + {% endfor %} + + {% endfor %} + +
{{ col }}
{{ cell }} + +
+ +
+ +
+ + + diff --git a/templates/ecosio_service.html b/templates/ecosio_service.html new file mode 100644 index 0000000..5abe3c0 --- /dev/null +++ b/templates/ecosio_service.html @@ -0,0 +1,50 @@ + + + + + Ecosio downloads + + + + + + + + + {% for date in downloads.keys() %} + + + + + + + + {% endfor %} + +

Available for download

System Errors

Data Issues

 {{ date }} {{ downloads[date][0] }}{{ downloads[date][1] }}{{ downloads[date][2] }}
+ + +


+ DOWNLOAD ALL AVAILABLE MESSAGES FOR ECOSIO + + + \ No newline at end of file diff --git a/templates/edit_csv.html b/templates/edit_csv.html new file mode 100644 index 0000000..ee625fb --- /dev/null +++ b/templates/edit_csv.html @@ -0,0 +1,44 @@ + + + + Maintain {{ csv }} + + + +

Maintain {{ csv }}

+ +
+ + + {% for col in header %} + + {% endfor %} + + + {% for row_index in range(rows|length + 1) %} + + {% for col_index in range(header|length) %} + + {% endfor %} + + {% endfor %} +
{{ col }}
+ +
+ +
+ +
+ + diff --git a/templates/find_rejectedids.html b/templates/find_rejectedids.html new file mode 100644 index 0000000..9812ae6 --- /dev/null +++ b/templates/find_rejectedids.html @@ -0,0 +1,39 @@ + + + + Rejected IDs + + + + +

Find Rejected IDs


+ +
+ + + + + + + + + + + + + + + + + + +
For invoices created later than:
For countrycode:
For invoice-ids:
+
+ + + + diff --git a/templates/home.html b/templates/home.html new file mode 100644 index 0000000..e09b9ea --- /dev/null +++ b/templates/home.html @@ -0,0 +1,45 @@ + + + + Invoice requests + + + + +


+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + diff --git a/templates/monthlyreport.html b/templates/monthlyreport.html new file mode 100644 index 0000000..6554780 --- /dev/null +++ b/templates/monthlyreport.html @@ -0,0 +1,39 @@ + + + + Monthly Report + + + + +

Monthly Report


+ +
+ + + + + + + + + + + + + + + + + + +
Countrycode:
For sales created in month:
Include invoices not reported before that month:
+
+ + + + diff --git a/templates/repair_rejectedids.html b/templates/repair_rejectedids.html new file mode 100644 index 0000000..237de38 --- /dev/null +++ b/templates/repair_rejectedids.html @@ -0,0 +1,57 @@ + + + + Buyers ID rejected + + + + +

Buyers ID Rejected


+The below list shows buyer-data rejected by the tax-office.
+Correct the compnay info and press save.
+A zip file will be offered with updated ecosio messages.
+You consumer data will not be saved.
+
+
+ +
+ + {% for row in rows %} + + + + + + + + + + {% endfor %} +
+ {{ row[0] }} + + {{row[1]}} + + {{row[2]}} + + {{row[3]}} + + {{row[4] }} + + + + + + +
+ +
+ +
+ + + diff --git a/templates/requests.html b/templates/requests.html new file mode 100644 index 0000000..ce50c09 --- /dev/null +++ b/templates/requests.html @@ -0,0 +1,32 @@ + + + + Invoices Folder + + +

Select a Store / date

+ +
+ + + +
+ + {% if xml_files %} +

Invoices

+ + {% elif folder %} +

No Invoices found or invalid folder.

+ {% endif %} + + diff --git a/templates/show_log.html b/templates/show_log.html new file mode 100644 index 0000000..1471b88 --- /dev/null +++ b/templates/show_log.html @@ -0,0 +1,25 @@ + + + + log + + + +

log


+   +   +   + +
{{ txt }}
+ +

Back

+ + diff --git a/templates/update_earliest_date.html b/templates/update_earliest_date.html new file mode 100644 index 0000000..1f0d1a8 --- /dev/null +++ b/templates/update_earliest_date.html @@ -0,0 +1,30 @@ + + + + Earliest date + + + +

Earliest Process date

+
+ No transactions from before this date wil be checked for invoices in the "create-invoices" process.

+ +
+ +

+ +
+

Back

+ + diff --git a/templates/view.html b/templates/view.html new file mode 100644 index 0000000..3c895e3 --- /dev/null +++ b/templates/view.html @@ -0,0 +1,22 @@ + + + + {{ filename }} + + + +

{{ filename }}

+ +
{{ content }}
+ +

← Back

+ + diff --git a/translations.py b/translations.py new file mode 100644 index 0000000..c90d23a --- /dev/null +++ b/translations.py @@ -0,0 +1,29 @@ +from localconfig import TRANSLATIONSFILE +import csv + +class Translations(): + def __init__(self): + ''' + Download the business unit CSV from the GK reporting server or pick it up from disk + + :param self: Description + ''' + # open csv file to read in all the stores to invoice + self.data = [] + with open(TRANSLATIONSFILE, newline="", encoding="utf-8") as f_in: + reader = csv.DictReader(f_in) + for row in reader: + self.data.append([row['type'],row['country'],row['from'],row['to']]) + + def translate(self, fromvalue, type='', country='all'): + # print(f"translating {fromvalue} {country}") + translations = [] + for kv in self.data: + if fromvalue==kv[2] and ( type=='' or type==kv[0]) and (country=='all' or country==kv[1]): + translations.append(kv[3]) + if len(translations) == 1: + return translations[0] + else: + if country != 'all': + return self.translate(fromvalue, type) + return f"pos: {fromvalue}"