List of commits:
Subject Hash Author Date (UTC)
Added a finish process and removed the order process fc33b421234ef320aa5a61f28cfb1e5d815477ca Sebastian 2019-05-08 13:02:21
Added a encoding sniffing to open the files in right encoding on Windows OS machines d0dbe5da1ca5810bfcc240a1e635ce053168b423 Sebastian 2019-05-06 14:54:04
Small usability improvements for the user to detect errors on different OS 2ec13ba3c85207c799eed1cf48ab1230d245a05f Sebastian 2019-05-06 08:25:54
Combined with the picklist creation project 4e5023c3c2bebc53794fe29edbcf9a7be93c826a Sebastian 2019-05-03 11:40:35
Created a building script for Linux based systems and made it possible to use the script from anywhere inside the filesystem e97b391d7b1cda885c99b6b483d414c75b288b75 Sebastian 2019-04-15 15:00:47
Added a working Linux executable Version, together with a different workspace creation process c84d49cf0f99fd3dcb7faabe82c125c8adc970cb Sebastian 2019-04-12 16:53:29
removed unnecessary files from the report and upload folder 94af82cbd9fd7f592fb6b421986c3d900f1bf532 Sebastian 2019-04-05 12:51:43
Added 2 options: a new order import to plenty and a fba shipment creation db5b9c168dabe3d6524b5674dd977044be286e0a Sebastian 2019-04-05 12:48:53
adjusted to another sync format and added a new export format that includes the sale price d33a1909c4f1ff88569509ad4510a5419e323136 Basti 2019-03-22 10:27:22
first Version of the Sync Upload de9ea87dff9ced84f635dd05d5ae039be870ae8a Basti 2019-03-19 16:32:44
First commit including Readme and folder structure 7e77aa7abd6013ce56d6878c7004973e32011a13 Basti 2019-03-19 10:44:36
Commit fc33b421234ef320aa5a61f28cfb1e5d815477ca - Added a finish process and removed the order process
Author: Sebastian
Author date (UTC): 2019-05-08 13:02
Committer name: Sebastian
Committer date (UTC): 2019-05-08 13:02
Parent(s): d0dbe5da1ca5810bfcc240a1e635ce053168b423
Signer:
Signing key:
Signing status: N
Tree: 851d8be7c9b8dc05a4539fe7873b6d39ef3d6c82
File Lines added Lines deleted
inventory_synchronisation.py 32 39
packages/__pycache__/picklist_creation.cpython-37.pyc 0 0
packages/__pycache__/shipment_finish.cpython-37.pyc 0 0
packages/__pycache__/syncfile.cpython-37.pyc 0 0
packages/shipment_finish.py 256 0
packages/syncfile.py 0 26
File inventory_synchronisation.py changed (mode: 100644) (index f1c7df8..bb3cb81)
... ... import sys
4 4 import os import os
5 5 import re import re
6 6 import chardet import chardet
7 from packages.syncfile import importAmazonOrder, importNewOrder
7 from packages.syncfile import importAmazonOrder, writeNewCsv
8 from packages.shipment_finish import finishShipment
8 9 #from packages.excelfile import createExcelSheet #from packages.excelfile import createExcelSheet
9 10
10 11 def main(): def main():
 
... ... def main():
96 97 config.write( "producer_list = ;\n" ) config.write( "producer_list = ;\n" )
97 98 config.write( "#=Enter your plentymarkets ID here;\n" ) config.write( "#=Enter your plentymarkets ID here;\n" )
98 99 config.write( "plenty_id = ;\n" ) config.write( "plenty_id = ;\n" )
99 config.write( "#=Name of the adress owner\n")
100 config.write( "AdressName = ;\n" )
101 config.write( "#=Adress + number\n" )
102 config.write( "AdressFieldOne = ;\n")
103 config.write( "AdressCity = ;\n" )
104 config.write( "AdressStateOrRegion = ;\n")
105 config.write( "AdressPostalCode = ;\n")
106 config.write( "#=DE or NL or UK etc. \n")
107 100 config.write( "CountryCode = ;\n") config.write( "CountryCode = ;\n")
108 101
109 102 if(os.path.isfile('./config.txt')): if(os.path.isfile('./config.txt')):
 
