From f4c19dec041cbf3438a9bbfa579e1d3f6374f66c Mon Sep 17 00:00:00 2001 From: Senad Uka Date: Wed, 27 Dec 2017 16:24:50 +0100 Subject: [PATCH] merging with upstream --- README.md | 3 +- helix/Services/s3_helper.py | 3 +- helix/json_builder.py | 10 ++++- helix/main.py | 59 +++++++++++++++++----------- helix/presenters/panel_presenter.py | 2 +- helix/sales_force/tasks.py | 61 +++++++++++++++++------------ helix/templates/download.html.jinja | 21 ++++++++-- 7 files changed, 103 insertions(+), 56 deletions(-) diff --git a/README.md b/README.md index 3df90cf..d63a964 100644 --- a/README.md +++ b/README.md @@ -44,9 +44,10 @@ AWS_S3_BUCKET="..." AWS_ACCESS_KEY_ID="..." AWS_SECRET_ACCESS_KEY="..." -SF_BASE_URL="https://test.salesforce.com" +SFDC_BASE_URL="https://test.salesforce.com" SFDC_ACCESS_KEY_ID="..." SFDC_SECRET_ACCESS_KEY="..." +SFDC_API_URL="https://sunpower--qa.cs8.my.salesforce.com" ``` diff --git a/helix/Services/s3_helper.py b/helix/Services/s3_helper.py index 26a8bc1..e9715a7 100644 --- a/helix/Services/s3_helper.py +++ b/helix/Services/s3_helper.py @@ -21,6 +21,7 @@ def s3_upload(bytes_or_file_like, filename=None, file_extension=None): # Assuming bucket already exists s3.Bucket(bucket_name).put_object(Key=filename, Body=bytes_or_file_like.read(), ACL='public-read') - file_url = 'https://s3.amazonaws.com/{}/{}'.format(bucket_name, filename) + # file_url = 'https://s3.amazonaws.com/{}/{}'.format(bucket_name, filename) # PermanentRedirect error + file_url = 'https://{}.s3.amazonaws.com/{}'.format(bucket_name, filename) print('Uploaded filename {} to S3: {}'.format(filename, file_url)) return file_url diff --git a/helix/json_builder.py b/helix/json_builder.py index 40dbd3a..2da3bed 100644 --- a/helix/json_builder.py +++ b/helix/json_builder.py @@ -5,12 +5,18 @@ except ImportError: class JsonBuilder: - def build_bom_output(self, rows): + def build_bom(self, rows): data = [] - headers = ['Part #', 'Description', 'Total'] + headers = ['itemId', 'description', 'quantity'] for row in rows: d = {} for i, value in enumerate(row): d[headers[i]] = value data.append(d) + return data + + def bom_to_json(self, data): return json.dumps(data) + + def build_bom_output(self, rows): + return self.bom_to_json(self.build_bom(rows)) diff --git a/helix/main.py b/helix/main.py index 5eb8a4c..c1cbc5d 100644 --- a/helix/main.py +++ b/helix/main.py @@ -41,16 +41,21 @@ app.config['PROFILE'] = True # Sales Force integrations oauth = OAuth() -SF_BASE_URL = os.getenv('SFDC_BASE_URL', 'https://test.salesforce.com') -sales_force = oauth.remote_app('sales_force', - consumer_key=os.getenv('SFDC_ACCESS_KEY_ID'), - consumer_secret=os.getenv('SFDC_SECRET_ACCESS_KEY'), - base_url=SF_BASE_URL, - request_token_url=None, # OAuth 2 - access_token_method='POST', # Sales Force requirement - access_token_url=SF_BASE_URL + '/services/oauth2/token', - authorize_url=SF_BASE_URL + '/services/oauth2/authorize', -) +SFDC_BASE_URL = os.getenv('SFDC_BASE_URL', 'https://test.salesforce.com') +try: + sales_force = oauth.remote_app('sales_force', + consumer_key=os.getenv('SFDC_ACCESS_KEY_ID'), + consumer_secret=os.getenv('SFDC_SECRET_ACCESS_KEY'), + base_url=SFDC_BASE_URL, + request_token_url=None, # OAuth 2 + access_token_method='POST', # Sales Force requirement + access_token_url=SFDC_BASE_URL + '/services/oauth2/token', + authorize_url=SFDC_BASE_URL + '/services/oauth2/authorize', + ) +except TypeError: + print('Sales Force integration disabled') + sales_force = None + assets_env = assets.Environment(app) assets_env.init_app(app) @@ -186,7 +191,7 @@ def summary(): return render_template('site_summary.html.jinja', context=context) -def handle_dxf_file(session_manager, file_contents, filename=None): +def handle_dxf_file(session_manager, file_contents, filename=None, save_file=True): errors = [] user_values = session_manager.user_values() validator = FileValidator(user_values) @@ -210,7 +215,8 @@ def handle_dxf_file(session_manager, file_contents, filename=None): DXFHelper(), SubarrayValidator()) csv = CsvBuilder().build_cad_output(dxf_data['panels']) - session_manager.save_uploaded_file(csv, dxf_file_name=filename) + if save_file: + session_manager.save_uploaded_file(csv, dxf_file_name=filename) buildings = dxf_data['buildings'] session_manager.save_buildings_polygons(buildings) @@ -334,7 +340,7 @@ def load_dxf_file(): db_session = sql_constant.sql_session_maker() session_manager = SessionManager(session, redis_constant.redis_store, db_session) - success, errors = handle_dxf_file(session_manager, file_contents, filename=filename) + success, errors = handle_dxf_file(session_manager, file_contents, filename=filename, save_file=False) session['dxf_link_loaded'] = True if success: return jsonify({'status': 'success'}) @@ -424,6 +430,10 @@ def download(): session_manager = SessionManager(session, redis_constant.redis_store, db_session) context = session_manager.context() context['current_step'] = 5 + error, data = session.pop('sfdc_export_urls', (None, None)) + if data is not None: + context['sfdc_export_error'] = error + context['sfdc_export_urls'] = data db_session.close() return render_template('download.html.jinja', context=context) @@ -540,7 +550,7 @@ def sales_force_authorized(): session_manager = SessionManager(session, redis_constant.redis_store, db_session) session['sales_force_token'] = resp['access_token'] - data = sf_tasks.get_site_characterization_from_sales_force(session, resp['instance_url']) + data = sf_tasks.get_site_characterization_from_sales_force(session) if data: session['dxf_link'] = data['dxf_link'] session_manager.save_form_submission(data) @@ -549,23 +559,27 @@ def sales_force_authorized(): return sales_force_logout() -# FIXME @app.route("/export-sfdc") def export_sfdc(): if not is_sfdc_session(): return redirect('/') db_session = sql_constant.sql_session_maker() session_manager = SessionManager(session, redis_constant.redis_store, db_session) - session_id = session_manager.session['id'] - data = sf_tasks.export_to_sfdc(session_id) + helix_session_id = session_manager.session['id'] + access_token = session['sales_force_token'] + sfid = session['SFID'] + error, data = sf_tasks.export_to_sfdc(helix_session_id, access_token, sfid) + data.pop('bom', None) + data['dxfUrlFromSF'] = session['dxf_link'] + session['sfdc_export_urls'] = (error, data) db_session.close() - return jsonify(data) - # return redirect('/download') + return redirect('/download') -@sales_force.tokengetter -def get_sales_force_token(token=None): - return session.get('sales_force_token') +if sales_force: + @sales_force.tokengetter + def get_sales_force_token(token=None): + return session.get('sales_force_token') @app.route('/sales_force_logout') @@ -574,6 +588,7 @@ def sales_force_logout(): session.pop('sales_force_token', None) session.pop('dxf_link', None) session.pop('dxf_link_loaded', None) + session.pop('sfdc_export_urls', None) session.clear() return redirect('/') # End of Sales Force Integration diff --git a/helix/presenters/panel_presenter.py b/helix/presenters/panel_presenter.py index b98b2ba..08017b5 100644 --- a/helix/presenters/panel_presenter.py +++ b/helix/presenters/panel_presenter.py @@ -68,7 +68,7 @@ class ProjectPresenter(object): # origin = self.find_origin(building) for point in building: point.x = point.x * spacing_x - point.y = abs((point.y * spacing_y - max_y)) + point.y = abs((point.y * spacing_y) - max_y) presentable_building.append(point.__dict__) return result diff --git a/helix/sales_force/tasks.py b/helix/sales_force/tasks.py index e66f004..0b72e4f 100644 --- a/helix/sales_force/tasks.py +++ b/helix/sales_force/tasks.py @@ -1,4 +1,5 @@ import io +import os import uuid import requests @@ -16,14 +17,12 @@ from helix.Services.s3_helper import s3_upload from helix.session_manager import SessionManager -def get_site_characterization_from_sales_force(session, base_url): - ''' - @base_url: Avoid URL_NOT_RESET errors - ''' +def get_site_characterization_from_sales_force(session): access_token = session['sales_force_token'] sfid = session['SFID'] helix_id = session['id'] - url = base_url + '/services/apexrest/v1/HelixRoofDetails' + SFDC_API_URL = os.getenv('SFDC_API_URL', 'https://sunpower--qa.cs8.my.salesforce.com') + url = SFDC_API_URL + '/services/apexrest/v1/HelixRoofDetails' headers = {'Authorization': 'Bearer {}'.format(access_token)} result = requests.get(url, headers=headers, params={'SFID': sfid, 'helix_session_id': helix_id}) if result.status_code == 200: @@ -50,12 +49,12 @@ def convert_sales_force_data_format_to_helix(data): # data['spectral_response_acceleration'] -def export_to_sfdc(session_id): +def export_to_sfdc(helix_session_id, access_token, sfid): step = 'Exporting to SFDC' try: # 1. Load User Values step = 'Loading User Values' - session = {'id': session_id} + session = {'id': helix_session_id} db_session = sql_constant.sql_session_maker() session_manager = SessionManager(session, redis_constant.redis_store, db_session) user_values = session_manager.user_values() @@ -67,7 +66,9 @@ def export_to_sfdc(session_id): csv_file = CsvBuilder().build_bom_output(bom) # 2.1 Generate BOM CSV file step = 'Generating BOM as JSON' - json_str = JsonBuilder().build_bom_output(bom) + json_builder = JsonBuilder() + bom_list = json_builder.build_bom(bom) + bom_list_json = json_builder.bom_to_json(bom_list) # 3. Generate DOCUMENTATION PDF file step = 'Generating Documentation' @@ -84,8 +85,8 @@ def export_to_sfdc(session_id): step = 'Uploading to S3' filename = uuid.uuid4().hex bom_csv_url = s3_upload(io.StringIO(csv_file), filename=filename + '.csv') - bom_json_url = s3_upload(io.StringIO(json_str), filename=filename + '.json') doc_url = s3_upload(io.BytesIO(document), filename=filename + '.pdf') + bom_json_url = s3_upload(io.StringIO(bom_list_json), filename=filename + '.json') if dxf_contents: # Optional dxf_url = s3_upload(io.StringIO(dxf_contents), filename=filename + '.dxf') else: @@ -93,26 +94,34 @@ def export_to_sfdc(session_id): # 6. Notify SFDC system with an API request step = 'Notifying SFDC' - SFDC_API_URL = 'https://localhost:8443/' # FIXME data = { - 'dxf_url': dxf_url, - 'bom_csv_url': bom_csv_url, - 'bom_json_url': bom_json_url, - 'documentation_url': doc_url, + 'dxfUrl': dxf_url, + 'bomCsvUrl': bom_csv_url, + 'documentationUrl': doc_url, + 'bom': bom_list, + 'helixSessionId': helix_session_id, + 'SFID': sfid, } - print(data) - # result = requests.post(SFDC_API_URL, data=data, timeout=30) - + headers = {'Authorization': 'Bearer {}'.format(access_token)} + SFDC_API_URL = os.getenv('SFDC_API_URL', 'https://sunpower--qa.cs8.my.salesforce.com') + url = SFDC_API_URL + '/services/apexrest/v1/HelixRoofDetails' + result = requests.post(url, headers=headers, data=data, timeout=30) # 7. Internal logs - # if result.status_code != 200: # FIXME - # print('') - # else: - # print('') + if result.status_code <= 299: + print('Sales Force notified successfully for session {}.'.format(helix_session_id)) + # print(result.content) + error = None + else: + error = 'Helix wasn\'t able to notify the Sales Force ({})'.format(result.status_code) + print(error) + print(result.content) + + # Only Helix need this information for audit + data['bomJsonUrl'] = bom_json_url db_session.close() - return data - # return result.status_code + return error, data except Exception as e: - msg = 'Error while {} for session {}'.format(step, session_id) - print(msg) - raise e + print('Error while {} for session {}'.format(step, helix_session_id)) + error = 'Error while {}'.format(step) + return error, {} diff --git a/helix/templates/download.html.jinja b/helix/templates/download.html.jinja index 568c808..7b1dfb1 100644 --- a/helix/templates/download.html.jinja +++ b/helix/templates/download.html.jinja @@ -1,9 +1,24 @@ {% extends "layout.html.jinja" %} {% set title = "Helix Calculator" %} {% block contents %} - {% for warning in context['warning_messages'] %} -
{{ warning.value }}
- {% endfor %} + {% if 'sfdc_export_urls' in context %} + {% if context['sfdc_export_error'] %} +
{{ context['sfdc_export_error'] }}
+ {% else %} +
Documents exported to Sales Force succesffully.
+ {% endif %} + + + {% endif %}

Download