initBasti / Amazon2PlentySync (public) (License: GPLv3) (since 2019-01-27) (hash sha1)
Transfer your data from you Amazon Flatfile spreadsheet over to the Plentymarkets system. How to is included in the readme
List of commits:
Subject Hash Author Date (UTC)
Added Markdown choosing, fixed various bugs 991ed44df370cf80fc2e2c51d7427d63e221888f Sebastian Fricke 2019-08-15 09:30:55
Changed the item upload format to fix errors in the sync, moved active upload to properties because it has to be done seperatly to the creation process 3b466364e3dcdf14b4cef5b8649ec9573c992324 Sebastian Fricke 2019-06-17 14:09:23
Removed the image upload from item upload and added a exportfile together with functions to get the variation id for the image upload, the image upload is now a single process 6349c4a7177345c25aa6d8ecd03740a75fa2520f Sebastian Fricke 2019-06-13 12:58:36
Updated the feature list to the current active list b5d1675bcb56c38a97c928d7800b6a29c2dea116 LagerBadel PC:Magdalena 2019-06-11 12:11:06
fixed a bug with the encoding of very large datasets were the 10000 letters were not enough, increased waiting time but removed some mistakes that way 8f431d6a68fb21699950b1ca48a1592976789c74 LagerBadel PC:Magdalena 2019-06-06 13:41:52
small debugging improvements in writeCSV and missing colors 88db9e1362a4178805671f443554a7f0d3db9e69 LagerBadel PC:Magdalena 2019-06-06 11:52:31
Major Update added a gui category chooser, attribute id connection and updated the whole Script to work on Elastic Sync a8a6156e26e2783a695c87bda35aba725fd77023 Sebastian Fricke 2019-06-05 12:45:29
fixed a bug with the encoding function 0c5b9dd0414037743bf39fdc3420d55035bffa61 Sebastian Fricke 2019-05-14 15:10:17
Major Update added a config file for better useability and added a gui to enter the category and the name of the product further work towards the rework from dynamic import to elastic sync e4356af15a4b8f7393f85bd51c16b330bc3555af Sebastian Fricke 2019-05-14 14:43:03
Changed the price upload to identify items that are not in plentymarkets and added a webshop price 4ab9bcd988f9eb26647748a8f80f25c8c5b7f2e2 Sebastian Fricke 2019-05-03 09:18:35
added Webshop to marketconnections 84f93694fe0c67972ad951649d9f6f0d577d3e29 Sebastian Fricke 2019-05-01 14:12:00
Added the modelnumber feature and removed the creation of empty features ea98391f2dbdf8fb8e601153b4f6ebfca504929c Sebastian Fricke 2019-05-01 12:31:19
Changed the feature upload into a loop for more overview 0a1bee82659a576c6fb4f2641aa3990d8d686b3c Sebastian Fricke 2019-05-01 10:04:20
Added a few new instructions to the Instructions file b4878c59958f89a02937de1dfc7aabbd23e71061 LagerBadel PC:Magdalena 2019-04-18 09:41:10
Made some fields not required but added Warnings for the log file, additionally some new amazon features were added. 6392338b7e9968be3bc4da9031144c3cc2cfae48 Sebastian Fricke 2019-04-18 09:37:51
Added an error log system and improved overall workflow 2e3763e436899466db9f03f70ea926869afd3219 Sebastian Fricke 2019-04-18 08:12:27
Added additional feature uploads 528cad4899d3e3adca5098c1a0ce92c2a6b8a853 Sebastian Fricke 2019-04-16 10:25:49
Added an optimization for the initial directory for Linux 58b340605cba0603520ada8a184cc9fba5f8c3b8 Sebastian Fricke 2019-04-16 10:22:18
Fixed a typo in the build script f7943d8b2c33b89b083380902f1b1281366a12b2 Sebastian Fricke 2019-04-16 08:13:51
Added a build script for Linux + removed the finished executables 8fcf82d5de859895d29a7f355c0d49700beb4e38 Sebastian Fricke 2019-04-16 08:10:13
Commit 991ed44df370cf80fc2e2c51d7427d63e221888f - Added Markdown choosing, fixed various bugs
Author: Sebastian Fricke
Author date (UTC): 2019-08-15 09:30
Committer name: Sebastian Fricke
Committer date (UTC): 2019-08-15 09:30
Parent(s): 3b466364e3dcdf14b4cef5b8649ec9573c992324
Signing key:
Tree: c89a5325b66c99092f5673335e9244f4bf55d34d
File Lines added Lines deleted
.gitignore 9 0
packages/amazon_data_upload.py 12 19
packages/color.py 2 2
packages/gui/category_chooser.py 44 4
packages/image_upload.py 18 14
packages/item_upload.py 91 79
packages/log_files.py 5 2
packages/price_upload.py 30 20
product_import.py 5 2
File .gitignore added (mode: 100644) (index 0000000..f03b946)
1 /Linux_Version
2 /Windows_Version
3 /packages/__pycache__
4 /Upload
5 /log
6 config.txt
7 main.py
8 /Input_files
9
File packages/amazon_data_upload.py changed (mode: 100644) (index 9712e77..e7ed4aa)
... ... def amazonDataUpload(flatfile):
48 48 'bags':27 'bags':27
49 49 } }
50 50
51 values = ''
51 52 product_type = '' product_type = ''
52 53
53 54 for row in reader: for row in reader:
54 if(row['parent_child'] == 'parent'):
55
56 if(row['feed_product_type'].lower() in [*type_id]):
57 for key in type_id:
58 if(row['feed_product_type'].lower() == key):
59 product_type = type_id[key]
60 if(not(product_type)):
61 raise barcode.EmptyFieldWarning('product_type')
62 values = [product_type, '1', '1']
63
64 Data[row['item_sku']] = SortedDict(zip(column_names, values))
65
66 if(row['parent_child'] == 'child' and row['parent_sku'] in [*Data]):
67 for key in column_names:
68 if(not(Data[ row[ 'parent_sku' ] ][ key ])):
69 try:
70 Data[ row[ 'parent_sku' ] ][ key ] = row[ key ]
71 except Exception as err:
72 print(err)
55 # go through the variations until the values are filled
56 if(row['feed_product_type'].lower() in [*type_id]):
57 for key in type_id:
58 if(row['feed_product_type'].lower() == key):
59 product_type = type_id[key]
60 if(not(product_type)):
61 raise barcode.EmptyFieldWarning('product_type')
62
63 values = [product_type, '1', '1']
64
65 Data[row['item_sku']] = SortedDict(zip(column_names, values))
73 66
74 67 return Data return Data
75 68
File packages/color.py changed (mode: 100644) (index 1d11780..24e0d18)
... ... def create_attributesync(color_dict, path):
66 66 Data = {} Data = {}
67 67 values = [] values = []
68 68
69 for row in color_dict:
69 for index, row in enumerate(color_dict):
70 70 try: try:
71 values = ['4', color_dict[row]['color_name'], color_dict[row]['highest-position'], color_dict[row]['color_name']]
71 values = ['4', color_dict[row]['color_name'], int(float(color_dict[row]['highest-position'])) + int(index + 1), color_dict[row]['color_name']]
72 72 except KeyError as err: except KeyError as err:
73 73 print(color_dict[row]) print(color_dict[row])
74 74 print("ERROR @ attribute sync creation: {0}".format(err)) print("ERROR @ attribute sync creation: {0}".format(err))
File packages/gui/category_chooser.py changed (mode: 100644) (index 1631dae..39554a4)
... ... from tkinter import messagebox as tmb
7 7 from packages import color as clr from packages import color as clr
8 8 from packages import item_upload from packages import item_upload
9 9
10 class MarkingDropdown(tkinter.Frame):
11 def __init__(self, master, *args, **kwargs):
12 tkinter.Frame.__init__(self, master, *args, **kwargs)
13 self.master = master
14 self.args = args
15 self.kwargs = kwargs
16 self.initialize()
17
18 def initialize(self):
19 self.grid()
20
21 self.optionvar = tkinter.StringVar(self)
22 self.resultvar = tkinter.StringVar(self)
23
24 self.options = {
25 'Neu':'14',
26 'Alt':'9',
27 'Item im Upload Prozess':'28'
28 }
29
30 self.optionvar.set('marking')
31
32 self.dropdown_menu = tkinter.OptionMenu(self, self.optionvar, *[ *self.options ])
33 self.dropdown_menu.grid(row=1, column=0, sticky="EW", padx=50)
34
35 self.optionvar.trace('w', self.change_dropdown)
36
37 def change_dropdown(self, *args):
38 if(self.optionvar.get() and not( self.optionvar.get() == 'marking' )):
39 self.resultvar = self.options[ self.optionvar.get() ]
40
10 41 class LabelBox(tkinter.Frame): class LabelBox(tkinter.Frame):
11 42 def __init__(self, master, similar_names): def __init__(self, master, similar_names):
12 43 tkinter.Frame.__init__(self, master) tkinter.Frame.__init__(self, master)
 
