Skip to content

Commit

Permalink
Merge pull request #390 from resilient-tech/version-14-hotfix
Browse files Browse the repository at this point in the history
chore: release v14
  • Loading branch information
sagarvora authored Mar 5, 2023
2 parents 0742a15 + 22bcc2b commit 9cf8e26
Show file tree
Hide file tree
Showing 44 changed files with 1,841 additions and 396 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ repos:
hooks:
- id: black

- repo: https://github.com/timothycrosley/isort
rev: 5.10.1
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
hooks:
- id: isort

Expand Down
25 changes: 17 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,26 @@ For a detailed overview of these features, please [refer to the documentation](h
Once you've [set up a Frappe site](https://frappeframework.com/docs/v14/user/en/installation/), installing India Compliance is simple:


1. Download the app using the Bench CLI
1. Download the app using the Bench CLI.

```bash
bench get-app https://github.com/resilient-tech/india-compliance.git
```
```bash
bench get-app --branch [branch name] https://github.com/resilient-tech/india-compliance.git
```

2. Install the app on your site
Replace `[branch name]` with the appropriate branch as per your setup:

```bash
bench --site [site name] install-app india_compliance
```
| Frappe Branch | India Compliance Branch |
|---------------|-------------------------|
| version-14 | version-14 |
| develop | next |

If it isn't specified, the `--branch` option will default to `next`.
2. Install the app on your site.
```bash
bench --site [site name] install-app india_compliance
```
## In-app Purchases
Expand Down
7 changes: 7 additions & 0 deletions india_compliance/gst_india/api_classes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,13 @@ def _make_request(
log.output = response_json
enqueue_integration_request(**log)

if self.sandbox_mode and not frappe.flags.ic_sandbox_message_shown:
frappe.msgprint(
_("GST API request was made in Sandbox Mode"),
alert=True,
)
frappe.flags.ic_sandbox_message_shown = True

def handle_failed_response(self, response_json):
# Override in subclass, return truthy value to stop frappe.throw
pass
Expand Down
15 changes: 12 additions & 3 deletions india_compliance/gst_india/api_classes/e_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ class EInvoiceAPI(BaseAPI):
API_NAME = "e-Invoice"
BASE_PATH = "ei/api"
SENSITIVE_HEADERS = BaseAPI.SENSITIVE_HEADERS + ("password",)
IGNORED_ERROR_CODES = {
"2150": "Duplicate IRN",
"2283": (
"IRN details cannot be provided as it is generated more than 2 days ago"
),
}

def setup(self, doc=None, *, company_gstin=None):
if not self.settings.enable_e_invoice:
Expand Down Expand Up @@ -43,9 +49,12 @@ def setup(self, doc=None, *, company_gstin=None):
)

def handle_failed_response(self, response_json):
# Don't fail in case of Duplicate IRN
if response_json.get("message").startswith("2150"):
return True
message = response_json.get("message", "").strip()

for error_code in self.IGNORED_ERROR_CODES:
if message.startswith(error_code):
response_json.error_code = error_code
return True

def get_e_invoice_by_irn(self, irn):
return self.get(endpoint="invoice/irn", params={"irn": irn})
Expand Down
12 changes: 5 additions & 7 deletions india_compliance/gst_india/api_classes/returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ def setup(self, company_gstin):
)

def handle_failed_response(self, response_json):
if response_json.get("errorCode") in self.IGNORED_ERROR_CODES:
error_code = response_json.get("errorCode")

if error_code in self.IGNORED_ERROR_CODES:
response_json.error_type = self.IGNORED_ERROR_CODES[error_code]
return True

