-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #23 from cloudblue/customers-export-sync
Customers export and sync functionality
- Loading branch information
Showing
37 changed files
with
1,279 additions
and
39 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,207 @@ | ||
import os | ||
from click import ClickException | ||
from cnct import ConnectClient, ClientError | ||
from iso3166 import countries | ||
from openpyxl import Workbook | ||
from openpyxl.styles import PatternFill | ||
from openpyxl.styles.colors import Color | ||
from openpyxl.worksheet.datavalidation import DataValidation | ||
from openpyxl.utils import quote_sheetname | ||
from cnctcli.api.utils import ( | ||
handle_http_error, | ||
) | ||
from tqdm import trange | ||
from cnctcli.actions.utils import DEFAULT_BAR_FORMAT | ||
|
||
COL_HEADERS = { | ||
'A': 'ID', | ||
'B': 'External ID', | ||
'C': 'External UID', | ||
'D': 'Action', | ||
'E': 'Hub ID', | ||
'F': 'Parent Search Criteria', | ||
'G': 'Parent Search Value', | ||
'H': 'Type', | ||
'I': 'Tax ID', | ||
'J': 'Company Name', | ||
'K': 'Address Line 1', | ||
'L': 'Address Line 2', | ||
'M': 'City', | ||
'N': 'State', | ||
'O': 'Zip', | ||
'P': 'Country', | ||
'Q': 'Technical Contact First Name', | ||
'R': 'Technical Contact Last Name', | ||
'S': 'Technical Contact Email', | ||
'T': 'Technical Contact Phone', | ||
} | ||
|
||
|
||
def dump_customers(api_url, api_key, account_id, output_file, silent, output_path=None): | ||
if not output_path: | ||
output_path = os.path.join(os.getcwd(), account_id) | ||
else: | ||
if not os.path.exists(output_path): | ||
raise ClickException( | ||
"Output Path does not exist" | ||
) | ||
output_path = os.path.join(output_path, account_id) | ||
|
||
if not output_file: | ||
output_file = os.path.join(output_path, 'customers.xlsx') | ||
|
||
if not os.path.exists(output_path): | ||
os.mkdir(output_path) | ||
elif not os.path.isdir(output_path): | ||
raise ClickException( | ||
"Exists a file with account id as name but a directory is expected, please rename it" | ||
) | ||
try: | ||
client = ConnectClient(api_key=api_key, endpoint=api_url, use_specs=False) | ||
wb = Workbook() | ||
_prepare_worksheet(wb.create_sheet('Customers')) | ||
_add_countries(wb.create_sheet('Countries')) | ||
|
||
customers = client.ns('tier').accounts.all() | ||
row_idx = 2 | ||
count = customers.count() | ||
progress = trange(0, count, disable=silent, leave=True, bar_format=DEFAULT_BAR_FORMAT) | ||
for customer in customers: | ||
progress.set_description(f'Processing customer {customer["id"]}') | ||
progress.update(1) | ||
_fill_customer_row(wb['Customers'], row_idx, customer["id"], client) | ||
row_idx += 1 | ||
except ClientError as error: | ||
handle_http_error(error) | ||
|
||
default_sheet = wb['Sheet'] | ||
wb.remove(default_sheet) | ||
wb.save(output_file) | ||
|
||
return output_file | ||
|
||
|
||
def _fill_customer_row(ws, row_idx, customer_id, client): | ||
action_validation = DataValidation( | ||
type='list', | ||
formula1='"-,create,update"', | ||
allow_blank=False, | ||
) | ||
action_validation.error = str('Action must be from list') | ||
action_validation.errorTitle = str('Invalid action') | ||
action_validation.prompt = str('Please choose action from list') | ||
action_validation.promptTitle = str('List of choices') | ||
search_criteria_validation = DataValidation( | ||
type='list', | ||
formula1='"-,id,external_id,external_uid"', | ||
allow_blank=False, | ||
) | ||
search_criteria_validation.error = str('Search criteria must be one from list') | ||
search_criteria_validation.errorTitle = str('Invalid search criteria') | ||
search_criteria_validation.prompt = str('Please choose search criteria from list') | ||
search_criteria_validation.promptTitle = str('List of choices') | ||
countries_validation = DataValidation( | ||
type='list', | ||
formula1="{sheet}!$A$1:$A${max}".format( | ||
sheet=quote_sheetname('Countries'), | ||
max=len(countries) + 1, | ||
), | ||
allow_blank=False, | ||
) | ||
countries_validation.error = 'Select country from list, must be 2 letter code' | ||
countries_validation.errorTitle = str('Invalid entry') | ||
countries_validation.prompt = str('Please choose country from list') | ||
countries_validation.promptTitle = str('List of choices') | ||
|
||
ws.add_data_validation(action_validation) | ||
ws.add_data_validation(search_criteria_validation) | ||
ws.add_data_validation(countries_validation) | ||
|
||
customer = client.ns('tier').accounts[ | ||
customer_id | ||
].get() | ||
ws.cell(row_idx, 1, value=customer.get('id', '-')) | ||
ws.cell(row_idx, 2, value=customer.get('external_id', '-')) | ||
ws.cell(row_idx, 3, value=customer.get('external_uid', '-')) | ||
ws.cell(row_idx, 4, value='-') | ||
ws.cell(row_idx, 5, value=customer['hub'].get('id', '-') if 'hub' in customer else '-') | ||
ws.cell(row_idx, 6, value='id' if 'parent' in customer else '-') | ||
ws.cell(row_idx, 7, value=customer['parent'].get('id', '-') if 'parent' in customer else '-') | ||
ws.cell(row_idx, 8, value=customer.get('type', '-')) | ||
ws.cell(row_idx, 9, value=customer.get('tax_id', '-')) | ||
ws.cell(row_idx, 10, value=customer.get('name', '-')) | ||
ws.cell(row_idx, 11, value=customer['contact_info'].get('address_line1', '-')) | ||
ws.cell(row_idx, 12, value=customer['contact_info'].get('address_line2', '-')) | ||
ws.cell(row_idx, 13, value=customer['contact_info'].get('city', '-')) | ||
ws.cell(row_idx, 14, value=customer['contact_info'].get('state', '-')) | ||
ws.cell(row_idx, 15, value=customer['contact_info'].get('zip', '-')) | ||
ws.cell(row_idx, 16, value=customer['contact_info'].get('country', '-')) | ||
ws.cell(row_idx, 17, value=customer['contact_info']['contact'].get('first_name', '-')) | ||
ws.cell(row_idx, 18, value=customer['contact_info']['contact'].get('last_name', '-')) | ||
ws.cell(row_idx, 19, value=customer['contact_info']['contact'].get('email', '-')) | ||
ws.cell( | ||
row_idx, 20, value=_get_phone_number( | ||
customer['contact_info']['contact'].get( | ||
'phone_number', | ||
'-', | ||
) | ||
) | ||
) | ||
|
||
action_validation.add(f'D{row_idx}') | ||
search_criteria_validation.add(f'F{row_idx}') | ||
countries_validation.add(f'P{row_idx}') | ||
|
||
|
||
def _get_phone_number(number): | ||
if number == '-': | ||
return number | ||
output_number = '' | ||
if 'country_code' in number: | ||
output_number = number['country_code'] | ||
if 'area_code' in number: | ||
output_number += number['area_code'] | ||
if 'phone_number' in number: | ||
output_number += number['phone_number'] | ||
if 'extension' in number: | ||
output_number += number['extension'] | ||
return output_number | ||
|
||
|
||
def _prepare_worksheet(ws): | ||
color = Color('d3d3d3') | ||
fill = PatternFill('solid', color) | ||
cels = ws['A1': 'T1'] | ||
for cel in cels[0]: | ||
if cel.column_letter in ['J', 'K', 'L']: | ||
ws.column_dimensions[cel.column_letter].width = 50 | ||
elif cel.column_letter in ['B', 'D', 'E', 'F']: | ||
ws.column_dimensions[cel.column_letter].width = 15 | ||
else: | ||
ws.column_dimensions[cel.column_letter].width = 20 | ||
ws.column_dimensions[cel.column_letter].auto_size = True | ||
cel.fill = fill | ||
cel.value = COL_HEADERS[cel.column_letter] | ||
|
||
|
||
def _add_countries(ws): | ||
col_headers = { | ||
'A': '2 letters country code', | ||
'B': 'Country name', | ||
} | ||
color = Color('d3d3d3') | ||
fill = PatternFill('solid', color) | ||
ws.column_dimensions['A'].width = 15 | ||
ws.column_dimensions['A'].auto_size = True | ||
ws.column_dimensions['B'].width = 50 | ||
cels = ws['A1': 'B1'] | ||
for cel in cels[0]: | ||
cel.fill = fill | ||
cel.value = col_headers[cel.column_letter] | ||
row_idx = 2 | ||
for country in countries: | ||
ws.cell(row_idx, 1, value=country.alpha2) | ||
ws.cell(row_idx, 2, value=country.name) | ||
row_idx += 1 | ||
ws.cell(row_idx, 1, value='-') | ||
ws.cell(row_idx, 2, value='Not Selected') |
Oops, something went wrong.