File inventory_synchronisation.py changed (mode: 100644) (index 523ff69..c5cbc34) |
... |
... |
import sys |
4 |
4 |
import os |
import os |
5 |
5 |
import re |
import re |
6 |
6 |
import chardet |
import chardet |
|
7 |
|
import requests |
7 |
8 |
from packages.syncfile import importFBA_Shipment, writeNewCsv |
from packages.syncfile import importFBA_Shipment, writeNewCsv |
8 |
9 |
from packages.shipment_finish import finishShipment |
from packages.shipment_finish import finishShipment |
9 |
10 |
from packages.plenty_export import plentyExport |
from packages.plenty_export import plentyExport |
|
... |
... |
def main(): |
19 |
20 |
|
|
20 |
21 |
use_current_dir = 'x' |
use_current_dir = 'x' |
21 |
22 |
newpath = '' |
newpath = '' |
22 |
|
export_file = {"filepath":"", |
|
23 |
|
"encoding":""} |
|
24 |
23 |
shipment_file = {"filepath":"", |
shipment_file = {"filepath":"", |
25 |
24 |
"encoding":""} |
"encoding":""} |
26 |
25 |
# Check if there is already a Report folder for the Amazon report files, if not create a new one. |
# Check if there is already a Report folder for the Amazon report files, if not create a new one. |
27 |
26 |
reportpath = os.getcwd() + '/Report' |
reportpath = os.getcwd() + '/Report' |
28 |
27 |
uploadpath = os.getcwd() + '/Upload' |
uploadpath = os.getcwd() + '/Upload' |
29 |
28 |
configpath = os.getcwd() + '/config.txt' |
configpath = os.getcwd() + '/config.txt' |
|
29 |
|
exporturl = '' |
30 |
30 |
|
|
31 |
31 |
print("\nCurrent directory : {0}\n".format(os.getcwd())) |
print("\nCurrent directory : {0}\n".format(os.getcwd())) |
32 |
32 |
if( not( os.path.exists(reportpath) ) or not( os.path.exists(uploadpath) ) ): |
if( not( os.path.exists(reportpath) ) or not( os.path.exists(uploadpath) ) ): |
|
... |
... |
def main(): |
47 |
47 |
else: |
else: |
48 |
48 |
print("y|n\n") |
print("y|n\n") |
49 |
49 |
|
|
50 |
|
with open(configpath , mode = 'w') as config: |
|
51 |
|
config.write( "#-Config file for the FBA Shipment Script;\n" ) |
|
52 |
|
config.write( "#= '#= marks the beginning of a comment', '= splits between name and value';\n" ) |
|
53 |
|
config.write( "#=location of upload and report folder;\n" ) |
|
54 |
|
config.write( "upload_folder = {0};\n".format(uploadpath) ) |
|
55 |
|
config.write( "report_folder = {0};\n".format(reportpath) ) |
|
56 |
50 |
else: |
else: |
57 |
51 |
if(os.path.isfile(configpath)): |
if(os.path.isfile(configpath)): |
58 |
52 |
with open(configpath, mode = 'r') as config: |
with open(configpath, mode = 'r') as config: |
|
... |
... |
def main(): |
68 |
62 |
uploadpath = option[1].strip(' ') |
uploadpath = option[1].strip(' ') |
69 |
63 |
if(option[0].strip(' ') == 'report_folder'): |
if(option[0].strip(' ') == 'report_folder'): |
70 |
64 |
reportpath = option[1].strip(' ') |
reportpath = option[1].strip(' ') |
|
65 |
|
|
71 |
66 |
else: |
else: |
72 |
67 |
if( not( os.path.exists(configpath) ) ): |
if( not( os.path.exists(configpath) ) ): |
73 |
68 |
with open(configpath , mode = 'w') as config: |
with open(configpath , mode = 'w') as config: |
|
... |
... |
def main(): |
76 |
71 |
config.write( "#=location of upload and report folder;\n" ) |
config.write( "#=location of upload and report folder;\n" ) |
77 |
72 |
config.write( "upload_folder = {0};\n".format(uploadpath) ) |
config.write( "upload_folder = {0};\n".format(uploadpath) ) |
78 |
73 |
config.write( "report_folder = {0};\n".format(reportpath) ) |
config.write( "report_folder = {0};\n".format(reportpath) ) |
|
74 |
|
config.write( "export_url = {0};\n".format(exporturl) ) |
79 |
75 |
|
|
80 |
76 |
if(not(os.path.exists(uploadpath) or os.path.exists(reportpath))): |
if(not(os.path.exists(uploadpath) or os.path.exists(reportpath))): |
81 |
|
newpath = askdirectory(title="Choose the directory for the folders") |
|
82 |
|
uploadpath = os.path.join(newpath, os.sep, 'Upload') |
|
83 |
|
reportpath = os.path.join(newpath, os.sep, 'Report') |
|
84 |
|
configpath = os.path.join(newpath, os.sep, 'Config.txt') |
|
85 |
|
with open(configpath , mode = 'w') as config: |
|
86 |
|
config.write( "#-Config file for the FBA Shipment Script;\n" ) |
|
87 |
|
config.write( "#= '#= marks the beginning of a comment', '= splits between name and value';\n" ) |
|
88 |
|
config.write( "#=location of upload and report folder;\n" ) |
|
89 |
|
config.write( "upload_folder = {0};\n".format(uploadpath) ) |
|
90 |
|
config.write( "report_folder = {0};\n".format(reportpath) ) |
|
|
77 |
|
write_new_config(exporturl='') |
|
78 |
|
|
|
79 |
|
# Get the Export URL |
|
80 |
|
if(os.path.exists(configpath)): |
|
81 |
|
with open(configpath, mode='r') as config: |
|
82 |
|
# Take every row into a list rows and strip them of spaces and new lines |
|
83 |
|
rows = (row.strip(' ').strip('\n').split(';') for row in config) |
|
84 |
|
|
|
85 |
|
for row in rows: |
|
86 |
|
# combine the list to a string and split it at the '=' |
|
87 |
|
option = "".join(row[0]).split('=') |
|
88 |
|
|
|
89 |
|
if(not(option[0].strip(' ') == '#')): |
|
90 |
|
if(option[0].strip(' ') == 'export_url'): |
|
91 |
|
exporturl = option[1].strip(' ').strip("'") |
|
92 |
|
|
91 |
93 |
|
|
92 |
94 |
|
|
93 |
95 |
# 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 |
|
... |
... |
def main(): |
96 |
98 |
print("{0}\n".format(line)) |
print("{0}\n".format(line)) |
97 |
99 |
print(" Preparation for the Script / Vorbereitung für den Script\n") |
print(" Preparation for the Script / Vorbereitung für den Script\n") |
98 |
100 |
print("{0}\n".format(line)) |
print("{0}\n".format(line)) |
99 |
|
print(" Get a export of all variations from plentymarkets\n & save it in Report\n") |
|
100 |
|
print(" Lade einen Export von allen Varianten in Plentymarkets\n & speichere diesen in Report\n") |
|
|
101 |
|
print(" The export is going to be downloaded automatically, if there are new items:\n Go to ElasticExport and download the 'Versand-Export'\n") |
|
102 |
|
print(" Der Export wird automatisch heruntergeladen, falls neue Produkte erstellt wurden:\n Gehe zum ElasticExport und lade den 'Versand-Export'\n") |
101 |
103 |
print("{0}\n".format(altline)) |
print("{0}\n".format(altline)) |
102 |
104 |
print(" Save your Storagereport from Amazon as .csv and name the column\n of the units to be sent as FBA-SHIPMENT\n") |
print(" Save your Storagereport from Amazon as .csv and name the column\n of the units to be sent as FBA-SHIPMENT\n") |
103 |
105 |
print(" Speichere deine Lagerbestandsdatei as .csv und benenne die Spalte\n mit den zu versendenden Artikeln als FBA-SHIPMENT\n") |
print(" Speichere deine Lagerbestandsdatei as .csv und benenne die Spalte\n mit den zu versendenden Artikeln als FBA-SHIPMENT\n") |
|
... |
... |
def main(): |
120 |
122 |
root.withdraw() |
root.withdraw() |
121 |
123 |
if(task.lower() == 'ama' or task.lower() == 'fba'): |
if(task.lower() == 'ama' or task.lower() == 'fba'): |
122 |
124 |
print("\n{0}\n".format(line)) |
print("\n{0}\n".format(line)) |
123 |
|
print("Open the export file of all items, to get the Variation ID which is needed for the Upload.\n") |
|
124 |
|
export_file['filepath'] = askopenfilename(initialdir=reportpath |
|
125 |
|
, title="Export from Plentymarkets" |
|
126 |
|
, filetypes=[ ("csv files" ,"*.csv" ) ] ) |
|
127 |
|
# detect the encoding of the file |
|
128 |
|
with open(export_file['filepath'], mode='rb') as item: |
|
129 |
|
raw_data = item.read(10000) |
|
130 |
|
export_file['encoding'] = chardet.detect(raw_data)['encoding'] |
|
|
125 |
|
try: |
|
126 |
|
print("Check if the current URL of the Export from Plentymarkets is valid: {0}\n" |
|
127 |
|
.format(requests.get(exporturl).status_code == 200)) |
|
128 |
|
if(not( requests.get(exporturl).status_code == 200 )): |
|
129 |
|
print("The Url : {0} isn't pointing to a valid file!".format(exporturl)) |
|
130 |
|
print("(If you want to change the URL go to the config and edit it)") |
|
131 |
|
except Exception as err: |
|
132 |
|
print("ERROR @ checking export url: {0}".format(err)) |
|
133 |
|
exporturl = input("Failed to load the url please enter it directly:\n") |
|
134 |
|
print("Check if the current URL of the Export from Plentymarkets is valid: {0}\n" |
|
135 |
|
.format(requests.get(exporturl).status_code == 200)) |
|
136 |
|
if( requests.get(exporturl).status_code == 200 ): |
|
137 |
|
write_new_config(exporturl=exporturl, newpath=os.path.normpath(reportpath + os.sep + os.pardir), |
|
138 |
|
uploadpath=uploadpath, reportpath=reportpath, configpath=configpath) |
|
139 |
|
|
|
140 |
|
|
131 |
141 |
|
|
132 |
142 |
# FINISH SHIPMENT PART |
# FINISH SHIPMENT PART |
133 |
143 |
if(task.lower() == 'fin'): |
if(task.lower() == 'fin'): |
|
... |
... |
def main(): |
172 |
182 |
raw_data = item.read(12000) |
raw_data = item.read(12000) |
173 |
183 |
shipment_file['encoding'] = chardet.detect(raw_data)['encoding'] |
shipment_file['encoding'] = chardet.detect(raw_data)['encoding'] |
174 |
184 |
|
|
175 |
|
importFBA_Shipment(export=export_file, reportfolder=reportpath, folder=uploadpath, |
|
|
185 |
|
importFBA_Shipment(exporturl=exporturl, reportfolder=reportpath, folder=uploadpath, |
176 |
186 |
stockreport=shipment_file |
stockreport=shipment_file |
177 |
187 |
) |
) |
178 |
188 |
|
|
|
... |
... |
def main(): |
209 |
219 |
|
|
210 |
220 |
if __name__ == '__main__': |
if __name__ == '__main__': |
211 |
221 |
main() |
main() |
|
222 |
|
|
|
223 |
|
def write_new_config(exporturl, newpath='', uploadpath='', reportpath='', configpath=''): |
|
224 |
|
if(not(newpath)): |
|
225 |
|
newpath = askdirectory(title="Choose the directory for the folders") |
|
226 |
|
if(not(uploadpath or reportpath or configpath)): |
|
227 |
|
uploadpath = os.path.join(newpath, os.sep, 'Upload') |
|
228 |
|
reportpath = os.path.join(newpath, os.sep, 'Report') |
|
229 |
|
configpath = os.path.join(newpath, os.sep, 'Config.txt') |
|
230 |
|
|
|
231 |
|
with open(configpath , mode = 'w') as config: |
|
232 |
|
config.write( "#-Config file for the FBA Shipment Script;\n" ) |
|
233 |
|
config.write( "#= '#= marks the beginning of a comment', '= splits between name and value';\n" ) |
|
234 |
|
config.write( "#=location of upload and report folder;\n" ) |
|
235 |
|
config.write( "upload_folder = {0};\n".format(uploadpath) ) |
|
236 |
|
config.write( "report_folder = {0};\n".format(reportpath) ) |
|
237 |
|
config.write( "export_url = {0};\n".format(exporturl) ) |
|
238 |
|
|
File packages/picklist_creation.py changed (mode: 100644) (index 332e2e3..bf26c91) |
1 |
1 |
from tkinter import Tk |
from tkinter import Tk |
2 |
2 |
import csv |
import csv |
3 |
3 |
import chardet |
import chardet |
|
4 |
|
import re |
4 |
5 |
from tkinter.filedialog import askopenfilename |
from tkinter.filedialog import askopenfilename |
5 |
6 |
from packages import syncfile |
from packages import syncfile |
6 |
7 |
|
|
|
... |
... |
def picklist_creation(shipmentlist, folder, uploadfolder): |
19 |
20 |
location_file['encoding'] = chardet.detect(raw_data)['encoding'] |
location_file['encoding'] = chardet.detect(raw_data)['encoding'] |
20 |
21 |
|
|
21 |
22 |
# The headers of the outputfile |
# The headers of the outputfile |
22 |
|
column_names = ['Sku', 'location', 'Barcode', '@location', 'Shipment', 'Versand', 'Kiste'] |
|
|
23 |
|
column_names = ['Sku', 'location', 'EAN-Barcode', 'FNSKU-Barcode', |
|
24 |
|
'@location', 'Shipment', 'Versand', 'Kiste'] |
23 |
25 |
|
|
24 |
26 |
# Define the Dictionary for the datasets and the list for multiple locations |
# Define the Dictionary for the datasets and the list for multiple locations |
25 |
27 |
# on a single SKU |
# on a single SKU |
|
... |
... |
def picklist_creation(shipmentlist, folder, uploadfolder): |
52 |
54 |
shipping_items.append(row['SKU']) |
shipping_items.append(row['SKU']) |
53 |
55 |
|
|
54 |
56 |
items_in_skulist = 0 |
items_in_skulist = 0 |
|
57 |
|
|
55 |
58 |
for skulist in locations: |
for skulist in locations: |
56 |
59 |
number = 0 |
number = 0 |
57 |
60 |
for index, row in enumerate( locations[ skulist ] ): |
for index, row in enumerate( locations[ skulist ] ): |
|
61 |
|
stock = 0 |
58 |
62 |
if(row['VariationNo'] in [*shipping_items]): |
if(row['VariationNo'] in [*shipping_items]): |
|
63 |
|
if(row['Stock']): |
|
64 |
|
stock = int(float(str( row['Stock']).replace(',', '.') )) |
59 |
65 |
items_in_skulist += 1 |
items_in_skulist += 1 |
60 |
66 |
number += 1 |
number += 1 |
61 |
|
values = [row['VariationNo'], row['LocationName'], row['Barcode'], row['Stock'], ''] |
|
|
67 |
|
values = [row['VariationNo'], row['LocationName'], '', row['Barcode'], stock, ''] |
62 |
68 |
|
|
63 |
69 |
Data[row['VariationNo'] + '+' + str(number)] = dict(zip(column_names, values)) |
Data[row['VariationNo'] + '+' + str(number)] = dict(zip(column_names, values)) |
64 |
70 |
|
|
|
... |
... |
def picklist_creation(shipmentlist, folder, uploadfolder): |
69 |
75 |
for row in reader: |
for row in reader: |
70 |
76 |
if(row['SKU']+'+1' in [*Data]): |
if(row['SKU']+'+1' in [*Data]): |
71 |
77 |
Data[row['SKU']+'+1']['Shipment'] = row['QTY'] |
Data[row['SKU']+'+1']['Shipment'] = row['QTY'] |
|
78 |
|
try: |
|
79 |
|
for index, search_match in enumerate( re.findall(row['SKU'], ",".join([*Data])) ): |
|
80 |
|
Data[search_match + '+' + str(index + 1)]['EAN-Barcode'] = row['EAN'] |
|
81 |
|
except KeyError as err: |
|
82 |
|
print("KeyError: {0}\n".format(err)) |
72 |
83 |
|
|
73 |
84 |
syncfile.writeNewCsv(dataset=Data,path=uploadfolder, header=column_names,name='picklist') |
syncfile.writeNewCsv(dataset=Data,path=uploadfolder, header=column_names,name='picklist') |
74 |
85 |
|
|
75 |
|
print("press ENTER to continue...\n") |
|
76 |
|
input() |
|
File packages/syncfile.py changed (mode: 100644) (index dfe86b0..aba9469) |
... |
... |
import sys |
2 |
2 |
import csv |
import csv |
3 |
3 |
import re |
import re |
4 |
4 |
import tkinter |
import tkinter |
|
5 |
|
import pandas |
5 |
6 |
import tkinter.filedialog |
import tkinter.filedialog |
6 |
7 |
from os.path import isfile |
from os.path import isfile |
7 |
8 |
from packages import picklist_creation |
from packages import picklist_creation |
|
... |
... |
def writeNewCsv(dataset, path, header, name): |
33 |
34 |
return output_path |
return output_path |
34 |
35 |
|
|
35 |
36 |
|
|
36 |
|
def importFBA_Shipment(export, reportfolder, folder, stockreport=''): |
|
|
37 |
|
def importFBA_Shipment(exporturl, reportfolder, folder, stockreport=''): |
37 |
38 |
# Define the headers of the new Sync File |
# Define the headers of the new Sync File |
38 |
|
column_names = ['SKU', 'ID', 'QTY'] |
|
|
39 |
|
column_names = ['SKU', 'ID', 'EAN', 'QTY'] |
39 |
40 |
|
|
40 |
41 |
# The beginning of the name of the file |
# The beginning of the name of the file |
41 |
42 |
syncname = '' |
syncname = '' |
|
... |
... |
def importFBA_Shipment(export, reportfolder, folder, stockreport=''): |
44 |
45 |
# initialize a dictionary to save the necessary data |
# initialize a dictionary to save the necessary data |
45 |
46 |
Data = {} |
Data = {} |
46 |
47 |
syncname = 'fba_shipment' |
syncname = 'fba_shipment' |
|
48 |
|
sku = '' |
|
49 |
|
amount = '' |
|
50 |
|
exportEAN = '' |
|
51 |
|
exportID = '' |
|
52 |
|
|
|
53 |
|
# Load the export from the URL that the elastic export created |
|
54 |
|
export = pandas.read_csv(exporturl, sep=';') |
47 |
55 |
|
|
48 |
56 |
with open(stockreport['filepath'], mode = 'r', encoding=stockreport['encoding']) as item: |
with open(stockreport['filepath'], mode = 'r', encoding=stockreport['encoding']) as item: |
49 |
57 |
reader = csv.DictReader(item, delimiter=';') |
reader = csv.DictReader(item, delimiter=';') |
|
... |
... |
def importFBA_Shipment(export, reportfolder, folder, stockreport=''): |
65 |
73 |
if(int(amount) > 8): |
if(int(amount) > 8): |
66 |
74 |
amount = 5 * round(int( amount ) / 5) |
amount = 5 * round(int( amount ) / 5) |
67 |
75 |
|
|
68 |
|
values = [sku, '', amount] |
|
|
76 |
|
exportEAN = '' |
|
77 |
|
exportFNSKU = '' |
|
78 |
|
if(export.loc[export['Variation.number'] == sku]['Variation.EAN'].values.any()): |
|
79 |
|
exportEAN = export.loc[export['Variation.number'] == sku]['Variation.EAN'].iloc[0] |
|
80 |
|
if(exportEAN == 'nan'): |
|
81 |
|
exportEAN = '' |
|
82 |
|
if(re.match(r'7', str( exportEAN ))): |
|
83 |
|
exportEAN = '0' + str(exportEAN) |
|
84 |
|
if(export.loc[export['Variation.number'] == sku]['Variation.id'].values.any()): |
|
85 |
|
exportID = export.loc[export['Variation.number'] == sku]['Variation.id'].iloc[0] |
69 |
86 |
|
|
70 |
|
Data[sku] = dict(zip(column_names, values)) |
|
|
87 |
|
# locate the right value for the sku by looking up via .loc method in the export |
|
88 |
|
try: |
|
89 |
|
values = [sku, exportID,int( exportEAN ), amount] |
|
90 |
|
except Exception: |
|
91 |
|
values = [sku, exportID, exportEAN, amount] |
71 |
92 |
|
|
72 |
|
# Open the Export file to get the right Variation ID for each SKU on the List |
|
73 |
|
with open(export['filepath'], mode='r', encoding=export['encoding']) as item: |
|
74 |
|
reader = csv.DictReader(item, delimiter=";") |
|
75 |
93 |
|
|
76 |
|
for row in reader: |
|
77 |
|
# Check if the row contains one of the SKU from the list |
|
78 |
|
if(row['VariationNumber'] in [*Data] and row['VariationID']): |
|
79 |
|
Data[row['VariationNumber']]['ID'] = row['VariationID'] |
|
|
94 |
|
Data[sku] = dict(zip(column_names, values)) |
|
95 |
|
|
80 |
96 |
# Write the finished Data dictionary into a new file |
# Write the finished Data dictionary into a new file |
81 |
97 |
|
|
82 |
98 |
shipment = writeNewCsv(dataset=Data, path=folder, header=column_names, name=syncname) |
shipment = writeNewCsv(dataset=Data, path=folder, header=column_names, name=syncname) |