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)
Refactor config handling a9be950a4e8d97fa97c7e9caff33fcbb1f476d9d Sebastian Fricke 2020-04-22 10:11:57
Fix gui/category_chooser: file change bug 9879e65c9aad9b1feb05b6121a0e33c129a8beb5 Sebastian Fricke 2020-04-22 10:09:36
update .gitignore 6c7628af605a72ced1e146c27da8639225ab9c6c Sebastian Fricke 2020-04-22 10:08:47
Fix error.py: Fix colorful messages on windows 31f0b106c7aee1962bba3efb5758f647170eceff Sebastian Fricke 2020-04-22 10:07:30
Enhanced error output to extra module dda37a22d21db1af6330fd62395682b91f46f5ec Sebastian Fricke 2020-01-27 10:56:00
Introduction infoPrint, removed unnecessary parameter 98b6779f95fcf6d3350f64e7d2a8151932415458 Sebastian Fricke 2020-01-16 14:27:15
Add Cdiscount price & coding style review 7c5451b067760100904aed947b2ba484ab9c9e45 Sebastian Fricke 2020-01-16 14:25:15
coding style, naming conventions & uninitialized 218378ca191510dc2092108a87e63ff83b4c6b31 Sebastian Fricke 2020-01-16 13:58:24
coding style & cleanup image upload module 04ac13fb764baecd1a419cbffcd9696a3ff5b680 Sebastian Fricke 2020-01-16 13:56:07
coding style improvements and colorful error msg 401db811c0edd62b14c7a0a29e2c1f6d2791774c Sebastian Fricke 2020-01-16 13:54:25
code cleanup and coding style category.py b1e41b45fe405d3826a9b6e452fb9e2f9f6697bf Sebastian Fricke 2020-01-16 10:43:44
Added the category config to the gitignore file b8b522d9ade4b59b5d0a0bd4f9b7c79e8db334c6 Sebastian Fricke 2020-01-15 14:56:06
Removed log function for category_config(not needed) c8ca8a3b6b968f1835697073e7d5fe1ea70b15ba Sebastian Fricke 2020-01-15 14:54:15
Added category_config functionality 7bd8256398b4af5c1feb3033d74cd9f29b047edc Sebastian Fricke 2020-01-15 14:53:20
improved error handling & adjusted names to naming convention cfcd91090a2598c6c51576bcdd53e03ab6c2f59b Sebastian Fricke 2020-01-15 14:47:42
Refactor CategoryChooser 562e6657c6fef89d0584731e54325cec013268a7 Sebastian Fricke 2020-01-15 14:42:11
Add category_config location to the script config 8698e4a99d63b06fde5c39787fc7d6f7400b9f47 Sebastian Fricke 2020-01-15 14:29:47
Refactor findConfig 321ae9d7edd69e8be0755cf5ba82289944d06ca3 Sebastian Fricke 2020-01-15 14:26:09
Add logging function: no category config warning e8323843a3b6c24ef274d6a12c10d76aa8b8f591 Sebastian Fricke 2020-01-14 14:38:39
Add module + test for the category-id config fadaf4515aab1009f4df4a1af5a2e8f82077bc4c Sebastian Fricke 2020-01-14 14:35:44
Commit a9be950a4e8d97fa97c7e9caff33fcbb1f476d9d - Refactor config handling
Use the configparser config implementation instead of a self made
implementation.
Merge the category id, feature id and path configuration into one file.
Improve handling of a missing config/invalide attribute file.
Author: Sebastian Fricke
Author date (UTC): 2020-04-22 10:11
Committer name: Sebastian Fricke
Committer date (UTC): 2020-04-22 10:11
Parent(s): 9879e65c9aad9b1feb05b6121a0e33c129a8beb5
Signing key:
Tree: f938e51d3fd59278255001ac7d541ba999ab2e54
File Lines added Lines deleted
packages/config.py 107 178
product_import.py 74 121
File packages/config.py changed (mode: 100644) (index 7bf76ee..2610a38)
1 """
2 2020-04-22
3 Sebastian Fricke
4 Panasiam
5 License: GPLv3
6
7 Helper functions for reading the configuration data
8 """
9 import inspect
1 10 import tkinter import tkinter
2 import tkinter.filedialog
3 import os
4 import csv
5 import enum
6 import datetime
7
8
9 class State(enum.Enum):
10 CONFIG_UPLOAD_EXIST = 0
11 CONFIG_DATA_EXIST = 1
12 CONFIG_ATTR_EXIST = 2
13 CONFIG_NOT_FOUND = 3
14 CONFIG_BAD = 4
15
16
17 fields = [
18 'upload_folder', 'data_folder',
19 'attribute_file', 'file_change_date',
20 'category_config'
21 ]
22
23
24 def config_open(path, option):
25 if(option not in ['r', 'w', 'a']):
26 print("Bad file opening option: [{1}] used with path {0}"
27 .format(path, option))
28 return []
29
30 with open(path, mode=option) as item:
31 # remove spaces/newlines, create list of options between ;
32 rows = [row.strip(' ').strip('\n').split(';') for row in item]
33
34 return rows
35
36
37 def config_creation():
38 current_path = ''
39 configpath = ''
40
41 root = tkinter.Tk()
42 root.withdraw()
43
44 current_path = os.getcwd()
45 configpath = os.path.join(current_path, 'config.txt')
46 if(not( os.path.isfile(configpath))):
47 with open(configpath, mode='w') as item:
48 item.write('upload_folder=\n')
49 item.write('data_folder=\n')
50 item.write('attribute_file=\n')
51 item.write('file_change_date=\n')
52 item.write('category_config=\n')
53 if(os.path.isfile(configpath)):
54 return configpath
55 else:
11 from tkinter.filedialog import askopenfilename
12 import configparser
13 from packages import error
14
15 def assignFeatures(config):
16 """
17 Parameter:
18 config => configparser config object from config.ini
19
20 Get the user-configured Plentymarkets Feature IDs from the config
21 Assign them to a dictionary and return the dictionary
22 Throw a warning for each missing field
23 """
24 features = {}
25 for key, value in config['FEATURES'].items():
26 if key == 'example-feature':
27 msg =\
28 str(f"Fill feature IDs from Plentymarkets into [FEATURES]")
29 error.warnPrint(msg=msg, err='',
30 linenumber=inspect.currentframe().f_back.f_lineno)
31 return None
32 try:
33 features[key] = int(value)
34 except ValueError as err:
35 msg = str(f"Wrong value in config for => {key} : {value}")
36 error.errorPrint(msg=msg, err=err,
37 linenumber=inspect.currentframe().f_back.f_lineno)
38
39 for key, value in features.items():
40 if not value:
41 msg = str(f"No Value set in config for [FEATURES]=>{key}")
42 error.warnPrint(msg=msg, err='',
43 linenumber=inspect.currentframe().f_back.f_lineno)
44
45 return features
46
47 def assignCategory(config):
48 """
49 Parameter:
50 config => configparser config object from config.ini
51
52 Get the user-configured Plentymarkets Category IDs from the config
53 Assign them to a dictionary and return the dictionary
54 """
55 category = {}
56
57 if not 'CATEGORY' in config.keys():
58 msg = str(f"No categories in config => {config.keys()}")
59 error.errorPrint(msg=msg, err='',
60 linenumber=inspect.currentframe().f_back.f_lineno)
56 61 return None return None
57
58
59 def config_read(configpath):
60 config = {'upload_folder': '', 'data_folder': '',
61 'attribute_file': '', 'file_change_date': '',
62 'category_config': ''}
63 rows = config_open(path=configpath, option='r')
64
65 for row in rows:
66 option = "".join(row[0]).split('=')
67
68 for field in fields:
69 if(option[0].strip(' ') == field):
70 config[field] = option[1].strip(' ')
71
72 return config
73
74
75 def config_write(configpath, data):
76 with open(configpath, mode='w') as item:
77 writer = csv.DictWriter(item, delimiter='=', lineterminator='\n',
78 fieldnames=['title', 'value'])
62 for key, value in config['CATEGORY'].items():
63 if key == 'example-category':
64 msg =\
65 str(f"Fill category IDs from Plentymarkets into [CATEGORY]")
66 error.warnPrint(msg=msg, err='',
67 linenumber=inspect.currentframe().f_back.f_lineno)
68 return None
79 69 try: try:
80 for row in data:
81 writer.writerow(data[row])
82 except Exception as err:
83 print("Error @ config write: error: {0}"
84 .format(err))
70 category[key] = int(value)
71 except ValueError as err:
72 msg = str(f"Wrong value in config for => {key} : {value}")
73 error.errorPrint(msg=msg, err=err,
74 linenumber=inspect.currentframe().f_back.f_lineno)
75
76 return category
77
78 def createConfig(name):
79 """
80 Parameter:
81 name => name of the file with to be created in the source root
82
83 Create a empty config and ask user for input to fill values
84 """
85
86 input_folder = tkinter.filedialog.askdirectory(
87 initialdir='.',
88 title="Choose a source folder")
89 upload_folder = tkinter.filedialog.askdirectory(
90 initialdir='.',
91 title="Choose a destiniation folder")
92 config = configparser.ConfigParser()
93 config['PATH'] = {
94 'upload_folder':upload_folder,
95 'data_folder':input_folder,
96 'attribute_file':'',
97 'file_change_date': ''
98 }
99 config['CATEGORY'] = {
100 'example-category':'category ID (integer)'
101 }
102 config['FEATURES'] = {
103 'example-feature':'feature ID (integer)'
104 }
105
106 with open('config.ini', 'w') as configfile:
107 config.write(configfile)
108
109 error.infoPrint("Fill out the Category and Feature field of the config")
85 110
86
87 def config_check(path):
88 states = []
89 if(not(path)):
90 return [State.CONFIG_NOT_FOUND]
91
92 rows = config_open(path=path, option='r')
93
94 # Check if all required fields are present
95 for field in fields:
96 # DEBUG TEST NOT FINAL
97 if(field not in rows):
98 print("ERROR: field:{0} not found in {1}"
99 .format(field, rows))
100 return [State.CONFIG_BAD]
101
102 for row in rows:
103 # Check if a equal sign exists
104 if('=' not in row):
105 print("ERROR: config options have to be split by =, = not found")
106 return [State.CONFIG_BAD]
107
108 # Check if only one equal sign was used
109 elif(row.count('=') > 1):
110 print("ERROR: equal sign can only be used as delimiter!")
111 return [State.CONFIG_BAD]
112
113 # Add each working file/dir from the config to the state list
114 for index, field in enumerate(fields):
115 option = "".join(row[0]).split('=')
116 if(field == 'file_change_date' and option[1]):
117 states.append(index)
118 if(option[0].strip(' ') == field and option[1]):
119 if(field == 'attribute_file'):
120 if(os.path.isfile(option[1].strip(' '))):
121 states.append(index)
122 else:
123 if(os.path.exists(option[1].strip(' '))):
124 states.append(index)
125
126 return states
127
128
129 def get_path(message, path_type, initialdir):
130 path = ''
131 if(path_type == 'dir'):
132 path = tkinter.filedilag.askdirectory(title=message,
133 initialdir=initialdir)
134 elif(path_type == 'file'):
135 path = tkinter.filedialog.askopenfilename(title=message,
136 initialdir=initialdir)
137 return path
138
139
140 def get_options(configpath, initialdir):
141 options = {'uploadpath': '',
142 'datapath': '',
143 'attributefile': '',
144 'date': '',
145 'category_config': ''}
146
147 # Check the config for mistakes and correct them
148 config_state = []
149 config_state = config_check(path=configpath)
150
151 if(State.CONFIG_NOT_FOUND in config_state):
152 configpath = config_creation()
153
154 elif(State.CONFIG_BAD in config_state):
155 os.remove(configpath)
156 configpath = config_creation
157
158 if(State.CONFIG_UPLOAD_EXIST not in config_state or
159 State.CONFIG_DATA_EXIST not in config_state or
160 State.CONFIG_ATTR_EXIST not in config_state or
161 State.CONFIG_NOT_FOUND in config_state or
162 State.CONFIG_BAD in config_state):
163 options['uploadpath'] = get_path(message='Path for Upload files',
164 path_type='dir',
165 initialdir=initialdir)
166 options['datapath'] = get_path(message='Path for Input files',
167 path_type='dir',
168 initialdir=initialdir)
169 options['attributefile'] = get_path(message='Path for attribute file',
170 path_type='file',
171 initialdir=initialdir)
172
173 options['date'] = datetime.datetime.now().strftime("%d.%m.%Y-%H:%M")
174
175 options['category_config'] = get_path(
176 message='Path for the category config',
177 path_type='file',
178 initialdir=initialdir)
179
180 config_write(configpath=configpath, data=options)
181
182 return options
111 return config
File product_import.py changed (mode: 100644) (index c5ee73a..d7299a3)
... ... import platform
5 5 import os import os
6 6 import time import time
7 7 import ntpath import ntpath
8 from packages.item_upload import itemUpload, WrongEncodingException, checkEncoding, checkFlatfile, itemPropertyUpload
8 import re
9 import datetime
10 try:
11 import configparser
12 except ImportError:
13 print("configparser module required")
14
15 from packages.item_upload import (
16 itemUpload, WrongEncodingException, checkEncoding,
17 checkFlatfile, itemPropertyUpload)
9 18 from packages.barcode import EmptyFieldWarning from packages.barcode import EmptyFieldWarning
10 19 from packages.amazon_data_upload import featureUpload from packages.amazon_data_upload import featureUpload
11 from packages.log_files import fileNotFoundLog, keyErrorLog, wrongEncodingLog, unboundLocalLog, emptyFieldWarningLog
20 from packages.log_files import (
21 fileNotFoundLog, keyErrorLog, wrongEncodingLog,
22 unboundLocalLog, emptyFieldWarningLog)
12 23 from packages.gui.category_chooser import CategoryChooser from packages.gui.category_chooser import CategoryChooser
13 from packages.config import config_creation, config_read, config_write
14 24 from packages.image_upload import imageUpload from packages.image_upload import imageUpload
15 from packages.category import CategoryConfig
25 from packages.config import assignFeatures, assignCategory, createConfig
16 26
17 27
18 28 def main(): def main():
 
