-
Notifications
You must be signed in to change notification settings - Fork 1
Added steps for creating invoice transaction and fetching projects #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,17 @@ | ||
from flask import Flask, render_template, redirect, request, session, abort, make_response, flash | ||
import hmac, json, hashlib, requests, secrets, uuid, datetime | ||
import hmac | ||
import json | ||
import hashlib | ||
import requests | ||
import secrets | ||
import uuid | ||
import datetime | ||
import config | ||
from intuitlib.client import AuthClient | ||
from intuitlib.enums import Scopes | ||
from quickbooks import QuickBooks | ||
from quickbooks.objects.customer import Customer | ||
#from asana.rest import ApiException | ||
# from asana.rest import ApiException | ||
from pprint import pprint | ||
from urllib.parse import urlencode | ||
from quickbooks.objects.item import Item | ||
|
@@ -34,36 +40,38 @@ | |
# Define the scopes | ||
scopes = [ | ||
Scopes.ACCOUNTING, | ||
Scopes.PROJECT_MANAGEMENT | ||
Scopes.PROJECTS | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added PROJECT_MANAGEMENT as scope in intuitlib meant for python? Has the intuitlib also been updated to include PROJECTS as scope instead of PROJECT_MANAGEMENT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mahajanpr I just checked the intuitlib https://github.com/intuit/oauth-pythonclient/blob/master/intuitlib/enums.py. The scope should be Scopes.PROJECT_MANAGEMENT. please use that and test it out. |
||
] | ||
|
||
auth_url = auth_client.get_authorization_url(scopes) | ||
|
||
|
||
@app.route('/qbo-login', methods = ['GET']) | ||
@app.route('/qbo-login', methods=['GET']) | ||
def button(): | ||
|
||
return redirect(auth_url) | ||
|
||
|
||
def getAuthHeader(): | ||
auth_header = 'Bearer {0}'.format(auth_client.access_token) | ||
return auth_header | ||
|
||
# get qbo access token | ||
@app.route('/callback', methods=['GET','POST']) | ||
|
||
|
||
@app.route('/callback', methods=['GET', 'POST']) | ||
def qboCallback(): | ||
try: | ||
|
||
auth_code = request.args.get('code') | ||
realm_id = request.args.get('realmId') | ||
|
||
auth_client.get_bearer_token(auth_code, realm_id=realm_id) | ||
|
||
|
||
|
||
session['new_token'] = auth_client.refresh_token | ||
session['realm_id'] = auth_client.realm_id | ||
session['auth_header'] = f'Bearer {auth_client.access_token}' | ||
|
||
flash('Successfully connected to QuickBooks') | ||
|
||
return redirect('/') | ||
|
@@ -76,80 +84,180 @@ def qboCallback(): | |
custName = [] | ||
custDict = {} | ||
# post data to QBO | ||
@app.route("/call-qbo",methods=['GET','POST']) | ||
|
||
|
||
@app.route("/call-qbo", methods=['GET', 'POST']) | ||
def callQbo(): | ||
try: | ||
qbo_service = QuickBooksService( | ||
auth_header=session['auth_header'], | ||
realm_id=session['realm_id'] | ||
) | ||
global custDict | ||
|
||
global custDict, custName | ||
custDict = qbo_service.get_customers() | ||
custName = qbo_service.get_customer_names() | ||
|
||
return render_template('index.html', customers=custName) | ||
except Exception as e: | ||
logger.error(f"Error in callQbo: {str(e)}") | ||
flash('Error fetching customers. Please try again.') | ||
return redirect('/') | ||
|
||
@app.route("/create-projects",methods=['GET','POST']) | ||
|
||
@app.route("/create-projects", methods=['GET', 'POST']) | ||
def getProjects(): | ||
try: | ||
global selected_custName, custID | ||
selected_custName = request.form.get('customers') | ||
if not selected_custName: | ||
flash('Please select a customer') | ||
return redirect('/') | ||
|
||
custID = next((k for k, v in custDict.items() if v == selected_custName), None) | ||
|
||
custID = next((k for k, v in custDict.items() | ||
if v == selected_custName), None) | ||
if not custID: | ||
flash('Invalid customer selected') | ||
return redirect('/') | ||
|
||
transport = RequestsHTTPTransport( | ||
url='https://qb.api.intuit.com/graphql', | ||
headers={ | ||
'Authorization': session['auth_header'], | ||
'Accept': 'application/json' | ||
} | ||
) | ||
|
||
client = Client(transport=transport, fetch_schema_from_transport=False) | ||
|
||
# Read the GraphQL mutation from file | ||
with open('static/graphql/project.graphql', 'r') as f: | ||
query = gql(f.read()) | ||
|
||
# Prepare variables using the service | ||
variables = prepare_variables(selected_custName, custID) | ||
|
||
result = client.execute(query, variable_values=variables) | ||
global projects | ||
projects = result.get('projectManagementCreateProject', {}) | ||
|
||
if not projects: | ||
flash('Failed to create project') | ||
return redirect('/') | ||
|
||
flash('Project created successfully') | ||
return render_template('index.html', customers=custName, project=projects) | ||
|
||
except Exception as e: | ||
logger.error(f"Error creating project: {str(e)}") | ||
flash('Error creating project. Please try again.') | ||
return redirect('/') | ||
|
||
|
||
@app.route("/create-invoice", methods=['GET', 'POST']) | ||
def createInvoice(): | ||
try: | ||
""" selected_custName = request.form.get('customers') | ||
if not selected_custName: | ||
flash('Please select a customer') | ||
return redirect('/') | ||
|
||
custID = next((k for k, v in custDict.items() | ||
if v == selected_custName), None) | ||
if not custID: | ||
flash('Invalid customer selected') | ||
return redirect('/') """ | ||
|
||
qbo_service = QuickBooksService( | ||
auth_header=session['auth_header'], | ||
realm_id=session['realm_id'] | ||
) | ||
|
||
logger.info(f"Projects variable:::::::::::::::: {projects}") | ||
customer_id = projects['customer']['id'] | ||
global invoiceDict | ||
invoiceDict = qbo_service.create_invoice( | ||
customer_id=customer_id, | ||
amount=199.00, | ||
description="Testing invoice with Project reference", | ||
project_id=projects['id'] if projects and 'id' in projects else None | ||
) | ||
|
||
if not invoiceDict: | ||
flash('Failed to create invoice') | ||
return redirect('/') | ||
|
||
flash('Invoice created successfully') | ||
logger.info(f"Invoice response: {invoiceDict}") | ||
|
||
invoice_id = invoiceDict.get('Invoice', {}).get('Id') | ||
invoiceDeepLink = f"https://app.qbo.intuit.com/app/invoice?txnId={invoice_id}&companyId={session['realm_id']}" | ||
return render_template('index.html', customers=custName, invoice=invoiceDict.get('Invoice', {}), invoiceDeepLink=invoiceDeepLink) | ||
|
||
except Exception as e: | ||
logger.error(f"Error creating Invoice: {str(e)}") | ||
flash('Error creating Invoice. Please try again.') | ||
return redirect('/') | ||
|
||
|
||
@app.route("/call-projects", methods=['GET', 'POST']) | ||
def callProjects(): | ||
try: | ||
transport = RequestsHTTPTransport( | ||
url='https://qb.api.intuit.com/graphql', | ||
headers={ | ||
'Authorization': session['auth_header'], | ||
'Accept': 'application/json' | ||
} | ||
) | ||
|
||
client = Client(transport=transport, fetch_schema_from_transport=False) | ||
|
||
# Read the GraphQL Query from file | ||
with open('static/graphql/get_projects.graphql', 'r') as f: | ||
query = gql(f.read()) | ||
|
||
# Prepare variables | ||
|
||
variables = { | ||
"first": 4, | ||
"filter": { | ||
"status": { | ||
"equals": None | ||
} | ||
}, | ||
"orderBy": ["DUE_DATE_DESC"] | ||
} | ||
|
||
result = client.execute(query, variable_values=variables) | ||
projects = result.get('projectManagementProjects', {}) | ||
|
||
if not projects: | ||
flash('Failed to fetch projects') | ||
return redirect('/') | ||
|
||
flash('Projects fetched successfully') | ||
edges = projects.get('edges', []) | ||
project_list = [edge['node'] for edge in edges] | ||
return render_template('index.html', projectList=project_list) | ||
|
||
except Exception as e: | ||
logger.error(f"Error in callProjects: {str(e)}") | ||
flash('Error fetching Projects. Please try again.') | ||
return redirect('/') | ||
|
||
# receive events from asana | ||
|
||
#hook_secret = None | ||
# hook_secret = None | ||
|
||
|
||
#@app.route("/create-webhook", methods=["GET", 'POST']) | ||
@app.route('/', methods =['GET', 'POST'] ) | ||
# @app.route("/create-webhook", methods=["GET", 'POST']) | ||
|
||
|
||
@app.route('/', methods=['GET', 'POST']) | ||
def home(): | ||
return render_template('index.html') | ||
|
||
#print(auth_url) | ||
#app.run(port=5001) | ||
|
||
# print(auth_url) | ||
# app.run(port=5001) | ||
if __name__ == '__main__': | ||
app.run(host='0.0.0.0', port=5001) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove this line containing "asana" reference all together on my behalf.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done