codys12 commited on
Commit
354bf5f
·
verified ·
1 Parent(s): 86e87e3

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +177 -0
app.py ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ from io import BytesIO
4
+
5
+ def process_woocommerce_data_in_memory(netcom_file):
6
+ """
7
+ Reads the uploaded NetCom CSV file in-memory, processes it to the WooCommerce format,
8
+ and returns the resulting CSV as bytes, suitable for download.
9
+ """
10
+ # Define the brand-to-logo mapping
11
+ brand_logo_map = {
12
+ "Amazon Web Services": "https://devthe.tech/wp-content/uploads/2025/02/aws.png",
13
+ "Cisco": "https://devthe.tech/wp-content/uploads/2025/02/cisco-e1738593292198-1.webp",
14
+ "Microsoft": "https://devthe.tech/wp-content/uploads/2025/01/Microsoft-e1737494120985-1.png"
15
+ }
16
+
17
+ # 1. Read the uploaded CSV into a DataFrame
18
+ netcom_df = pd.read_csv(netcom_file.name, encoding='latin1')
19
+ netcom_df.columns = netcom_df.columns.str.strip() # standardize column names
20
+
21
+ # 2. Create aggregated dates and times for each Course ID
22
+ date_agg = (
23
+ netcom_df.groupby('Course ID')['Course Start Date']
24
+ .apply(lambda x: ','.join(x.astype(str).unique()))
25
+ .reset_index(name='Aggregated_Dates')
26
+ )
27
+
28
+ time_agg = (
29
+ netcom_df.groupby('Course ID')
30
+ .apply(
31
+ lambda df: ','.join(
32
+ f"{st}-{et} {tz}"
33
+ for st, et, tz in zip(df['Course Start Time'],
34
+ df['Course End Time'],
35
+ df['Time Zone'])
36
+ )
37
+ )
38
+ .reset_index(name='Aggregated_Times')
39
+ )
40
+
41
+ # 3. Extract unique parent products from the NetCom data
42
+ parent_products = netcom_df.drop_duplicates(subset=['Course ID'])
43
+
44
+ # 4. Merge aggregated dates and times into the parent product DataFrame
45
+ parent_products = parent_products.merge(date_agg, on='Course ID', how='left')
46
+ parent_products = parent_products.merge(time_agg, on='Course ID', how='left')
47
+
48
+ # 5. Create the parent (variable) product DataFrame
49
+ woo_parent_df = pd.DataFrame({
50
+ 'Type': 'variable',
51
+ 'SKU': parent_products['Course ID'],
52
+ 'Name': parent_products['Course Name'],
53
+ 'Published': 1,
54
+ 'Visibility in catalog': 'visible',
55
+ 'Short description': parent_products['Decription'],
56
+ 'Description': parent_products['Decription'],
57
+ 'Tax status': 'taxable',
58
+ 'In stock?': 1,
59
+ 'Stock': 1,
60
+ 'Sold individually?': 1,
61
+ 'Regular price': parent_products['SRP Pricing'].replace('[\$,]', '', regex=True),
62
+ 'Categories': 'courses',
63
+ 'Images': parent_products['Vendor'].map(brand_logo_map).fillna(''),
64
+ 'Parent': '',
65
+ 'Brands': parent_products['Vendor'],
66
+ 'Attribute 1 name': 'Date',
67
+ 'Attribute 1 value(s)': parent_products['Aggregated_Dates'],
68
+ 'Attribute 1 visible': 'visible',
69
+ 'Attribute 1 global': 1,
70
+ 'Attribute 2 name': 'Location',
71
+ 'Attribute 2 value(s)': 'Virtual',
72
+ 'Attribute 2 visible': 'visible',
73
+ 'Attribute 2 global': 1,
74
+ 'Attribute 3 name': 'Time',
75
+ 'Attribute 3 value(s)': parent_products['Aggregated_Times'],
76
+ 'Attribute 3 visible': 'visible',
77
+ 'Attribute 3 global': 1,
78
+ 'Meta: outline': parent_products['Outline'],
79
+ 'Meta: days': parent_products['Duration'],
80
+ 'Meta: location': 'Virtual',
81
+ 'Meta: overview': parent_products['Target Audience'],
82
+ 'Meta: objectives': parent_products['Objectives'],
83
+ 'Meta: prerequisites': parent_products['RequiredPrerequisite'].fillna(''),
84
+ 'Meta: agenda': parent_products['Outline'] # Agenda now copies the outline
85
+ })
86
+
87
+ # 6. Create the child (variation) product DataFrame
88
+ woo_child_df = pd.DataFrame({
89
+ 'Type': 'variation, virtual',
90
+ 'SKU': netcom_df['Course SID'],
91
+ 'Name': netcom_df['Course Name'],
92
+ 'Published': 1,
93
+ 'Visibility in catalog': 'visible',
94
+ 'Short description': netcom_df['Decription'],
95
+ 'Description': netcom_df['Decription'],
96
+ 'Tax status': 'taxable',
97
+ 'In stock?': 1,
98
+ 'Stock': 1,
99
+ 'Sold individually?': 1,
100
+ 'Regular price': netcom_df['SRP Pricing'].replace('[\$,]', '', regex=True),
101
+ 'Categories': 'courses',
102
+ 'Images': netcom_df['Vendor'].map(brand_logo_map).fillna(''),
103
+ 'Parent': netcom_df['Course ID'],
104
+ 'Brands': netcom_df['Vendor'],
105
+ 'Attribute 1 name': 'Date',
106
+ 'Attribute 1 value(s)': netcom_df['Course Start Date'],
107
+ 'Attribute 1 visible': 'visible',
108
+ 'Attribute 1 global': 1,
109
+ 'Attribute 2 name': 'Location',
110
+ 'Attribute 2 value(s)': 'Virtual',
111
+ 'Attribute 2 visible': 'visible',
112
+ 'Attribute 2 global': 1,
113
+ 'Attribute 3 name': 'Time',
114
+ 'Attribute 3 value(s)': netcom_df.apply(
115
+ lambda row: f"{row['Course Start Time']}-{row['Course End Time']} {row['Time Zone']}", axis=1
116
+ ),
117
+ 'Attribute 3 visible': 'visible',
118
+ 'Attribute 3 global': 1,
119
+ 'Meta: outline': netcom_df['Outline'],
120
+ 'Meta: days': netcom_df['Duration'],
121
+ 'Meta: location': 'Virtual',
122
+ 'Meta: overview': netcom_df['Target Audience'],
123
+ 'Meta: objectives': netcom_df['Objectives'],
124
+ 'Meta: prerequisites': netcom_df['RequiredPrerequisite'].fillna(''),
125
+ 'Meta: agenda': netcom_df['Outline'] # Agenda now copies the outline
126
+ })
127
+
128
+ # 7. Combine parent and child data
129
+ woo_final_df = pd.concat([woo_parent_df, woo_child_df], ignore_index=True)
130
+
131
+ # 8. Define the desired column order (matching WooCommerce import format)
132
+ column_order = [
133
+ 'Type', 'SKU', 'Name', 'Published', 'Visibility in catalog',
134
+ 'Short description', 'Description', 'Tax status', 'In stock?',
135
+ 'Stock', 'Sold individually?', 'Regular price', 'Categories', 'Images',
136
+ 'Parent', 'Brands', 'Attribute 1 name', 'Attribute 1 value(s)', 'Attribute 1 visible',
137
+ 'Attribute 1 global', 'Attribute 2 name', 'Attribute 2 value(s)', 'Attribute 2 visible',
138
+ 'Attribute 2 global', 'Attribute 3 name', 'Attribute 3 value(s)', 'Attribute 3 visible',
139
+ 'Attribute 3 global', 'Meta: outline', 'Meta: days', 'Meta: location', 'Meta: overview',
140
+ 'Meta: objectives', 'Meta: prerequisites', 'Meta: agenda'
141
+ ]
142
+ woo_final_df = woo_final_df[column_order]
143
+
144
+ # 9. Convert the final DataFrame to CSV in memory
145
+ output_buffer = BytesIO()
146
+ woo_final_df.to_csv(output_buffer, index=False, encoding='utf-8-sig')
147
+ output_buffer.seek(0)
148
+
149
+ return output_buffer
150
+
151
+ def process_file_and_return_csv(uploaded_file):
152
+ """
153
+ Gradio wrapper function:
154
+ - Takes the uploaded file,
155
+ - Processes it,
156
+ - Returns a tuple that Gradio can interpret as a downloadable file.
157
+ """
158
+ processed_csv_io = process_woocommerce_data_in_memory(uploaded_file)
159
+
160
+ # Gradio expects a tuple (filename, file_obj) when returning a downloadable file
161
+ return ("WooCommerce_Mapped_Data.csv", processed_csv_io.getvalue())
162
+
163
+
164
+ #########################
165
+ # Gradio App #
166
+ #########################
167
+
168
+ app = gr.Interface(
169
+ fn=process_file_and_return_csv,
170
+ inputs=gr.File(label="Upload NetCom CSV", file_types=["text", "csv"]),
171
+ outputs=gr.File(label="Download WooCommerce CSV"),
172
+ title="NetCom to WooCommerce CSV Processor",
173
+ description="Upload your NetCom Reseller Schedule CSV to generate the WooCommerce import-ready CSV."
174
+ )
175
+
176
+ if __name__ == "__main__":
177
+ app.launch()