... ... class CategoryChooser(tkinter.Tk):
290 321 self.atrpath = atrpath self.atrpath = atrpath
291 322 self.atrdate = atrdate self.atrdate = atrdate
292 323 self.newpath = {'upload-path':'', 'attribute-path':''} self.newpath = {'upload-path':'', 'attribute-path':''}
293 self.data = {'name':'', 'categories':''}
324 self.data = {'name':'', 'categories':'', 'marking':''}
294 325 self.protocol("WM_WINDOW_DELETE", self.close_app) self.protocol("WM_WINDOW_DELETE", self.close_app)
295 326 self.missingcolors = {} self.missingcolors = {}
296 327 # Window position properties # Window position properties
 
... ... class CategoryChooser(tkinter.Tk):
340 371 self.namechooser = tkinter.Entry(self, width=50, bg="white") self.namechooser = tkinter.Entry(self, width=50, bg="white")
341 372 self.namechooser.grid(row=6, columnspan=3, pady=10, padx=10) self.namechooser.grid(row=6, columnspan=3, pady=10, padx=10)
342 373
374 self.markingdesc = DescBox(master=self, desctext="Choose a marking for the product")
375 self.markingdesc.grid(row=7, columnspan=3, pady=10, padx=10)
376
377 self.markingchooser = MarkingDropdown(master=self)
378 self.markingchooser.grid(row=8, columnspan=3, pady=10, padx=10)
379
343 380 self.accept = tkinter.Button(self, text="Accept", self.accept = tkinter.Button(self, text="Accept",
344 command=lambda: self.get_input(self.dropdown.resultbox.get(), self.namechooser.get()))
345 self.accept.grid(row=7, column=3, pady=10, padx=10)
381 command=lambda: self.get_input(self.dropdown.resultbox.get(),
382 self.namechooser.get(),
383 self.markingchooser.resultvar.get()))
384 self.accept.grid(row=9, column=3, pady=10, padx=10)
346 385
347 def get_input(self, categories, name):
386 def get_input(self, categories, name, marking):
348 387 self.data['name'] = name self.data['name'] = name
349 388 self.data['categories'] = categories self.data['categories'] = categories
389 self.data['marking'] = marking
350 390 # Close the gui after accepting the input to stop the mainloop # Close the gui after accepting the input to stop the mainloop
351 391 self.close_app() self.close_app()
352 392
File packages/image_upload.py changed (mode: 100644) (index 13971f0..c416081)
... ... def imageUpload(flatfile, attributefile, exportfile, uploadfolder):
33 33 try: try:
34 34 Data = SortedDict() Data = SortedDict()
35 35
36 column_names = ['Multi-URL', 'connect-variation', 'mandant',
37 'availability', 'listing', 'connect-color']
38 linkstring = ''
36 column_names = ['VariationID', 'Multi-URL', 'connect-variation', 'mandant',
37 'listing', 'connect-color']
39 38 attributeID = '' attributeID = ''
40 39 variation_id = 0 variation_id = 0
41 40
42 41 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item: with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
43 42 reader = csv.DictReader(item, delimiter=';') reader = csv.DictReader(item, delimiter=';')
44 43 for index, row in enumerate( reader ): for index, row in enumerate( reader ):
44 linkstring = ''
45 45 imglinks = [ imglinks = [
46 46 row['main_image_url'], row['main_image_url'],
47 47 row['other_image_url1'], row['other_image_url1'],
 
... ... def imageUpload(flatfile, attributefile, exportfile, uploadfolder):
61 61 for img in imglinks: for img in imglinks:
62 62 if(not(searchSpecialImage(img))): if(not(searchSpecialImage(img))):
63 63 if(not(linkstring)): if(not(linkstring)):
64 linkstring += img + ';' + str( num )
65 num += 1
64 if(img):
65 linkstring += img + ';' + str( num )
66 num += 1
66 67 else: else:
67 linkstring += ',' + img + ';' + str( num )
68 num += 1
68 if(img):
69 linkstring += ',' + img + ';' + str( num )
70 num += 1
69 71 if(searchSpecialImage(img)): if(searchSpecialImage(img)):
70 72 print("\n{0} is a special image\n".format(img)) print("\n{0} is a special image\n".format(img))
71 73 if(not(linkstring)): if(not(linkstring)):
72 linkstring += img + ';' + str( num )
73 num += 1
74 if(img):
75 linkstring += img + ';' + str( num )
76 num += 1
74 77 else: else:
75 linkstring += ',' + img + ';' + str( num )
76 num += 1
78 if(img):
79 linkstring += ',' + img + ';' + str( num )
80 num += 1
77 81
78 82
79 83 except Exception as err: except Exception as err:
 
... ... def imageUpload(flatfile, attributefile, exportfile, uploadfolder):
85 89 print("Error @ get Color Attribute ID {0}\n".format(err)) print("Error @ get Color Attribute ID {0}\n".format(err))
86 90
87 91
88 values=[linkstring, variation_id, -1,
89 -1, -1, attributeID]
92 values=[variation_id, linkstring, 1, -1,
93 -1, attributeID]
90 94
91 95 Data[row['item_sku']] = dict(zip(column_names, values)) Data[row['item_sku']] = dict(zip(column_names, values))
92 96
93 97 except Exception as err: except Exception as err:
94 98 print("Error @ imageupload line: {0} : {1}".format(sys.exc_info()[2].tb_lineno, err)) print("Error @ imageupload line: {0} : {1}".format(sys.exc_info()[2].tb_lineno, err))
95 99
96 barcode.writeCSV(dataobject=Data, name='Image_', columns=column_names, folder=uploadfolder)
100 barcode.writeCSV(dataobject=Data, name='Image_', columns=column_names, upload_path=uploadfolder)
97 101 return Data return Data
File packages/item_upload.py changed (mode: 100644) (index 59433c1..7003fa6)
... ... from os.path import isfile
7 7 from sys import exit from sys import exit
8 8 from packages import barcode, amazon_data_upload, price_upload, image_upload from packages import barcode, amazon_data_upload, price_upload, image_upload
9 9
10
11 try:
12 from sortedcontainers import SortedDict
13 except ImportError:
14 print("the sortedcontainers module is required to run this program.")
15 raise ImportError
16
17 10 class WrongEncodingException(Exception): class WrongEncodingException(Exception):
18 11 pass pass
19 12
20 def check_flatfile(flatfile):
21 try:
22 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
23 reader = csv.DictReader(item, delimiter=';')
24
25 first_row = [* list(reader)[0] ]
26 if(not( 'feed_product_type' in first_row )):
27 if( 'Marke' in first_row ):
28 print("Please cut the first two rows from the flatfile for this script\n")
29 return False
30 else:
31 print("This file contains the wrong column header\n{0}\n".format(','.join(first_row)))
32 return False
33 else:
34 return True
35 except Exception as err:
36 print("ERROR @ flatfile checking : {0}".format(err))
37
38 def check_encoding(file_dict):
39 try:
40 with open(file_dict['path'], mode='rb') as item:
41 try:
42 raw_data = item.read()
43 except Exception as err:
44 print("ERROR: {0}\n".format(err))
45 file_dict['encoding'] = chardet.detect(raw_data)['encoding']
46 print("chardet data for {0}\n{1}\n".format(file_dict['path'], chardet.detect(raw_data)))
47
48 except Exception as err:
49 print("Error : {0}\n".format(err))
50
51 return file_dict
52
53 def get_variationid(exportfile, sku):
54
55 variationid = 0
56 with open(exportfile['path'], mode = 'r', encoding = exportfile['encoding']) as item:
57 reader = csv.DictReader(item, delimiter = ';')
58
59 for row in reader:
60 if(row['VariationNo'] == sku):
61 variationid = row['VariationId']
62 if(not(variationid)):
63 print("No Variation ID found for {0}\n".format(sku))
64
65 return variationid
66
67 13 def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data): def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
68 14 # The column headers for the output file as expected from the # The column headers for the output file as expected from the
69 15 # plentymarkets dataformat # plentymarkets dataformat
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
71 17 'Length', 'Width', 'Length', 'Width',
72 18 'Height', 'Weight', 'Height', 'Weight',
73 19 'Name', 'MainWarehouse', 'Name', 'MainWarehouse',
74 'Attributes',
20 'Attributes', 'Position',
75 21 'ItemOriginCountry', 'ItemTextKeywords', 'ItemOriginCountry', 'ItemTextKeywords',
76 22 'ItemProducer', 'ItemProducerID', 'ItemProducer', 'ItemProducerID',
77 23 'ItemTextName', 'ItemTextDescription', 'ItemTextName', 'ItemTextDescription',
78 24 'ExternalID', 'ExternalID',
25 'NetStockPositivVis', 'NetStockNegativInvis',
79 26 'VariationAvailability', 'Category-IDs', 'VariationAvailability', 'Category-IDs',
80 27 'Standard-Category', 'Standard-Category-Webshop', 'Standard-Category', 'Standard-Category-Webshop',
81 28 'Mandant-Active', 'Webshop-Active', 'Mandant-Active', 'Webshop-Active',
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
107 54
108 55 # PACKAGE PROPERTIES # PACKAGE PROPERTIES
109 56 package_properties = get_properties(flatfile) package_properties = get_properties(flatfile)
57 group_parent = ''
110 58
111 59 try: try:
112 60 # FILL DICTIONARY # FILL DICTIONARY
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
119 67 try: try:
120 68 # SET KEYWORDS # SET KEYWORDS
121 69 keywords = '' keywords = ''
122 # Item Flags for new products to download the correct export
123 item_flag = ''
124 70 if(row['generic_keywords']): if(row['generic_keywords']):
125 71 keywords = row[ 'generic_keywords' ] keywords = row[ 'generic_keywords' ]
126 72
127 73 if(not(keywords)): if(not(keywords)):
128 raise barcode.EmptyFieldWarning('generic_keywords')
74 try:
75 raise barcode.EmptyFieldWarning('generic_keywords')
76 except Exception:
77 print("Generic Keywords are empty!")
129 78
130 79 # SET ATTRIBUTES # SET ATTRIBUTES
131 80 attributes = '' attributes = ''
132 81 if(row['parent_child'] == 'child'): if(row['parent_child'] == 'child'):
133 82 attributes = get_attributes(dataset=row, sets=color_size_sets) attributes = get_attributes(dataset=row, sets=color_size_sets)
83 if(group_parent and row['parent_sku'] == group_parent):
84 position += 1
134 85
135 86 if(row['parent_child'] == 'parent'): if(row['parent_child'] == 'parent'):
136 item_flag = 21
87 group_parent = row['item_sku']
88 position = 0
137 89
138 90 try: try:
139 91 values = [ values = [
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
141 93 package_properties[ 'length' ] * 10, package_properties[ 'width' ] * 10, package_properties[ 'length' ] * 10, package_properties[ 'width' ] * 10,
142 94 package_properties[ 'height' ] * 10, package_properties[ 'weight' ], package_properties[ 'height' ] * 10, package_properties[ 'weight' ],
143 95 row['item_name'], '104', row['item_name'], '104',
144 attributes,
96 attributes, position,
145 97 '62', keywords, '62', keywords,
146 98 row['brand_name'].upper(), '3', row['brand_name'].upper(), '3',
147 99 input_data['name'], row['product_description'], input_data['name'], row['product_description'],
148 100 '', # externalID '', # externalID
149 '3', input_data['categories'],
101 '1', '1', # NetStock pos = Vis & neg = Invis
102 '2', input_data['categories'],
150 103 input_data['categories'][0:2], input_data['categories'][0:2], input_data['categories'][0:2], input_data['categories'][0:2],
151 104 'Y', 'Y', # mandant 'Y', 'Y', # mandant
152 105 '', '', # barcode '', '', # barcode
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
158 111 '', '', '',# producttype & fba amazon '', '', '',# producttype & fba amazon
159 112 '','','','','','',# prices '','','','','','',# prices
160 113 '', '', '', #asin '', '', '', #asin
161 item_flag # item flag 1 the sign of the item status
114 input_data['marking']
162 115 ] ]
163 116
164 117 except KeyError: except KeyError:
165 118 raise KeyError raise KeyError
166 119 print('Error at the Values') print('Error at the Values')
167 Data[row['item_sku']] = SortedDict(zip(column_names, values))
120 Data[row['item_sku']] = collections.OrderedDict(zip(column_names, values))
168 121 except KeyError as err: except KeyError as err:
169 122 print("Error at : 'if(row['parent_child'] == 'parent'):'") print("Error at : 'if(row['parent_child'] == 'parent'):'")
170 123 return row['item_sku'] return row['item_sku']
 
... ... def itemUpload(flatfile, intern, stocklist, attributefile, folder, input_data):
175 128 for row in reader: for row in reader:
176 129 try: try:
177 130 if(row['amazon_sku'] in [*Data]): if(row['amazon_sku'] in [*Data]):
178 Data[row['amazon_sku']]['ItemID'] = row['article_id']
179 131 Data[row['amazon_sku']]['ExternalID'] = row['full_number'] Data[row['amazon_sku']]['ExternalID'] = row['full_number']
180 132 except KeyError as keyerr: except KeyError as keyerr:
181 133 print(keyerr) print(keyerr)
 
... ... def itemPropertyUpload(flatfile, folder):
312 264 Data = {} Data = {}
313 265 for index, row in enumerate( properties ): for index, row in enumerate( properties ):
314 266 for prop in property_id: for prop in property_id:
315 values = [row, property_id[prop], properties[row][prop], 'DE']
267 values = [row, property_id[prop], properties[row][prop], 'DE', 1]
316 268
317 269 Data[row + prop] = dict(zip(column_names, values)) Data[row + prop] = dict(zip(column_names, values))
318 270
 
... ... def get_properties(flatfile):
323 275 properties = {'length':0, properties = {'length':0,
324 276 'width':0, 'width':0,
325 277 'height':0, 'height':0,
326 'weight':0,
327 '1'}
278 'weight':0}
328 279
329 280 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item: with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
330 281 reader = csv.DictReader(item, delimiter=";") reader = csv.DictReader(item, delimiter=";")
 
... ... def get_properties(flatfile):
362 313
363 314 return properties return properties
364 315
365 def get_attributes(dataset, sets):
366
367 output_string = ''
368 if(len(sets[dataset['parent_sku']]['color']) > 1):
369 output_string = 'color_name:' + dataset['color_name']
370 if(len(sets[dataset['parent_sku']]['size']) > 1):
371 if(not(output_string)):
372 output_string = 'size_name:' + dataset['size_name']
373 else:
374 output_string = output_string + ';size_name:' + dataset['size_name']
375 return output_string
376
377 316 def find_similar_attr(flatfile): def find_similar_attr(flatfile):
378 317
379 318 Data = {} Data = {}
 
... ... def search_child(item_list, parent):
426 365 child_dict[item[0]] = item[1] child_dict[item[0]] = item[1]
427 366
428 367 return child_dict return child_dict
368
369 def check_flatfile(flatfile):
370 try:
371 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
372 reader = csv.DictReader(item, delimiter=';')
373
374 first_row = [* list(reader)[0] ]
375 if(not( 'feed_product_type' in first_row )):
376 if( 'Marke' in first_row ):
377 print("Please cut the first two rows from the flatfile for this script\n")
378 return False
379 else:
380 print("This file contains the wrong column header\n{0}\n".format(','.join(first_row)))
381 return False
382 else:
383 return True
384 except Exception as err:
385 print("ERROR @ flatfile checking : {0}".format(err))
386
387 def check_encoding(file_dict):
388 try:
389 with open(file_dict['path'], mode='rb') as item:
390 try:
391 raw_data = item.read()
392 except Exception as err:
393 print("ERROR: {0}\n".format(err))
394 file_dict['encoding'] = chardet.detect(raw_data)['encoding']
395 print("chardet data for {0}\n{1}\n".format(file_dict['path'], chardet.detect(raw_data)))
396
397 except Exception as err:
398 print("Error : {0}\n".format(err))
399
400 return file_dict
401
402 def get_variationid(exportfile, sku):
403
404 variationid = 0
405 with open(exportfile['path'], mode = 'r', encoding = exportfile['encoding']) as item:
406 reader = csv.DictReader(item, delimiter = ';')
407
408 for row in reader:
409 if('VariationNo' in [*row]):
410 if(row['VariationNo'] == sku):
411 variationid = row['VariationId']
412 else:
413 try:
414 if(row[ [*row][1] ] == sku):
415 for i in range( len([*row] )):
416 # matches .id .ID _ID _id ID id
417 if(re.search(r'\bid', [*row][i].lower())):
418 print("found ID in {0} value: {1}".format([*row][i], row[ [*row][i] ]))
419 variationid = row[ [*row][i] ]
420 except Exception as err:
421 print("ERROR @ alternative header reading method in get_variationid: line: {0}, error: {1}"
422 .format(sys.exc_info()[2].tb_lineno, err))
423 print("press ENTER to continue...")
424 input()
425 if(not(variationid)):
426 print("No Variation ID found for {0}\n".format(sku))
427
428 return variationid
429
430 def get_attributes(dataset, sets):
431
432 output_string = ''
433 if(len(sets[dataset['parent_sku']]['color']) > 1):
434 output_string = 'color_name:' + dataset['color_name']
435 if(len(sets[dataset['parent_sku']]['size']) > 1):
436 if(not(output_string)):
437 output_string = 'size_name:' + dataset['size_name']
438 else:
439 output_string = output_string + ';size_name:' + dataset['size_name']
440 return output_string
File packages/log_files.py changed (mode: 100644) (index 6e76dff..c4d6478)
... ... def unboundLocalLog(log_path, step_number, step_desc, variable_name, file_name):
43 43 unboundLocalLogger.error("ERROR : In the file {2}, the variable {3} was used before any value was assigned to it.\nAt Step {0} : {1}." unboundLocalLogger.error("ERROR : In the file {2}, the variable {3} was used before any value was assigned to it.\nAt Step {0} : {1}."
44 44 .format(step_number, step_desc, file_name, variable_name)) .format(step_number, step_desc, file_name, variable_name))
45 45 def emptyFieldWarningLog(log_path, step_number, step_desc, field_name, file_name): def emptyFieldWarningLog(log_path, step_number, step_desc, field_name, file_name):
46 emptyFieldLogger = function_logger(log_path, logging.WARN, logging.WARN)
47 emptyFieldLogger.warning("EMPTY FIELD: In the file {3}, the field {2} is empty! At Step {0} : {1}.".format(step_number, step_desc, field_name, file_name))
46 try:
47 emptyFieldLogger = function_logger(log_path, logging.WARN, logging.WARN)
48 emptyFieldLogger.warning("EMPTY FIELD: In the file {3}, the field {2} is empty! At Step {0} : {1}.".format(step_number, step_desc, field_name, file_name))
49 except Exception as err:
50 print("ERROR @ emptyFieldWarningLog: {0}".format(err))
File packages/price_upload.py changed (mode: 100644) (index b2502c1..1e2dba6)
... ... def priceUpload(flatfile):
21 21 # create a Data Dictionary and fill it with the necessary values from the # create a Data Dictionary and fill it with the necessary values from the
22 22 # flatfile # flatfile
23 23 Data = SortedDict() Data = SortedDict()
24 standard_price = 0
25 variation_price = 0
24 26
25 27 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item: with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
26 28 reader = DictReader(item, delimiter=";") reader = DictReader(item, delimiter=";")
 
... ... def priceUpload(flatfile):
31 33 for scndrow in reader: for scndrow in reader:
32 34 if(row['parent_child'] == 'parent'): if(row['parent_child'] == 'parent'):
33 35 if(scndrow['parent_child'] == 'child' and scndrow['standard_price'] and row['item_sku'] == scndrow['parent_sku']): if(scndrow['parent_child'] == 'child' and scndrow['standard_price'] and row['item_sku'] == scndrow['parent_sku']):
34 row['standard_price'] = scndrow['standard_price']
36 standard_price = scndrow['standard_price']
37 print("reach standard_price set parent standard_price : {0}".format(standard_price))
35 38 break break
36 39 elif(row['parent_child'] == 'child'): elif(row['parent_child'] == 'child'):
37 40 if(scndrow['parent_child'] == 'child' and scndrow['standard_price'] and row['parent_sku'] == scndrow['parent_sku']): if(scndrow['parent_child'] == 'child' and scndrow['standard_price'] and row['parent_sku'] == scndrow['parent_sku']):
38 row['standard_price'] = scndrow['standard_price']
41 print("reach standard_price set child")
42 standard_price = scndrow['standard_price']
39 43 break break
44
45 with open(flatfile['path'], mode='r', encoding=flatfile['encoding']) as item:
46 reader = DictReader(item, delimiter=";")
47
48 for row in reader:
40 49 if(row['standard_price']): if(row['standard_price']):
41 for price in prices:
42 if(prices[ price ]['id'] == '3'):
43 # Ebay price calculation
44 prices[ price ]['value'] = ( int( round( float( row['standard_price'] ) - (float( row['standard_price'] ) * 0.10) ) ) - 0.05 )
45 if(prices[ price ]['id'] == '5'):
46 # Webshop price calculation
47 prices[ price ]['value'] = ( int( round( float( row['standard_price'] ) - (float( row['standard_price'] ) * 0.16666666) ) ) - 0.05 )
48 if(prices[ price ]['id'] == '6'):
49 # Etsy price calculation
50 prices[ price ]['value'] = ( int( round( float( row['standard_price'] ) + (float( row['standard_price'] ) * 0.1) ) ) - 0.15 )
51 else:
52 prices[ price ]['value'] = row['standard_price']
53 values = [prices['price']['value'], prices['ebay']['value'],
54 prices['amazon']['value'], prices['webshop']['value'],
55 prices['etsy']['value']]
56
57 Data[row['item_sku']] = SortedDict(zip(column_names, values))
50 variation_price = row['standard_price']
58 51 else: else:
59 print("{0} doesn't have a price!\n".format(row['item_sku']))
52 variation_price = standard_price
53 for price in prices:
54 if(prices[ price ]['id'] == '3'):
55 # Ebay price calculation
56 prices[ price ]['value'] = ( int( round( float( variation_price ) - (float( variation_price ) * 0.10) ) ) - 0.05 )
57 if(prices[ price ]['id'] == '5'):
58 # Webshop price calculation
59 prices[ price ]['value'] = ( int( round( float( variation_price ) - (float( variation_price ) * 0.16666666) ) ) - 0.05 )
60 if(prices[ price ]['id'] == '6'):
61 # Etsy price calculation
62 prices[ price ]['value'] = ( int( round( float( variation_price ) + (float( variation_price ) * 0.1) ) ) - 0.15 )
63 else:
64 prices[ price ]['value'] = variation_price
65 values = [prices['price']['value'], prices['ebay']['value'],
66 prices['amazon']['value'], prices['webshop']['value'],
67 prices['etsy']['value']]
68
69 Data[row['item_sku']] = SortedDict(zip(column_names, values))
60 70
61 71 return Data return Data
62 72
File product_import.py changed (mode: 100644) (index f8f82cb..cfcd626)
... ... from tkinter.filedialog import askopenfilename
3 3 import sys import sys
4 4 import platform import platform
5 5 import os import os
6 import time
6 7 import ntpath import ntpath
7 8 from packages.item_upload import itemUpload, WrongEncodingException, check_encoding, check_flatfile, itemPropertyUpload from packages.item_upload import itemUpload, WrongEncodingException, check_encoding, check_flatfile, itemPropertyUpload
8 9 from packages.barcode import EmptyFieldWarning from packages.barcode import EmptyFieldWarning
 
... ... def main():
122 123 while (LOOP_ACTIVE): while (LOOP_ACTIVE):
123 124 if(cchooser): if(cchooser):
124 125 cchooser.update() cchooser.update()
125 if(cchooser.data['name'] and cchooser.data['categories']):
126 time.sleep(0.3)
127 if(cchooser.data['name'] and cchooser.data['categories'] and\
128 cchooser.data['marking']):
126 129 LOOP_ACTIVE = False LOOP_ACTIVE = False
127 130 cchooser.destroy() cchooser.destroy()
128 131 # END GUI # END GUI
 
... ... def main():
248 251 title="Export File from Plentymarkets", title="Export File from Plentymarkets",
249 252 filetypes=[ ("csv files", "*.csv") ]) filetypes=[ ("csv files", "*.csv") ])
250 253
251 plenty_export = check_encoding(sheet)
254 plenty_export = check_encoding(plenty_export)
252 255
253 256 step += 1 step += 1
254 257 imageUpload(flatfile=sheet, attributefile=attributefile, exportfile=plenty_export, uploadfolder=upload_folder) imageUpload(flatfile=sheet, attributefile=attributefile, exportfile=plenty_export, uploadfolder=upload_folder)
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/Amazon2PlentySync

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

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

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