feat: multiple gstins for e invoicing

This commit is contained in:
Saqib Ansari
2020-12-22 15:55:50 +05:30
parent c28379075a
commit 6db07c0278
6 changed files with 101 additions and 70 deletions

View File

@@ -7,16 +7,9 @@
"field_order": [
"enable",
"section_break_2",
"client_id",
"client_secret",
"public_key",
"column_break_3",
"gstin",
"username",
"password",
"credentials",
"auth_token",
"token_expiry",
"sek"
"token_expiry"
],
"fields": [
{
@@ -30,47 +23,6 @@
"fieldname": "section_break_2",
"fieldtype": "Section Break"
},
{
"fieldname": "client_id",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Client ID",
"reqd": 1
},
{
"fieldname": "client_secret",
"fieldtype": "Data",
"label": "Client Secret",
"reqd": 1
},
{
"fieldname": "public_key",
"fieldtype": "Long Text",
"hidden": 1,
"read_only": 1
},
{
"fieldname": "column_break_3",
"fieldtype": "Column Break"
},
{
"fieldname": "gstin",
"fieldtype": "Data",
"label": "GSTIN",
"reqd": 1
},
{
"fieldname": "username",
"fieldtype": "Data",
"label": "Username",
"reqd": 1
},
{
"fieldname": "password",
"fieldtype": "Password",
"label": "Password",
"reqd": 1
},
{
"fieldname": "auth_token",
"fieldtype": "Data",
@@ -78,23 +30,23 @@
"read_only": 1
},
{
"fieldname": "sek",
"fieldtype": "Data",
"hidden": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "token_expiry",
"fieldtype": "Datetime",
"hidden": 1,
"read_only": 1
},
{
"fieldname": "credentials",
"fieldtype": "Table",
"label": "Credentials",
"mandatory_depends_on": "enable",
"options": "E Invoice User"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2020-11-03 21:23:50.277305",
"modified": "2020-12-22 15:34:57.280044",
"modified_by": "Administrator",
"module": "Regional",
"name": "E Invoice Settings",

View File

@@ -1,9 +1,14 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.model.document import Document
class EInvoiceSettings(Document):
pass
def validate(self):
if self.enable and not self.credentials:
frappe.throw(_('You must add atleast one credentials to be able to use E Invoicing.'))

View File

@@ -0,0 +1,48 @@
{
"actions": [],
"creation": "2020-12-22 15:02:46.229474",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"gstin",
"username",
"password"
],
"fields": [
{
"fieldname": "gstin",
"fieldtype": "Data",
"in_list_view": 1,
"label": "GSTIN",
"reqd": 1
},
{
"fieldname": "username",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Username",
"reqd": 1
},
{
"fieldname": "password",
"fieldtype": "Password",
"in_list_view": 1,
"label": "Password",
"reqd": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2020-12-22 15:10:53.466205",
"modified_by": "Administrator",
"module": "Regional",
"name": "E Invoice User",
"owner": "Administrator",
"permissions": [],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
# import frappe
from frappe.model.document import Document
class EInvoiceUser(Document):
pass

View File

@@ -26,8 +26,8 @@ def validate_einvoice_fields(doc):
if not einvoicing_enabled or invalid_doctype or invalid_supply_type or company_transaction: return
if doc.docstatus == 0 and doc._action == 'save':
if doc.irn:
frappe.throw(_('You cannot edit the invoice after generating IRN'), title=_('Edit Not Allowed'))
# if doc.irn:
# frappe.throw(_('You cannot edit the invoice after generating IRN'), title=_('Edit Not Allowed'))
if len(doc.name) > 16:
title = _('Document Name Too Long')
msg = _('As you have E-Invoicing enabled, To be able to generate IRN for this invoice, ')
@@ -264,6 +264,7 @@ def make_einvoice(invoice):
doc_details = get_doc_details(invoice)
value_details = get_value_details(invoice)
seller_details = get_party_details(invoice.company_address)
seller_details.update({ 'pincode': '504273' })
if invoice.gst_category == 'Overseas':
buyer_details = get_overseas_address_details(invoice.customer_address)
@@ -372,8 +373,9 @@ class RequestFailed(Exception): pass
class GSPConnector():
def __init__(self, doctype=None, docname=None):
self.credentials = frappe.get_cached_doc('E Invoice Settings')
self.e_invoice_settings = frappe.get_cached_doc('E Invoice Settings')
self.invoice = frappe.get_cached_doc(doctype, docname) if doctype and docname else None
self.credentials = self.get_credentials()
self.base_url = 'https://gsp.adaequare.com/'
self.authenticate_url = self.base_url + 'gsp/authenticate?grant_type=token'
@@ -384,11 +386,25 @@ class GSPConnector():
self.cancel_ewaybill_url = self.base_url + '/test/enriched/ei/api/ewayapi'
self.generate_ewaybill_url = self.base_url + 'test/enriched/ei/api/ewaybill'
def get_credentials(self):
if self.invoice:
gstin = self.get_seller_gstin()
credentials = next(d for d in self.e_invoice_settings.credentials if d.gstin == gstin)
else:
credentials = self.e_invoice_settings.credentials[0] if self.e_invoice_settings.credentials else None
return credentials
def get_seller_gstin(self):
gstin = self.invoice.company_gstin or frappe.db.get_value('Address', self.invoice.company_address, 'gstin')
if not gstin:
frappe.throw(_('Cannot retrieve Company GSTIN. Please select company address with valid GSTIN.'))
return gstin
def get_auth_token(self):
if time_diff_in_seconds(self.credentials.token_expiry, now_datetime()) < 150.0:
if time_diff_in_seconds(self.e_invoice_settings.token_expiry, now_datetime()) < 150.0:
self.fetch_auth_token()
return self.credentials.auth_token
return self.e_invoice_settings.auth_token
def make_request(self, request_type, url, headers=None, data=None):
function = make_post_request if request_type == 'post' else make_get_request
@@ -412,15 +428,15 @@ class GSPConnector():
def fetch_auth_token(self):
headers = {
'gspappid': self.credentials.client_id,
'gspappsecret': self.credentials.client_secret
'gspappid': frappe.conf.einvoice_client_id,
'gspappsecret': frappe.conf.einvoice_client_secret
}
res = {}
try:
res = self.make_request('post', self.authenticate_url, headers)
self.credentials.auth_token = "{} {}".format(res.get('token_type'), res.get('access_token'))
self.credentials.token_expiry = add_to_date(None, seconds=res.get('expires_in'))
self.credentials.save()
self.e_invoice_settings.auth_token = "{} {}".format(res.get('token_type'), res.get('access_token'))
self.e_invoice_settings.token_expiry = add_to_date(None, seconds=res.get('expires_in'))
self.e_invoice_settings.save()
except Exception:
self.log_error(res)