... ... def main():
114 107 # Ask the user if the task is to import received items at amazon or to # Ask the user if the task is to import received items at amazon or to
115 108 # create a new order for production # create a new order for production
116 109 line = "#" * 70 line = "#" * 70
117 altline = "|" * 70
110 altline = "-" * 70
118 111 print("{0}\n".format(line)) print("{0}\n".format(line))
119 112 print(" Preparation for the Script / Vorbereitung für den Script\n") print(" Preparation for the Script / Vorbereitung für den Script\n")
120 113 print("{0}\n".format(line)) print("{0}\n".format(line))
 
... ... def main():
130 123
131 124 task = '' task = ''
132 125
133 while(not(task.lower() == 'amazon' or task.lower() == 'order' or task.lower() == 'fba')):
134 task = input('Do you want to create a new production order (order)||DEPRECATED||\nDo you want to import received items at Amazon (amazon)?\nOr do you want to create a new Shipping to Amazon (fba)?\n')
135 if(not(task.lower() == 'amazon' or task.lower() == 'fba')):
136 print("Please enter either 'amazon' or 'fba'.\n")
126 while(not(task.lower() == 'ama' or task.lower() == 'fin' or task.lower() == 'fba')):
127 task = input('Do you want to create a new FBA Shipment?(fba)\nDo you want to finish a shipment?(fin)\nOr do you want to import received items at Amazon (ama)?\n')
128 if(not(task.lower() == 'ama' or task.lower() == 'fin' or task.lower() == 'fba')):
129 print("Please enter either 'fba', 'fin' or 'ama'.\n")
137 130
138 # Ask the User to enter the ID of the order that he wants to change
131 # Set to 0000 because the current state of the script doesnt need the orderid anymore
139 132 order ='0000' order ='0000'
140 133
141 134 # A filedialog for the export and the report file # A filedialog for the export and the report file
142 135 root = Tk() root = Tk()
143 136 root.withdraw() root.withdraw()
144 print("\n{0}\n".format(line))
145 print("Open the export file of all items, to get the Variation ID which is needed for the Upload.\n")
146 export_file['filepath'] = askopenfilename(initialdir=reportpath
147 , title="Export from Plentymarkets"
148 , filetypes=[ ("csv files" ,"*.csv" ) ] )
149 # detect the encoding of the file
150 with open(export_file['filepath'], mode='rb') as item:
151 raw_data = item.read()
152 export_file['encoding'] = chardet.detect(raw_data)['encoding']
137 if(task.lower() == 'ama' or task.lower() == 'fba'):
138 print("\n{0}\n".format(line))
139 print("Open the export file of all items, to get the Variation ID which is needed for the Upload.\n")
140 export_file['filepath'] = askopenfilename(initialdir=reportpath
141 , title="Export from Plentymarkets"
142 , filetypes=[ ("csv files" ,"*.csv" ) ] )
143 # detect the encoding of the file
144 with open(export_file['filepath'], mode='rb') as item:
145 raw_data = item.read()
146 export_file['encoding'] = chardet.detect(raw_data)['encoding']
153 147
154 148 # AMAZON RECEIVED PART # AMAZON RECEIVED PART
155 if(task.lower() == 'amazon'):
149 if(task.lower() == 'ama'):
156 150 print("Open the report file of the recent delivered FBA packages,\nthis will contain the amount of items that amazon received.\n") print("Open the report file of the recent delivered FBA packages,\nthis will contain the amount of items that amazon received.\n")
157 151 print("\n{0}\n".format(line)) print("\n{0}\n".format(line))
158 152 shipment_file['filepath'] = askopenfilename(initialdir=reportpath shipment_file['filepath'] = askopenfilename(initialdir=reportpath
 
... ... def main():
171 165 print("Something went terribly wrong...") print("Something went terribly wrong...")
172 166 print(Err) print(Err)
173 167
174 # NEW ORDER IMPORT PART
175 if(task.lower() == 'order'):
176 print("Open the Excel list of items to be ordered.\n")
177 print("\n{0}\n".format(line))
168 # FINISH SHIPMENT PART
169 if(task.lower() == 'fin'):
170 print("{0}\n".format(line))
171 print("Open the finished picklist as .csv\n")
172 print("{0}\n".format(altline))
173 print("Öffne die fertig gestellte Pickliste im .csv Format\n")
178 174 shipment_file['filepath'] = askopenfilename(initialdir=reportpath shipment_file['filepath'] = askopenfilename(initialdir=reportpath
179 , title="Order list for production"
175 , title="Finished picklist from the shipment"
180 176 , filetypes=[ ("csv files" ,"*.csv" ) ] ) , filetypes=[ ("csv files" ,"*.csv" ) ] )
181 177 # detect the encoding of the file # detect the encoding of the file
182 178 with open(shipment_file['filepath'], mode='rb') as item: with open(shipment_file['filepath'], mode='rb') as item:
 
... ... def main():
184 180 shipment_file['encoding'] = chardet.detect(raw_data)['encoding'] shipment_file['encoding'] = chardet.detect(raw_data)['encoding']
185 181
186 182 try: try:
187 order = importNewOrder(export=export_file, folder=uploadpath, orderlist=shipment_file,
188 orderid=order, producerlist=producer,
189 plentyid=configid)
183 plenty_Data = {}
184 plenty_Data = finishShipment(picklist=shipment_file, folder=reportpath)
185 writeNewCsv(dataset=plenty_Data['data'],
186 path=uploadpath,
187 header=plenty_Data['fields'],
188 name='Plenty_Stock')
190 189 except Exception as Err: except Exception as Err:
191 190 print("Something went terribly wrong...") print("Something went terribly wrong...")
192 191 print(Err) print(Err)
 
... ... def main():
207 206 importAmazonOrder(export=export_file, reportfolder=reportpath, folder=uploadpath, importAmazonOrder(export=export_file, reportfolder=reportpath, folder=uploadpath,
208 207 orderid=order, plentyid=configid, stockreport=shipment_file orderid=order, plentyid=configid, stockreport=shipment_file
209 208 ) )
210 #try:
211 #print("here will be the function for the ExcelSheet")
212 #createExcelSheet(export, report)
213 #except Exception as Err:
214 #print("Something went terribly wrong...")
215 #print(Err)
216 209
217 210 if __name__ == '__main__': if __name__ == '__main__':
218 211 main() main()
File packages/__pycache__/picklist_creation.cpython-37.pyc changed (mode: 100644) (index 2a63a0d..848d35c)
File packages/__pycache__/shipment_finish.cpython-37.pyc added (mode: 100644) (index 0000000..d5479a5)
File packages/__pycache__/syncfile.cpython-37.pyc changed (mode: 100644) (index 10ed670..d08846b)
File packages/shipment_finish.py added (mode: 100644) (index 0000000..98276cb)
1 """Finish the shipment by taking the the completed picking list
2 and sorting them into the official lists of Amazon"""
3
4 import tkinter
5 import tkinter.filedialog
6 import os
7 import sys
8 import csv
9 import chardet
10
11 # Define and initialize the line seperators
12 line = "#"*70
13 altline = "-"*70
14
15
16 def finishShipment(picklist, folder):
17 # keys: barcode, packages : { package : {qty, location, packet} }
18 # for the inboundplan for loop through all packages
19
20 Data = {}
21 shipped_items = {}
22
23 column_names = ['barcode', 'packages']
24
25 # Check the picklist for encoding
26 with open(picklist['filepath'], mode='rb') as item:
27 raw_data = item.read()
28 picklist['encoding'] = chardet.detect(raw_data)['encoding']
29
30 # Open the picklist and get combine all rows where the same sku was taken from
31 # multiple locations
32 with open(picklist['filepath'], mode='r', encoding=picklist['encoding']) as item:
33 reader = csv.DictReader(item, delimiter=';')
34
35 for row in reader:
36 try:
37 if('Versand' in [*row]):
38 if(row['Versand']):
39 if(not(row['Sku'] in [*shipped_items])):
40 # Create a list of rows for each SKU
41 shipped_items[row['Sku']] = list()
42 shipped_items[row['Sku']].append(row)
43 elif(row['Sku'] in [*shipped_items]):
44 shipped_items[row['Sku']].append(row)
45
46 if(not(row['Barcode'])):
47 print("WARNING: SKU: {0}\t has no Barcode!\n".format(row['Sku']))
48 else:
49 print("There is no column 'Versand'!\n")
50 print("press ENTER to continue...\n")
51 input()
52 sys.exit()
53 except KeyError:
54 print("The keys of the picklist are:\n{0}\n".format("\n".join([*row])))
55 print("press ENTER to continue...\n")
56 input()
57 sys.exit()
58 except Exception as err:
59 print("ERROR: {0} at {1}.\n".format(err, sys.exc_info()[2].tb_lineno))
60 print("press ENTER to continue...\n")
61 input()
62 sys.exit()
63
64 # Go through the shipped_items dictionary and fill the Data dictionary
65 try:
66 for sku in shipped_items:
67 packages = {}
68
69 for index, row in enumerate( shipped_items[ sku ] ):
70 packages[int( index )] = {'quantity':row['Versand'],
71 'packet':row['Kiste'],
72 'location':row['location']}
73
74 values = [shipped_items[ sku ][0]['Barcode'], packages]
75
76 Data[sku] = dict(zip(column_names, values))
77 except Exception as err:
78 print("ERROR: {0} at {1}.\n".format(err, sys.exc_info()[2].tb_lineno))
79 print("press ENTER to continue...\n")
80 input()
81 sys.exit()
82
83 # Check the values of Data TEST
84 #for row in Data:
85 # print("SKU: {0}, Barcode: {1}\n".format( row, Data[ row ]['barcode'] ))
86 # for package in Data[ row ]['packages']:
87 # print("QTY: {0}, PACKET: {1}, from LOCATION: {2}\n"
88 # .format(Data[row]['packages'][ package ]['quantity'],
89 # Data[row]['packages'][ package ]['packet'],
90 # Data[row]['packages'][ package ]['location']))
91
92 #Filling out a inbound plan from amazon
93 createInboundPlan(dataset=Data, folder=folder)
94 #Reducing the storage location quantity in plentymarkets
95 plenty_Data = {}
96 plenty_Data = reducePlentyMarketsQty(dataset=Data, folder=folder)
97
98 return plenty_Data
99
100 def createInboundPlan(dataset, folder):
101 root = tkinter.Tk()
102 root.withdraw()
103
104 print("{0}\n".format(line))
105 print("In order to fill out the Inbound plan, please go to\n")
106 print("Amazon->Inventory->Manage FBA Shipments->Upload Inbound Plan File\n")
107 print("Download a Template and save the sheet 'create inboundplan template'\n")
108 print("as .csv, in the Report folder.\n")
109 print("{0}\n".format(altline))
110 print("Um den Anlieferplan auszufüllen, bitte gehe auf\n")
111 print("Amazon->Lagerbestand->Sendungen an Amazon verwalten->Anlieferplan hochladen\n")
112 print("Lade eine Vorlage herunter und speichere den sheet\n")
113 print("'Vorlage für Anlieferplan erstellen' als .csv in Report\n")
114 print("{0}\n".format(line))
115
116 print("press ENTER to continue...\n")
117 input()
118
119 inboundplan = {'filepath':'',
120 'encoding':''}
121
122 inboundplan['filepath'] = tkinter.filedialog.askopenfilename(initialdir=folder,
123 title="Inbound-plan Template file")
124
125 if(inboundplan['filepath']):
126 # Get encoding of the file
127 with open(inboundplan['filepath'], mode='rb') as item:
128 raw_data = item.read()
129 inboundplan['encoding'] = chardet.detect(raw_data)['encoding']
130
131 # Check if the file has the right template
132 with open(inboundplan['filepath'], mode='r', encoding=inboundplan['encoding']) as item:
133 reader = csv.DictReader(item, delimiter="\t")
134
135 for i in range(10):
136 next(reader)
137
138 for row in reader:
139 if(not( 'PlanName' in [*row])):
140 print("Wrong File Type!\n")
141 print("press ENTER to continue...\n")
142 input()
143 sys.exit()
144 else:
145 break
146
147 with open(inboundplan['filepath'], mode='a', encoding=inboundplan['encoding']) as item:
148 writer = csv.DictWriter(item, delimiter='\t', fieldnames=['MerchantSKU', 'Quantity'])
149
150 for row in dataset:
151 sku_total_qty = 0
152 for package in dataset[row]['packages']:
153 sku_total_qty += int( dataset[row]['packages'][ package ]['quantity'] )
154
155 try:
156 writer.writerow({ 'MerchantSKU':row, 'Quantity':sku_total_qty })
157 except Exception as err:
158 print("ERROR: {0}\n".format(err))
159 print("press ENTER to continue...\n")
160 input()
161
162 if(os.path.isfile(inboundplan['filepath'])):
163 print("{0}\n".format(line))
164 print("File was created at\n{0}.\n".format(folder))
165 print("Please make sure to fill out all delivery data.\n")
166 print("{0}\n".format(altline))
167 print("Datei wurde erstellt in\n{0}.\n".format(folder))
168 print("Bitte stelle sicher das alle Versandsinformationen eingetragen sind.\n")
169 print("{0}\n".format(line))
170 else:
171 print("{0}\n".format(line))
172 print("Something went wrong..\n")
173 print("{0}\n".format(line))
174 print("press ENTER to continue...\n")
175 input()
176 else:
177 print("{0}\n".format(line))
178 print("No file choosen, skipping inbound plan creation...\n")
179
180 def reducePlentyMarketsQty(dataset, folder):
181 root = tkinter.Tk()
182 root.withdraw()
183
184 print("{0}\n".format(line))
185 print("Please get an export of the Plentymarkets locations\n")
186 # This part changes when dynamic export get deprecated
187 print("Go to Plentymarkets->Data->dynamic export->ID 49(location dataformat)\n")
188 print("choose only positive physical content and click on the cog symbol.\n")
189 print("Save it inside the Report folder.\n")
190 print("{0}\n".format(altline))
191 print("Bitte exportiere die aktuellen Plentymarkets Lagerplätze\n")
192 print("Gehe auf Plentymarkets->Daten->dynamischer Export->ID 49(Lagerplatz Datenformat)\n")
193 print("Wähle nur positven physischen Lagerbestand und klicke auf das Zahnrad Symbol.\n")
194 print("Speichere diesen Export im Report Ordner.\n")
195 print("{0}\n".format(line))
196
197 print("press ENTER to continue...\n")
198 input()
199
200 locationlist = {'filepath':'',
201 'encoding':''}
202
203 locationlist['filepath'] = tkinter.filedialog.askopenfilename(initialdir=folder,
204 title="Current locationlist from Plentymarkets")
205
206 if(locationlist['filepath']):
207 # Get encoding of the file
208 with open(locationlist['filepath'], mode='rb') as item:
209 raw_data = item.read()
210 locationlist['encoding'] = chardet.detect(raw_data)['encoding']
211
212 # Read the Data from the location list into a Data Dictionary
213 Data = {}
214
215 column_names = ['LocationName', 'LocationID', 'ItemID',
216 'VariationNo', 'VariationString', 'ItemTextName',
217 'Barcode', 'Stock', 'WarehouseID', 'VariationID']
218
219 with open(locationlist['filepath'], mode='r', encoding=locationlist['encoding']) as item:
220 reader = csv.DictReader(item, delimiter=";")
221
222 for row in reader:
223 value = ''
224 values = [value for value in range( len(column_names) )]
225 for index, name in enumerate( column_names ):
226 values[index] = row[column_names[index]]
227 # remove the ,00 from every stock number
228 if(name == 'Stock'):
229 try:
230 values[index] = int( float( values[index].replace(',','.') ) )
231 except Exception as err:
232 print("ERROR @ ,00 removal : {0}\n".format(err))
233 print("values[index] : {0}, values[index] type : {1}\n".format(values[index], type(values[index])))
234 print("row['VariationNo'] : {0} \n Header List: {1}\n".format(row['VariationNo'], " , ".join([*row])))
235 print("press ENTER to continue...\n")
236 input()
237
238 Data[row['VariationNo'] + '-' + str(row['LocationID'])] = dict(zip(column_names, values))
239
240 # subtract the shipping quantity (dataset dictionary) from the Stock (Data dictionary)
241 # When the SKU and the LocationName match
242 for data_row in Data:
243 for pick_row in dataset:
244 for package in dataset[pick_row]['packages']:
245 if(dataset[pick_row]['barcode'] == Data[data_row]['Barcode']\
246 and dataset[pick_row]['packages'][package]['location'] == Data[data_row]['LocationName']):
247 #print("OLD: {0}\t".format( Data[data_row]['Stock'] ))
248 #print("SHIPPED: {0}\t".format(int(dataset[pick_row]['packages'][package]['quantity'])))
249
250 Data[data_row]['Stock'] = int(Data[data_row]['Stock']) - int(dataset[pick_row]['packages'][package]['quantity'])
251
252 #print("NEW: {0}\n".format( Data[data_row]['Stock'] ))
253
254 Data_and_fields = {'data':Data, 'fields':column_names}
255 return Data_and_fields
256
File packages/syncfile.py changed (mode: 100644) (index a61e4fd..a47770b)
... ... import tkinter.filedialog
6 6 from os.path import isfile from os.path import isfile
7 7 from packages import picklist_creation from packages import picklist_creation
8 8
9 # Define and initialize the line seperators
10 line = "#"*70
11 altline = "|"*70
12
13 9 def writeNewCsv(dataset, path, header, name): def writeNewCsv(dataset, path, header, name):
14 10 '''Write Data into new CSV for Upload '''Write Data into new CSV for Upload
15 11 OUTPUT OUTPUT
 
... ... def importNewOrder(export, folder, orderlist, orderid, producerlist, plentyid):
292 288
293 289 return orderid return orderid
294 290
295 def createInboundPlan(folder, shipmentlist, deliverydata):
296 # Get the Inbound plan from amazon fill it out with the information from
297 # the deliverydata
298 root = tkinter.Tk()
299 root.withdraw()
300
301 print("{0}\n".format(line))
302 print("In order to fill out the Inbound plan, please go to\n")
303 print("Amazon->Inventory->Manage FBA Shipments->Upload Inbound Plan File\n")
304 print("Download a Template and save the sheet 'create inboundplan template'\n")
305 print("as .csv, in the Report folder.\n")
306 print("{0}\n".format(altline))
307 print("Um den Anlieferplan auszufüllen, bitte gehe auf\n")
308 print("Amazon->Lagerbestand->Sendungen an Amazon verwalten->Anlieferplan hochladen\n")
309 print("Lade eine Vorlage herunter und speichere den sheet\n")
310 print("'Vorlage für Anlieferplan erstellen' als .csv in Report\n")
311 print("{0}\n".format(line))
312
313 os.system('pause')
314
315 inboundplan = tkinter.filedialog.askopenfilename(initialdir=folder,
316 title="Inbound-plan Template file")
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/initBasti/Complete_Order_Plenty_Update

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/initBasti/Complete_Order_Plenty_Update

Clone this repository using git:
git clone git://git.rocketgit.com/user/initBasti/Complete_Order_Plenty_Update

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main