mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-07 07:02:54 +00:00
Merge branch 'develop' into fix-repayment-schedule
This commit is contained in:
@@ -1410,7 +1410,7 @@ class PurchaseInvoice(BuyingController):
|
|||||||
self.repost_future_sle_and_gle()
|
self.repost_future_sle_and_gle()
|
||||||
|
|
||||||
self.update_project()
|
self.update_project()
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
unlink_inter_company_doc(self.doctype, self.name, self.inter_company_invoice_reference)
|
||||||
self.ignore_linked_doctypes = (
|
self.ignore_linked_doctypes = (
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
// For license information, please see license.txt
|
||||||
|
|
||||||
|
frappe.ui.form.on('Repost Payment Ledger', {
|
||||||
|
setup: function(frm) {
|
||||||
|
frm.set_query("voucher_type", () => {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
name: ['in', ['Purchase Invoice', 'Sales Invoice', 'Payment Entry', 'Journal Entry']]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
frm.fields_dict['repost_vouchers'].grid.get_field('voucher_type').get_query = function(doc) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
name: ['in', ['Purchase Invoice', 'Sales Invoice', 'Payment Entry', 'Journal Entry']]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.fields_dict['repost_vouchers'].grid.get_field('voucher_no').get_query = function(doc) {
|
||||||
|
if (doc.company) {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: doc.company,
|
||||||
|
docstatus: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
refresh: function(frm) {
|
||||||
|
|
||||||
|
if (frm.doc.docstatus==1 && ['Queued', 'Failed'].find(x => x == frm.doc.repost_status)) {
|
||||||
|
frm.set_intro(__("Use 'Repost in background' button to trigger background job. Job can only be triggered when document is in Queued or Failed status."));
|
||||||
|
var btn_label = __("Repost in background")
|
||||||
|
|
||||||
|
frm.add_custom_button(btn_label, () => {
|
||||||
|
frappe.call({
|
||||||
|
method: 'erpnext.accounts.doctype.repost_payment_ledger.repost_payment_ledger.execute_repost_payment_ledger',
|
||||||
|
args: {
|
||||||
|
docname: frm.doc.name,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
frappe.msgprint(__('Reposting in the background.'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@@ -0,0 +1,159 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"allow_rename": 1,
|
||||||
|
"creation": "2022-10-19 21:59:33.553852",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"editable_grid": 1,
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"filters_section",
|
||||||
|
"company",
|
||||||
|
"posting_date",
|
||||||
|
"column_break_4",
|
||||||
|
"voucher_type",
|
||||||
|
"add_manually",
|
||||||
|
"status_section",
|
||||||
|
"repost_status",
|
||||||
|
"repost_error_log",
|
||||||
|
"selected_vouchers_section",
|
||||||
|
"repost_vouchers",
|
||||||
|
"amended_from"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"default": "Today",
|
||||||
|
"fieldname": "posting_date",
|
||||||
|
"fieldtype": "Date",
|
||||||
|
"label": "Posting Date",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "voucher_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Voucher Type",
|
||||||
|
"options": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "amended_from",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Amended From",
|
||||||
|
"no_copy": 1,
|
||||||
|
"options": "Repost Payment Ledger",
|
||||||
|
"print_hide": 1,
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "company",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Company",
|
||||||
|
"options": "Company",
|
||||||
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "selected_vouchers_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Vouchers"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "filters_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Filters"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_4",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "repost_vouchers",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Selected Vouchers",
|
||||||
|
"options": "Repost Payment Ledger Items"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "repost_status",
|
||||||
|
"fieldtype": "Select",
|
||||||
|
"label": "Repost Status",
|
||||||
|
"options": "\nQueued\nFailed\nCompleted",
|
||||||
|
"read_only": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "status_section",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"label": "Status"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"description": "Ignore Voucher Type filter and Select Vouchers Manually",
|
||||||
|
"fieldname": "add_manually",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Add Manually"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:doc.repost_error_log",
|
||||||
|
"fieldname": "repost_error_log",
|
||||||
|
"fieldtype": "Long Text",
|
||||||
|
"label": "Repost Error Log"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"index_web_pages_for_search": 1,
|
||||||
|
"is_submittable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2022-11-08 07:38:40.079038",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Repost Payment Ledger",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "System Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"delete": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"submit": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"create": 1,
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts User",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": 1,
|
||||||
|
"export": 1,
|
||||||
|
"permlevel": 1,
|
||||||
|
"print": 1,
|
||||||
|
"read": 1,
|
||||||
|
"report": 1,
|
||||||
|
"role": "Accounts Manager",
|
||||||
|
"share": 1,
|
||||||
|
"write": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
import copy
|
||||||
|
|
||||||
|
import frappe
|
||||||
|
from frappe import _, qb
|
||||||
|
from frappe.model.document import Document
|
||||||
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
|
from frappe.utils.background_jobs import is_job_queued
|
||||||
|
|
||||||
|
from erpnext.accounts.utils import _delete_pl_entries, create_payment_ledger_entry
|
||||||
|
|
||||||
|
VOUCHER_TYPES = ["Sales Invoice", "Purchase Invoice", "Payment Entry", "Journal Entry"]
|
||||||
|
|
||||||
|
|
||||||
|
def repost_ple_for_voucher(voucher_type, voucher_no, gle_map=None):
|
||||||
|
if voucher_type and voucher_no and gle_map:
|
||||||
|
_delete_pl_entries(voucher_type, voucher_no)
|
||||||
|
create_payment_ledger_entry(gle_map, cancel=0)
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def start_payment_ledger_repost(docname=None):
|
||||||
|
"""
|
||||||
|
Repost Payment Ledger Entries for Vouchers through Background Job
|
||||||
|
"""
|
||||||
|
if docname:
|
||||||
|
repost_doc = frappe.get_doc("Repost Payment Ledger", docname)
|
||||||
|
if repost_doc.docstatus == 1 and repost_doc.repost_status in ["Queued", "Failed"]:
|
||||||
|
try:
|
||||||
|
for entry in repost_doc.repost_vouchers:
|
||||||
|
doc = frappe.get_doc(entry.voucher_type, entry.voucher_no)
|
||||||
|
|
||||||
|
if doc.doctype in ["Payment Entry", "Journal Entry"]:
|
||||||
|
gle_map = doc.build_gl_map()
|
||||||
|
else:
|
||||||
|
gle_map = doc.get_gl_entries()
|
||||||
|
|
||||||
|
repost_ple_for_voucher(entry.voucher_type, entry.voucher_no, gle_map)
|
||||||
|
|
||||||
|
frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_error_log", "")
|
||||||
|
frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_status", "Completed")
|
||||||
|
except Exception as e:
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
traceback = frappe.get_traceback()
|
||||||
|
if traceback:
|
||||||
|
message = "Traceback: <br>" + traceback
|
||||||
|
frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_error_log", message)
|
||||||
|
|
||||||
|
frappe.db.set_value(repost_doc.doctype, repost_doc.name, "repost_status", "Failed")
|
||||||
|
|
||||||
|
|
||||||
|
class RepostPaymentLedger(Document):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(RepostPaymentLedger, self).__init__(*args, **kwargs)
|
||||||
|
self.vouchers = []
|
||||||
|
|
||||||
|
def before_validate(self):
|
||||||
|
self.load_vouchers_based_on_filters()
|
||||||
|
self.set_status()
|
||||||
|
|
||||||
|
def load_vouchers_based_on_filters(self):
|
||||||
|
if not self.add_manually:
|
||||||
|
self.repost_vouchers.clear()
|
||||||
|
self.get_vouchers()
|
||||||
|
self.extend("repost_vouchers", copy.deepcopy(self.vouchers))
|
||||||
|
|
||||||
|
def get_vouchers(self):
|
||||||
|
self.vouchers.clear()
|
||||||
|
|
||||||
|
filter_on_voucher_types = [self.voucher_type] if self.voucher_type else VOUCHER_TYPES
|
||||||
|
|
||||||
|
for vtype in filter_on_voucher_types:
|
||||||
|
doc = qb.DocType(vtype)
|
||||||
|
doctype_name = ConstantColumn(vtype)
|
||||||
|
query = (
|
||||||
|
qb.from_(doc)
|
||||||
|
.select(doctype_name.as_("voucher_type"), doc.name.as_("voucher_no"))
|
||||||
|
.where(
|
||||||
|
(doc.docstatus == 1)
|
||||||
|
& (doc.company == self.company)
|
||||||
|
& (doc.posting_date.gte(self.posting_date))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
entries = query.run(as_dict=True)
|
||||||
|
self.vouchers.extend(entries)
|
||||||
|
|
||||||
|
def set_status(self):
|
||||||
|
if self.docstatus == 0:
|
||||||
|
self.repost_status = "Queued"
|
||||||
|
|
||||||
|
def on_submit(self):
|
||||||
|
execute_repost_payment_ledger(self.name)
|
||||||
|
frappe.msgprint(_("Repost started in the background"))
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def execute_repost_payment_ledger(docname):
|
||||||
|
"""Repost Payment Ledger Entries by background job."""
|
||||||
|
|
||||||
|
job_name = "payment_ledger_repost_" + docname
|
||||||
|
|
||||||
|
if not is_job_queued(job_name):
|
||||||
|
frappe.enqueue(
|
||||||
|
method="erpnext.accounts.doctype.repost_payment_ledger.repost_payment_ledger.start_payment_ledger_repost",
|
||||||
|
docname=docname,
|
||||||
|
is_async=True,
|
||||||
|
job_name=job_name,
|
||||||
|
)
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
frappe.listview_settings["Repost Payment Ledger"] = {
|
||||||
|
add_fields: ["repost_status"],
|
||||||
|
get_indicator: function(doc) {
|
||||||
|
var colors = {
|
||||||
|
'Queued': 'orange',
|
||||||
|
'Completed': 'green',
|
||||||
|
'Failed': 'red',
|
||||||
|
};
|
||||||
|
let status = doc.repost_status;
|
||||||
|
return [__(status), colors[status], 'status,=,'+status];
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
|
# See license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestRepostPaymentLedger(FrappeTestCase):
|
||||||
|
pass
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"actions": [],
|
||||||
|
"creation": "2022-10-20 10:44:18.796489",
|
||||||
|
"doctype": "DocType",
|
||||||
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"voucher_type",
|
||||||
|
"voucher_no"
|
||||||
|
],
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldname": "voucher_type",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Voucher Type",
|
||||||
|
"options": "DocType"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "voucher_no",
|
||||||
|
"fieldtype": "Dynamic Link",
|
||||||
|
"label": "Voucher No",
|
||||||
|
"options": "voucher_type"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"istable": 1,
|
||||||
|
"links": [],
|
||||||
|
"modified": "2022-10-28 14:47:11.838109",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Accounts",
|
||||||
|
"name": "Repost Payment Ledger Items",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC",
|
||||||
|
"states": []
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
# import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
|
||||||
|
class RepostPaymentLedgerItems(Document):
|
||||||
|
pass
|
||||||
@@ -64,6 +64,25 @@ 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.doc.docstatus===1) {
|
||||||
|
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'));
|
||||||
|
me.frm.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}).removeClass('btn-default').addClass('btn-warning');
|
||||||
|
}
|
||||||
|
|
||||||
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": [
|
||||||
@@ -1035,6 +1036,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"depends_on": "redeem_loyalty_points",
|
"depends_on": "redeem_loyalty_points",
|
||||||
"fieldname": "loyalty_redemption_account",
|
"fieldname": "loyalty_redemption_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -1333,6 +1335,7 @@
|
|||||||
"options": "fa fa-money"
|
"options": "fa fa-money"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"depends_on": "is_pos",
|
"depends_on": "is_pos",
|
||||||
"fieldname": "cash_bank_account",
|
"fieldname": "cash_bank_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -1432,6 +1435,7 @@
|
|||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"depends_on": "is_pos",
|
"depends_on": "is_pos",
|
||||||
"fieldname": "account_for_change_amount",
|
"fieldname": "account_for_change_amount",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -1480,6 +1484,7 @@
|
|||||||
"hide_seconds": 1
|
"hide_seconds": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "write_off_account",
|
"fieldname": "write_off_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hide_days": 1,
|
"hide_days": 1,
|
||||||
@@ -1703,6 +1708,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",
|
||||||
@@ -1917,6 +1923,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"depends_on": "eval:doc.is_internal_customer",
|
"depends_on": "eval:doc.is_internal_customer",
|
||||||
"description": "Unrealized Profit / Loss account for intra-company transfers",
|
"description": "Unrealized Profit / Loss account for intra-company transfers",
|
||||||
"fieldname": "unrealized_profit_loss_account",
|
"fieldname": "unrealized_profit_loss_account",
|
||||||
@@ -1959,6 +1966,7 @@
|
|||||||
"label": "Disable Rounded Total"
|
"label": "Disable Rounded Total"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "additional_discount_account",
|
"fieldname": "additional_discount_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Discount Account",
|
"label": "Discount Account",
|
||||||
@@ -2097,6 +2105,15 @@
|
|||||||
"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",
|
||||||
|
"no_copy": 1,
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
@@ -2109,7 +2126,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-10-11 13:07:36.488095",
|
"modified": "2022-11-07 16:02:07.972258",
|
||||||
"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:
|
||||||
@@ -367,7 +373,8 @@ class SalesInvoice(SellingController):
|
|||||||
if self.update_stock == 1:
|
if self.update_stock == 1:
|
||||||
self.repost_future_sle_and_gle()
|
self.repost_future_sle_and_gle()
|
||||||
|
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
self.db_set("repost_required", 0)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction"
|
frappe.db.get_single_value("Selling Settings", "sales_update_frequency") == "Each Transaction"
|
||||||
@@ -514,6 +521,92 @@ 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):
|
||||||
|
if hasattr(self, "repost_required"):
|
||||||
|
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() + ["cost_center", "project"]
|
||||||
|
|
||||||
|
# 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 child tables
|
||||||
|
if self.check_if_child_table_updated(
|
||||||
|
"items",
|
||||||
|
doc_before_update,
|
||||||
|
("income_account", "expense_account", "discount_account"),
|
||||||
|
accounting_dimensions,
|
||||||
|
):
|
||||||
|
needs_repost = 1
|
||||||
|
|
||||||
|
if self.check_if_child_table_updated(
|
||||||
|
"taxes", doc_before_update, ("account_head",), accounting_dimensions
|
||||||
|
):
|
||||||
|
needs_repost = 1
|
||||||
|
|
||||||
|
self.validate_accounts()
|
||||||
|
|
||||||
|
# validate if deferred revenue is enabled for any item
|
||||||
|
# Don't allow to update the invoice if deferred revenue is enabled
|
||||||
|
for item in self.get("items"):
|
||||||
|
if item.enable_deferred_revenue:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Deferred Revenue is enabled for item {0}. You cannot update the invoice after submission."
|
||||||
|
).format(item.item_code)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.db_set("repost_required", needs_repost)
|
||||||
|
|
||||||
|
def check_if_child_table_updated(
|
||||||
|
self, child_table, doc_before_update, fields_to_check, accounting_dimensions
|
||||||
|
):
|
||||||
|
# Check if any field affecting accounting entry is altered
|
||||||
|
for index, item in enumerate(self.get(child_table)):
|
||||||
|
for field in fields_to_check:
|
||||||
|
if doc_before_update.get(child_table)[index].get(field) != item.get(field):
|
||||||
|
return True
|
||||||
|
|
||||||
|
for dimension in accounting_dimensions:
|
||||||
|
if doc_before_update.get(child_table)[index].get(dimension) != item.get(dimension):
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def repost_accounting_entries(self):
|
||||||
|
if self.repost_required:
|
||||||
|
self.docstatus = 2
|
||||||
|
self.make_gl_entries_on_cancel()
|
||||||
|
self.docstatus = 1
|
||||||
|
self.make_gl_entries()
|
||||||
|
self.db_set("repost_required", 0)
|
||||||
|
else:
|
||||||
|
frappe.throw(_("No updates pending for reposting"))
|
||||||
|
|
||||||
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
|
||||||
@@ -2306,7 +2399,7 @@ def get_loyalty_programs(customer):
|
|||||||
lp_details = get_loyalty_programs(customer)
|
lp_details = get_loyalty_programs(customer)
|
||||||
|
|
||||||
if len(lp_details) == 1:
|
if len(lp_details) == 1:
|
||||||
frappe.db.set(customer, "loyalty_program", lp_details[0])
|
customer.db_set("loyalty_program", lp_details[0])
|
||||||
return lp_details
|
return lp_details
|
||||||
else:
|
else:
|
||||||
return lp_details
|
return lp_details
|
||||||
|
|||||||
@@ -2729,6 +2729,31 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
|
|
||||||
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
|
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
|
||||||
|
|
||||||
|
# Update Invoice post submit and then check GL Entries again
|
||||||
|
|
||||||
|
si.load_from_db()
|
||||||
|
si.items[0].income_account = "Service - _TC"
|
||||||
|
si.additional_discount_account = "_Test Account Sales - _TC"
|
||||||
|
si.taxes[0].account_head = "TDS Payable - _TC"
|
||||||
|
si.save()
|
||||||
|
|
||||||
|
si.load_from_db()
|
||||||
|
self.assertTrue(si.repost_required)
|
||||||
|
|
||||||
|
si.repost_accounting_entries()
|
||||||
|
|
||||||
|
expected_gle = [
|
||||||
|
["_Test Account Sales - _TC", 22.0, 0.0, nowdate()],
|
||||||
|
["Debtors - _TC", 88, 0.0, nowdate()],
|
||||||
|
["Service - _TC", 0.0, 100.0, nowdate()],
|
||||||
|
["TDS Payable - _TC", 0.0, 10.0, nowdate()],
|
||||||
|
]
|
||||||
|
|
||||||
|
check_gl_entries(self, si.name, expected_gle, add_days(nowdate(), -1))
|
||||||
|
|
||||||
|
si.load_from_db()
|
||||||
|
self.assertFalse(si.repost_required)
|
||||||
|
|
||||||
def test_asset_depreciation_on_sale_with_pro_rata(self):
|
def test_asset_depreciation_on_sale_with_pro_rata(self):
|
||||||
"""
|
"""
|
||||||
Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on its date of sale.
|
Tests if an Asset set to depreciate yearly on June 30, that gets sold on Sept 30, creates an additional depreciation entry on its date of sale.
|
||||||
@@ -3286,6 +3311,7 @@ def check_gl_entries(doc, voucher_no, expected_gle, posting_date):
|
|||||||
"""select account, debit, credit, posting_date
|
"""select account, debit, credit, posting_date
|
||||||
from `tabGL Entry`
|
from `tabGL Entry`
|
||||||
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
|
where voucher_type='Sales Invoice' and voucher_no=%s and posting_date > %s
|
||||||
|
and is_cancelled = 0
|
||||||
order by posting_date asc, account asc""",
|
order by posting_date asc, account asc""",
|
||||||
(voucher_no, posting_date),
|
(voucher_no, posting_date),
|
||||||
as_dict=1,
|
as_dict=1,
|
||||||
|
|||||||
@@ -438,6 +438,7 @@
|
|||||||
"label": "Accounting Details"
|
"label": "Accounting Details"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "income_account",
|
"fieldname": "income_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Income Account",
|
"label": "Income Account",
|
||||||
@@ -450,6 +451,7 @@
|
|||||||
"width": "120px"
|
"width": "120px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "expense_account",
|
"fieldname": "expense_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Expense Account",
|
"label": "Expense Account",
|
||||||
@@ -469,6 +471,7 @@
|
|||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"default": ":Company",
|
"default": ":Company",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -800,6 +803,7 @@
|
|||||||
"options": "Finance Book"
|
"options": "Finance Book"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "project",
|
"fieldname": "project",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Project",
|
"label": "Project",
|
||||||
@@ -822,7 +826,6 @@
|
|||||||
"label": "Incoming Rate (Costing)",
|
"label": "Incoming Rate (Costing)",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Company:company:default_currency",
|
"options": "Company:company:default_currency",
|
||||||
"precision": "6",
|
|
||||||
"print_hide": 1
|
"print_hide": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -835,6 +838,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"fieldname": "discount_account",
|
"fieldname": "discount_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Discount Account",
|
"label": "Discount Account",
|
||||||
|
|||||||
@@ -51,6 +51,7 @@
|
|||||||
"oldfieldtype": "Data"
|
"oldfieldtype": "Data"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "account_head",
|
"fieldname": "account_head",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -63,6 +64,7 @@
|
|||||||
"search_index": 1
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
"default": ":Company",
|
"default": ":Company",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -216,12 +218,13 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-05 20:04:01.726867",
|
"modified": "2022-10-17 13:08:17.776528",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Taxes and Charges",
|
"name": "Sales Taxes and Charges",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [],
|
"permissions": [],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC"
|
"sort_order": "ASC",
|
||||||
|
"states": []
|
||||||
}
|
}
|
||||||
@@ -1146,10 +1146,10 @@ def repost_gle_for_stock_vouchers(
|
|||||||
if not existing_gle or not compare_existing_and_expected_gle(
|
if not existing_gle or not compare_existing_and_expected_gle(
|
||||||
existing_gle, expected_gle, precision
|
existing_gle, expected_gle, precision
|
||||||
):
|
):
|
||||||
_delete_gl_entries(voucher_type, voucher_no)
|
_delete_accounting_ledger_entries(voucher_type, voucher_no)
|
||||||
voucher_obj.make_gl_entries(gl_entries=expected_gle, from_repost=True)
|
voucher_obj.make_gl_entries(gl_entries=expected_gle, from_repost=True)
|
||||||
else:
|
else:
|
||||||
_delete_gl_entries(voucher_type, voucher_no)
|
_delete_accounting_ledger_entries(voucher_type, voucher_no)
|
||||||
|
|
||||||
if not frappe.flags.in_test:
|
if not frappe.flags.in_test:
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
@@ -1161,18 +1161,28 @@ def repost_gle_for_stock_vouchers(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def _delete_gl_entries(voucher_type, voucher_no):
|
def _delete_pl_entries(voucher_type, voucher_no):
|
||||||
frappe.db.sql(
|
|
||||||
"""delete from `tabGL Entry`
|
|
||||||
where voucher_type=%s and voucher_no=%s""",
|
|
||||||
(voucher_type, voucher_no),
|
|
||||||
)
|
|
||||||
ple = qb.DocType("Payment Ledger Entry")
|
ple = qb.DocType("Payment Ledger Entry")
|
||||||
qb.from_(ple).delete().where(
|
qb.from_(ple).delete().where(
|
||||||
(ple.voucher_type == voucher_type) & (ple.voucher_no == voucher_no)
|
(ple.voucher_type == voucher_type) & (ple.voucher_no == voucher_no)
|
||||||
).run()
|
).run()
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_gl_entries(voucher_type, voucher_no):
|
||||||
|
gle = qb.DocType("GL Entry")
|
||||||
|
qb.from_(gle).delete().where(
|
||||||
|
(gle.voucher_type == voucher_type) & (gle.voucher_no == voucher_no)
|
||||||
|
).run()
|
||||||
|
|
||||||
|
|
||||||
|
def _delete_accounting_ledger_entries(voucher_type, voucher_no):
|
||||||
|
"""
|
||||||
|
Remove entries from both General and Payment Ledger for specified Voucher
|
||||||
|
"""
|
||||||
|
_delete_gl_entries(voucher_type, voucher_no)
|
||||||
|
_delete_pl_entries(voucher_type, voucher_no)
|
||||||
|
|
||||||
|
|
||||||
def sort_stock_vouchers_by_posting_date(
|
def sort_stock_vouchers_by_posting_date(
|
||||||
stock_vouchers: List[Tuple[str, str]]
|
stock_vouchers: List[Tuple[str, str]]
|
||||||
) -> List[Tuple[str, str]]:
|
) -> List[Tuple[str, str]]:
|
||||||
|
|||||||
@@ -361,7 +361,7 @@ class PurchaseOrder(BuyingController):
|
|||||||
self.update_reserved_qty_for_subcontract()
|
self.update_reserved_qty_for_subcontract()
|
||||||
self.check_on_hold_or_closed_status()
|
self.check_on_hold_or_closed_status()
|
||||||
|
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class RequestforQuotation(BuyingController):
|
|||||||
|
|
||||||
if self.docstatus < 1:
|
if self.docstatus < 1:
|
||||||
# after amend and save, status still shows as cancelled, until submit
|
# after amend and save, status still shows as cancelled, until submit
|
||||||
frappe.db.set(self, "status", "Draft")
|
self.db_set("status", "Draft")
|
||||||
|
|
||||||
def validate_duplicate_supplier(self):
|
def validate_duplicate_supplier(self):
|
||||||
supplier_list = [d.supplier for d in self.suppliers]
|
supplier_list = [d.supplier for d in self.suppliers]
|
||||||
@@ -73,14 +73,14 @@ class RequestforQuotation(BuyingController):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
frappe.db.set(self, "status", "Submitted")
|
self.db_set("status", "Submitted")
|
||||||
for supplier in self.suppliers:
|
for supplier in self.suppliers:
|
||||||
supplier.email_sent = 0
|
supplier.email_sent = 0
|
||||||
supplier.quote_status = "Pending"
|
supplier.quote_status = "Pending"
|
||||||
self.send_to_supplier()
|
self.send_to_supplier()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_supplier_email_preview(self, supplier):
|
def get_supplier_email_preview(self, supplier):
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ class Supplier(TransactionBase):
|
|||||||
|
|
||||||
def after_rename(self, olddn, newdn, merge=False):
|
def after_rename(self, olddn, newdn, merge=False):
|
||||||
if frappe.defaults.get_global_default("supp_master_name") == "Supplier Name":
|
if frappe.defaults.get_global_default("supp_master_name") == "Supplier Name":
|
||||||
frappe.db.set(self, "supplier_name", newdn)
|
self.db_set("supplier_name", newdn)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ class SupplierQuotation(BuyingController):
|
|||||||
self.validate_valid_till()
|
self.validate_valid_till()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
frappe.db.set(self, "status", "Submitted")
|
self.db_set("status", "Submitted")
|
||||||
self.update_rfq_supplier_status(1)
|
self.update_rfq_supplier_status(1)
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
self.update_rfq_supplier_status(0)
|
self.update_rfq_supplier_status(0)
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ class Opportunity(TransactionBase, CRMNote):
|
|||||||
if not self.get(field) and frappe.db.field_exists(self.opportunity_from, field):
|
if not self.get(field) and frappe.db.field_exists(self.opportunity_from, field):
|
||||||
try:
|
try:
|
||||||
value = frappe.db.get_value(self.opportunity_from, self.party_name, field)
|
value = frappe.db.get_value(self.opportunity_from, self.party_name, field)
|
||||||
frappe.db.set(self, field, value)
|
self.db_set(field, value)
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
event.add_participant(self.doctype, self.name)
|
event.add_participant(self.doctype, self.name)
|
||||||
event.insert(ignore_permissions=1)
|
event.insert(ignore_permissions=1)
|
||||||
|
|
||||||
frappe.db.set(self, "status", "Submitted")
|
self.db_set("status", "Submitted")
|
||||||
|
|
||||||
def create_schedule_list(self, start_date, end_date, no_of_visit, sales_person):
|
def create_schedule_list(self, start_date, end_date, no_of_visit, sales_person):
|
||||||
schedule_list = []
|
schedule_list = []
|
||||||
@@ -245,7 +245,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
self.generate_schedule()
|
self.generate_schedule()
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
frappe.db.set(self, "status", "Draft")
|
self.db_set("status", "Draft")
|
||||||
|
|
||||||
def update_amc_date(self, serial_nos, amc_expiry_date=None):
|
def update_amc_date(self, serial_nos, amc_expiry_date=None):
|
||||||
for serial_no in serial_nos:
|
for serial_no in serial_nos:
|
||||||
@@ -344,7 +344,7 @@ class MaintenanceSchedule(TransactionBase):
|
|||||||
if d.serial_no:
|
if d.serial_no:
|
||||||
serial_nos = get_valid_serial_nos(d.serial_no)
|
serial_nos = get_valid_serial_nos(d.serial_no)
|
||||||
self.update_amc_date(serial_nos)
|
self.update_amc_date(serial_nos)
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
delete_events(self.doctype, self.name)
|
delete_events(self.doctype, self.name)
|
||||||
|
|
||||||
def on_trash(self):
|
def on_trash(self):
|
||||||
|
|||||||
@@ -125,12 +125,12 @@ class MaintenanceVisit(TransactionBase):
|
|||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.update_customer_issue(1)
|
self.update_customer_issue(1)
|
||||||
frappe.db.set(self, "status", "Submitted")
|
self.db_set("status", "Submitted")
|
||||||
self.update_status_and_actual_date()
|
self.update_status_and_actual_date()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.check_if_last_visit()
|
self.check_if_last_visit()
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
self.update_status_and_actual_date(cancel=True)
|
self.update_status_and_actual_date(cancel=True)
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
|
|||||||
@@ -206,8 +206,8 @@ class BOM(WebsiteGenerator):
|
|||||||
self.manage_default_bom()
|
self.manage_default_bom()
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.db.set(self, "is_active", 0)
|
self.db_set("is_active", 0)
|
||||||
frappe.db.set(self, "is_default", 0)
|
self.db_set("is_default", 0)
|
||||||
|
|
||||||
# check if used in any other bom
|
# check if used in any other bom
|
||||||
self.validate_bom_links()
|
self.validate_bom_links()
|
||||||
@@ -449,10 +449,10 @@ class BOM(WebsiteGenerator):
|
|||||||
not frappe.db.exists(dict(doctype="BOM", docstatus=1, item=self.item, is_default=1))
|
not frappe.db.exists(dict(doctype="BOM", docstatus=1, item=self.item, is_default=1))
|
||||||
and self.is_active
|
and self.is_active
|
||||||
):
|
):
|
||||||
frappe.db.set(self, "is_default", 1)
|
self.db_set("is_default", 1)
|
||||||
frappe.db.set_value("Item", self.item, "default_bom", self.name)
|
frappe.db.set_value("Item", self.item, "default_bom", self.name)
|
||||||
else:
|
else:
|
||||||
frappe.db.set(self, "is_default", 0)
|
self.db_set("is_default", 0)
|
||||||
item = frappe.get_doc("Item", self.item)
|
item = frappe.get_doc("Item", self.item)
|
||||||
if item.default_bom == self.name:
|
if item.default_bom == self.name:
|
||||||
frappe.db.set_value("Item", self.item, "default_bom", None)
|
frappe.db.set_value("Item", self.item, "default_bom", None)
|
||||||
|
|||||||
@@ -373,7 +373,7 @@ class WorkOrder(Document):
|
|||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.validate_cancel()
|
self.validate_cancel()
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
if self.production_plan and frappe.db.exists(
|
if self.production_plan and frappe.db.exists(
|
||||||
"Production Plan Item Reference", {"parent": self.production_plan}
|
"Production Plan Item Reference", {"parent": self.production_plan}
|
||||||
|
|||||||
@@ -100,9 +100,7 @@ def get_default_holiday_list():
|
|||||||
|
|
||||||
def check_if_within_operating_hours(workstation, operation, from_datetime, to_datetime):
|
def check_if_within_operating_hours(workstation, operation, from_datetime, to_datetime):
|
||||||
if from_datetime and to_datetime:
|
if from_datetime and to_datetime:
|
||||||
if not cint(
|
if not frappe.db.get_single_value("Manufacturing Settings", "allow_production_on_holidays"):
|
||||||
frappe.db.get_value("Manufacturing Settings", None, "allow_production_on_holidays")
|
|
||||||
):
|
|
||||||
check_workstation_for_holiday(workstation, from_datetime, to_datetime)
|
check_workstation_for_holiday(workstation, from_datetime, to_datetime)
|
||||||
|
|
||||||
if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")):
|
if not cint(frappe.db.get_value("Manufacturing Settings", None, "allow_overtime")):
|
||||||
|
|||||||
@@ -92,18 +92,26 @@ frappe.ui.form.on("Timesheet", {
|
|||||||
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
|
frm.fields_dict["time_logs"].grid.toggle_enable("billing_hours", false);
|
||||||
frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
|
frm.fields_dict["time_logs"].grid.toggle_enable("is_billable", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let filters = {
|
||||||
|
"status": "Open"
|
||||||
|
};
|
||||||
|
|
||||||
|
if (frm.doc.customer) {
|
||||||
|
filters["customer"] = frm.doc.customer;
|
||||||
|
}
|
||||||
|
|
||||||
|
frm.set_query('parent_project', function(doc) {
|
||||||
|
return {
|
||||||
|
filters: filters
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.trigger('setup_filters');
|
frm.trigger('setup_filters');
|
||||||
frm.trigger('set_dynamic_field_label');
|
frm.trigger('set_dynamic_field_label');
|
||||||
},
|
},
|
||||||
|
|
||||||
customer: function(frm) {
|
customer: function(frm) {
|
||||||
frm.set_query('parent_project', function(doc) {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
"customer": doc.customer
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
||||||
frm.set_query('project', 'time_logs', function(doc) {
|
frm.set_query('project', 'time_logs', function(doc) {
|
||||||
return {
|
return {
|
||||||
filters: {
|
filters: {
|
||||||
|
|||||||
@@ -143,6 +143,12 @@ var get_payment_mode_account = function(frm, mode_of_payment, callback) {
|
|||||||
|
|
||||||
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
cur_frm.cscript.account_head = function(doc, cdt, cdn) {
|
||||||
var d = locals[cdt][cdn];
|
var d = locals[cdt][cdn];
|
||||||
|
|
||||||
|
if (doc.docstatus == 1) {
|
||||||
|
// Should not trigger any changes on change post submit
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(!d.charge_type && d.account_head){
|
if(!d.charge_type && d.account_head){
|
||||||
frappe.msgprint(__("Please select Charge Type first"));
|
frappe.msgprint(__("Please select Charge Type first"));
|
||||||
frappe.model.set_value(cdt, cdn, "account_head", "");
|
frappe.model.set_value(cdt, cdn, "account_head", "");
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ class Customer(TransactionBase):
|
|||||||
|
|
||||||
def after_rename(self, olddn, newdn, merge=False):
|
def after_rename(self, olddn, newdn, merge=False):
|
||||||
if frappe.defaults.get_global_default("cust_master_name") == "Customer Name":
|
if frappe.defaults.get_global_default("cust_master_name") == "Customer Name":
|
||||||
frappe.db.set(self, "customer_name", newdn)
|
self.db_set("customer_name", newdn)
|
||||||
|
|
||||||
def set_loyalty_program(self):
|
def set_loyalty_program(self):
|
||||||
if self.loyalty_program:
|
if self.loyalty_program:
|
||||||
|
|||||||
@@ -87,13 +87,13 @@ class InstallationNote(TransactionBase):
|
|||||||
frappe.throw(_("Please pull items from Delivery Note"))
|
frappe.throw(_("Please pull items from Delivery Note"))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
frappe.db.set(self, "status", "Draft")
|
self.db_set("status", "Draft")
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.validate_serial_no()
|
self.validate_serial_no()
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
frappe.db.set(self, "status", "Submitted")
|
self.db_set("status", "Submitted")
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
self.update_prevdoc_status()
|
self.update_prevdoc_status()
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|||||||
@@ -119,10 +119,10 @@ class Quotation(SellingController):
|
|||||||
if not (self.is_fully_ordered() or self.is_partially_ordered()):
|
if not (self.is_fully_ordered() or self.is_partially_ordered()):
|
||||||
get_lost_reasons = frappe.get_list("Quotation Lost Reason", fields=["name"])
|
get_lost_reasons = frappe.get_list("Quotation Lost Reason", fields=["name"])
|
||||||
lost_reasons_lst = [reason.get("name") for reason in get_lost_reasons]
|
lost_reasons_lst = [reason.get("name") for reason in get_lost_reasons]
|
||||||
frappe.db.set(self, "status", "Lost")
|
self.db_set("status", "Lost")
|
||||||
|
|
||||||
if detailed_reason:
|
if detailed_reason:
|
||||||
frappe.db.set(self, "order_lost_reason", detailed_reason)
|
self.db_set("order_lost_reason", detailed_reason)
|
||||||
|
|
||||||
for reason in lost_reasons_list:
|
for reason in lost_reasons_list:
|
||||||
if reason.get("lost_reason") in lost_reasons_lst:
|
if reason.get("lost_reason") in lost_reasons_lst:
|
||||||
|
|||||||
@@ -246,7 +246,7 @@ class SalesOrder(SellingController):
|
|||||||
self.update_project()
|
self.update_project()
|
||||||
self.update_prevdoc_status("cancel")
|
self.update_prevdoc_status("cancel")
|
||||||
|
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
self.update_blanket_order()
|
self.update_blanket_order()
|
||||||
|
|
||||||
|
|||||||
@@ -207,15 +207,14 @@ class Company(NestedSet):
|
|||||||
frappe.local.flags.ignore_root_company_validation = True
|
frappe.local.flags.ignore_root_company_validation = True
|
||||||
create_charts(self.name, self.chart_of_accounts, self.existing_company)
|
create_charts(self.name, self.chart_of_accounts, self.existing_company)
|
||||||
|
|
||||||
frappe.db.set(
|
self.db_set(
|
||||||
self,
|
|
||||||
"default_receivable_account",
|
"default_receivable_account",
|
||||||
frappe.db.get_value(
|
frappe.db.get_value(
|
||||||
"Account", {"company": self.name, "account_type": "Receivable", "is_group": 0}
|
"Account", {"company": self.name, "account_type": "Receivable", "is_group": 0}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
frappe.db.set(
|
|
||||||
self,
|
self.db_set(
|
||||||
"default_payable_account",
|
"default_payable_account",
|
||||||
frappe.db.get_value(
|
frappe.db.get_value(
|
||||||
"Account", {"company": self.name, "account_type": "Payable", "is_group": 0}
|
"Account", {"company": self.name, "account_type": "Payable", "is_group": 0}
|
||||||
@@ -491,12 +490,12 @@ class Company(NestedSet):
|
|||||||
cc_doc.flags.ignore_mandatory = True
|
cc_doc.flags.ignore_mandatory = True
|
||||||
cc_doc.insert()
|
cc_doc.insert()
|
||||||
|
|
||||||
frappe.db.set(self, "cost_center", _("Main") + " - " + self.abbr)
|
self.db_set("cost_center", _("Main") + " - " + self.abbr)
|
||||||
frappe.db.set(self, "round_off_cost_center", _("Main") + " - " + self.abbr)
|
self.db_set("round_off_cost_center", _("Main") + " - " + self.abbr)
|
||||||
frappe.db.set(self, "depreciation_cost_center", _("Main") + " - " + self.abbr)
|
self.db_set("depreciation_cost_center", _("Main") + " - " + self.abbr)
|
||||||
|
|
||||||
def after_rename(self, olddn, newdn, merge=False):
|
def after_rename(self, olddn, newdn, merge=False):
|
||||||
frappe.db.set(self, "company_name", newdn)
|
self.db_set("company_name", newdn)
|
||||||
|
|
||||||
frappe.db.sql(
|
frappe.db.sql(
|
||||||
"""update `tabDefaultValue` set defvalue=%s
|
"""update `tabDefaultValue` set defvalue=%s
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ class MaterialRequest(BuyingController):
|
|||||||
self.title = _("{0} Request for {1}").format(self.material_request_type, items)[:100]
|
self.title = _("{0} Request for {1}").format(self.material_request_type, items)[:100]
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
# frappe.db.set(self, 'status', 'Submitted')
|
|
||||||
self.update_requested_qty()
|
self.update_requested_qty()
|
||||||
self.update_requested_qty_in_production_plan()
|
self.update_requested_qty_in_production_plan()
|
||||||
if self.material_request_type == "Purchase":
|
if self.material_request_type == "Purchase":
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ class TestMaterialRequest(FrappeTestCase):
|
|||||||
po.load_from_db()
|
po.load_from_db()
|
||||||
mr.update_status("Stopped")
|
mr.update_status("Stopped")
|
||||||
self.assertRaises(frappe.InvalidStatusError, po.submit)
|
self.assertRaises(frappe.InvalidStatusError, po.submit)
|
||||||
frappe.db.set(po, "docstatus", 1)
|
po.db_set("docstatus", 1)
|
||||||
self.assertRaises(frappe.InvalidStatusError, po.cancel)
|
self.assertRaises(frappe.InvalidStatusError, po.cancel)
|
||||||
|
|
||||||
# resubmit and check for per complete
|
# resubmit and check for per complete
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ frappe.listview_settings['Stock Entry'] = {
|
|||||||
"`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`",
|
"`tabStock Entry`.`purpose`", "`tabStock Entry`.`work_order`", "`tabStock Entry`.`bom_no`",
|
||||||
"`tabStock Entry`.`is_return`"],
|
"`tabStock Entry`.`is_return`"],
|
||||||
get_indicator: function (doc) {
|
get_indicator: function (doc) {
|
||||||
debugger
|
|
||||||
if(doc.is_return===1 && doc.purpose === "Material Transfer for Manufacture") {
|
if(doc.is_return===1 && doc.purpose === "Material Transfer for Manufacture") {
|
||||||
return [__("Material Returned from WIP"), "orange",
|
return [__("Material Returned from WIP"), "orange",
|
||||||
"is_return,=,1|purpose,=,Material Transfer for Manufacture|docstatus,<,2"];
|
"is_return,=,1|purpose,=,Material Transfer for Manufacture|docstatus,<,2"];
|
||||||
|
|||||||
@@ -57,6 +57,18 @@ frappe.ui.form.on('Subcontracting Receipt', {
|
|||||||
filters: { 'company': frm.doc.company }
|
filters: { 'company': frm.doc.company }
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
frappe.db.get_single_value('Buying Settings', 'backflush_raw_materials_of_subcontract_based_on').then(val => {
|
||||||
|
if (val == 'Material Transferred for Subcontract') {
|
||||||
|
frm.fields_dict['supplied_items'].grid.grid_rows.forEach((grid_row) => {
|
||||||
|
grid_row.docfields.forEach((df) => {
|
||||||
|
if (df.fieldname == 'consumed_qty') {
|
||||||
|
df.read_only = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
refresh: (frm) => {
|
refresh: (frm) => {
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ from frappe import _
|
|||||||
def get_data():
|
def get_data():
|
||||||
return {
|
return {
|
||||||
"fieldname": "subcontracting_receipt_no",
|
"fieldname": "subcontracting_receipt_no",
|
||||||
|
"non_standard_fieldnames": {
|
||||||
|
"Subcontracting Receipt": "return_against",
|
||||||
|
},
|
||||||
"internal_links": {
|
"internal_links": {
|
||||||
"Subcontracting Order": ["items", "subcontracting_order"],
|
"Subcontracting Order": ["items", "subcontracting_order"],
|
||||||
"Project": ["items", "project"],
|
"Project": ["items", "project"],
|
||||||
@@ -11,5 +14,6 @@ def get_data():
|
|||||||
},
|
},
|
||||||
"transactions": [
|
"transactions": [
|
||||||
{"label": _("Reference"), "items": ["Subcontracting Order", "Quality Inspection", "Project"]},
|
{"label": _("Reference"), "items": ["Subcontracting Order", "Quality Inspection", "Project"]},
|
||||||
|
{"label": _("Returns"), "items": ["Subcontracting Receipt"]},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,207 +1,208 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2022-04-18 10:45:16.538479",
|
"creation": "2022-04-18 10:45:16.538479",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
"field_order": [
|
||||||
"main_item_code",
|
"main_item_code",
|
||||||
"rm_item_code",
|
"rm_item_code",
|
||||||
"item_name",
|
"item_name",
|
||||||
"bom_detail_no",
|
"bom_detail_no",
|
||||||
"col_break1",
|
"col_break1",
|
||||||
"description",
|
"description",
|
||||||
"stock_uom",
|
"stock_uom",
|
||||||
"conversion_factor",
|
"conversion_factor",
|
||||||
"reference_name",
|
"reference_name",
|
||||||
"secbreak_1",
|
"secbreak_1",
|
||||||
"rate",
|
"rate",
|
||||||
"col_break2",
|
"col_break2",
|
||||||
"amount",
|
"amount",
|
||||||
"secbreak_2",
|
"secbreak_2",
|
||||||
"available_qty_for_consumption",
|
"available_qty_for_consumption",
|
||||||
"required_qty",
|
"required_qty",
|
||||||
"col_break3",
|
"col_break3",
|
||||||
"consumed_qty",
|
"consumed_qty",
|
||||||
"current_stock",
|
"current_stock",
|
||||||
"secbreak_3",
|
"secbreak_3",
|
||||||
"batch_no",
|
"batch_no",
|
||||||
"col_break4",
|
"col_break4",
|
||||||
"serial_no",
|
"serial_no",
|
||||||
"subcontracting_order"
|
"subcontracting_order"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldname": "main_item_code",
|
"fieldname": "main_item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Item Code",
|
"label": "Item Code",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "rm_item_code",
|
"fieldname": "rm_item_code",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Raw Material Item Code",
|
"label": "Raw Material Item Code",
|
||||||
"options": "Item",
|
"options": "Item",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "description",
|
"fieldname": "description",
|
||||||
"fieldtype": "Text Editor",
|
"fieldtype": "Text Editor",
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
"label": "Description",
|
"label": "Description",
|
||||||
"print_width": "300px",
|
"print_width": "300px",
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"width": "300px"
|
"width": "300px"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "batch_no",
|
"fieldname": "batch_no",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Batch No",
|
"label": "Batch No",
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Batch"
|
"options": "Batch"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "serial_no",
|
"fieldname": "serial_no",
|
||||||
"fieldtype": "Text",
|
"fieldtype": "Text",
|
||||||
"label": "Serial No",
|
"label": "Serial No",
|
||||||
"no_copy": 1
|
"no_copy": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col_break1",
|
"fieldname": "col_break1",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "required_qty",
|
"fieldname": "required_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Required Qty",
|
"label": "Required Qty",
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "consumed_qty",
|
"fieldname": "consumed_qty",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Consumed Qty",
|
"label": "Consumed Qty",
|
||||||
"reqd": 1
|
"read_only": 1,
|
||||||
},
|
"reqd": 1
|
||||||
{
|
},
|
||||||
"fieldname": "stock_uom",
|
{
|
||||||
"fieldtype": "Link",
|
"fieldname": "stock_uom",
|
||||||
"label": "Stock Uom",
|
"fieldtype": "Link",
|
||||||
"options": "UOM",
|
"label": "Stock Uom",
|
||||||
"read_only": 1
|
"options": "UOM",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "rate",
|
{
|
||||||
"fieldtype": "Currency",
|
"fieldname": "rate",
|
||||||
"label": "Rate",
|
"fieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"label": "Rate",
|
||||||
"read_only": 1
|
"options": "Company:company:default_currency",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "amount",
|
{
|
||||||
"fieldtype": "Currency",
|
"fieldname": "amount",
|
||||||
"label": "Amount",
|
"fieldtype": "Currency",
|
||||||
"options": "Company:company:default_currency",
|
"label": "Amount",
|
||||||
"read_only": 1
|
"options": "Company:company:default_currency",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"default": "1",
|
{
|
||||||
"fieldname": "conversion_factor",
|
"default": "1",
|
||||||
"fieldtype": "Float",
|
"fieldname": "conversion_factor",
|
||||||
"hidden": 1,
|
"fieldtype": "Float",
|
||||||
"label": "Conversion Factor",
|
"hidden": 1,
|
||||||
"read_only": 1
|
"label": "Conversion Factor",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "current_stock",
|
{
|
||||||
"fieldtype": "Float",
|
"fieldname": "current_stock",
|
||||||
"in_list_view": 1,
|
"fieldtype": "Float",
|
||||||
"label": "Current Stock",
|
"in_list_view": 1,
|
||||||
"read_only": 1
|
"label": "Current Stock",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "reference_name",
|
{
|
||||||
"fieldtype": "Data",
|
"fieldname": "reference_name",
|
||||||
"hidden": 1,
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"hidden": 1,
|
||||||
"label": "Reference Name",
|
"in_list_view": 1,
|
||||||
"read_only": 1
|
"label": "Reference Name",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "bom_detail_no",
|
{
|
||||||
"fieldtype": "Data",
|
"fieldname": "bom_detail_no",
|
||||||
"hidden": 1,
|
"fieldtype": "Data",
|
||||||
"in_list_view": 1,
|
"hidden": 1,
|
||||||
"label": "BOM Detail No",
|
"in_list_view": 1,
|
||||||
"read_only": 1
|
"label": "BOM Detail No",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "secbreak_1",
|
{
|
||||||
"fieldtype": "Section Break"
|
"fieldname": "secbreak_1",
|
||||||
},
|
"fieldtype": "Section Break"
|
||||||
{
|
},
|
||||||
"fieldname": "col_break2",
|
{
|
||||||
"fieldtype": "Column Break"
|
"fieldname": "col_break2",
|
||||||
},
|
"fieldtype": "Column Break"
|
||||||
{
|
},
|
||||||
"fieldname": "secbreak_2",
|
{
|
||||||
"fieldtype": "Section Break"
|
"fieldname": "secbreak_2",
|
||||||
},
|
"fieldtype": "Section Break"
|
||||||
{
|
},
|
||||||
"fieldname": "col_break3",
|
{
|
||||||
"fieldtype": "Column Break"
|
"fieldname": "col_break3",
|
||||||
},
|
"fieldtype": "Column Break"
|
||||||
{
|
},
|
||||||
"fieldname": "secbreak_3",
|
{
|
||||||
"fieldtype": "Section Break"
|
"fieldname": "secbreak_3",
|
||||||
},
|
"fieldtype": "Section Break"
|
||||||
{
|
},
|
||||||
"fieldname": "col_break4",
|
{
|
||||||
"fieldtype": "Column Break"
|
"fieldname": "col_break4",
|
||||||
},
|
"fieldtype": "Column Break"
|
||||||
{
|
},
|
||||||
"fieldname": "item_name",
|
{
|
||||||
"fieldtype": "Data",
|
"fieldname": "item_name",
|
||||||
"label": "Item Name",
|
"fieldtype": "Data",
|
||||||
"read_only": 1
|
"label": "Item Name",
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"fieldname": "subcontracting_order",
|
{
|
||||||
"fieldtype": "Link",
|
"fieldname": "subcontracting_order",
|
||||||
"hidden": 1,
|
"fieldtype": "Link",
|
||||||
"label": "Subcontracting Order",
|
"hidden": 1,
|
||||||
"no_copy": 1,
|
"label": "Subcontracting Order",
|
||||||
"options": "Subcontracting Order",
|
"no_copy": 1,
|
||||||
"print_hide": 1,
|
"options": "Subcontracting Order",
|
||||||
"read_only": 1
|
"print_hide": 1,
|
||||||
},
|
"read_only": 1
|
||||||
{
|
},
|
||||||
"default": "0",
|
{
|
||||||
"fieldname": "available_qty_for_consumption",
|
"default": "0",
|
||||||
"fieldtype": "Float",
|
"fieldname": "available_qty_for_consumption",
|
||||||
"in_list_view": 1,
|
"fieldtype": "Float",
|
||||||
"label": "Available Qty For Consumption",
|
"in_list_view": 1,
|
||||||
"print_hide": 1,
|
"label": "Available Qty For Consumption",
|
||||||
"read_only": 1
|
"print_hide": 1,
|
||||||
}
|
"read_only": 1
|
||||||
],
|
}
|
||||||
"idx": 1,
|
],
|
||||||
"istable": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"istable": 1,
|
||||||
"modified": "2022-09-02 22:28:53.392381",
|
"links": [],
|
||||||
"modified_by": "Administrator",
|
"modified": "2022-11-07 17:17:21.670761",
|
||||||
"module": "Subcontracting",
|
"modified_by": "Administrator",
|
||||||
"name": "Subcontracting Receipt Supplied Item",
|
"module": "Subcontracting",
|
||||||
"naming_rule": "Autoincrement",
|
"name": "Subcontracting Receipt Supplied Item",
|
||||||
"owner": "Administrator",
|
"naming_rule": "Autoincrement",
|
||||||
"permissions": [],
|
"owner": "Administrator",
|
||||||
"sort_field": "modified",
|
"permissions": [],
|
||||||
"sort_order": "DESC",
|
"sort_field": "modified",
|
||||||
"states": [],
|
"sort_order": "DESC",
|
||||||
"track_changes": 1
|
"states": [],
|
||||||
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -35,7 +35,7 @@ class WarrantyClaim(TransactionBase):
|
|||||||
lst1 = ",".join(x[0] for x in lst)
|
lst1 = ",".join(x[0] for x in lst)
|
||||||
frappe.throw(_("Cancel Material Visit {0} before cancelling this Warranty Claim").format(lst1))
|
frappe.throw(_("Cancel Material Visit {0} before cancelling this Warranty Claim").format(lst1))
|
||||||
else:
|
else:
|
||||||
frappe.db.set(self, "status", "Cancelled")
|
self.db_set("status", "Cancelled")
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
pass
|
pass
|
||||||
|
|||||||
Reference in New Issue
Block a user