Skip to content

Instantly share code, notes, and snippets.

@ugurunver
Last active December 3, 2017 17:45
Show Gist options
  • Save ugurunver/ab944b2cccf5c3e4efeffd297cc98161 to your computer and use it in GitHub Desktop.
Save ugurunver/ab944b2cccf5c3e4efeffd297cc98161 to your computer and use it in GitHub Desktop.
fatura tarihi urlencode
import json
import requests
try:
from urllib import urlencode
except ImportError:
from urllib.parse import urlencode
API = 'http://api.test.propars.net/api/v1/'
class Client(object):
"""
Api istek-cevap iskeletini olusturan siniftir. username ve password alir, call_api metodunu saglar.
"""
token = None
def __init__(self, username, password):
super(Client, self).__init__()
self.token = self._get_token(username, password)
def _get_token(self, username, password):
assert not self.token
data = {'username': username, 'password': password}
auth_url = API+'api-token-auth/'
response = self.call_api('POST', auth_url, data)
# response => {'expire_date': '2016-08-29T20:04:00.696+03:00', 'token': '3f6388844726fcacd892838df380ff2dda418d7b'}
return response['token']
def call_api(self, method, url, data=None):
# donusleri json olarak yapmasi icin Accept header'i gerekli
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
# login isteginde token olmayacak, o nedenle sarta bagli tutuldu ve parametre zorunlu yapilmadi
if self.token:
headers['Authorization'] = 'Token {}'.format(self.token)
data = json.dumps(data)
return requests.request(method, url, data=data, headers=headers).json()
class SaleClient(Client):
"""
Fatura olusturma sureci boyunca kullanilacak api metotlarini saglayan siniftir.
"""
customer_endpoint = API + 'core/customer/'
customer_address_endpoint = API + 'core/customeraddress/'
sale_endpoint = API + 'core/sale/'
invoice_endpoint = API + 'finance/saleinvoice/'
item_endpoint = API + 'core/item/'
def get_currencies(self):
return self.call_api(method='GET', url=API + 'core/currency/')['results']
def get_units(self):
return self.call_api(method='GET', url=API + 'core/liquidstockunits/')['results']
def get_customer_by_id(self, customer_code):
"""Verilen koda gore arama yapar, sonuc bulunursa ilk bulunan musteriyi doner"""
response = self.call_api(method='GET', url=self.customer_endpoint+'?integration_store_id='+str(customer_code))
if len(response['results']):
return response['results'][0]
def create_customer(self, data):
return self.call_api(method='POST', url=self.customer_endpoint, data=data)
def create_address(self, data):
return self.call_api(method='POST', url=self.customer_address_endpoint, data=data)
def get_item_by_code(self, product_code):
"""Verilen koda gore arama yapar, sonuc bulunursa ilk bulunan urunu doner"""
response = self.call_api(method='GET', url=self.item_endpoint + '?product_code='+product_code)
if len(response['results']):
return response['results'][0]
def create_item(self, urun_data):
return self.call_api(method='POST', url=self.item_endpoint, data=urun_data)
def create_sale(self, data):
return self.call_api(method='POST', url=self.sale_endpoint, data=data)
def get_or_create_category(self, kategori_data):
"""
Verilen datadaki category_code alanina gore sunucuda arama yapar, sonuc bulursa buldugu sonucu, bulamazsa
olusturdugu yeni kategoriyi doner.
"""
url = API + 'core/category/'
response = self.call_api(method='GET', url=url + '?category_code='+kategori_data['category_code'])
if len(response['results']):
return response['results'][0]
else:
return self.call_api(method='POST', url=url, data=kategori_data)
def get_or_create_brand(self, marka_data):
"""
Verilen datadaki brand_code alanina gore sunucuda arama yapar, sonuc bulursa buldugu sonucu, bulamazsa
olusturdugu yeni markayi doner.
"""
url = API + 'core/brand/'
response = self.call_api(method='GET', url=url + '?brand_code='+marka_data['brand_code'])
if len(response['results']):
return response['results'][0]
else:
return self.call_api(method='POST', url=url, data=marka_data)
def send_earchive(self, fatura_id, fatura_tarihi=None):
endpoint = self.invoice_endpoint + 'send_to_earchive_for_sale/?sale_id='+str(fatura_id)
if fatura_tarihi:
endpoint += '&'+urlencode(dict(invoice_date=str(fatura_tarihi)))
print(endpoint)
return self.call_api(method='POST', url=endpoint)
def send_einvoice(self, fatura_id, fatura_tarihi=None):
endpoint = self.invoice_endpoint + 'send_to_einvoice_for_sale/?sale_id='+str(fatura_id)
if fatura_tarihi:
endpoint += '&'+urlencode(dict(invoice_date=str(fatura_tarihi)))
return self.call_api(method='POST', url=url)
def main():
"""
Asagida ortalama bir fatura bilgisi parcalar halinde ve Propars apisindeki alan isimleriyle (urunKodu haric) bulunmakta.
currency ve unit id'leri cok seyrek olarak guncellendigi icin kod icinde kullanilabilir. Degerleri gormek icin
print(api_client.get_currencies())
print(api_client.get_units())
:return:
"""
api_client = SaleClient('[email protected]', 'parola') # panele giris yapilabilen bir eposta-parola cifti
musteri_data = {
"name": 'Test Müşteri',
"integration_store_id": 'abc-123', # musteri kodu
"email": "[email protected]",
"telephone_number": "02120001122",
"fax_number": "",
"city_name": "İstanbul",
"district": "Avcılar",
"company_title": "Firma Ünvanı",
"tax_office": "Avcılar", # vergi dairesi
"tax_number": "1234567890", # kurumsal musteride bu alana 10 haneli vkn yazilacak
"tc_identity_number": "", # bireysel musteride bu alana 11 haneli vkn yazilacak
"customer_type": "organizational", # bireyselde individual, kurumsalda organizational
"source": "store", # sabit store olacak
}
fatura_adres_data = {
"name": "Fatura alıcı adı veya ünvan",
"code": "xyz-123", # adres kodu
"telephone_number": "02129998877",
"fax_number": "",
"city_name": "İstanbul",
"district": "Avcılar",
"address": "Test mahallesi. Test sokak. No: 1"
}
fatura_data = {
'customer': "<asagida tespit edilen musteri'nin id'si ile doldurulacak>",
'billing_address': "<asagida tespit edilen fatura_adresi'nin id'si ile doldurulacak>",
'order_date': '2017-07-01T09:00:00+0300',
'notes': 'Fatura notları serbest metin',
'currency': 1,
'box': 'SENTBOX', # SENTBOX: Giden fatura, INBOX: Gelen fatura (varsayilani SENTBOX)
'einvoice_type': 'SATIS',
'einvoice_profile': 'TEMELFATURA',
'items': [
{
'product_name': 'Test Ürünü 1',
'urunKodu': 'abc-321---', # sunucuya fatura icinde gonderilmeyecek, urun tespiti icin asagida kullaniliyor
'price': '123.45', # decimal birim fiyat
'quantity': '10', # integer miktar
'vat_rate': '18', # kdv orani
'discount_rate': '10', # iskonto orani,
'unit': 1,
},
{
'product_name': 'Test Ürünü 2',
'urunKodu': 'abc-321-2---', # sunucuya gonderilmeyecek, urun tespiti icin asagida kullaniliyor
'price': '10.00', # decimal birim fiyat
'quantity': '1', # integer miktar
'vat_rate': '8', # kdv orani
'discount_rate': '0', # decimal iskonto orani,
'unit': 1,
}
]
}
# Urunler icin urun kodu mevcutsa sunucuda kodla arama yapilir ve bulunan urun fatura ile eslenerek stok takibi vb.
# islemleri yapilabilir. Urun kodunuz yoksa bu adimi atlabilirsiniz ve faturada sadece urun adi (product_name) kullanabilirsiniz.
# Baska bir deyisle, fatura urunu icin 'item' alani zorunlu degildir, 'product_name' alani yeterlidir.
for fatura_urunu in fatura_data['items']:
product_code = fatura_urunu.pop('urunKodu') # pop: product_code keyini siler ve degerini dondurur
item = api_client.get_item_by_code(product_code)
if item:
fatura_urunu['item'] = item['id']
else:
# Yine dilerseniz fatura urunlerinizi stok olarak kaydedebilirsiniz. Ancak bu durumda kategori ve marka
# bilgisine ihtiyac duyulacaktir.
kategori_data = {'category_name': 'Genel', 'category_code': 'genel'}
marka_data = {'brand_name': 'Genel', 'brand_code': 'genel'}
urun_data = fatura_urunu.copy() # fatura urunu icerigine sahip yeni bir obje uretir
urun_data['product_code'] = product_code
urun_data['amount'] = urun_data.pop('quantity') # quantity alaninin adini amount ile degistiriyoruz
urun_data['tax_rate'] = urun_data.pop('vat_rate') # vat_rate alaninin adini tax_rate ile degistiriyoruz
urun_data['currency'] = 1
urun_data['category'] = api_client.get_or_create_category(kategori_data)['id']
urun_data['brand'] = api_client.get_or_create_brand(marka_data)['id']
item = api_client.create_item(urun_data)
fatura_urunu['item'] = item['id']
# 1) Musteri koduna gore musteri tespiti
# NOT: musteri kodunuz yoksa bu alani atlayabilirsiniz ancak her fatura icin yeni musteri olusturulacaktir
musteri = api_client.get_customer_by_id(musteri_data['integration_store_id'])
if not musteri:
# musteri koduna gore sunucuda musteri bulunamadi ise yeni musteri olusturulur
# NOT: (musteri kodunuz yoksa bu adimdan baslayabilrsiniz)
# billing_address alani kullanilarak, yeni musteri olusturulurken fatura adresi ile beraber olusturulur
musteri_data['billing_address'] = fatura_adres_data
musteri = api_client.create_customer(musteri_data)
fatura_adresi = musteri['billing_address']
else:
# Musteri kodunuz mevcutsa ve sunucuda o kodla eslesen musteri bulunmus ise buraya girilecektir. Burada,
# yukarida mevcut musterilerden getirilmis olan musteri verisinin icinde 'addresses' keyi ile bir adres listesi
# gelecektir. Bu liste icindeki adreslerde ele alinan adres kodu (fatura_adres_data['code']) ile eslesen
# adres aranir, bulunamazsa yeni adres olusturulur.
for _musteri_adres in musteri['addresses']:
if _musteri_adres['code'] == fatura_adres_data['code']:
fatura_adresi = _musteri_adres
break
else:
fatura_adres_data['customer'] = musteri['id']
fatura_adresi = api_client.create_address(fatura_adres_data)
fatura_data['customer'] = musteri['id']
fatura_data['billing_address'] = fatura_adresi['id']
fatura_siparis = api_client.create_sale(fatura_data)
# olusturulan faturayi efatura/earsiv olarak gonderebilmek icin son bir api istegi yapilir
fatura_tarihi = '2017-07-01T09:00:00+0300' # None olursa siparis tarihi fatura tarihi olarak kullanilir.
if musteri['is_einvoice_user']:
fatura = api_client.send_einvoice(fatura_siparis['id'], fatura_tarihi)
else:
fatura = api_client.send_earchive(fatura_siparis['id'], fatura_tarihi)
print(fatura)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment