Merge branch 'develop' of github.com:frappe/erpnext into feature-pick-list
This commit is contained in:
commit
8de8a78235
@ -5,7 +5,7 @@ import frappe
|
|||||||
from erpnext.hooks import regional_overrides
|
from erpnext.hooks import regional_overrides
|
||||||
from frappe.utils import getdate
|
from frappe.utils import getdate
|
||||||
|
|
||||||
__version__ = '12.0.7'
|
__version__ = '12.0.8'
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
'''Get default company for user'''
|
'''Get default company for user'''
|
||||||
|
@ -128,6 +128,7 @@ class Account(NestedSet):
|
|||||||
"account_currency": self.account_currency,
|
"account_currency": self.account_currency,
|
||||||
"parent_account": parent_acc_name_map[company]
|
"parent_account": parent_acc_name_map[company]
|
||||||
})
|
})
|
||||||
|
if not self.check_if_child_acc_exists(doc):
|
||||||
doc.save()
|
doc.save()
|
||||||
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
frappe.msgprint(_("Account {0} is added in the child company {1}")
|
||||||
.format(doc.name, company))
|
.format(doc.name, company))
|
||||||
@ -172,6 +173,24 @@ class Account(NestedSet):
|
|||||||
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
if frappe.db.get_value("GL Entry", {"account": self.name}):
|
||||||
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
|
||||||
|
|
||||||
|
def check_if_child_acc_exists(self, doc):
|
||||||
|
''' Checks if a account in parent company exists in the '''
|
||||||
|
info = frappe.db.get_value("Account", {
|
||||||
|
"account_name": doc.account_name,
|
||||||
|
"account_number": doc.account_number
|
||||||
|
}, ['company', 'account_currency', 'is_group', 'root_type', 'account_type', 'balance_must_be', 'account_name'], as_dict=1)
|
||||||
|
|
||||||
|
if not info:
|
||||||
|
return
|
||||||
|
|
||||||
|
doc = vars(doc)
|
||||||
|
dict_diff = [k for k in info if k in doc and info[k] != doc[k] and k != "company"]
|
||||||
|
if dict_diff:
|
||||||
|
frappe.throw(_("Account {0} already exists in child company {1}. The following fields have different values, they should be same:<ul><li>{2}</li></ul>")
|
||||||
|
.format(info.account_name, info.company, '</li><li>'.join(dict_diff)))
|
||||||
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
def convert_group_to_ledger(self):
|
def convert_group_to_ledger(self):
|
||||||
if self.check_if_child_exists():
|
if self.check_if_child_exists():
|
||||||
throw(_("Account with child nodes cannot be converted to ledger"))
|
throw(_("Account with child nodes cannot be converted to ledger"))
|
||||||
|
@ -50,7 +50,7 @@ class BankTransaction(StatusUpdater):
|
|||||||
if paid_amount and allocated_amount:
|
if paid_amount and allocated_amount:
|
||||||
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
|
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
|
||||||
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
|
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).".format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount))))
|
||||||
elif flt(allocated_amount[0]["allocated_amount"]) == flt(paid_amount):
|
else:
|
||||||
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
|
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
|
||||||
self.clear_simple_entry(payment_entry)
|
self.clear_simple_entry(payment_entry)
|
||||||
|
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
"customer",
|
"customer",
|
||||||
"column_break_3",
|
"column_break_3",
|
||||||
"posting_date",
|
"posting_date",
|
||||||
"outstanding_amount"
|
"outstanding_amount",
|
||||||
|
"debit_to"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@ -48,10 +49,18 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fetch_from": "sales_invoice.debit_to",
|
||||||
|
"fieldname": "debit_to",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Debit to",
|
||||||
|
"options": "Account",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2019-05-30 19:27:29.436153",
|
"modified": "2019-08-07 15:13:55.808349",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Discounted Invoice",
|
"name": "Discounted Invoice",
|
||||||
|
@ -13,25 +13,41 @@ frappe.ui.form.on('Invoice Discounting', {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
frm.events.filter_accounts("bank_account", frm, {"account_type": "Bank"});
|
|
||||||
frm.events.filter_accounts("bank_charges_account", frm, {"root_type": "Expense"});
|
frm.events.filter_accounts("bank_account", frm, [["account_type", "=", "Bank"]]);
|
||||||
frm.events.filter_accounts("short_term_loan", frm, {"root_type": "Liability"});
|
frm.events.filter_accounts("bank_charges_account", frm, [["root_type", "=", "Expense"]]);
|
||||||
frm.events.filter_accounts("accounts_receivable_credit", frm, {"account_type": "Receivable"});
|
frm.events.filter_accounts("short_term_loan", frm, [["root_type", "=", "Liability"]]);
|
||||||
frm.events.filter_accounts("accounts_receivable_discounted", frm, {"account_type": "Receivable"});
|
frm.events.filter_accounts("accounts_receivable_discounted", frm, [["account_type", "=", "Receivable"]]);
|
||||||
frm.events.filter_accounts("accounts_receivable_unpaid", frm, {"account_type": "Receivable"});
|
frm.events.filter_accounts("accounts_receivable_credit", frm, [["account_type", "=", "Receivable"]]);
|
||||||
|
frm.events.filter_accounts("accounts_receivable_unpaid", frm, [["account_type", "=", "Receivable"]]);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
filter_accounts: (fieldname, frm, addl_filters) => {
|
filter_accounts: (fieldname, frm, addl_filters) => {
|
||||||
let filters = {
|
let filters = [
|
||||||
"company": frm.doc.company,
|
["company", "=", frm.doc.company],
|
||||||
"is_group": 0
|
["is_group", "=", 0]
|
||||||
};
|
];
|
||||||
if(addl_filters) Object.assign(filters, addl_filters);
|
if(addl_filters){
|
||||||
|
filters = $.merge(filters , addl_filters);
|
||||||
|
}
|
||||||
|
|
||||||
frm.set_query(fieldname, () => { return { "filters": filters }; });
|
frm.set_query(fieldname, () => { return { "filters": filters }; });
|
||||||
},
|
},
|
||||||
|
|
||||||
|
refresh_filters: (frm) =>{
|
||||||
|
let invoice_accounts = Object.keys(frm.doc.invoices).map(function(key) {
|
||||||
|
return frm.doc.invoices[key].debit_to;
|
||||||
|
});
|
||||||
|
let filters = [
|
||||||
|
["account_type", "=", "Receivable"],
|
||||||
|
["name", "not in", invoice_accounts]
|
||||||
|
];
|
||||||
|
frm.events.filter_accounts("accounts_receivable_credit", frm, filters);
|
||||||
|
frm.events.filter_accounts("accounts_receivable_discounted", frm, filters);
|
||||||
|
frm.events.filter_accounts("accounts_receivable_unpaid", frm, filters);
|
||||||
|
},
|
||||||
|
|
||||||
refresh: (frm) => {
|
refresh: (frm) => {
|
||||||
frm.events.show_general_ledger(frm);
|
frm.events.show_general_ledger(frm);
|
||||||
|
|
||||||
@ -132,6 +148,7 @@ frappe.ui.form.on('Invoice Discounting', {
|
|||||||
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
|
frm.doc.invoices = frm.doc.invoices.filter(row => row.sales_invoice);
|
||||||
let row = frm.add_child("invoices");
|
let row = frm.add_child("invoices");
|
||||||
$.extend(row, v);
|
$.extend(row, v);
|
||||||
|
frm.events.refresh_filters(frm);
|
||||||
});
|
});
|
||||||
refresh_field("invoices");
|
refresh_field("invoices");
|
||||||
}
|
}
|
||||||
@ -190,8 +207,10 @@ frappe.ui.form.on('Invoice Discounting', {
|
|||||||
frappe.ui.form.on('Discounted Invoice', {
|
frappe.ui.form.on('Discounted Invoice', {
|
||||||
sales_invoice: (frm) => {
|
sales_invoice: (frm) => {
|
||||||
frm.events.calculate_total_amount(frm);
|
frm.events.calculate_total_amount(frm);
|
||||||
|
frm.events.refresh_filters(frm);
|
||||||
},
|
},
|
||||||
invoices_remove: (frm) => {
|
invoices_remove: (frm) => {
|
||||||
frm.events.calculate_total_amount(frm);
|
frm.events.calculate_total_amount(frm);
|
||||||
|
frm.events.refresh_filters(frm);
|
||||||
}
|
}
|
||||||
});
|
});
|
@ -12,6 +12,7 @@ from erpnext.accounts.general_ledger import make_gl_entries
|
|||||||
class InvoiceDiscounting(AccountsController):
|
class InvoiceDiscounting(AccountsController):
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_mandatory()
|
self.validate_mandatory()
|
||||||
|
self.validate_invoices()
|
||||||
self.calculate_total_amount()
|
self.calculate_total_amount()
|
||||||
self.set_status()
|
self.set_status()
|
||||||
self.set_end_date()
|
self.set_end_date()
|
||||||
@ -24,6 +25,15 @@ class InvoiceDiscounting(AccountsController):
|
|||||||
if self.docstatus == 1 and not (self.loan_start_date and self.loan_period):
|
if self.docstatus == 1 and not (self.loan_start_date and self.loan_period):
|
||||||
frappe.throw(_("Loan Start Date and Loan Period are mandatory to save the Invoice Discounting"))
|
frappe.throw(_("Loan Start Date and Loan Period are mandatory to save the Invoice Discounting"))
|
||||||
|
|
||||||
|
def validate_invoices(self):
|
||||||
|
discounted_invoices = [record.sales_invoice for record in
|
||||||
|
frappe.get_all("Discounted Invoice",fields = ["sales_invoice"], filters= {"docstatus":1})]
|
||||||
|
|
||||||
|
for record in self.invoices:
|
||||||
|
if record.sales_invoice in discounted_invoices:
|
||||||
|
frappe.throw("Row({0}): {1} is already discounted in {2}"
|
||||||
|
.format(record.idx, frappe.bold(record.sales_invoice), frappe.bold(record.parent)))
|
||||||
|
|
||||||
def calculate_total_amount(self):
|
def calculate_total_amount(self):
|
||||||
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
|
self.total_amount = sum([flt(d.outstanding_amount) for d in self.invoices])
|
||||||
|
|
||||||
@ -212,7 +222,8 @@ def get_invoices(filters):
|
|||||||
name as sales_invoice,
|
name as sales_invoice,
|
||||||
customer,
|
customer,
|
||||||
posting_date,
|
posting_date,
|
||||||
outstanding_amount
|
outstanding_amount,
|
||||||
|
debit_to
|
||||||
from `tabSales Invoice` si
|
from `tabSales Invoice` si
|
||||||
where
|
where
|
||||||
docstatus = 1
|
docstatus = 1
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
frappe.ui.form.on('Payment Order', {
|
|
||||||
refresh: function(frm) {
|
|
||||||
if (frm.doc.docstatus==1 && frm.doc.payment_order_type==='Payment Entry') {
|
|
||||||
frm.add_custom_button(__('Generate Text File'), function() {
|
|
||||||
frm.trigger("generate_text_and_download_file");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
generate_text_and_download_file: (frm) => {
|
|
||||||
return frappe.call({
|
|
||||||
method: "erpnext.regional.india.bank_remittance.generate_report",
|
|
||||||
args: {
|
|
||||||
name: frm.doc.name
|
|
||||||
},
|
|
||||||
freeze: true,
|
|
||||||
callback: function(r) {
|
|
||||||
{
|
|
||||||
frm.reload_doc();
|
|
||||||
const a = document.createElement('a');
|
|
||||||
let file_obj = r.message;
|
|
||||||
a.href = file_obj.file_url;
|
|
||||||
a.target = '_blank';
|
|
||||||
a.download = file_obj.file_name;
|
|
||||||
a.click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
@ -257,11 +257,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
|||||||
voucher_type = ('Credit Note'
|
voucher_type = ('Credit Note'
|
||||||
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
|
if d.voucher_type == 'Sales Invoice' else 'Debit Note')
|
||||||
|
|
||||||
dr_or_cr = ('credit_in_account_currency'
|
|
||||||
if d.reference_type == 'Sales Invoice' else 'debit_in_account_currency')
|
|
||||||
|
|
||||||
reconcile_dr_or_cr = ('debit_in_account_currency'
|
reconcile_dr_or_cr = ('debit_in_account_currency'
|
||||||
if dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
|
if d.dr_or_cr == 'credit_in_account_currency' else 'credit_in_account_currency')
|
||||||
|
|
||||||
jv = frappe.get_doc({
|
jv = frappe.get_doc({
|
||||||
"doctype": "Journal Entry",
|
"doctype": "Journal Entry",
|
||||||
@ -272,8 +269,7 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
|||||||
'account': d.account,
|
'account': d.account,
|
||||||
'party': d.party,
|
'party': d.party,
|
||||||
'party_type': d.party_type,
|
'party_type': d.party_type,
|
||||||
reconcile_dr_or_cr: (abs(d.allocated_amount)
|
d.dr_or_cr: abs(d.allocated_amount),
|
||||||
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
|
|
||||||
'reference_type': d.against_voucher_type,
|
'reference_type': d.against_voucher_type,
|
||||||
'reference_name': d.against_voucher
|
'reference_name': d.against_voucher
|
||||||
},
|
},
|
||||||
@ -281,7 +277,8 @@ def reconcile_dr_cr_note(dr_cr_notes):
|
|||||||
'account': d.account,
|
'account': d.account,
|
||||||
'party': d.party,
|
'party': d.party,
|
||||||
'party_type': d.party_type,
|
'party_type': d.party_type,
|
||||||
dr_or_cr: abs(d.allocated_amount),
|
reconcile_dr_or_cr: (abs(d.allocated_amount)
|
||||||
|
if abs(d.unadjusted_amount) > abs(d.allocated_amount) else abs(d.unadjusted_amount)),
|
||||||
'reference_type': d.voucher_type,
|
'reference_type': d.voucher_type,
|
||||||
'reference_name': d.voucher_no
|
'reference_name': d.voucher_no
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ def get_item_tax_data():
|
|||||||
# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
|
# example: {'Consulting Services': {'Excise 12 - TS': '12.000'}}
|
||||||
|
|
||||||
itemwise_tax = {}
|
itemwise_tax = {}
|
||||||
taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax`""", as_dict=1)
|
taxes = frappe.db.sql(""" select parent, tax_type, tax_rate from `tabItem Tax Template Detail`""", as_dict=1)
|
||||||
|
|
||||||
for tax in taxes:
|
for tax in taxes:
|
||||||
if tax.parent not in itemwise_tax:
|
if tax.parent not in itemwise_tax:
|
||||||
@ -432,7 +432,6 @@ def get_customer_id(doc, customer=None):
|
|||||||
|
|
||||||
return cust_id
|
return cust_id
|
||||||
|
|
||||||
|
|
||||||
def make_customer_and_address(customers):
|
def make_customer_and_address(customers):
|
||||||
customers_list = []
|
customers_list = []
|
||||||
for customer, data in iteritems(customers):
|
for customer, data in iteritems(customers):
|
||||||
@ -449,7 +448,6 @@ def make_customer_and_address(customers):
|
|||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
return customers_list
|
return customers_list
|
||||||
|
|
||||||
|
|
||||||
def add_customer(data):
|
def add_customer(data):
|
||||||
customer = data.get('full_name') or data.get('customer')
|
customer = data.get('full_name') or data.get('customer')
|
||||||
if frappe.db.exists("Customer", customer.strip()):
|
if frappe.db.exists("Customer", customer.strip()):
|
||||||
@ -466,21 +464,18 @@ def add_customer(data):
|
|||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
return customer_doc.name
|
return customer_doc.name
|
||||||
|
|
||||||
|
|
||||||
def get_territory(data):
|
def get_territory(data):
|
||||||
if data.get('territory'):
|
if data.get('territory'):
|
||||||
return data.get('territory')
|
return data.get('territory')
|
||||||
|
|
||||||
return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
|
return frappe.db.get_single_value('Selling Settings','territory') or _('All Territories')
|
||||||
|
|
||||||
|
|
||||||
def get_customer_group(data):
|
def get_customer_group(data):
|
||||||
if data.get('customer_group'):
|
if data.get('customer_group'):
|
||||||
return data.get('customer_group')
|
return data.get('customer_group')
|
||||||
|
|
||||||
return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
|
return frappe.db.get_single_value('Selling Settings', 'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
|
||||||
|
|
||||||
|
|
||||||
def make_contact(args, customer):
|
def make_contact(args, customer):
|
||||||
if args.get('email_id') or args.get('phone'):
|
if args.get('email_id') or args.get('phone'):
|
||||||
name = frappe.db.get_value('Dynamic Link',
|
name = frappe.db.get_value('Dynamic Link',
|
||||||
@ -506,7 +501,6 @@ def make_contact(args, customer):
|
|||||||
doc.flags.ignore_mandatory = True
|
doc.flags.ignore_mandatory = True
|
||||||
doc.save(ignore_permissions=True)
|
doc.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
def make_address(args, customer):
|
def make_address(args, customer):
|
||||||
if not args.get('address_line1'):
|
if not args.get('address_line1'):
|
||||||
return
|
return
|
||||||
@ -521,7 +515,10 @@ def make_address(args, customer):
|
|||||||
address = frappe.get_doc('Address', name)
|
address = frappe.get_doc('Address', name)
|
||||||
else:
|
else:
|
||||||
address = frappe.new_doc('Address')
|
address = frappe.new_doc('Address')
|
||||||
address.country = frappe.get_cached_value('Company', args.get('company'), 'country')
|
if args.get('company'):
|
||||||
|
address.country = frappe.get_cached_value('Company',
|
||||||
|
args.get('company'), 'country')
|
||||||
|
|
||||||
address.append('links', {
|
address.append('links', {
|
||||||
'link_doctype': 'Customer',
|
'link_doctype': 'Customer',
|
||||||
'link_name': customer
|
'link_name': customer
|
||||||
@ -533,7 +530,6 @@ def make_address(args, customer):
|
|||||||
address.flags.ignore_mandatory = True
|
address.flags.ignore_mandatory = True
|
||||||
address.save(ignore_permissions=True)
|
address.save(ignore_permissions=True)
|
||||||
|
|
||||||
|
|
||||||
def make_email_queue(email_queue):
|
def make_email_queue(email_queue):
|
||||||
name_list = []
|
name_list = []
|
||||||
for key, data in iteritems(email_queue):
|
for key, data in iteritems(email_queue):
|
||||||
@ -550,7 +546,6 @@ def make_email_queue(email_queue):
|
|||||||
|
|
||||||
return name_list
|
return name_list
|
||||||
|
|
||||||
|
|
||||||
def validate_item(doc):
|
def validate_item(doc):
|
||||||
for item in doc.get('items'):
|
for item in doc.get('items'):
|
||||||
if not frappe.db.exists('Item', item.get('item_code')):
|
if not frappe.db.exists('Item', item.get('item_code')):
|
||||||
@ -569,7 +564,6 @@ def validate_item(doc):
|
|||||||
item_doc.save(ignore_permissions=True)
|
item_doc.save(ignore_permissions=True)
|
||||||
frappe.db.commit()
|
frappe.db.commit()
|
||||||
|
|
||||||
|
|
||||||
def submit_invoice(si_doc, name, doc, name_list):
|
def submit_invoice(si_doc, name, doc, name_list):
|
||||||
try:
|
try:
|
||||||
si_doc.insert()
|
si_doc.insert()
|
||||||
@ -585,7 +579,6 @@ def submit_invoice(si_doc, name, doc, name_list):
|
|||||||
|
|
||||||
return name_list
|
return name_list
|
||||||
|
|
||||||
|
|
||||||
def save_invoice(doc, name, name_list):
|
def save_invoice(doc, name, name_list):
|
||||||
try:
|
try:
|
||||||
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
if not frappe.db.exists('Sales Invoice', {'offline_pos_name': name}):
|
||||||
|
@ -206,9 +206,9 @@ class SalesInvoice(SellingController):
|
|||||||
total_amount_in_payments = 0
|
total_amount_in_payments = 0
|
||||||
for payment in self.payments:
|
for payment in self.payments:
|
||||||
total_amount_in_payments += payment.amount
|
total_amount_in_payments += payment.amount
|
||||||
|
invoice_total = self.rounded_total or self.grand_total
|
||||||
if total_amount_in_payments < self.rounded_total:
|
if total_amount_in_payments < invoice_total:
|
||||||
frappe.throw(_("Total payments amount can't be greater than {}".format(-self.rounded_total)))
|
frappe.throw(_("Total payments amount can't be greater than {}".format(-invoice_total)))
|
||||||
|
|
||||||
def validate_pos_paid_amount(self):
|
def validate_pos_paid_amount(self):
|
||||||
if len(self.payments) == 0 and self.is_pos:
|
if len(self.payments) == 0 and self.is_pos:
|
||||||
|
@ -1762,18 +1762,11 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
|||||||
this.si_docs = this.get_submitted_invoice() || [];
|
this.si_docs = this.get_submitted_invoice() || [];
|
||||||
this.email_queue_list = this.get_email_queue() || {};
|
this.email_queue_list = this.get_email_queue() || {};
|
||||||
this.customers_list = this.get_customers_details() || {};
|
this.customers_list = this.get_customers_details() || {};
|
||||||
if(this.customer_doc) {
|
|
||||||
this.freeze = this.customer_doc.display
|
|
||||||
}
|
|
||||||
|
|
||||||
freeze_screen = this.freeze_screen || false;
|
|
||||||
|
|
||||||
if ((this.si_docs.length || this.email_queue_list || this.customers_list) && !this.freeze) {
|
|
||||||
this.freeze = true;
|
|
||||||
|
|
||||||
|
if (this.si_docs.length || this.email_queue_list || this.customers_list) {
|
||||||
frappe.call({
|
frappe.call({
|
||||||
method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
|
method: "erpnext.accounts.doctype.sales_invoice.pos.make_invoice",
|
||||||
freeze: freeze_screen,
|
freeze: true,
|
||||||
args: {
|
args: {
|
||||||
doc_list: me.si_docs,
|
doc_list: me.si_docs,
|
||||||
email_queue_list: me.email_queue_list,
|
email_queue_list: me.email_queue_list,
|
||||||
|
@ -197,8 +197,10 @@ class ReceivablePayableReport(object):
|
|||||||
if self.filters.based_on_payment_terms and gl_entries_data:
|
if self.filters.based_on_payment_terms and gl_entries_data:
|
||||||
self.payment_term_map = self.get_payment_term_detail(voucher_nos)
|
self.payment_term_map = self.get_payment_term_detail(voucher_nos)
|
||||||
|
|
||||||
|
self.gle_inclusion_map = {}
|
||||||
for gle in gl_entries_data:
|
for gle in gl_entries_data:
|
||||||
if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers, return_entries):
|
if self.is_receivable_or_payable(gle, self.dr_or_cr, future_vouchers, return_entries):
|
||||||
|
self.gle_inclusion_map[gle.name] = True
|
||||||
outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
|
outstanding_amount, credit_note_amount, payment_amount = self.get_outstanding_amount(
|
||||||
gle,self.filters.report_date, self.dr_or_cr, return_entries)
|
gle,self.filters.report_date, self.dr_or_cr, return_entries)
|
||||||
temp_outstanding_amt = outstanding_amount
|
temp_outstanding_amt = outstanding_amount
|
||||||
@ -409,7 +411,9 @@ class ReceivablePayableReport(object):
|
|||||||
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
for e in self.get_gl_entries_for(gle.party, gle.party_type, gle.voucher_type, gle.voucher_no):
|
||||||
if getdate(e.posting_date) <= report_date \
|
if getdate(e.posting_date) <= report_date \
|
||||||
and (e.name!=gle.name or (e.voucher_no in return_entries and not return_entries.get(e.voucher_no))):
|
and (e.name!=gle.name or (e.voucher_no in return_entries and not return_entries.get(e.voucher_no))):
|
||||||
|
if e.name!=gle.name and self.gle_inclusion_map.get(e.name):
|
||||||
|
continue
|
||||||
|
self.gle_inclusion_map[e.name] = True
|
||||||
amount = flt(e.get(reverse_dr_or_cr), self.currency_precision) - flt(e.get(dr_or_cr), self.currency_precision)
|
amount = flt(e.get(reverse_dr_or_cr), self.currency_precision) - flt(e.get(dr_or_cr), self.currency_precision)
|
||||||
if e.voucher_no not in return_entries:
|
if e.voucher_no not in return_entries:
|
||||||
payment_amount += amount
|
payment_amount += amount
|
||||||
|
@ -135,11 +135,11 @@ def get_chart_data(filters, columns, asset, liability, equity):
|
|||||||
|
|
||||||
datasets = []
|
datasets = []
|
||||||
if asset_data:
|
if asset_data:
|
||||||
datasets.append({'name':'Assets', 'values': asset_data})
|
datasets.append({'name': _('Assets'), 'values': asset_data})
|
||||||
if liability_data:
|
if liability_data:
|
||||||
datasets.append({'name':'Liabilities', 'values': liability_data})
|
datasets.append({'name': _('Liabilities'), 'values': liability_data})
|
||||||
if equity_data:
|
if equity_data:
|
||||||
datasets.append({'name':'Equity', 'values': equity_data})
|
datasets.append({'name': _('Equity'), 'values': equity_data})
|
||||||
|
|
||||||
chart = {
|
chart = {
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -27,8 +27,8 @@ frappe.query_reports["Payment Period Based On Invoice Date"] = {
|
|||||||
fieldname:"payment_type",
|
fieldname:"payment_type",
|
||||||
label: __("Payment Type"),
|
label: __("Payment Type"),
|
||||||
fieldtype: "Select",
|
fieldtype: "Select",
|
||||||
options: "Incoming\nOutgoing",
|
options: __("Incoming") + "\n" + __("Outgoing"),
|
||||||
default: "Incoming"
|
default: __("Incoming")
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname":"party_type",
|
"fieldname":"party_type",
|
||||||
|
@ -39,8 +39,8 @@ def execute(filters=None):
|
|||||||
return columns, data
|
return columns, data
|
||||||
|
|
||||||
def validate_filters(filters):
|
def validate_filters(filters):
|
||||||
if (filters.get("payment_type") == "Incoming" and filters.get("party_type") == "Supplier") or \
|
if (filters.get("payment_type") == _("Incoming") and filters.get("party_type") == "Supplier") or \
|
||||||
(filters.get("payment_type") == "Outgoing" and filters.get("party_type") == "Customer"):
|
(filters.get("payment_type") == _("Outgoing") and filters.get("party_type") == "Customer"):
|
||||||
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
|
frappe.throw(_("{0} payment entries can not be filtered by {1}")\
|
||||||
.format(filters.payment_type, filters.party_type))
|
.format(filters.payment_type, filters.party_type))
|
||||||
|
|
||||||
@ -51,7 +51,7 @@ def get_columns(filters):
|
|||||||
_("Party Type") + "::100",
|
_("Party Type") + "::100",
|
||||||
_("Party") + ":Dynamic Link/Party Type:140",
|
_("Party") + ":Dynamic Link/Party Type:140",
|
||||||
_("Posting Date") + ":Date:100",
|
_("Posting Date") + ":Date:100",
|
||||||
_("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == "Outgoing" else ":Link/Sales Invoice:130"),
|
_("Invoice") + (":Link/Purchase Invoice:130" if filters.get("payment_type") == _("Outgoing") else ":Link/Sales Invoice:130"),
|
||||||
_("Invoice Posting Date") + ":Date:130",
|
_("Invoice Posting Date") + ":Date:130",
|
||||||
_("Payment Due Date") + ":Date:130",
|
_("Payment Due Date") + ":Date:130",
|
||||||
_("Debit") + ":Currency:120",
|
_("Debit") + ":Currency:120",
|
||||||
@ -69,7 +69,7 @@ def get_conditions(filters):
|
|||||||
conditions = []
|
conditions = []
|
||||||
|
|
||||||
if not filters.party_type:
|
if not filters.party_type:
|
||||||
if filters.payment_type == "Outgoing":
|
if filters.payment_type == _("Outgoing"):
|
||||||
filters.party_type = "Supplier"
|
filters.party_type = "Supplier"
|
||||||
else:
|
else:
|
||||||
filters.party_type = "Customer"
|
filters.party_type = "Customer"
|
||||||
@ -101,7 +101,7 @@ def get_entries(filters):
|
|||||||
|
|
||||||
def get_invoice_posting_date_map(filters):
|
def get_invoice_posting_date_map(filters):
|
||||||
invoice_details = {}
|
invoice_details = {}
|
||||||
dt = "Sales Invoice" if filters.get("payment_type") == "Incoming" else "Purchase Invoice"
|
dt = "Sales Invoice" if filters.get("payment_type") == _("Incoming") else "Purchase Invoice"
|
||||||
for t in frappe.db.sql("select name, posting_date, due_date from `tab{0}`".format(dt), as_dict=1):
|
for t in frappe.db.sql("select name, posting_date, due_date from `tab{0}`".format(dt), as_dict=1):
|
||||||
invoice_details[t.name] = t
|
invoice_details[t.name] = t
|
||||||
|
|
||||||
|
@ -75,11 +75,11 @@ def get_chart_data(filters, columns, income, expense, net_profit_loss):
|
|||||||
|
|
||||||
datasets = []
|
datasets = []
|
||||||
if income_data:
|
if income_data:
|
||||||
datasets.append({'name': 'Income', 'values': income_data})
|
datasets.append({'name': _('Income'), 'values': income_data})
|
||||||
if expense_data:
|
if expense_data:
|
||||||
datasets.append({'name': 'Expense', 'values': expense_data})
|
datasets.append({'name': _('Expense'), 'values': expense_data})
|
||||||
if net_profit:
|
if net_profit:
|
||||||
datasets.append({'name': 'Net Profit/Loss', 'values': net_profit})
|
datasets.append({'name': _('Net Profit/Loss'), 'values': net_profit})
|
||||||
|
|
||||||
chart = {
|
chart = {
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -255,9 +255,15 @@ class Asset(AccountsController):
|
|||||||
precision = self.precision("gross_purchase_amount")
|
precision = self.precision("gross_purchase_amount")
|
||||||
|
|
||||||
if row.depreciation_method in ("Straight Line", "Manual"):
|
if row.depreciation_method in ("Straight Line", "Manual"):
|
||||||
|
depreciation_left = (cint(row.total_number_of_depreciations) - cint(self.number_of_depreciations_booked))
|
||||||
|
|
||||||
|
if not depreciation_left:
|
||||||
|
frappe.msgprint(_("All the depreciations has been booked"))
|
||||||
|
depreciation_amount = flt(row.expected_value_after_useful_life)
|
||||||
|
return depreciation_amount
|
||||||
|
|
||||||
depreciation_amount = (flt(row.value_after_depreciation) -
|
depreciation_amount = (flt(row.value_after_depreciation) -
|
||||||
flt(row.expected_value_after_useful_life)) / (cint(row.total_number_of_depreciations) -
|
flt(row.expected_value_after_useful_life)) / depreciation_left
|
||||||
cint(self.number_of_depreciations_booked))
|
|
||||||
else:
|
else:
|
||||||
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision)
|
depreciation_amount = flt(depreciable_value * (flt(row.rate_of_depreciation) / 100), precision)
|
||||||
|
|
||||||
|
@ -6,15 +6,13 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup
|
from erpnext.crm.doctype.utils import get_scheduled_employees_for_popup, strip_number
|
||||||
from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number
|
from frappe.contacts.doctype.contact.contact import get_contact_with_phone_number
|
||||||
from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number
|
from erpnext.crm.doctype.lead.lead import get_lead_with_phone_number
|
||||||
|
|
||||||
class CallLog(Document):
|
class CallLog(Document):
|
||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
# strip 0 from the start of the number for proper number comparisions
|
number = strip_number(self.get('from'))
|
||||||
# eg. 07888383332 should match with 7888383332
|
|
||||||
number = self.get('from').lstrip('0')
|
|
||||||
self.contact = get_contact_with_phone_number(number)
|
self.contact = get_contact_with_phone_number(number)
|
||||||
self.lead = get_lead_with_phone_number(number)
|
self.lead = get_lead_with_phone_number(number)
|
||||||
|
|
||||||
@ -48,13 +46,14 @@ def add_call_summary(call_log, summary):
|
|||||||
doc.add_comment('Comment', frappe.bold(_('Call Summary')) + '<br><br>' + summary)
|
doc.add_comment('Comment', frappe.bold(_('Call Summary')) + '<br><br>' + summary)
|
||||||
|
|
||||||
def get_employees_with_number(number):
|
def get_employees_with_number(number):
|
||||||
|
number = strip_number(number)
|
||||||
if not number: return []
|
if not number: return []
|
||||||
|
|
||||||
employee_emails = frappe.cache().hget('employees_with_number', number)
|
employee_emails = frappe.cache().hget('employees_with_number', number)
|
||||||
if employee_emails: return employee_emails
|
if employee_emails: return employee_emails
|
||||||
|
|
||||||
employees = frappe.get_all('Employee', filters={
|
employees = frappe.get_all('Employee', filters={
|
||||||
'cell_number': ['like', '%{}'.format(number.lstrip('0'))],
|
'cell_number': ['like', '%{}%'.format(number)],
|
||||||
'user_id': ['!=', '']
|
'user_id': ['!=', '']
|
||||||
}, fields=['user_id'])
|
}, fields=['user_id'])
|
||||||
|
|
||||||
@ -64,23 +63,29 @@ def get_employees_with_number(number):
|
|||||||
return employee
|
return employee
|
||||||
|
|
||||||
def set_caller_information(doc, state):
|
def set_caller_information(doc, state):
|
||||||
'''Called from hoooks on creation of Lead or Contact'''
|
'''Called from hooks on creation of Lead or Contact'''
|
||||||
if doc.doctype not in ['Lead', 'Contact']: return
|
if doc.doctype not in ['Lead', 'Contact']: return
|
||||||
|
|
||||||
numbers = [doc.get('phone'), doc.get('mobile_no')]
|
numbers = [doc.get('phone'), doc.get('mobile_no')]
|
||||||
for_doc = doc.doctype.lower()
|
# contact for Contact and lead for Lead
|
||||||
|
fieldname = doc.doctype.lower()
|
||||||
|
|
||||||
|
# contact_name or lead_name
|
||||||
|
display_name_field = '{}_name'.format(fieldname)
|
||||||
|
|
||||||
for number in numbers:
|
for number in numbers:
|
||||||
|
number = strip_number(number)
|
||||||
if not number: continue
|
if not number: continue
|
||||||
print(number)
|
|
||||||
filters = frappe._dict({
|
filters = frappe._dict({
|
||||||
'from': ['like', '%{}'.format(number.lstrip('0'))],
|
'from': ['like', '%{}'.format(number)],
|
||||||
for_doc: ''
|
fieldname: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
logs = frappe.get_all('Call Log', filters=filters)
|
logs = frappe.get_all('Call Log', filters=filters)
|
||||||
|
|
||||||
for log in logs:
|
for log in logs:
|
||||||
call_log = frappe.get_doc('Call Log', log.name)
|
frappe.db.set_value('Call Log', log.name, {
|
||||||
call_log.set(for_doc, doc.name)
|
fieldname: doc.name,
|
||||||
call_log.save(ignore_permissions=True)
|
display_name_field: doc.get_title()
|
||||||
|
}, update_modified=False)
|
||||||
|
@ -41,6 +41,11 @@ def get_data():
|
|||||||
"name": "Lead Source",
|
"name": "Lead Source",
|
||||||
"description": _("Track Leads by Lead Source.")
|
"description": _("Track Leads by Lead Source.")
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"type": "doctype",
|
||||||
|
"name": "Contract",
|
||||||
|
"description": _("Helps you keep tracks of Contracts based on Supplier, Customer and Employee"),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -371,7 +371,7 @@ def get_expense_account(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
|
|
||||||
return frappe.db.sql("""select tabAccount.name from `tabAccount`
|
return frappe.db.sql("""select tabAccount.name from `tabAccount`
|
||||||
where (tabAccount.report_type = "Profit and Loss"
|
where (tabAccount.report_type = "Profit and Loss"
|
||||||
or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed"))
|
or tabAccount.account_type in ("Expense Account", "Fixed Asset", "Temporary", "Asset Received But Not Billed", "Capital Work in Progress"))
|
||||||
and tabAccount.is_group=0
|
and tabAccount.is_group=0
|
||||||
and tabAccount.docstatus!=2
|
and tabAccount.docstatus!=2
|
||||||
and tabAccount.{key} LIKE %(txt)s
|
and tabAccount.{key} LIKE %(txt)s
|
||||||
|
@ -45,6 +45,7 @@ class SellingController(StockController):
|
|||||||
self.set_gross_profit()
|
self.set_gross_profit()
|
||||||
set_default_income_account_for_item(self)
|
set_default_income_account_for_item(self)
|
||||||
self.set_customer_address()
|
self.set_customer_address()
|
||||||
|
self.validate_for_duplicate_items()
|
||||||
|
|
||||||
def set_missing_values(self, for_validate=False):
|
def set_missing_values(self, for_validate=False):
|
||||||
|
|
||||||
@ -381,6 +382,34 @@ class SellingController(StockController):
|
|||||||
if self.get(address_field):
|
if self.get(address_field):
|
||||||
self.set(address_display_field, get_address_display(self.get(address_field)))
|
self.set(address_display_field, get_address_display(self.get(address_field)))
|
||||||
|
|
||||||
|
def validate_for_duplicate_items(self):
|
||||||
|
check_list, chk_dupl_itm = [], []
|
||||||
|
if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
|
||||||
|
return
|
||||||
|
|
||||||
|
for d in self.get('items'):
|
||||||
|
if self.doctype == "Sales Invoice":
|
||||||
|
e = [d.item_code, d.description, d.warehouse, d.sales_order or d.delivery_note, d.batch_no or '']
|
||||||
|
f = [d.item_code, d.description, d.sales_order or d.delivery_note]
|
||||||
|
elif self.doctype == "Delivery Note":
|
||||||
|
e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
|
||||||
|
f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
|
||||||
|
elif self.doctype == "Sales Order":
|
||||||
|
e = [d.item_code, d.description, d.warehouse, d.batch_no or '']
|
||||||
|
f = [d.item_code, d.description]
|
||||||
|
|
||||||
|
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
|
||||||
|
if e in check_list:
|
||||||
|
frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
|
||||||
|
else:
|
||||||
|
check_list.append(e)
|
||||||
|
else:
|
||||||
|
if f in chk_dupl_itm:
|
||||||
|
frappe.throw(_("Note: Item {0} entered multiple times").format(d.item_code))
|
||||||
|
else:
|
||||||
|
chk_dupl_itm.append(f)
|
||||||
|
|
||||||
|
|
||||||
def validate_items(self):
|
def validate_items(self):
|
||||||
# validate items to see if they have is_sales_item enabled
|
# validate items to see if they have is_sales_item enabled
|
||||||
from erpnext.controllers.buying_controller import validate_item_type
|
from erpnext.controllers.buying_controller import validate_item_type
|
||||||
|
@ -54,6 +54,8 @@ def get_last_issue_from_customer(customer_name):
|
|||||||
|
|
||||||
|
|
||||||
def get_scheduled_employees_for_popup(communication_medium):
|
def get_scheduled_employees_for_popup(communication_medium):
|
||||||
|
if not communication_medium: return []
|
||||||
|
|
||||||
now_time = frappe.utils.nowtime()
|
now_time = frappe.utils.nowtime()
|
||||||
weekday = frappe.utils.get_weekday()
|
weekday = frappe.utils.get_weekday()
|
||||||
|
|
||||||
@ -73,3 +75,10 @@ def get_scheduled_employees_for_popup(communication_medium):
|
|||||||
employee_emails = set([employee.user_id for employee in employees])
|
employee_emails = set([employee.user_id for employee in employees])
|
||||||
|
|
||||||
return employee_emails
|
return employee_emails
|
||||||
|
|
||||||
|
def strip_number(number):
|
||||||
|
if not number: return
|
||||||
|
# strip 0 from the start of the number for proper number comparisions
|
||||||
|
# eg. 07888383332 should match with 7888383332
|
||||||
|
number = number.lstrip('0')
|
||||||
|
return number
|
@ -5,6 +5,8 @@ frappe.listview_settings['Leave Application'] = {
|
|||||||
return [__("Approved"), "green", "status,=,Approved"];
|
return [__("Approved"), "green", "status,=,Approved"];
|
||||||
} else if (doc.status === "Rejected") {
|
} else if (doc.status === "Rejected") {
|
||||||
return [__("Rejected"), "red", "status,=,Rejected"];
|
return [__("Rejected"), "red", "status,=,Rejected"];
|
||||||
|
} else {
|
||||||
|
return [__("Open"), "red", "status,=,Open"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -23,7 +23,8 @@ def get_columns():
|
|||||||
_("Model") + ":data:50", _("Location") + ":data:100",
|
_("Model") + ":data:50", _("Location") + ":data:100",
|
||||||
_("Log") + ":Link/Vehicle Log:100", _("Odometer") + ":Int:80",
|
_("Log") + ":Link/Vehicle Log:100", _("Odometer") + ":Int:80",
|
||||||
_("Date") + ":Date:100", _("Fuel Qty") + ":Float:80",
|
_("Date") + ":Date:100", _("Fuel Qty") + ":Float:80",
|
||||||
_("Fuel Price") + ":Float:100",_("Service Expense") + ":Float:100"
|
_("Fuel Price") + ":Float:100",_("Fuel Expense") + ":Float:100",
|
||||||
|
_("Service Expense") + ":Float:100"
|
||||||
]
|
]
|
||||||
return columns
|
return columns
|
||||||
|
|
||||||
@ -32,7 +33,8 @@ def get_log_data(filters):
|
|||||||
data = frappe.db.sql("""select
|
data = frappe.db.sql("""select
|
||||||
vhcl.license_plate as "License", vhcl.make as "Make", vhcl.model as "Model",
|
vhcl.license_plate as "License", vhcl.make as "Make", vhcl.model as "Model",
|
||||||
vhcl.location as "Location", log.name as "Log", log.odometer as "Odometer",
|
vhcl.location as "Location", log.name as "Log", log.odometer as "Odometer",
|
||||||
log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price"
|
log.date as "Date", log.fuel_qty as "Fuel Qty", log.price as "Fuel Price",
|
||||||
|
log.fuel_qty * log.price as "Fuel Expense"
|
||||||
from
|
from
|
||||||
`tabVehicle` vhcl,`tabVehicle Log` log
|
`tabVehicle` vhcl,`tabVehicle Log` log
|
||||||
where
|
where
|
||||||
@ -58,7 +60,7 @@ def get_chart_data(data,period_list):
|
|||||||
total_ser_exp=0
|
total_ser_exp=0
|
||||||
for row in data:
|
for row in data:
|
||||||
if row["Date"] <= period.to_date and row["Date"] >= period.from_date:
|
if row["Date"] <= period.to_date and row["Date"] >= period.from_date:
|
||||||
total_fuel_exp+=flt(row["Fuel Price"])
|
total_fuel_exp+=flt(row["Fuel Expense"])
|
||||||
total_ser_exp+=flt(row["Service Expense"])
|
total_ser_exp+=flt(row["Service Expense"])
|
||||||
fueldata.append([period.key,total_fuel_exp])
|
fueldata.append([period.key,total_fuel_exp])
|
||||||
servicedata.append([period.key,total_ser_exp])
|
servicedata.append([period.key,total_ser_exp])
|
||||||
|
@ -605,7 +605,6 @@ erpnext.patches.v11_1.rename_depends_on_lwp
|
|||||||
execute:frappe.delete_doc("Report", "Inactive Items")
|
execute:frappe.delete_doc("Report", "Inactive Items")
|
||||||
erpnext.patches.v11_1.delete_scheduling_tool
|
erpnext.patches.v11_1.delete_scheduling_tool
|
||||||
erpnext.patches.v12_0.rename_tolerance_fields
|
erpnext.patches.v12_0.rename_tolerance_fields
|
||||||
erpnext.patches.v12_0.make_custom_fields_for_bank_remittance #14-06-2019
|
|
||||||
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
execute:frappe.delete_doc_if_exists("Page", "support-analytics")
|
||||||
erpnext.patches.v12_0.remove_patient_medical_record_page
|
erpnext.patches.v12_0.remove_patient_medical_record_page
|
||||||
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
|
erpnext.patches.v11_1.move_customer_lead_to_dynamic_column
|
||||||
@ -626,4 +625,5 @@ erpnext.patches.v12_0.add_default_buying_selling_terms_in_company
|
|||||||
erpnext.patches.v12_0.update_ewaybill_field_position
|
erpnext.patches.v12_0.update_ewaybill_field_position
|
||||||
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
|
erpnext.patches.v12_0.create_accounting_dimensions_in_missing_doctypes
|
||||||
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
erpnext.patches.v11_1.set_status_for_material_request_type_manufacture
|
||||||
|
erpnext.patches.v12_0.remove_bank_remittance_custom_fields
|
||||||
erpnext.patches.v12_0.generate_leave_ledger_entries
|
erpnext.patches.v12_0.generate_leave_ledger_entries
|
@ -1,12 +0,0 @@
|
|||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from erpnext.regional.india.setup import make_custom_fields
|
|
||||||
|
|
||||||
def execute():
|
|
||||||
frappe.reload_doc("accounts", "doctype", "tax_category")
|
|
||||||
frappe.reload_doc("stock", "doctype", "item_manufacturer")
|
|
||||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
|
||||||
if not company:
|
|
||||||
return
|
|
||||||
|
|
||||||
make_custom_fields()
|
|
@ -0,0 +1,14 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from erpnext.regional.india.setup import make_custom_fields
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
frappe.reload_doc("accounts", "doctype", "tax_category")
|
||||||
|
frappe.reload_doc("stock", "doctype", "item_manufacturer")
|
||||||
|
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||||
|
if not company:
|
||||||
|
return
|
||||||
|
if frappe.db.exists("Custom Field", "Company-bank_remittance_section"):
|
||||||
|
deprecated_fields = ['bank_remittance_section', 'client_code', 'remittance_column_break', 'product_code']
|
||||||
|
for i in range(len(deprecated_fields)):
|
||||||
|
frappe.delete_doc("Custom Field", 'Company-'+deprecated_fields[i])
|
@ -1,190 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# Copyright (c) 2018, Frappe and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
|
||||||
import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
from frappe.utils import cint,cstr, today
|
|
||||||
from frappe import _
|
|
||||||
import re
|
|
||||||
import datetime
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
def create_bank_remittance_txt(name):
|
|
||||||
payment_order = frappe.get_cached_doc("Payment Order", name)
|
|
||||||
|
|
||||||
no_of_records = len(payment_order.get("references"))
|
|
||||||
total_amount = sum(entry.get("amount") for entry in payment_order.get("references"))
|
|
||||||
|
|
||||||
product_code, client_code, company_email = frappe.db.get_value("Company",
|
|
||||||
filters={'name' : payment_order.company},
|
|
||||||
fieldname=['product_code', 'client_code', 'email'])
|
|
||||||
|
|
||||||
header, file_name = get_header_row(payment_order, client_code)
|
|
||||||
batch = get_batch_row(payment_order, no_of_records, total_amount, product_code)
|
|
||||||
|
|
||||||
detail = []
|
|
||||||
for ref_doc in payment_order.get("references"):
|
|
||||||
detail += get_detail_row(ref_doc, payment_order, company_email)
|
|
||||||
|
|
||||||
trailer = get_trailer_row(no_of_records, total_amount)
|
|
||||||
detail_records = "\n".join(detail)
|
|
||||||
|
|
||||||
return "\n".join([header, batch, detail_records, trailer]), file_name
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def generate_report(name):
|
|
||||||
data, file_name = create_bank_remittance_txt(name)
|
|
||||||
|
|
||||||
f = frappe.get_doc({
|
|
||||||
'doctype': 'File',
|
|
||||||
'file_name': file_name,
|
|
||||||
'content': data,
|
|
||||||
"attached_to_doctype": 'Payment Order',
|
|
||||||
"attached_to_name": name,
|
|
||||||
'is_private': True
|
|
||||||
})
|
|
||||||
f.save()
|
|
||||||
return {
|
|
||||||
'file_url': f.file_url,
|
|
||||||
'file_name': file_name
|
|
||||||
}
|
|
||||||
|
|
||||||
def generate_file_name(name, company_account, date):
|
|
||||||
''' generate file name with format (account_code)_mmdd_(payment_order_no) '''
|
|
||||||
bank, acc_no = frappe.db.get_value("Bank Account", {"name": company_account}, ['bank', 'bank_account_no'])
|
|
||||||
return bank[:1]+str(acc_no)[-4:]+'_'+date.strftime("%m%d")+sanitize_data(name, '')[4:]+'.txt'
|
|
||||||
|
|
||||||
def get_header_row(doc, client_code):
|
|
||||||
''' Returns header row and generated file name '''
|
|
||||||
file_name = generate_file_name(doc.name, doc.company_bank_account, doc.posting_date)
|
|
||||||
header = ["H"]
|
|
||||||
header.append(validate_field_size(client_code, "Client Code", 20))
|
|
||||||
header += [''] * 3
|
|
||||||
header.append(validate_field_size(file_name, "File Name", 20))
|
|
||||||
return "~".join(header), file_name
|
|
||||||
|
|
||||||
def get_batch_row(doc, no_of_records, total_amount, product_code):
|
|
||||||
batch = ["B"]
|
|
||||||
batch.append(validate_field_size(no_of_records, "No Of Records", 5))
|
|
||||||
batch.append(validate_amount(format(total_amount, '0.2f'), 17))
|
|
||||||
batch.append(sanitize_data(doc.name, '_')[:20])
|
|
||||||
batch.append(format_date(doc.posting_date))
|
|
||||||
batch.append(validate_field_size(product_code,"Product Code", 20))
|
|
||||||
return "~".join(batch)
|
|
||||||
|
|
||||||
def get_detail_row(ref_doc, payment_entry, company_email):
|
|
||||||
|
|
||||||
payment_date = format_date(payment_entry.posting_date)
|
|
||||||
payment_entry = frappe.get_cached_doc('Payment Entry', ref_doc.payment_entry)
|
|
||||||
supplier_bank_details = frappe.get_cached_doc('Bank Account', ref_doc.bank_account)
|
|
||||||
company_bank_acc_no = frappe.db.get_value("Bank Account", {'name': payment_entry.bank_account}, ['bank_account_no'])
|
|
||||||
|
|
||||||
addr_link = frappe.db.get_value('Dynamic Link',
|
|
||||||
{
|
|
||||||
'link_doctype': 'Supplier',
|
|
||||||
'link_name': 'Sample Supplier',
|
|
||||||
'parenttype':'Address',
|
|
||||||
'parent': ('like', '%-Billing')
|
|
||||||
}, 'parent')
|
|
||||||
|
|
||||||
supplier_billing_address = frappe.get_cached_doc('Address', addr_link)
|
|
||||||
email = ','.join(filter(None, [supplier_billing_address.email_id, company_email]))
|
|
||||||
|
|
||||||
detail = OrderedDict(
|
|
||||||
record_identifier='D',
|
|
||||||
payment_ref_no=sanitize_data(ref_doc.payment_entry),
|
|
||||||
payment_type=cstr(payment_entry.mode_of_payment)[:10],
|
|
||||||
amount=str(validate_amount(format(ref_doc.amount, '.2f'),13)),
|
|
||||||
payment_date=payment_date,
|
|
||||||
instrument_date=payment_date,
|
|
||||||
instrument_number='',
|
|
||||||
dr_account_no_client=str(validate_field_size(company_bank_acc_no, "Company Bank Account", 20)),
|
|
||||||
dr_description='',
|
|
||||||
dr_ref_no='',
|
|
||||||
cr_ref_no='',
|
|
||||||
bank_code_indicator='M',
|
|
||||||
beneficiary_code='',
|
|
||||||
beneficiary_name=sanitize_data(validate_information(payment_entry, "party", 160), ' '),
|
|
||||||
beneficiary_bank=sanitize_data(validate_information(supplier_bank_details, "bank", 10)),
|
|
||||||
beneficiary_branch_code=cstr(validate_information(supplier_bank_details, "branch_code", 11)),
|
|
||||||
beneficiary_acc_no=validate_information(supplier_bank_details, "bank_account_no", 20),
|
|
||||||
location='',
|
|
||||||
print_location='',
|
|
||||||
beneficiary_address_1=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line1), ' '), " Beneficiary Address 1", 50),
|
|
||||||
beneficiary_address_2=validate_field_size(sanitize_data(cstr(supplier_billing_address.address_line2), ' '), " Beneficiary Address 2", 50),
|
|
||||||
beneficiary_address_3='',
|
|
||||||
beneficiary_address_4='',
|
|
||||||
beneficiary_address_5='',
|
|
||||||
beneficiary_city=validate_field_size(cstr(supplier_billing_address.city), "Beneficiary City", 20),
|
|
||||||
beneficiary_zipcode=validate_field_size(cstr(supplier_billing_address.pincode), "Pin Code", 6),
|
|
||||||
beneficiary_state=validate_field_size(cstr(supplier_billing_address.state), "Beneficiary State", 20),
|
|
||||||
beneficiary_email=cstr(email)[:255],
|
|
||||||
beneficiary_mobile=validate_field_size(cstr(supplier_billing_address.phone), "Beneficiary Mobile", 10),
|
|
||||||
payment_details_1='',
|
|
||||||
payment_details_2='',
|
|
||||||
payment_details_3='',
|
|
||||||
payment_details_4='',
|
|
||||||
delivery_mode=''
|
|
||||||
)
|
|
||||||
detail_record = ["~".join(list(detail.values()))]
|
|
||||||
|
|
||||||
detail_record += get_advice_rows(payment_entry)
|
|
||||||
return detail_record
|
|
||||||
|
|
||||||
def get_advice_rows(payment_entry):
|
|
||||||
''' Returns multiple advice rows for a single detail entry '''
|
|
||||||
payment_entry_date = payment_entry.posting_date.strftime("%b%y%d%m").upper()
|
|
||||||
mode_of_payment = payment_entry.mode_of_payment
|
|
||||||
advice_rows = []
|
|
||||||
for record in payment_entry.references:
|
|
||||||
advice = ['E']
|
|
||||||
advice.append(cstr(mode_of_payment))
|
|
||||||
advice.append(cstr(record.total_amount))
|
|
||||||
advice.append('')
|
|
||||||
advice.append(cstr(record.outstanding_amount))
|
|
||||||
advice.append(record.reference_name)
|
|
||||||
advice.append(format_date(record.due_date))
|
|
||||||
advice.append(payment_entry_date)
|
|
||||||
advice_rows.append("~".join(advice))
|
|
||||||
return advice_rows
|
|
||||||
|
|
||||||
def get_trailer_row(no_of_records, total_amount):
|
|
||||||
''' Returns trailer row '''
|
|
||||||
trailer = ["T"]
|
|
||||||
trailer.append(validate_field_size(no_of_records, "No of Records", 5))
|
|
||||||
trailer.append(validate_amount(format(total_amount, "0.2f"), 17))
|
|
||||||
return "~".join(trailer)
|
|
||||||
|
|
||||||
def sanitize_data(val, replace_str=''):
|
|
||||||
''' Remove all the non-alphanumeric characters from string '''
|
|
||||||
pattern = re.compile('[\W_]+')
|
|
||||||
return pattern.sub(replace_str, val)
|
|
||||||
|
|
||||||
def format_date(val):
|
|
||||||
''' Convert a datetime object to DD/MM/YYYY format '''
|
|
||||||
return val.strftime("%d/%m/%Y")
|
|
||||||
|
|
||||||
def validate_amount(val, max_int_size):
|
|
||||||
''' Validate amount to be within the allowed limits '''
|
|
||||||
int_size = len(str(val).split('.')[0])
|
|
||||||
|
|
||||||
if int_size > max_int_size:
|
|
||||||
frappe.throw(_("Amount for a single transaction exceeds maximum allowed amount, create a separate payment order by splitting the transactions"))
|
|
||||||
|
|
||||||
return val
|
|
||||||
|
|
||||||
def validate_information(obj, attr, max_size):
|
|
||||||
''' Checks if the information is not set in the system and is within the size '''
|
|
||||||
if hasattr(obj, attr):
|
|
||||||
return validate_field_size(getattr(obj, attr), frappe.unscrub(attr), max_size)
|
|
||||||
|
|
||||||
else:
|
|
||||||
frappe.throw(_("{0} is mandatory for generating remittance payments, set the field and try again".format(frappe.unscrub(attr))))
|
|
||||||
|
|
||||||
def validate_field_size(val, label, max_size):
|
|
||||||
''' check the size of the val '''
|
|
||||||
if len(cstr(val)) > max_size:
|
|
||||||
frappe.throw(_("{0} field is limited to size {1}".format(label, max_size)))
|
|
||||||
return cstr(val)
|
|
@ -407,14 +407,6 @@ def make_custom_fields(update=True):
|
|||||||
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
|
fieldtype='Link', options='Salary Component', insert_after='basic_component'),
|
||||||
dict(fieldname='arrear_component', label='Arrear Component',
|
dict(fieldname='arrear_component', label='Arrear Component',
|
||||||
fieldtype='Link', options='Salary Component', insert_after='hra_component'),
|
fieldtype='Link', options='Salary Component', insert_after='hra_component'),
|
||||||
dict(fieldname='bank_remittance_section', label='Bank Remittance Settings',
|
|
||||||
fieldtype='Section Break', collapsible=1, insert_after='arrear_component'),
|
|
||||||
dict(fieldname='client_code', label='Client Code', fieldtype='Data',
|
|
||||||
insert_after='bank_remittance_section'),
|
|
||||||
dict(fieldname='remittance_column_break', fieldtype='Column Break',
|
|
||||||
insert_after='client_code'),
|
|
||||||
dict(fieldname='product_code', label='Product Code', fieldtype='Data',
|
|
||||||
insert_after='remittance_column_break'),
|
|
||||||
],
|
],
|
||||||
'Employee Tax Exemption Declaration':[
|
'Employee Tax Exemption Declaration':[
|
||||||
dict(fieldname='hra_section', label='HRA Exemption',
|
dict(fieldname='hra_section', label='HRA Exemption',
|
||||||
|
@ -156,33 +156,21 @@ class Gstr1Report(object):
|
|||||||
|
|
||||||
|
|
||||||
if self.filters.get("type_of_business") == "B2B":
|
if self.filters.get("type_of_business") == "B2B":
|
||||||
customers = frappe.get_all("Customer",
|
conditions += "and ifnull(gst_category, '') in ('Registered Regular', 'Deemed Export', 'SEZ') and is_return != 1"
|
||||||
filters={
|
|
||||||
"gst_category": ["in", ["Registered Regular", "Deemed Export", "SEZ"]]
|
|
||||||
})
|
|
||||||
|
|
||||||
if customers:
|
|
||||||
conditions += """ and ifnull(gst_category, '') != 'Overseas' and is_return != 1
|
|
||||||
and customer in ({0})""".format(", ".join([frappe.db.escape(c.name) for c in customers]))
|
|
||||||
|
|
||||||
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
|
if self.filters.get("type_of_business") in ("B2C Large", "B2C Small"):
|
||||||
b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit')
|
b2c_limit = frappe.db.get_single_value('GST Settings', 'b2c_limit')
|
||||||
if not b2c_limit:
|
if not b2c_limit:
|
||||||
frappe.throw(_("Please set B2C Limit in GST Settings."))
|
frappe.throw(_("Please set B2C Limit in GST Settings."))
|
||||||
|
|
||||||
customers = frappe.get_all("Customer",
|
|
||||||
filters={
|
|
||||||
"gst_category": ["in", ["Unregistered"]]
|
|
||||||
})
|
|
||||||
|
|
||||||
if self.filters.get("type_of_business") == "B2C Large" and customers:
|
if self.filters.get("type_of_business") == "B2C Large" and customers:
|
||||||
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
|
conditions += """ and SUBSTR(place_of_supply, 1, 2) != SUBSTR(company_gstin, 1, 2)
|
||||||
and grand_total > {0} and is_return != 1 and customer in ({1})""".\
|
and grand_total > {0} and is_return != 1 and gst_category ='Unregistered' """.\
|
||||||
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
|
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
|
||||||
elif self.filters.get("type_of_business") == "B2C Small" and customers:
|
elif self.filters.get("type_of_business") == "B2C Small" and customers:
|
||||||
conditions += """ and (
|
conditions += """ and (
|
||||||
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
|
SUBSTR(place_of_supply, 1, 2) = SUBSTR(company_gstin, 1, 2)
|
||||||
or grand_total <= {0}) and is_return != 1 and customer in ({1})""".\
|
or grand_total <= {0}) and is_return != 1 and gst_category ='Unregistered' """.\
|
||||||
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
|
format(flt(b2c_limit), ", ".join([frappe.db.escape(c.name) for c in customers]))
|
||||||
|
|
||||||
elif self.filters.get("type_of_business") == "CDNR":
|
elif self.filters.get("type_of_business") == "CDNR":
|
||||||
|
@ -72,9 +72,7 @@ class SalesOrder(SellingController):
|
|||||||
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
|
frappe.msgprint(_("Warning: Sales Order {0} already exists against Customer's Purchase Order {1}").format(so[0][0], self.po_no))
|
||||||
|
|
||||||
def validate_for_items(self):
|
def validate_for_items(self):
|
||||||
check_list = []
|
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
check_list.append(cstr(d.item_code))
|
|
||||||
|
|
||||||
# used for production plan
|
# used for production plan
|
||||||
d.transaction_date = self.transaction_date
|
d.transaction_date = self.transaction_date
|
||||||
@ -83,13 +81,6 @@ class SalesOrder(SellingController):
|
|||||||
where item_code = %s and warehouse = %s", (d.item_code, d.warehouse))
|
where item_code = %s and warehouse = %s", (d.item_code, d.warehouse))
|
||||||
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
|
d.projected_qty = tot_avail_qty and flt(tot_avail_qty[0][0]) or 0
|
||||||
|
|
||||||
# check for same entry multiple times
|
|
||||||
unique_chk_list = set(check_list)
|
|
||||||
if len(unique_chk_list) != len(check_list) and \
|
|
||||||
not cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
|
|
||||||
frappe.msgprint(_("Same item has been entered multiple times"),
|
|
||||||
title=_("Warning"), indicator='orange')
|
|
||||||
|
|
||||||
def product_bundle_has_stock_item(self, product_bundle):
|
def product_bundle_has_stock_item(self, product_bundle):
|
||||||
"""Returns true if product bundle has stock item"""
|
"""Returns true if product bundle has stock item"""
|
||||||
ret = len(frappe.db.sql("""select i.name from tabItem i, `tabProduct Bundle Item` pbi
|
ret = len(frappe.db.sql("""select i.name from tabItem i, `tabProduct Bundle Item` pbi
|
||||||
|
@ -4,7 +4,7 @@ frappe.provide('erpnext.pos');
|
|||||||
frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
|
frappe.pages['point-of-sale'].on_page_load = function(wrapper) {
|
||||||
frappe.ui.make_app_page({
|
frappe.ui.make_app_page({
|
||||||
parent: wrapper,
|
parent: wrapper,
|
||||||
title: 'Point of Sale',
|
title: __('Point of Sale'),
|
||||||
single_column: true
|
single_column: true
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -166,24 +166,7 @@ class DeliveryNote(SellingController):
|
|||||||
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project))
|
frappe.throw(_("Customer {0} does not belong to project {1}").format(self.customer, self.project))
|
||||||
|
|
||||||
def validate_for_items(self):
|
def validate_for_items(self):
|
||||||
check_list, chk_dupl_itm = [], []
|
|
||||||
if cint(frappe.db.get_single_value("Selling Settings", "allow_multiple_items")):
|
|
||||||
return
|
|
||||||
|
|
||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
e = [d.item_code, d.description, d.warehouse, d.against_sales_order or d.against_sales_invoice, d.batch_no or '']
|
|
||||||
f = [d.item_code, d.description, d.against_sales_order or d.against_sales_invoice]
|
|
||||||
|
|
||||||
if frappe.db.get_value("Item", d.item_code, "is_stock_item") == 1:
|
|
||||||
if e in check_list:
|
|
||||||
frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
|
|
||||||
else:
|
|
||||||
check_list.append(e)
|
|
||||||
else:
|
|
||||||
if f in chk_dupl_itm:
|
|
||||||
frappe.msgprint(_("Note: Item {0} entered multiple times").format(d.item_code))
|
|
||||||
else:
|
|
||||||
chk_dupl_itm.append(f)
|
|
||||||
#Customer Provided parts will have zero valuation rate
|
#Customer Provided parts will have zero valuation rate
|
||||||
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
|
if frappe.db.get_value('Item', d.item_code, 'is_customer_provided_item'):
|
||||||
d.allow_zero_valuation_rate = 1
|
d.allow_zero_valuation_rate = 1
|
||||||
|
@ -124,6 +124,7 @@ class Item(WebsiteGenerator):
|
|||||||
self.update_defaults_from_item_group()
|
self.update_defaults_from_item_group()
|
||||||
self.validate_auto_reorder_enabled_in_stock_settings()
|
self.validate_auto_reorder_enabled_in_stock_settings()
|
||||||
self.cant_change()
|
self.cant_change()
|
||||||
|
self.update_show_in_website()
|
||||||
|
|
||||||
if not self.get("__islocal"):
|
if not self.get("__islocal"):
|
||||||
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
self.old_item_group = frappe.db.get_value(self.doctype, self.name, "item_group")
|
||||||
@ -476,6 +477,10 @@ class Item(WebsiteGenerator):
|
|||||||
|
|
||||||
[self.remove(d) for d in to_remove]
|
[self.remove(d) for d in to_remove]
|
||||||
|
|
||||||
|
def update_show_in_website(self):
|
||||||
|
if self.disabled:
|
||||||
|
self.show_in_website = False
|
||||||
|
|
||||||
def update_template_tables(self):
|
def update_template_tables(self):
|
||||||
template = frappe.get_doc("Item", self.variant_of)
|
template = frappe.get_doc("Item", self.variant_of)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user