· 4 years ago · May 13, 2021, 01:06 AM
1import pandas as pd
2import json
3import yaml
4import requests
5from requests_oauthlib import OAuth1Session, OAuth1
6from urllib.parse import urlencode
7from woocommerce import API
8import functions
9import data
10
11# Retrieve config info - fill out config.example.yml as needed, and rename it to config.yml
12with open("config.yml", 'r') as configInfo:
13 config = yaml.safe_load(configInfo)
14
15# Set variables
16ApiKey = config['WC']['apiKey']
17ApiSecret = config['WC']['apiSecret']
18AppName = config['WC']['appName']
19BaseURL = config['WC']['baseURL']
20UserID = config['WC']['userID']
21ReturnURL = config['WC']['returnURL']
22CallbackURL = config['WC']['callbackURL']
23WcVersion = config['WC']['wcVersion']
24Filter_Products = config['ETL']['FilterPrice']
25Filter_Variations = config['ETL']['FilterPriceVar']
26PriceParams = {'status': 'publish',
27 'type': 'variable',
28 'per_page': 50}
29
30# Endpoints
31AuthEndpoint = BaseURL + config['WC']['endpoints']['auth']
32ProductsEndpoint = BaseURL + config['WC']['endpoints']['products']
33OrdersEndpoint = BaseURL + config['WC']['endpoints']['orders']
34CategoriesEndpoint = BaseURL + config['WC']['endpoints']['categories']
35VarEndpointBase = config['WC']['endpoints']['variations']
36
37# We will be using Oauth1 for the purposes of this solution, so we do not need to
38# worry about utilizing API callbacks just yet. I will provide the info in case
39# we want to come back to it later.
40
41# Generate API connect variables for automated key generation, if needed later
42params = {
43 "app_name": AppName,
44 "scope": "read_write",
45 "user_id": UserID,
46 "return_url": ReturnURL,
47 "callback_url": CallbackURL
48}
49
50# For HTTP Basic Auth
51wcAPI = API(
52 url=BaseURL,
53 consumer_key=ApiKey,
54 consumer_secret=ApiSecret,
55 version=WcVersion,
56 wp_api=True
57)
58
59# If API Callback is needed (for automated key generation), we can print out and follow the KeyURL.
60QueryString = urlencode(params)
61KeyURL = ("%s?%s" % (AuthEndpoint, QueryString))
62
63# Create OAuth1 Session
64# Retrieve = OAuth1Session(ApiKey, client_secret=ApiSecret)
65AppAuth = OAuth1(ApiKey, ApiSecret)
66
67# Local data from data.py
68LocalPriceDF = data.df
69LocalPriceJSON = LocalPriceDF.to_json(orient="records")
70
71# Product data from WooCommerce
72WebsitePriceList = (requests.get(ProductsEndpoint, auth=AppAuth, params=PriceParams).json())
73WebsitePriceBase = (requests.get(ProductsEndpoint, auth=AppAuth, params=PriceParams))
74
75UpdateSource = json.loads(LocalPriceJSON)
76UpdateTarget = WebsitePriceList
77
78# Getting next link for next products info API call
79NextLink = requests.get(ProductsEndpoint, auth=AppAuth, params=PriceParams).links['next']['url']
80
81# Product Update Addition Loop
82print('retrieving list of updatable products from API')
83print('adding page 1 to updatable products')
84while NextLink:
85 print('adding page ' + NextLink[-1] + ' to updatable products')
86 UpdateTargetAddon = requests.get(NextLink, auth=AppAuth).json()
87 UpdateTarget.extend(UpdateTargetAddon)
88 try:
89 if requests.get(NextLink, auth=AppAuth).links['next']['url']:
90 print('updating next page link...')
91 NextLink = requests.get(NextLink, auth=AppAuth).links['next']['url']
92 except KeyError:
93 print('reached end of applicable products list. moving on...')
94 break
95
96# Use List Comprehension to morph the product list to a more manageable size.
97# For more info on List Comprehension: https://www.w3schools.com/python/python_lists_comprehension.asp
98print('trimming:')
99print(Filter_Products)
100print('from product page')
101for item in UpdateTarget:
102 [item.pop(key) for key in Filter_Products]
103
104# Audit length of product list
105print('Completed UpdateTarget product list creation.')
106print('Updatable products list from WooCommerce contains '
107 + str(len(UpdateTarget)) +
108 ' products - note that these do not include item variations - we will grab those next')
109
110# uncomment below for list of target updates for audit purposes
111# for product in UpdateTarget:
112# print((str(product['id'])) + ', ' + (product['name']) + ', ' + (product['price']))
113
114
115# Creating workable list of variations and adding specific variation API endpoints
116VarIDList = []
117Variations = []
118for product in UpdateTarget:
119 VarIDAdd = {'id': product['id'], 'variations' : []}
120 for variable in product['variations']:
121 AddURL = {'var_id': variable, 'url': ProductsEndpoint + str(product['id']) + VarEndpointBase + str(variable)}
122 VarIDAdd['variations'].append(AddURL)
123 VarIDList.append(VarIDAdd)
124 Variations.extend(product['variations'])
125
126# Call the API to get Variation info
127# This takes a while. May be a more resource/time effective way to do this...?
128FinalVarList = []
129print('adding variations to FinalVarList - this may take a while (1 request per variation)')
130print(str(len(Variations)) + ' variations to retrieve.')
131for ID in VarIDList:
132 FinalVarAdd = {}
133 AuditMultiple = 50
134 for variation in ID['variations']:
135 AddInfo = requests.get(variation['url'], auth=AppAuth, params=PriceParams).json()
136 [AddInfo.pop(key) for key in Filter_Variations]
137# print(AddInfo)
138 FinalVarList.append(AddInfo)
139 if len(FinalVarList) % AuditMultiple == 1:
140 print('Progress: ' + str(len(FinalVarList)) + ' variations added. '
141 + str(len(Variations) - len(FinalVarList)) + ' remaining')
142 else:
143 continue
144
145print('Completed FinalVarList variation list creation.')
146print('Updatable variation list contains '+str(len(FinalVarList))+' product variations')
147
148# Create list of ItemIDs to grab from local DB
149ItemIDList = []
150print('grabbing list of updatable ItemIDs from local DB')
151for var in FinalVarList:
152 add = var['sku']
153 ItemIDList.append(add)
154
155# Trim UpdateSource into only containing items we retrieved from WooCommerce
156print('Trimming eligible products from UpdateSource')
157UpdateSource = functions.trim_sql_results(UpdateSource, ItemIDList)
158print('Local data contains '+str(len(UpdateSource))+' products that match WooCommerce data')
159
160# Next step is adding the website price to the update list
161for var in FinalVarList:
162 TargetSourceDifference = []
163 for product in UpdateSource:
164 if var['sku'] == product['ItemID']:
165 TargetSourceDifference.append(var)