feat: GST E Invoicing (#23455)
* feat: init e-invoice settings
* feat: read public key file
* feat: rsa encryption with public key
* feat: save token and sek from auth request
* chore: handle error response
* feat: AES decryption of SEK with appkey
* feat: decrypt json data with SEK
* feat: make e invoice from erpnext sales invoice
* feat: generate IRN
* feat: decode signed json and QR code
* chore: validations
* feat: cancel IRN
* feat: complete e-invoice schema
* chore: move e-invoice settings to regional
* chore: split einvoice settings and operations
* chore: rename schema to template & js cleanup
* feat: make IRN field on regional setup
* feat: Generate & Cancel IRN from Sales Invoice
* chore: minor fixes
* fix: item discount
* chore: show irn cancelled check after cancellation
* fix: hide cancel irn dialog on error
* fix: public key is required on validate
* fix: cannot find attached key file
* fix: validation if e invoicing is disabled
* fix: do not show generate irn for invalid supply type
* fix: update irn_cancelled after cancelling irn
* chore: show irn field for proper gst_category
* feat: e-way bill details in e-invoice
* fix: save e-way bill no on irn generation
* chore: no copy on e invoice custom fields
* feat: cancel e-way bill before cancelling IRN
* feat: manual download / upload json
* chore: group e-invoicing actions
* fix: fn name
* chore: save signed invoice and qrcode after uplaoding irn
* fix: fetch token if not valid
* chore: move einvoicing stuff to seperate folder
* feat: QRCode Image and E-Invoice Print Format
* fix: bug
* fix: invalid syntax
* chore: code cleanup
* chore: clean up e invoice actions
* fix: download & upload e-invoice
* fix: print format
* fix: validations
* fix: add permissions on regional setup
* feat: add patch
* fix: validate document name
* fix: return date
* fix: credit note einvoice
* fix: validations
* fix: error logging
* fix: e_invoice module not found
* fix: add missing package
* fix: rename e_invoice_utils.py
* fix: einvoice field validation
* fix: patch
* fix: invoice totals calculation
* fix: other charges calculation
* chore: improve document name validation message
* fix: qr code image string
* feat: initialize GSP connector
* chore: remove unwanted fields
* fix: qr code generation
* feat: fetch and cache GSTIN details
* feat: generate & cancel IRN
* feat: cancel eway bill
* chore: remove unwanted fuctions
* chore: clean up einvoice actions
* fix: attach qrcode on irn generation
* fix: generate & cancel IRN
* fix: show/hide eway bill fields
* fix: valiations
* feat: generate eway bill from IRN
* chore: remove unwanted imports
* chore: error logging
* feat: header & footer in GST E Invoice
* chore: remove test pincode
* fix: invalid syntax
* feat: cess non advolem on einvoice item
* chore: remove fetch token from e invocie settings
* fix: imports
* fix: error handling
* feat: update timeline on einvoice actions
* fix: qrcode image size
* fix: exclude intra company transactions
* fix: eway bill test
* fix: ewaybill mandatory conditions
* chore: add tests
* fix: returning condition
* feat: log e-invocing requests
* chore: add ack date and ack no field for print formats
* fix: sider issues
* feat: show e-invoice preview before IRN generation
* fix: use as_list for error message
* fix: minor ux issues
* fix: dialog is undefined
* fix: error handling
* feat: add docs link to e invoice settings
* feat: multiple gstins for e invoicing
* fix: uncomment test condition
* fix: remove test pincode
* fix: cannot cancel irn without submitting sales invoice
* chore: code cleanup
* fix: sider issues
* fix: e invoice request log permissions
Co-authored-by: Nabin Hait <nabinhait@gmail.com>
diff --git a/erpnext/regional/india/setup.py b/erpnext/regional/india/setup.py
index cbcd6e3..5321a9a 100644
--- a/erpnext/regional/india/setup.py
+++ b/erpnext/regional/india/setup.py
@@ -87,7 +87,7 @@
)).insert()
def add_permissions():
- for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report', 'Lower Deduction Certificate'):
+ for doctype in ('GST HSN Code', 'GST Settings', 'GSTR 3B Report', 'Lower Deduction Certificate', 'E Invoice Settings'):
add_permission(doctype, 'All', 0)
for role in ('Accounts Manager', 'Accounts User', 'System Manager'):
add_permission(doctype, role, 0)
@@ -103,9 +103,10 @@
def add_print_formats():
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
frappe.reload_doc("accounts", "print_format", "gst_pos_invoice")
+ frappe.reload_doc("accounts", "print_format", "GST E-Invoice")
frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
- name in('GST POS Invoice', 'GST Tax Invoice') """)
+ name in('GST POS Invoice', 'GST Tax Invoice', 'GST E-Invoice') """)
def make_custom_fields(update=True):
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
@@ -351,7 +352,6 @@
'label': 'Mode of Transport',
'fieldtype': 'Select',
'options': '\nRoad\nAir\nRail\nShip',
- 'default': 'Road',
'insert_after': 'transporter_name',
'print_hide': 1,
'translatable': 0
@@ -388,13 +388,34 @@
'fieldname': 'ewaybill',
'label': 'E-Way Bill No.',
'fieldtype': 'Data',
- 'depends_on': 'eval:(doc.docstatus === 1)',
+ 'depends_on': 'eval:((doc.docstatus === 1 || doc.ewaybill) && doc.eway_bill_cancelled === 0)',
'allow_on_submit': 1,
'insert_after': 'tax_id',
'translatable': 0
}
]
+ si_einvoice_fields = [
+ dict(fieldname='irn', label='IRN', fieldtype='Data', read_only=1, insert_after='customer', no_copy=1, print_hide=1,
+ depends_on='eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed Export"], doc.gst_category) && doc.irn_cancelled === 0'),
+
+ dict(fieldname='ack_no', label='Ack. No.', fieldtype='Data', read_only=1, hidden=1, insert_after='irn', no_copy=1, print_hide=1),
+
+ dict(fieldname='ack_date', label='Ack. Date', fieldtype='Data', read_only=1, hidden=1, insert_after='ack_no', no_copy=1, print_hide=1),
+
+ dict(fieldname='irn_cancelled', label='IRN Cancelled', fieldtype='Check', no_copy=1, print_hide=1,
+ depends_on='eval:(doc.irn_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'),
+
+ dict(fieldname='eway_bill_cancelled', label='E-Way Bill Cancelled', fieldtype='Check', no_copy=1, print_hide=1,
+ depends_on='eval:(doc.eway_bill_cancelled === 1)', read_only=1, allow_on_submit=1, insert_after='customer'),
+
+ dict(fieldname='signed_einvoice', fieldtype='Code', options='JSON', hidden=1, no_copy=1, print_hide=1, read_only=1),
+
+ dict(fieldname='signed_qr_code', fieldtype='Code', options='JSON', hidden=1, no_copy=1, print_hide=1, read_only=1),
+
+ dict(fieldname='qrcode_image', label='QRCode', fieldtype='Attach Image', hidden=1, no_copy=1, print_hide=1, read_only=1)
+ ]
+
custom_fields = {
'Address': [
dict(fieldname='gstin', label='Party GSTIN', fieldtype='Data',
@@ -407,7 +428,7 @@
'Purchase Invoice': purchase_invoice_gst_category + invoice_gst_fields + purchase_invoice_itc_fields + purchase_invoice_gst_fields,
'Purchase Order': purchase_invoice_gst_fields,
'Purchase Receipt': purchase_invoice_gst_fields,
- 'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields,
+ 'Sales Invoice': sales_invoice_gst_category + invoice_gst_fields + sales_invoice_shipping_fields + sales_invoice_gst_fields + si_ewaybill_fields + si_einvoice_fields,
'Delivery Note': sales_invoice_gst_fields + ewaybill_fields + sales_invoice_shipping_fields,
'Sales Order': sales_invoice_gst_fields,
'Tax Category': inter_state_gst_field,