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)
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
Changed the EAN type from UPC to GTIN_13 which is the correct one. ea74c1d8c001ae6895f07bbecbcb9a0898400b95 Sebastian Fricke 2019-04-15 13:04:54
fixed a bug with item_name + changed the item_name assignment to include the variation name instead of the parent name 7dedb2bb9afac7d5625ccbf9c05f6ff4b1b1e5e1 LagerBadel PC:Magdalena 2019-04-15 12:32:33
Added usage instructions in english and german language. e2f291e2a00ac9283ab9d843e652d7b77fa6bbaf Sebastian Fricke 2019-04-15 09:59:36
Added usage instructions in english and german language. 30646f203ae8847cfa4971cb62187dca8406b8d7 Sebastian Fricke 2019-04-15 09:58:26
Fixed small compilation mistakes concerning positional arguments dc011ec52cf578e2910edde1aeacb893bb2e57f9 Sebastian Fricke 2019-04-15 07:16:14
Fixed a problem with the Upload folder when the executable is within its Folder outside of the root 6ca74a5bbbf13036405c654225de2540cddf2ed0 Sebastian Fricke 2019-04-15 07:02:13
Small improvements with the error handling inside item_upload.py 8d8361aa6ca7fca69407fb6c2f7450a9fd3ad40d LagerBadel PC:Magdalena 2019-04-12 12:31:39
Fixed the Windows Version because of corrupted Sym Links from the Windows Version 21c1d49e6508a27e3ba86741843c4141e09be2ee Sebastian Fricke 2019-04-12 11:57:28
The push from the windows machine corrupted the Linux Version, it is now re compiled. 1a642842228b959ad9ca1253b6e0df25d75e3d67 Sebastian Fricke 2019-04-12 09:34:27
Added a executable File db4d6f812ada2d497e2ffa255ddf62fd88c98e9f Sebastian Fricke 2019-04-12 08:24:14
current working version 10-04-19 f57799f6815c8c76217f64e292d6cf61e0deffb7 Sebastian Fricke 2019-04-10 14:40:36
Changed the collection_name field to the newer seasons field in the property upload b13a2282d20e97f6f414e02ace9673246678adc4 Sebastian Fricke 2019-03-29 09:59:05
Added a feature upload and removed a test print from the barcode upload b04dc65a93ff10c650cdaf48d1a7922ff4769ecc Sebastian Fricke 2019-03-28 14:57:54
Added FNSKU code and removed freetext fields to replace them with properties 4f77496d60be1afbd90a7279b14643267b4430cc Sebastian Fricke 2019-03-27 11:09:55
Commit 6392338b7e9968be3bc4da9031144c3cc2cfae48 - Made some fields not required but added Warnings for the log file, additionally some new amazon features were added.
Author: Sebastian Fricke
Author date (UTC): 2019-04-18 09:37
Committer name: Sebastian Fricke
Committer date (UTC): 2019-04-18 09:37
Parent(s): 2e3763e436899466db9f03f70ea926869afd3219
Signing key:
Tree: 0a66a4f166f783d76a6ae712b10c448bf75a333d
File Lines added Lines deleted
packages/amazon_data_upload.py 2 1
packages/item_upload.py 4 0
packages/log_files.py 3 0
packages/variation_upload.py 17 0
product_import.py 20 4
File packages/amazon_data_upload.py changed (mode: 100644) (index 88086dc..fb4e3b5)
... ... def amazonDataUpload(flatfile, export, folder):
64 64 for key in type_id: for key in type_id:
65 65 if(row['feed_product_type'].lower() == key): if(row['feed_product_type'].lower() == key):
66 66 product_type = type_id[key] product_type = type_id[key]
67
67 if(not(product_type)):
68 raise variation_upload.EmptyFieldWarning('product_type')
68 69 values = [product_type, '1', values = [product_type, '1',
69 70 '0','1'] '0','1']
70 71
File packages/item_upload.py changed (mode: 100644) (index 1c15612..5b16495)
... ... def itemUpload(flatfile, intern, folder):
89 89 # except Exception as err: # except Exception as err:
90 90 # print(err) # print(err)
91 91 # print("The combination of the keywords failed!") # print("The combination of the keywords failed!")
92 keywords = ''
92 93 if(row['generic_keywords']): if(row['generic_keywords']):
93 94 keywords = row[ 'generic_keywords' ] keywords = row[ 'generic_keywords' ]
94 95
96 if(not(keywords)):
97 raise variation_upload.EmptyFieldWarning('generic_keywords')
98
95 99 try: try:
96 100 values = ['', row['item_sku'], row['package_length'] * 10, values = ['', row['item_sku'], row['package_length'] * 10,
97 101 row['package_width'] * 10, row['package_width'] * 10,
File packages/log_files.py changed (mode: 100644) (index f6c312d..b081199)
... ... def unboundLocalLog(log_path, step_number, step_desc, variable_name, file_name):
41 41 unboundLocalLogger = function_logger(log_path, logging.ERROR, logging.ERROR) unboundLocalLogger = function_logger(log_path, logging.ERROR, logging.ERROR)
42 42 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}."
43 43 .format(step_number, step_desc, file_name, variable_name)) .format(step_number, step_desc, file_name, variable_name))
44 def emptyFieldWarningLog(log_path, step_number, step_desc, field_name, file_name):
45 emptyFieldLogger = function_logger(log_path, logging.WARN, logging.WARN)
46 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))
File packages/variation_upload.py changed (mode: 100644) (index b950cb3..667be57)
... ... except ImportError:
10 10 print("the sortedcontainers module is required to run this program.") print("the sortedcontainers module is required to run this program.")
11 11 raise ImportError raise ImportError
12 12
13 class EmptyFieldWarning(Exception):
14 def __init__(self, errorargs):
15 Exception.__init__(self, "Following field/s are empty {0}".format(errorargs))
16 self.errorargs = errorargs
13 17
14 18 def writeCSV(dataobject, name, columns, upload_path): def writeCSV(dataobject, name, columns, upload_path):
15 19 '''Write Data into new CSV for Upload '''Write Data into new CSV for Upload
 
