Skip to content

Commit 13b98f7

Browse files
feat: extract ct data into csv command
1 parent 7a27355 commit 13b98f7

File tree

1 file changed

+132
-0
lines changed

1 file changed

+132
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
from datetime import datetime
2+
import csv
3+
from enum import Enum
4+
from itertools import product
5+
6+
from commerce_coordinator.apps.commercetools.management.commands._ct_api_client_command import (
7+
CommercetoolsAPIClientCommand
8+
)
9+
10+
11+
# Enum for product types
12+
class ProductType(Enum):
13+
EDX_COURSE_ENTITLEMENT = "edx_course_entitlement"
14+
EDX_PROGRAM = "edx_program"
15+
OC_SELF_PACED = "oc_self_paced"
16+
17+
STAGE_PRODUCT_TYPE_ID_MAPPING = {
18+
ProductType.EDX_COURSE_ENTITLEMENT.value: "12e5510c-a4d6-4301-9caf-17053e57ff71",
19+
ProductType.EDX_PROGRAM.value: "79fb6abe-8373-4dec-a8d1-51242b1798b8",
20+
ProductType.OC_SELF_PACED.value: "9f8ec882-043a-4225-8811-00ac5acfd580"
21+
}
22+
23+
class Command(CommercetoolsAPIClientCommand):
24+
help = "Fetch and verify course attributes from CommerceTools"
25+
26+
def handle(self, *args, **options):
27+
# Specify product type to fetch
28+
product_type = ProductType.EDX_COURSE_ENTITLEMENT
29+
30+
# Fetch products based on type
31+
products = self.fetch_products(product_type)
32+
33+
# Write data to CSV
34+
self.write_attributes_to_csv(products, product_type)
35+
36+
def fetch_products(self, product_type):
37+
limit = 500
38+
offset = 0
39+
products = []
40+
41+
product_type_id = STAGE_PRODUCT_TYPE_ID_MAPPING.get(product_type.value)
42+
43+
while True:
44+
products_result = self.ct_api_client.base_client.products.query(
45+
limit=limit,
46+
offset=offset,
47+
where=f"productType(id=\"{product_type_id}\")"
48+
)
49+
for product in products_result.results:
50+
attributes = self.extract_product_attributes(product, product_type.value)
51+
products.extend(attributes)
52+
53+
if products_result.offset + products_result.limit >= products_result.total:
54+
break
55+
offset += limit
56+
57+
return products
58+
59+
def extract_product_attributes(self, product, product_type):
60+
# Extract common product-level attributes
61+
common_attributes = {
62+
"product_type": product_type,
63+
"product_id": product.id,
64+
"product_key": product.key,
65+
"published_status": product.master_data.published,
66+
"name": product.master_data.current.name.get('en-US', ''),
67+
"slug": product.master_data.current.slug.get('en-US', ''),
68+
"description": (
69+
product.master_data.current.description.get('en-US', '')
70+
if product.master_data.current.description
71+
else ''
72+
),
73+
"date_created": product.created_at,
74+
"master_variant_key": product.master_data.current.master_variant.key,
75+
"master_variant_sku": product.master_data.current.master_variant.sku,
76+
"master_variant_image_url": (
77+
product.master_data.current.master_variant.images[0].url
78+
if product.master_data.current.master_variant.images
79+
else None
80+
),
81+
}
82+
83+
product_rows = [] # This will hold the product and variant rows
84+
85+
# Add the master variant attributes
86+
if len(product.master_data.current.variants) == 0:
87+
master_variant_attributes = {attr.name: attr.value for attr in
88+
product.master_data.current.master_variant.attributes}
89+
product_rows.append({**common_attributes, **master_variant_attributes})
90+
91+
# Add attributes for each variant and create a separate row, including variant_key and variant_sku
92+
for variant in product.master_data.current.variants:
93+
variant_attributes = {attr.name: attr.value for attr in variant.attributes}
94+
variant_row = {
95+
**common_attributes,
96+
"variant_key": variant.key, # Add variant_key
97+
"variant_sku": variant.sku, # Add variant_sku
98+
"variant_image_url": (
99+
variant.images[0].url
100+
if variant.images
101+
else None
102+
),
103+
**variant_attributes,
104+
}
105+
# Create a new row for each variant, combining common product data with variant-specific attributes
106+
product_rows.append(variant_row)
107+
108+
return product_rows
109+
110+
def write_attributes_to_csv(self, products, product_type):
111+
if not products:
112+
print(f"No products found for type {product_type}.")
113+
return
114+
115+
# Dynamically extract all unique keys across all product dictionaries
116+
keys = set()
117+
for product in products:
118+
keys.update(product.keys())
119+
120+
# Convert keys set back to a list and sort them if you want a consistent order
121+
keys = sorted(list(keys))
122+
123+
# Define CSV filename with product type and date
124+
filename = f"{product_type.value}_attributes_{datetime.now().strftime('%Y%m%d')}.csv"
125+
126+
# Write to CSV
127+
with open(filename, "w", newline="") as output_file:
128+
dict_writer = csv.DictWriter(output_file, fieldnames=keys)
129+
dict_writer.writeheader()
130+
dict_writer.writerows(products)
131+
132+
print(f"\n\n\n\n\n\n\nCSV file '{filename}' written successfully with {len(products)} records.")

0 commit comments

Comments
 (0)