This is a tool for comparing 2 entities' attributes with the OMS. For example, customer support would like to compare order attributes between Production and UAT.
Key points
Pycharm app to help user to compare two entity attributes
Pre-requisite
Pycharm installed on your computer
vscode installed with the command line. (alternative diff can be used. see the compare section in the code)
Steps to run Pycharm app:Create a new pycharm project and copy and paste the below code into the main.py. Install all dependency libraries. Update retailer variables and Run the programThe result will also launch vscode with a visualisation of file comparison: The <Batch_no>_log file has been changed to executable: which means, you can get reopen the result by running the <batch_no>_log file in the command line. note: this is tested in Mac. User might need to re-tune the permission in Windows.
Fluent Commerce
1import json
2import requests
3import os
4from graphqlclient import GraphQLClient
5from http.client import IncompleteRead
6from datetime import datetime
789#10# Prereq: install vscode cli version: https://code.visualstudio.com/docs/setup/mac11#12# Program: This program will extract 2 entities and compare the attributes by using vscode diff.13#1415# provide either account or retailer oauth as long as the login is able to get the entity attributes16#########################1718accountId_A ='{{accountID_A}}'19oauth_url_A ='{{oauth_A}}'20graphql_url_A ='https://{{url_A}}/graphql'21entity_name_A ='orders'22entity_ref_A ='CC_75014'23# can compare any entities with attributes:24#entity_name_A = 'fulfilments'25#entity_ref_A = '61d07f67-f529-4f68-8682-0e32d8ca3110'2627accountId_B ='{{accountID_B}}'28oauth_url_B ='{{oauth_B}}'29graphql_url_B ='https://{{url_B}}/graphql'30entity_name_B ='orders'31entity_ref_B ='CC_43422'323334#***********************************************************************************35# After configuring the above variables, you can simply run the apps to review the result.36####################################################################################37####################################################################################3839404142#unique batch no for each run43batch_no = datetime.now().strftime("%Y%m%d%H%M%S")44####################################################################################45# standard def to extract API data:46####################################################################################47defget_page_of_data(pquery,client, after, first):48 res = client.execute(pquery,{'after': after,'first': first})49 data = json.loads(res)['data']50return data
5152### ------ Get Dataset for account A ---- ###53defget_token_A():54 auth_token_response = requests.post(oauth_url_A)55if auth_token_response.status_code ==200:56print(auth_token_response.json())57else:58print("Couldn't get auth token {}".format(auth_token_response.status_code))59 access_token ='Bearer '+ auth_token_response.json()['access_token']60print("Access token: {}".format(access_token))61return access_token
6263definit_client_A():64 client = GraphQLClient(graphql_url_A)65 client.inject_token(get_token_A())66return client
6768defget_all_data_A(pquery,pentity, client=init_client_A(), all_labels=[], cursor=None, first=50, retries_left=5):69global data
70try:71 data = get_page_of_data(pquery,client, cursor, first)72except IncompleteRead:73print('reconnect and keep tracking')74if retries_left >0:75 retries_left = retries_left -176 client = init_client_A()77 get_all_data_A(pquery,pentity,client, all_labels, cursor, retries_left)78else:79print('retries exhausted')80return all_labels
81except:82print("error occurred for cursor: {} retrying with retries left:{}".format(cursor, retries_left))83if retries_left >0:84 retries_left = retries_left -185 get_all_data_A(pquery,pentity,client, all_labels, cursor, retries_left)86else:87print('retries exhausted')88return all_labels
89if data isnotNone:90 new_labels =[]or data[pentity]['edges']91 has_next_page = data[pentity]['pageInfo']['hasNextPage']92 all_labels = all_labels + new_labels
93if has_next_page:94iflen(new_labels)>0:95 cursor = get_cursor(new_labels)96 all_labels = get_all_data_A(pquery,pentity,client, all_labels, cursor)97return all_labels
9899100defget_cursor(new_labels):101iflen(new_labels)>0:102 last =len(new_labels)-1103whileTrue:104if'cursor'in new_labels[last]:105return new_labels[last]['cursor']106else:107 last -=1108if'cursor'in new_labels[last]:109return new_labels[last]['cursor']110else:111pass112113114### ------ Get Dataset for account B ---- ###115defget_token_B():116 auth_token_response = requests.post(oauth_url_B)117if auth_token_response.status_code ==200:118print(auth_token_response.json())119else:120print("Couldn't get auth token {}".format(auth_token_response.status_code))121 access_token ='Bearer '+ auth_token_response.json()['access_token']122print("Access token: {}".format(access_token))123return access_token
124125definit_client_B():126 client = GraphQLClient(graphql_url_B)127 client.inject_token(get_token_B())128return client
129130defget_all_data_B(pquery,pentity,client=init_client_B(), all_labels=[], cursor=None, first=50, retries_left=5):131global data
132try:133 data = get_page_of_data(pquery,client, cursor, first)134except IncompleteRead:135print('reconnect and keep tracking')136if retries_left >0:137 retries_left = retries_left -1138 client = init_client_B()139 get_all_data_B(pquery,pentity,client, all_labels, cursor, retries_left)140else:141print('retries exhausted')142return all_labels
143except:144print("error occurred for cursor: {} retrying with retries left:{}".format(cursor, retries_left))145if retries_left >0:146 retries_left = retries_left -1147 get_all_data_B(pquery,pentity,client, all_labels, cursor, retries_left)148else:149print('retries exhausted')150return all_labels
151if data isnotNone:152 new_labels =[]or data[pentity]['edges']153 has_next_page = data[pentity]['pageInfo']['hasNextPage']154 all_labels = all_labels + new_labels
155if has_next_page:156iflen(new_labels)>0:157 cursor = get_cursor(new_labels)158 all_labels = get_all_data_B(pquery,pentity,client, all_labels, cursor)159return all_labels
160161162163defcompareFiles(file1, file2):164 cmd ='code -d '+ file1 +' '+ file2
165 os.system(cmd)166 os.system('echo '+ cmd +'>> '+ batch_no+"_log")167 os.system('chmod 755 '+ batch_no +"_log")168## Alternative way to compare file by using diff command:169#cmd = 'diff -y ' + file1 + ' ' + file2 + \170# '> '+ (batch_no + '_diff_' + file1 + '_' + file2 + '_') + '.txt'171#os.system(cmd)172173#########################################################################################################174#### Entity175#########################################################################################################176177entity_query ='''
178 edges {
179 node {
180 id
181 ref
182 createdOn
183 updatedOn
184 status
185 attributes{
186 attr_name: name
187 attr_type: type
188 attr_value: value
189 }
190 }
191 cursor
192 }
193 pageInfo {
194 hasNextPage
195 }
196 }
197 }
198 '''199200entity_query_headerA ='query extractEntity($after:String, $first:Int) {'+entity_name_A+'(after:$after, first:$first, ref:"'+entity_ref_A+'"){'+entity_query
201entity_query_headerB ='query extractEntity($after:String, $first:Int) {'+entity_name_B+'(after:$after, first:$first, ref:"'+entity_ref_B+'"){'+ entity_query
202entity_ListA =[]203entity_ListB =[]204entity_filenameA = batch_no+'_'+ accountId_A +'_'+ entity_name_A +'_'+ entity_ref_A +'_A.csv'205entity_filenameB = batch_no+'_'+ accountId_B +'_'+ entity_name_B +'_'+ entity_ref_B +'_B.csv'206207defprocess_entity_result(all_labels,pfilename, pentityname,paccountId,pgraphqlURL ):208file=open(pfilename,"w")209file.write("ACCOUNT:"+ paccountId +"\n")210file.write("URL:"+ pgraphqlURL +"\n")211 attributes =[]212for data in all_labels:213iflen(data.keys())>0:214file.write("ENTITY:"+ pentityname +"\n")215file.write("ID:"+str(data['node']['id'])+"\n")216file.write("REF:"+str(data['node']['ref'])+"\n")217file.write("CREATEDON:"+str(data['node']['createdOn'])+"\n")218file.write("UPDATEDON:"+str(data['node']['updatedOn'])+"\n")219file.write("STATUS:"+str(data['node']['status'])+"\n")220file.write("ATTRIBUTES count("+str(len(data['node']['attributes']))+"):\n")221#print(data['node']['attributes'])222#print(len(data['node']['attributes']))223224#get all attributes and sort it.225 n =0226while n <len(data['node']['attributes']):227 attributes.append(data['node']['attributes'][n]['attr_name']+","+data['node']['attributes'][n]['attr_type']+","+str(data['node']['attributes'][n]['attr_value']))228 n +=1229 attributes.sort()230231#write the sorted attributes into the file.232 n =0233while n <len(attributes):234file.write(attributes[n]+"\n")235 n +=1236#print(attributes)237file.close()238239# get entity A240result = get_all_data_A(pquery=entity_query_headerA,pentity=entity_name_A)241process_entity_result(result,entity_filenameA,entity_name_A, accountId_A, graphql_url_A)242243# get entity B244result = get_all_data_B(pquery=entity_query_headerB,pentity=entity_name_B)245process_entity_result(result,entity_filenameB,entity_name_B,accountId_B, graphql_url_B)246247# compare Files248compareFiles(entity_filenameA, entity_filenameB)249250251252253254