... ... def main():
20 30 #define variable used throughout the script #define variable used throughout the script
21 31 upload_folder = '' upload_folder = ''
22 32 log_folder = '' log_folder = ''
23 recent_path = ''
24 config_path = ''
33 input_folder = ''
25 34 attribute_date = '' attribute_date = ''
26 config = dict()
35 features = {}
36 category_id = {}
27 37 sheet = {'path':'', 'encoding':''} sheet = {'path':'', 'encoding':''}
28 38 intern_number = {'path':'', 'encoding':''} intern_number = {'path':'', 'encoding':''}
29 39 stocklist = {'path':'', 'encoding':''} stocklist = {'path':'', 'encoding':''}
30 40 plenty_export = {'path':'', 'encoding':''} plenty_export = {'path':'', 'encoding':''}
31 41 attributefile = {'path':'', 'encoding':''} attributefile = {'path':'', 'encoding':''}
32 step = int(0)
42 step = 0
33 43 fexc = '' fexc = ''
34 44
35 cat_conf = CategoryConfig()
36
37 # Create a list of step names where every name fits to the index of a step number
45 # Create a list of step names where every name fits
46 # to the index of a step number
38 47 step_name = ['environment-creation', step_name = ['environment-creation',
39 'config-creation',
40 48 'config-reading', 'config-reading',
41 49 'category-config', 'category-config',
42 50 'import-flatfile', 'import-flatfile',
 
... ... def main():
50 58 'image-upload' 'image-upload'
51 59 ] ]
52 60
53 # define the features for plentymarkets
54 features = {
55 'color_map':1,
56 'model':4,
57 'neck_size':5,
58 'sleeve_type':8,
59 'pattern_type':11,
60 'collar_style':12,
61 'item_name':13,
62 'closure_type':14,
63 'style_name':15,
64 'care_instructions':16,
65 'package_length':17,
66 'package_width':18,
67 'package_height':19,
68 'package_weight':20
69 }
70 # Check if the os is Linux, in that case the initial directory is Documents
71 # Unless Documents is not available in which case it is ~
72 if(platform.system() == 'Linux'):
73 if(os.path.exists(path='/home/' + os.getlogin() + '/Documents/')):
74 initial_directory = '/home/' + os.getlogin() + '/Documents/'
75 else:
76 initial_directory = '/home/' + os.getlogin()
61 step += 1
62 if not os.path.exists('config.ini'):
63 config = createConfig(name='config.ini')
64 else:
65 config = configparser.ConfigParser()
66 config.read('config.ini')
77 67
78 step += 1;
79 # CONFIG CREATION
80 # Create a config if there is none
81 config_path = config_creation()
68 upload_folder = config['PATH']['upload_folder']
69 input_folder = config['PATH']['data_folder']
70 attribute_date = config['PATH']['file_change_date']
71 attributefile['path'] = config['PATH']['attribute_file']
82 72
83 step += 1;
84 # CONFIG READING
85 # Get the Upload and data folder from the config if possible
86 config = config_read(config_path)
87 if(config['upload_folder']):
88 upload_folder = config['upload_folder']
89 if(config['data_folder']):
90 recent_path = config['data_folder']
91 if(config['attribute_file']):
92 attributefile['path'] = config['attribute_file']
73 # Initial start or invalid attribute file
74 if(not(attributefile['path']) or
75 not os.path.exists(attributefile['path'])):
76 attributefile['path'] = askopenfilename(initialdir=input_folder,
77 title="Color Attributes from PlentyMarkets",
78 filetypes=[ ("csv files", "*.csv") ])
93 79 attributefile = checkEncoding(attributefile) attributefile = checkEncoding(attributefile)
94 if(config['file_change_date']):
95 attribute_date = config['file_change_date']
96 if(config['category_config']):
97 cat_conf.path['path'] = config['category_config']
98 cat_conf.path = checkEncoding(cat_conf.path)
99
100 # Category Config
101 if(not(cat_conf.path['path'])):
102 if(not(cat_conf.findConfig(os.path.dirname(
103 os.path.abspath(__file__))))):
104 print('no category config found\n')
105 print('Press Enter to continue...')
106 input()
107 sys.exit()
108 cat_conf.readConfig()
80 config['PATH']['attribute_file'] = attributefile['path']
81 config['PATH']['file_change_date'] =\
82 datetime.datetime.now().strftime('%d.%m.%Y-%H:%M')
109 83
110 if(not(recent_path)):
111 recent_path = tkinter.filedialog.askdirectory(initialdir=initial_directory,
112 title="Choose a folder from where to upload")
113 # END of CONFIG READING
84 with open('config.ini', 'w') as configfile:
85 config.write(configfile)
114 86
115 # If the config is fresh built load in the attribute file manually
116 if(not(attributefile['path'])):
117 attributefile['path'] = askopenfilename(initialdir=recent_path,
118 title="Color Attributes from PlentyMarkets",
119 filetypes=[ ("csv files", "*.csv") ])
87 if not attributefile['encoding']:
120 88 attributefile = checkEncoding(attributefile) attributefile = checkEncoding(attributefile)
89 features = assignFeatures(config=config)
90 if not features:
91 exit(1)
92 step += 1
93 category_id = assignCategory(config=config)
94 if not category_id:
95 exit(1)
96
97 if(not(input_folder)):
98 input_folder = tkinter.filedialog.askdirectory(
99 initialdir='.',
100 title="Choose a folder from where to upload")
121 101
122 # Import Flatfile
123 102 step += 1 step += 1
124 sheet['path'] = askopenfilename(initialdir=recent_path,
103 sheet['path'] = askopenfilename(initialdir=input_folder,
125 104 title="Amazon Flatfile as .csv", title="Amazon Flatfile as .csv",
126 105 filetypes=[ ("csv files", "*.csv") ]) filetypes=[ ("csv files", "*.csv") ])
127 106
128 107 sheet = checkEncoding(sheet) sheet = checkEncoding(sheet)
129 108
130 # Check if the file was loaded properly and got the correct format
131 109 try: try:
132 110 if(not( checkFlatfile(sheet) )): if(not( checkFlatfile(sheet) )):
133 111 print('Please fix the flatfile and try again.\n') print('Please fix the flatfile and try again.\n')
 
