205 lines
6.2 KiB
Python
205 lines
6.2 KiB
Python
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.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):
|
|
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]:
|
|
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')
|
|
|
|
return id
|
|
|