def get(self, action, return_period, otp=None, params=None):
response = super().get(
return super().get(
params={"action": action, "gstin": self.company_gstin, **(params or {})},
headers={
"requestid": self.generate_request_id(),
Expand All @@ -41,11 +44,6 @@ def get(self, action, return_period, otp=None, params=None):
},
)

if error_type := self.IGNORED_ERROR_CODES.get(response.errorCode):
response.error_type = error_type

return response


class GSTR2bAPI(ReturnsAPI):
API_NAME = "GSTR-2B"
Expand Down
2 changes: 1 addition & 1 deletion india_compliance/gst_india/client_scripts/item.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ frappe.ui.form.on('Item', {
if ((!frm.doc.taxes || !frm.doc.taxes.length) && frm.doc.gst_hsn_code) {
frappe.db.get_doc("GST HSN Code", frm.doc.gst_hsn_code).then(hsn_doc => {
$.each(hsn_doc.taxes || [], function(i, tax) {
let a = frappe.model.add_child(cur_frm.doc, 'Item Tax', 'taxes');
let a = frappe.model.add_child(frm.doc, 'Item Tax', 'taxes');
a.item_tax_template = tax.item_tax_template;
a.tax_category = tax.tax_category;
a.valid_from = tax.valid_from;
Expand Down
120 changes: 101 additions & 19 deletions india_compliance/gst_india/client_scripts/sales_invoice_list.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,111 @@
const erpnext_onload = frappe.listview_settings["Sales Invoice"].onload;
frappe.listview_settings["Sales Invoice"].onload = function (list_view) {
const DOCTYPE = "Sales Invoice";
const erpnext_onload = frappe.listview_settings[DOCTYPE].onload;
frappe.listview_settings[DOCTYPE].onload = function (list_view) {
if (erpnext_onload) {
erpnext_onload(list_view);
}

const action = async () => {
if (!frappe.perm.has_perm(DOCTYPE, 0, "submit")) return;

if (gst_settings.enable_e_waybill)
add_bulk_action_for_submitted_invoices(
list_view,
__("Generate e-Waybill JSON"),
generate_e_waybill_json
);

if (ic.is_e_invoice_enabled())
add_bulk_action_for_submitted_invoices(
list_view,
__("Enqueue Bulk e-Invoice Generation"),
enqueue_bulk_e_invoice_generation
);
};

function add_bulk_action_for_submitted_invoices(list_view, label, callback) {
list_view.page.add_actions_menu_item(label, async () => {
const selected_docs = list_view.get_checked_items();
const docnames = list_view.get_checked_items(true);

for (let doc of selected_docs) {
if (doc.docstatus !== 1) {
frappe.throw(
__("e-Waybill JSON can only be generated from a submitted document")
);
}
const submitted_docs = await validate_if_submitted(selected_docs);
if (submitted_docs) callback(submitted_docs);
});
}

async function generate_e_waybill_json(docnames) {
const ewb_data = await frappe.xcall(
"india_compliance.gst_india.utils.e_waybill.generate_e_waybill_json",
{ doctype: DOCTYPE, docnames }
);

trigger_file_download(ewb_data, get_e_waybill_file_name());
}

async function enqueue_bulk_e_invoice_generation(docnames) {
const now = frappe.datetime.system_datetime();

const job_id = await frappe.xcall(
"india_compliance.gst_india.utils.e_invoice.enqueue_bulk_e_invoice_generation",
{ docnames }
);

const creation_filter = `[">", "${now}"]`;
const api_requests_link = frappe.utils.generate_route({
type: "doctype",
name: "Integration Request",
route_options: {
integration_request_service: "India Compliance API",
creation: creation_filter,
},
});
const error_logs_link = frappe.utils.generate_route({
type: "doctype",
name: "Error Log",
route_options: {
creation: creation_filter,
},
});

frappe.msgprint(
__(
`Bulk e-Invoice Generation has been queued. You can track the
<a href='{0}'>Background Job</a>,
<a href='{1}'>API Request(s)</a>,
and <a href='{2}'>Error Log(s)</a>.`,
[
frappe.utils.get_form_link("RQ Job", job_id),
api_requests_link,
error_logs_link,
]
)
);
}

async function validate_if_submitted(selected_docs) {
const valid_docs = [];
const invalid_docs = [];

for (const doc of selected_docs) {
if (doc.docstatus != 1) {
invalid_docs.push(doc.name);
} else {
valid_docs.push(doc.name);
}
}

const ewb_data = await frappe.xcall(
"india_compliance.gst_india.utils.e_waybill.generate_e_waybill_json",
{ doctype: list_view.doctype, docnames }
);
if (!invalid_docs.length) return valid_docs;

trigger_file_download(ewb_data, get_e_waybill_file_name());
};
if (!valid_docs.length) {
frappe.throw(__("This action can only be performed on submitted documents"));
}

list_view.page.add_actions_menu_item(__("Generate e-Waybill JSON"), action, false);
const confirmed = await new Promise(resolve => {
frappe.confirm(
__(
"This action can only be performed on submitted documents. Do you want to continue without the following documents?<br><br><strong>{0}</strong>",
[invalid_docs.join("<br>")]
),
() => resolve(true)
);
});

};
return confirmed ? valid_docs : false;
}
10 changes: 4 additions & 6 deletions india_compliance/gst_india/constants/custom_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@
"fieldname": "gst_section",
"label": "GST Details",
"fieldtype": "Section Break",
"insert_after": "language",
"insert_after": "gst_vehicle_type",
"print_hide": 1,
"collapsible": 1,
},
Expand Down Expand Up @@ -554,6 +554,7 @@
"fieldtype": "Link",
"options": "GST HSN Code",
"insert_after": "item_group",
"allow_in_quick_entry": 1,
},
{
"fieldname": "is_nil_exempt",
Expand Down Expand Up @@ -600,10 +601,7 @@
"insert_after": "customer",
"no_copy": 1,
"print_hide": 1,
"depends_on": (
'eval:in_list(["Registered Regular", "SEZ", "Overseas", "Deemed'
' Export"], doc.gst_category)'
),
"depends_on": 'eval:doc.gst_category != "Unregistered"',
"translatable": 0,
},
{
Expand Down Expand Up @@ -681,7 +679,7 @@
"fieldname": "transporter_info",
"label": "Transporter Info",
"fieldtype": "Section Break",
"insert_after": "terms",
"insert_after": "language",
"collapsible": 1,
"collapsible_depends_on": "transporter",
"print_hide": 1,
Expand Down
Loading

0 comments on commit 9cf8e26

Please sign in to comment.