... ... def main():
140 118 input() input()
141 119 sys.exit() sys.exit()
142 120
143 step += 1;
144 # GUI
145 # Ask the user for input inside a gui asking for categories and name
146 cchooser = CategoryChooser(None, cat_conf.id_list, upload_folder, sheet, attributefile,
147 attribute_date)
121 step += 1
122 cchooser = CategoryChooser(master=None, categories=category_id,
123 upath=upload_folder, flatfile=sheet,
124 atrpath=attributefile, atrdate=attribute_date)
148 125 cchooser.title("Choose the category and name") cchooser.title("Choose the category and name")
149 126 LOOP_ACTIVE = True LOOP_ACTIVE = True
150 127 while (LOOP_ACTIVE): while (LOOP_ACTIVE):
 
... ... def main():
155 132 cchooser.data['marking']): cchooser.data['marking']):
156 133 LOOP_ACTIVE = False LOOP_ACTIVE = False
157 134 cchooser.destroy() cchooser.destroy()
158 # END GUI
159 135
160 136 user_data = cchooser.data user_data = cchooser.data
161 specific_name = user_data['name'].strip(' ').strip("'").strip("\"").strip("_").strip("\n").lower()
162 # Writing the changes into the config for the next start of the script
163 if(cchooser.newpath['upload-path'] and cchooser.newpath['attribute-path']):
164 config_update = {'row1':{ 'title': 'upload_folder', 'value': cchooser.newpath['upload-path'] },
165 'row2':{ 'title':'data_folder', 'value':recent_path },
166 'row3':{ 'title':'attribute_file', 'value': cchooser.newpath['attribute-path'] },
167 'row4':{ 'title':'file_change_date', 'value':cchooser.atrdate }}
168 try:
169 config_write(config_path, config_update)
170 except Exception as err:
171 print("ERROR: {0}\n".format(err))
172 upload_folder = cchooser.newpath
173 attributefile['path'] = cchooser.newpath['attribute-path']
174 attribute_date = cchooser.atrdate
175 elif(not( cchooser.newpath['upload-path'] ) and cchooser.newpath['attribute-path']):
176 config_update = {'row1':{ 'title': 'upload_folder', 'value': upload_folder },
177 'row2':{ 'title':'data_folder', 'value':recent_path },
178 'row3':{ 'title':'attribute_file', 'value': cchooser.newpath['attribute-path'] },
179 'row4':{ 'title':'file_change_date', 'value':cchooser.atrdate }}
180 try:
181 config_write(config_path, config_update)
182 except Exception as err:
183 print("ERROR: {0}\n".format(err))
137 specific_name = re.sub(r'[(){}<>\\/"\'\\ \\n]', '', user_data['name'])
138
139 if(cchooser.newpath['upload-path'] != '' and
140 cchooser.newpath['upload-path'] != upload_folder):
141 config['PATH']['upload_folder'] = cchooser.newpath['upload-path']
142 upload_folder = cchooser.newpath['upload-path']
143 if(cchooser.newpath['attribute-path'] != '' and
144 cchooser.newpath['attribute-path'] != attributefile['path']):
145 config['PATH']['attribute_file'] = cchooser.newpath['attribute-path']
146 config['PATH']['file_change_date'] = cchooser.atrdate
184 147 attributefile['path'] = cchooser.newpath['attribute-path'] attributefile['path'] = cchooser.newpath['attribute-path']
185 attribute_date = cchooser.atrdate
186 elif(cchooser.newpath['upload-path'] and not( cchooser.newpath['attribute-path'] )):
187 config_update = {'row1':{ 'title': 'upload_folder', 'value': cchooser.newpath['upload-path'] },
188 'row2':{ 'title':'data_folder', 'value':recent_path },
189 'row3':{ 'title':'attribute_file', 'value': attributefile['path'] },
190 'row4':{ 'title':'file_change_date', 'value': attribute_date }}
191 try:
192 config_write(config_path, config_update)
193 except Exception as err:
194 print("ERROR: {0}\n".format(err))
195 upload_folder = cchooser.newpath
196 # END of Writing config part
148 with open('config.ini', 'w') as configfile:
149 config.write(configfile)
197 150
198 151 if(user_data): if(user_data):
199 152 # Check if there is already a log folder within the upload folder # Check if there is already a log folder within the upload folder
 
