feat: Editable Sales Invoice
This commit is contained in:
parent
e543dca6a0
commit
30da6ab2c1
@ -64,6 +64,27 @@ erpnext.accounts.SalesInvoiceController = class SalesInvoiceController extends e
|
|||||||
|
|
||||||
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
this.frm.toggle_reqd("due_date", !this.frm.doc.is_return);
|
||||||
|
|
||||||
|
if (this.frm.doc.repost_required) {
|
||||||
|
this.frm.set_intro(__("Accounting entries for this invoice needs to be reposted. Please click on 'Repost' button to update."));
|
||||||
|
this.frm.add_custom_button(__('Repost Accounting Entries'),
|
||||||
|
() => {
|
||||||
|
this.frm.call({
|
||||||
|
doc: this.frm.doc,
|
||||||
|
method: 'repost_accounting_entries',
|
||||||
|
freeze: true,
|
||||||
|
freeze_message: __('Reposting...'),
|
||||||
|
callback: (r) => {
|
||||||
|
if (!r.exc) {
|
||||||
|
frappe.msgprint(__('Accounting Entries are reposted'));
|
||||||
|
this.frm.trigger('refresh');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
$(`["${encodeURIComponent("Repost Accounting Entries")}"]`).css('color', 'red');
|
||||||
|
}
|
||||||
|
|
||||||
if (this.frm.doc.is_return) {
|
if (this.frm.doc.is_return) {
|
||||||
this.frm.return_print_format = "Sales Invoice Return";
|
this.frm.return_print_format = "Sales Invoice Return";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -207,6 +207,7 @@
|
|||||||
"is_internal_customer",
|
"is_internal_customer",
|
||||||
"is_discounted",
|
"is_discounted",
|
||||||
"remarks",
|
"remarks",
|
||||||
|
"repost_required",
|
||||||
"connections_tab"
|
"connections_tab"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@ -1703,6 +1704,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"default": "No",
|
"default": "No",
|
||||||
"fieldname": "is_opening",
|
"fieldname": "is_opening",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
@ -2097,6 +2099,14 @@
|
|||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Write Off",
|
"label": "Write Off",
|
||||||
"width": "50%"
|
"width": "50%"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "repost_required",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"hidden": 1,
|
||||||
|
"label": "Repost Required",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
@ -2109,7 +2119,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-10-11 13:07:36.488095",
|
"modified": "2022-10-15 19:15:49.526529",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@ -11,6 +11,9 @@ from frappe.utils import add_days, cint, cstr, flt, formatdate, get_link_to_form
|
|||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
from erpnext.accounts.deferred_revenue import validate_service_stop_date
|
||||||
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
|
get_accounting_dimensions,
|
||||||
|
)
|
||||||
from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
|
from erpnext.accounts.doctype.loyalty_program.loyalty_program import (
|
||||||
get_loyalty_program_details_with_points,
|
get_loyalty_program_details_with_points,
|
||||||
validate_loyalty_points,
|
validate_loyalty_points,
|
||||||
@ -100,13 +103,11 @@ class SalesInvoice(SellingController):
|
|||||||
self.validate_debit_to_acc()
|
self.validate_debit_to_acc()
|
||||||
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
self.clear_unallocated_advances("Sales Invoice Advance", "advances")
|
||||||
self.add_remarks()
|
self.add_remarks()
|
||||||
self.validate_write_off_account()
|
|
||||||
self.validate_account_for_change_amount()
|
|
||||||
self.validate_fixed_asset()
|
self.validate_fixed_asset()
|
||||||
self.set_income_account_for_fixed_assets()
|
self.set_income_account_for_fixed_assets()
|
||||||
self.validate_item_cost_centers()
|
self.validate_item_cost_centers()
|
||||||
self.validate_income_account()
|
|
||||||
self.check_conversion_rate()
|
self.check_conversion_rate()
|
||||||
|
self.validate_accounts()
|
||||||
|
|
||||||
validate_inter_company_party(
|
validate_inter_company_party(
|
||||||
self.doctype, self.customer, self.company, self.inter_company_invoice_reference
|
self.doctype, self.customer, self.company, self.inter_company_invoice_reference
|
||||||
@ -170,6 +171,11 @@ class SalesInvoice(SellingController):
|
|||||||
|
|
||||||
self.reset_default_field_value("set_warehouse", "items", "warehouse")
|
self.reset_default_field_value("set_warehouse", "items", "warehouse")
|
||||||
|
|
||||||
|
def validate_accounts(self):
|
||||||
|
self.validate_write_off_account()
|
||||||
|
self.validate_account_for_change_amount()
|
||||||
|
self.validate_income_account()
|
||||||
|
|
||||||
def validate_fixed_asset(self):
|
def validate_fixed_asset(self):
|
||||||
for d in self.get("items"):
|
for d in self.get("items"):
|
||||||
if d.is_fixed_asset and d.meta.get_field("asset") and d.asset:
|
if d.is_fixed_asset and d.meta.get_field("asset") and d.asset:
|
||||||
@ -514,6 +520,64 @@ class SalesInvoice(SellingController):
|
|||||||
def on_update(self):
|
def on_update(self):
|
||||||
self.set_paid_amount()
|
self.set_paid_amount()
|
||||||
|
|
||||||
|
def on_update_after_submit(self):
|
||||||
|
needs_repost = 0
|
||||||
|
# Check if any field affecting accounting entry is altered
|
||||||
|
doc_before_update = self.get_doc_before_save()
|
||||||
|
accounting_dimensions = get_accounting_dimensions()
|
||||||
|
|
||||||
|
# Check if opening entry check updated
|
||||||
|
if doc_before_update.get("is_opening") != self.is_opening:
|
||||||
|
needs_repost = 1
|
||||||
|
|
||||||
|
if not needs_repost:
|
||||||
|
# Parent Level Accounts excluding party account
|
||||||
|
for field in (
|
||||||
|
"additional_discount_account",
|
||||||
|
"cash_bank_account",
|
||||||
|
"account_for_change_amount",
|
||||||
|
"write_off_account",
|
||||||
|
"loyalty_redemption_account",
|
||||||
|
"unrealized_profit_loss_account",
|
||||||
|
):
|
||||||
|
if doc_before_update.get(field) != self.get(field):
|
||||||
|
needs_repost = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# Check for parent accounting dimensions
|
||||||
|
for dimension in accounting_dimensions:
|
||||||
|
if doc_before_update.get(dimension) != self.get(dimension):
|
||||||
|
needs_repost = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
# Check for parent level
|
||||||
|
for index, item in enumerate(self.get("items")):
|
||||||
|
for field in (
|
||||||
|
"income_account",
|
||||||
|
"expense_account",
|
||||||
|
"discount_account",
|
||||||
|
"deferred_revenue_account",
|
||||||
|
):
|
||||||
|
if doc_before_update.get("items")[index].get(field) != item.get(field):
|
||||||
|
needs_repost = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
for dimension in accounting_dimensions:
|
||||||
|
if doc_before_update.get("items")[index].get(dimension) != item.get(dimension):
|
||||||
|
needs_repost = 1
|
||||||
|
break
|
||||||
|
|
||||||
|
self.validate_accounts()
|
||||||
|
self.db_set("repost_required", needs_repost)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def repost_accounting_entries(self):
|
||||||
|
self.docstatus = 2
|
||||||
|
self.make_gl_entries_on_cancel()
|
||||||
|
self.docstatus = 1
|
||||||
|
self.make_gl_entries()
|
||||||
|
self.db_set("repost_required", 0)
|
||||||
|
|
||||||
def set_paid_amount(self):
|
def set_paid_amount(self):
|
||||||
paid_amount = 0.0
|
paid_amount = 0.0
|
||||||
base_paid_amount = 0.0
|
base_paid_amount = 0.0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user