... ... def variationUpload(flatfile, intern_number, folder):
69 73 pack_length = 0 pack_length = 0
70 74 pack_width = 0 pack_width = 0
71 75 pack_weight = 0 pack_weight = 0
76 attributes = ''
77
72 78 try: try:
73 79 if(row['package_height'] and if(row['package_height'] and
74 80 row['package_length'] and row['package_length'] and
 
... ... def variationUpload(flatfile, intern_number, folder):
88 94 if(row['package_weight']): if(row['package_weight']):
89 95 pack_weight = int(row['package_weight']) pack_weight = int(row['package_weight'])
90 96
97 if(not(pack_width or pack_length or pack_height or pack_weight)):
98 raise EmptyFieldWarning('package properties')
99
91 100 if(row['color_name']): if(row['color_name']):
92 101 attributes = 'color_name:' + row['color_name'] attributes = 'color_name:' + row['color_name']
93 102
94 103 if(row['size_name'] and number_sizes > 1): if(row['size_name'] and number_sizes > 1):
95 104 attributes += ';size_name:' + row['size_name'] attributes += ';size_name:' + row['size_name']
96 105
106 if(not(attributes)):
107 raise EmptyFieldWarning('plentymarkets attributes')
108
97 109 try: try:
98 110 values = ['', '', row['item_sku'], row['item_name'], '', values = ['', '', row['item_sku'], row['item_name'], '',
99 111 pack_length * 10, pack_length * 10,
 
... ... def EANUpload(flatfile, export, stocklist, folder):
178 190 if(barcode == 'EAN'): if(barcode == 'EAN'):
179 191 code = row['external_product_id'] code = row['external_product_id']
180 192
193 if(not(barcode)):
194 raise EmptyFieldWarning('barcode(EAN)')
181 195 values = [ values = [
182 196 barcode_types[barcode]['id'], barcode_types[barcode]['name'], barcode_types[barcode]['id'], barcode_types[barcode]['name'],
183 197 barcode_types[barcode]['type'], code, barcode_types[barcode]['type'], code,
 
... ... def EANUpload(flatfile, export, stocklist, folder):
206 220 if(barcode == 'FNSKU'): if(barcode == 'FNSKU'):
207 221 code = row['fnsku'] code = row['fnsku']
208 222
223 if(not(code)):
224 raise EmptyFieldWarning('barcode(FNSKU)')
225
209 226 if(code): if(code):
210 227 Data[row['MASTER'] + barcode]['Code'] = code Data[row['MASTER'] + barcode]['Code'] = code
211 228
File product_import.py changed (mode: 100644) (index 6363d0b..971deb5)
... ... import platform
5 5 import os import os
6 6 import ntpath import ntpath
7 7 from packages.item_upload import itemUpload, itemPropertyUpload, WrongEncodingException from packages.item_upload import itemUpload, itemPropertyUpload, WrongEncodingException
8 from packages.variation_upload import variationUpload, setActive, EANUpload, marketConnection
8 from packages.variation_upload import variationUpload, setActive, EANUpload, marketConnection, EmptyFieldWarning
9 9 from packages.stock_upload import priceUpload from packages.stock_upload import priceUpload
10 10 from packages.amazon_data_upload import amazonSkuUpload, amazonDataUpload, asinUpload, featureUpload from packages.amazon_data_upload import amazonSkuUpload, amazonDataUpload, asinUpload, featureUpload
11 11 from packages.image_upload import imageUpload from packages.image_upload import imageUpload
12 from packages.log_files import fileNotFoundLog, keyErrorLog, wrongEncodingLog, unboundLocalLog
12 from packages.log_files import fileNotFoundLog, keyErrorLog, wrongEncodingLog, unboundLocalLog, emptyFieldWarningLog
13 13
14 14
15 15 def main(): def main():
 
... ... def main():
87 87 try: try:
88 88 print("\nItem Upload\n") print("\nItem Upload\n")
89 89 itemUpload(sheet, intern_number, upload_folder) itemUpload(sheet, intern_number, upload_folder)
90 except WrongEncodingException as wexc:
90 except WrongEncodingException:
91 91 wrongEncodingLog(log_path=log_folder, step_number=step, step_desc=step_name[step], file_name="flatfile") wrongEncodingLog(log_path=log_folder, step_number=step, step_desc=step_name[step], file_name="flatfile")
92 92 except KeyError as kexc: except KeyError as kexc:
93 93 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
 
... ... def main():
97 97 fileNotFoundLog(log_path=log_folder, step_number=step, step_desc=step_name[step], file_name="flatfile") fileNotFoundLog(log_path=log_folder, step_number=step, step_desc=step_name[step], file_name="flatfile")
98 98 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
99 99 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
100 except EmptyFieldWarning as eexc:
101 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
100 102 except Exception as exc: except Exception as exc:
101 103 print("Item Upload failed!\n") print("Item Upload failed!\n")
102 104 print("Here: ", exc, '\n') print("Here: ", exc, '\n')
 
... ... def main():
114 116 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
115 117 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
116 118 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
119 except EmptyFieldWarning as eexc:
120 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
117 121 except Exception as exc: except Exception as exc:
118 122 print("VariationUpload failed!\n") print("VariationUpload failed!\n")
119 123 e = sys.exc_info() e = sys.exc_info()
 
... ... def main():
148 152 featureUpload(flatfile=sheet, feature='sleeve_type', feature_id=8, folder=upload_folder) featureUpload(flatfile=sheet, feature='sleeve_type', feature_id=8, folder=upload_folder)
149 153 featureUpload(flatfile=sheet, feature='pattern_type', feature_id=11, folder=upload_folder) featureUpload(flatfile=sheet, feature='pattern_type', feature_id=11, folder=upload_folder)
150 154 featureUpload(flatfile=sheet, feature='collar_style', feature_id=12, folder=upload_folder) featureUpload(flatfile=sheet, feature='collar_style', feature_id=12, folder=upload_folder)
155 featureUpload(flatfile=sheet, feature='closure_type', feature_id=14, folder=upload_folder)
156 featureUpload(flatfile=sheet, feature='style_name', feature_id=15, folder=upload_folder)
157 featureUpload(flatfile=sheet, feature='care_instructions', feature_id=16, folder=upload_folder)
151 158 step += 1 step += 1
152 159 setActive(sheet, export, upload_folder) setActive(sheet, export, upload_folder)
153 160 step += 1 step += 1
 
... ... def main():
158 165 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
159 166 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
160 167 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
168 except EmptyFieldWarning as eexc:
169 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
161 170 except OSError as err: except OSError as err:
162 171 print(err) print(err)
163 172 print("Missing Data, check if you have\n - a flatfile\n - a intern file table\n - export file from plentymarkets\n - a sheet with the stock numbers!\n") print("Missing Data, check if you have\n - a flatfile\n - a intern file table\n - export file from plentymarkets\n - a sheet with the stock numbers!\n")
164 sys.exit()
165 173
166 174 print("\nOpen your amazon storage report and save it as an csv.\n") print("\nOpen your amazon storage report and save it as an csv.\n")
167 175
 
... ... def main():
191 199 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
192 200 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
193 201 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
202 except EmptyFieldWarning as eexc:
203 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
194 204
195 205 print("\nCreate a upload file for the additional Information to Amazon Products like bullet points, lifestyle etc.\n") print("\nCreate a upload file for the additional Information to Amazon Products like bullet points, lifestyle etc.\n")
196 206
 
... ... def main():
201 211 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
202 212 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
203 213 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
214 except EmptyFieldWarning as eexc:
215 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
204 216
205 217 print("\nCollect the ASIN Numbers matching to the Variationnumber(Sku) and format them into the dataformat format.\n") print("\nCollect the ASIN Numbers matching to the Variationnumber(Sku) and format them into the dataformat format.\n")
206 218
 
... ... def main():
211 223 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
212 224 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
213 225 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
226 except EmptyFieldWarning as eexc:
227 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
214 228
215 229 print("\nCollect the imagelinks from the flatfile, sorts them and assigns the variation ID.\n") print("\nCollect the imagelinks from the flatfile, sorts them and assigns the variation ID.\n")
216 230
 
... ... def main():
234 248 keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet)) keyErrorLog(log_path=log_folder, step_number=step, step_desc=step_name[step], key_name=kexc, file_name=ntpath.basename(sheet))
235 249 except UnboundLocalError as uexc: except UnboundLocalError as uexc:
236 250 unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args) unboundLocalLog(log_path=log_folder, step_number=step, step_desc=step_name[step], filename=ntpath.basename(sheet), variable_name=uexc.args)
251 except EmptyFieldWarning as eexc:
252 emptyFieldWarningLog(log_path=log_folder, step_number=step, step_desc=step_name[step], field_name=eexc.errorargs, file_name=ntpath.basename(sheet))
237 253 except Exception as err: except Exception as err:
238 254 print(err) print(err)
239 255 print("Market connection failed!") print("Market connection failed!")
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