... ... def main():
204 157 log_folder = os.path.join(upload_folder, 'log') log_folder = os.path.join(upload_folder, 'log')
205 158
206 159 step += 1 step += 1
207 intern_number['path'] = askopenfilename(initialdir=recent_path,
160 intern_number['path'] = askopenfilename(initialdir=input_folder,
208 161 title="The Intern Numbers as .csv", title="The Intern Numbers as .csv",
209 162 filetypes=[ ("csv files", "*.csv") ]) filetypes=[ ("csv files", "*.csv") ])
210 163
 
... ... def main():
212 165
213 166 step += 1; step += 1;
214 167 try: try:
215 stocklist['path'] = askopenfilename(initialdir=recent_path,
168 stocklist['path'] = askopenfilename(initialdir=input_folder,
216 169 title="The Stockreport from Amazon as .csv", title="The Stockreport from Amazon as .csv",
217 170 filetypes=[ ("csv files", "*.csv") ]) filetypes=[ ("csv files", "*.csv") ])
218 171
 
... ... def main():
311 264
312 265 # IMPORT Export FIlE # IMPORT Export FIlE
313 266 step += 1 step += 1
314 plenty_export['path'] = askopenfilename(initialdir=recent_path,
267 plenty_export['path'] = askopenfilename(initialdir=input_folder,
315 268 title="Export File from Plentymarkets", title="Export File from Plentymarkets",
316 269 filetypes=[ ("csv files", "*.csv") ]) filetypes=[ ("csv files", "*.csv") ])
317 270
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