import requests import json, yaml from requests.auth import HTTPBasicAuth import urllib.parse from rowers.utils import dologging import datetime from django.utils import timezone from rowsandall_app.settings import ( IDOKLAD_CLIENT_ID, IDOKLAD_CLIENT_SECRET, ) contacts_url = 'https://api.idoklad.cz/v3/Contacts' invoice_url = 'https://api.idoklad.cz/v3/IssuedInvoices' email_url = 'https://api.idoklad.cz/v3/Mails/IssuedInvoice/Send' from rowers.tasks import handle_send_email_noinvoice from rowers.utils import myqueue import django_rq queuehigh = django_rq.get_queue('high') from rowers.models import iDokladToken #idoklad_countries = json.loads(open('rowers/idoklad_countries.json').read())["Data"]["Items"] with open('rowers/idoklad_countries.yaml') as f: idoklad_countries = yaml.load(f, Loader=yaml.FullLoader)["Data"]["Items"] def get_country_id(code): for c in idoklad_countries: if c['Code'] == code: return c['Id'] return 1 def idoklad_token(): try: token = iDokladToken.objects.get(id=1) except iDokladToken.DoesNotExist: return None if token.updated_at + datetime.timedelta(seconds=token.expires_in) < timezone.now(): headers = { 'Content-Type': 'application/x-www-form-urlencoded', } data = { 'grant_type': 'refresh_token', 'client_id': IDOKLAD_CLIENT_ID, 'client_secret': IDOKLAD_CLIENT_SECRET, 'scope': 'eet offline_access', 'refresh_token': token.refresh_token, } response = requests.post('https://identity.idoklad.cz/server/connect/token', headers=headers, data=data) if response.status_code == 200: token = response.json() token['updated_at'] = timezone.now() token = iDokladToken.objects.filter(id=1).update(**token) return iDokladToken.objects.get(id=1) else: return None return token def get_contacts(rower): token = idoklad_token() if token is None: return None headers = { 'Authorization': 'Bearer {t}'.format(t=token.access_token), } url = contacts_url+'?filter=(Email~eq~'+urllib.parse.quote(rower.user.email)+')' dologging('idoklad.log','Searching Contact url: '+str(url)) res = requests.get(url, headers=headers) dologging('idoklad.log','Searching Contact Status code '+str(res.status_code)+'\n') if res.status_code != 200: # pragma: no cover return None data = res.json()['Data']['Items'] if len(data) >= 1: r = data[0] return r['Id'] return None # pragma def create_contact(rower): print("idoklad create contact", rower) token = idoklad_token() if token is None: return None data = { 'City': rower.city, 'CompanyName': rower.user.first_name+" "+rower.user.last_name, 'CountryId': get_country_id(rower.country.code), 'Email': rower.user.email, 'Firstname': rower.user.first_name, 'PostalCode': rower.postal_code, 'Street': rower.street_address, 'Surname': rower.user.last_name, 'DeliveryAddresses': [] } if rower.country.numeric is None: data['CountryId'] = 1 dologging('idoklad.log','Creating idoklad contact for '+str(rower.user.email)+'\n') headers = { 'Authorization': 'Bearer {t}'.format(t=token.access_token), "Content-Type": "application/json", "Accept": "application/json", } res = requests.post(contacts_url, json=data, headers=headers) if res.status_code not in [200, 201]: dologging('idoklad.log','Contact Created - reason '+str(res.reason)+'\n') _ = myqueue.enqueue( queuehigh, handle_send_email_noinvoice, rower.user.email, rower.user.first_name, rower.user.last_name, 'idoklad Contact creation failed for '+str(rower.user.email)+'\n'+str(res.text) ) return 0 id = res.json()['Data']['Id'] return id def create_invoice(rower, amount, braintreeid, dosend=True, contact_id=None, name=None): t = idoklad_token() if t is None: return None if not contact_id: contact_id = get_contacts(rower) if not name: name = 'Rowsandall Subscription '+str(braintreeid) if not contact_id: return 0 token = idoklad_token() if token is None: return 0 dologging('idoklad.log','Creating idoklad invoice for '+str(rower.user.email)+'\n') headers = { 'Authorization': 'Bearer {t}'.format(t=token.access_token), } res = requests.get(invoice_url+'/Default', headers=headers) post_data = res.json()['Data'] post_data['DateOfPayment'] = timezone.now().strftime('%Y-%m-%d') post_data['Description'] = name post_data['Items'][0]['Name'] = name post_data['Items'][0]['UnitPrice'] = amount post_data['PartnerId'] = contact_id post_data['ItemsTextPrefix'] = 'We invoice you for '+str(name)+' in the amount of '+str(amount)+' EUR.' post_data['ItemsTextSuffix'] = 'This invoice was already paid. Please do not pay it again.' post_data['Items'][0]['VatRate'] = 0.0 post_data['Items'][0]['VatRateType'] = 2 post_data['Items'][0]['VatCodeId'] = 3 post_data['CurrencyId'] = 2 post_data['ReportLanguage'] = 3 post_data.pop('ExchangeRate', None) res = requests.post(invoice_url, json=post_data, headers=headers) dologging('idoklad.log','Invoice Created - status code '+str(res.status_code)+'\n') if res.status_code not in [200, 201]: dologging('idoklad.log','Invoice Created - reason '+str(res.reason)+'\n') return 0 id = res.json()['Data']['Id'] if dosend: data = { 'AttachmentIds': [], 'DocumentId': id, 'EmailBody': 'Dear customer, we are sending you the invoice for your subscription. Please do not hesitate to contact us if you have any questions. Best regards, Rowsandall Team', 'EmailSubject': 'Rowsandall Subscription Invoice', 'Method': 1, 'ReportLanguage': 3, 'SendToSelf': True, 'SendToPartner': True, 'SendToAccountant': False, } headers = { 'Authorization': 'Bearer {access_token}'.format(access_token=token.access_token), 'Content-Type': 'application/json', 'Accept': 'application/json', } res = requests.post(email_url, json=data, headers=headers) dologging('idoklad.log','Invoice Sent - status code '+str(res.status_code)+'\n') if res.status_code not in [200, 201]: dologging('idoklad.log','Invoice Sent - reason '+str(res.text)+'\n') _ = myqueue.enqueue( queuehigh, handle_send_email_noinvoice, rower.user.email, rower.user.first_name, rower.user.last_name, 'idoklad Invoice sending failed for '+str(rower.user.email)+'\n'+str(res.text) ) return id