Ported v3 fixes to v4

Commit range: webnotes/erpnext@e4b72df2f4bd7272c42e90f6faec3c27aa763b82..webnotes/erpnext@85441b0180f84246259d5a0ab4e3bcbf29355efe
This commit is contained in:
Anand Doshi 2014-04-16 15:21:46 +05:30
parent 13429a3b34
commit 652bc0784a
18 changed files with 194 additions and 144 deletions

View File

@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
from frappe.utils import flt, cstr, cint
from frappe.utils import flt, cstr, cint, getdate, add_days, formatdate
from frappe import msgprint, throw, _
from frappe.model.document import Document
@ -151,6 +151,27 @@ class Account(Document):
and not self.get_authorized_user():
throw(_("{0} Credit limit {0} crossed").format(_(credit_limit_from), credit_limit))
def validate_due_date(self, posting_date, due_date):
credit_days = (self.credit_days or frappe.db.get_value("Company", self.company, "credit_days"))
if credit_days is None:
return
posting_date, due_date = getdate(posting_date), getdate(due_date)
diff = (due_date - posting_date).days
if diff < 0:
frappe.throw(_("Due Date cannot be before Posting Date"))
elif diff > credit_days:
is_credit_controller = frappe.db.get_value("Accounts Settings", None,
"credit_controller") in frappe.user.get_roles()
if is_credit_controller:
msgprint(_("Note: Due Date exceeds the allowed credit days by {0} day(s)").format(
diff - credit_days))
else:
max_due_date = formatdate(add_days(posting_date, credit_days))
frappe.throw(_("Due Date cannot be after {0}").format(max_due_date))
def validate_trash(self):
"""checks gl entries and if child exists"""
if not self.parent_account:

View File

@ -25,8 +25,7 @@ class GLEntry(Document):
validate_balance_type(self.account, adv_adj)
# Update outstanding amt on against voucher
if self.against_voucher and self.against_voucher_type != "POS" \
and update_outstanding == 'Yes':
if self.against_voucher and update_outstanding == 'Yes':
update_outstanding_amt(self.account, self.against_voucher_type,
self.against_voucher)

View File

@ -212,7 +212,7 @@ class JournalVoucher(AccountsController):
self.is_approving_authority = 0
# Fetch credit controller role
approving_authority = frappe.db.get_value("Global Defaults", None,
approving_authority = frappe.db.get_value("Accounts Settings", None,
"credit_controller")
# Check logged-in user is authorized

View File

@ -50,6 +50,7 @@ class PurchaseInvoice(BuyingController):
self.validate_with_previous_doc()
self.validate_uom_is_integer("uom", "qty")
self.set_aging_date()
frappe.get_doc("Account", self.credit_to).validate_due_date(self.posting_date, self.due_date)
self.set_against_expense_account()
self.validate_write_off_account()
self.update_valuation_rate("entries")

View File

@ -138,7 +138,7 @@ class TestPurchaseInvoice(unittest.TestCase):
wrapper.load_from_db()
expected_values = [
["_Test FG Item", 90, 7059],
["_Test FG Item", 90, 59],
["_Test Item Home Desktop 200", 135, 177]
]
for i, item in enumerate(wrapper.get("entries")):

View File

@ -23,7 +23,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
// show debit_to in print format
this.frm.set_df_property("debit_to", "print_hide", 0);
}
// toggle to pos view if is_pos is 1 in user_defaults
if ((cint(frappe.defaults.get_user_defaults("is_pos"))===1 || this.frm.doc.is_pos)) {
if(this.frm.doc.__islocal && !this.frm.doc.amended_from && !this.frm.doc.customer) {
@ -34,14 +34,14 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
});
}
}
// if document is POS then change default print format to "POS Invoice"
if(cur_frm.doc.is_pos && cur_frm.doc.docstatus===1) {
locals.DocType[cur_frm.doctype].default_print_format = "POS Invoice";
cur_frm.setup_print_layout();
}
},
refresh: function(doc, dt, dn) {
this._super();
@ -59,7 +59,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
};
frappe.set_route("query-report", "General Ledger");
}, "icon-table");
var percent_paid = cint(flt(doc.grand_total - doc.outstanding_amount) / flt(doc.grand_total) * 100);
cur_frm.dashboard.add_progress(percent_paid + "% Paid", percent_paid);
@ -69,10 +69,10 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
// show Make Delivery Note button only if Sales Invoice is not created from Delivery Note
var from_delivery_note = false;
from_delivery_note = cur_frm.doc.entries
.some(function(item) {
return item.delivery_note ? true : false;
.some(function(item) {
return item.delivery_note ? true : false;
});
if(!from_delivery_note)
cur_frm.appframe.add_primary_action(__('Make Delivery'), cur_frm.cscript['Make Delivery Note'])
}
@ -89,7 +89,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
sales_order_btn: function() {
this.$sales_order_btn = cur_frm.appframe.add_primary_action(__('From Sales Order'),
this.$sales_order_btn = cur_frm.appframe.add_primary_action(__('From Sales Order'),
function() {
frappe.model.map_current_doc({
method: "erpnext.selling.doctype.sales_order.sales_order.make_sales_invoice",
@ -106,7 +106,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
},
delivery_note_btn: function() {
this.$delivery_note_btn = cur_frm.appframe.add_primary_action(__('From Delivery Note'),
this.$delivery_note_btn = cur_frm.appframe.add_primary_action(__('From Delivery Note'),
function() {
frappe.model.map_current_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
@ -124,11 +124,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
});
});
},
tc_name: function() {
this.get_terms();
},
is_pos: function(callback_fn) {
cur_frm.cscript.hide_fields(this.frm.doc);
if(cint(this.frm.doc.is_pos)) {
@ -146,7 +146,7 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
me.set_default_values();
me.set_dynamic_labels();
me.calculate_taxes_and_totals();
if(callback_fn) callback_fn();
}
}
@ -154,11 +154,11 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
}
}
},
customer: function() {
if(this.frm.updating_party_details)
return;
erpnext.utils.get_party_details(this.frm,
erpnext.utils.get_party_details(this.frm,
"erpnext.accounts.party.get_party_details", {
posting_date: this.frm.doc.posting_date,
party: this.frm.doc.customer,
@ -167,42 +167,42 @@ erpnext.accounts.SalesInvoiceController = erpnext.selling.SellingController.exte
price_list: this.frm.doc.selling_price_list,
})
},
debit_to: function() {
this.customer();
},
allocated_amount: function() {
this.calculate_total_advance("Sales Invoice", "advance_adjustment_details");
this.frm.refresh_fields();
},
write_off_outstanding_amount_automatically: function() {
if(cint(this.frm.doc.write_off_outstanding_amount_automatically)) {
frappe.model.round_floats_in(this.frm.doc, ["grand_total", "paid_amount"]);
// this will make outstanding amount 0
this.frm.set_value("write_off_amount",
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount),
this.frm.set_value("write_off_amount",
flt(this.frm.doc.grand_total - this.frm.doc.paid_amount),
precision("write_off_amount"));
}
this.calculate_outstanding_amount();
this.calculate_outstanding_amount(false);
this.frm.refresh_fields();
},
write_off_amount: function() {
this.write_off_outstanding_amount_automatically();
},
paid_amount: function() {
this.write_off_outstanding_amount_automatically();
},
entries_add: function(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
this.frm.script_manager.copy_from_first_row("entries", row, ["income_account", "cost_center"]);
},
set_dynamic_labels: function() {
this._super();
this.hide_fields(this.frm.doc);
@ -224,9 +224,9 @@ cur_frm.cscript.hide_fields = function(doc) {
'gross_profit_percent', 'get_advances_received',
'advance_adjustment_details', 'sales_partner', 'commission_rate',
'total_commission', 'advances'];
item_flds_normal = ['sales_order', 'delivery_note']
if(cint(doc.is_pos) == 1) {
hide_field(par_flds);
unhide_field('payments_section');
@ -239,15 +239,15 @@ cur_frm.cscript.hide_fields = function(doc) {
}
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_normal, true);
}
item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse']
cur_frm.fields_dict['entries'].grid.set_column_disp(item_flds_stock,
(cint(doc.update_stock)==1 ? true : false));
// India related fields
if (frappe.boot.sysdefaults.country == 'India') unhide_field(['c_form_applicable', 'c_form_no']);
else hide_field(['c_form_applicable', 'c_form_no']);
cur_frm.refresh_fields();
}
@ -305,7 +305,7 @@ cur_frm.fields_dict.cash_bank_account.get_query = function(doc) {
'group_or_ledger': 'Ledger',
'company': doc.company
}
}
}
}
cur_frm.fields_dict.write_off_account.get_query = function(doc) {
@ -326,7 +326,7 @@ cur_frm.fields_dict.write_off_cost_center.get_query = function(doc) {
'group_or_ledger': 'Ledger',
'company': doc.company
}
}
}
}
//project name
@ -335,7 +335,7 @@ cur_frm.fields_dict['project_name'].get_query = function(doc, cdt, cdn) {
return{
query: "erpnext.controllers.queries.get_project_name",
filters: {'customer': doc.customer}
}
}
}
// Income Account in Details Table
@ -365,10 +365,10 @@ if (sys_defaults.auto_accounting_for_stock) {
// -----------------------------
cur_frm.fields_dict["entries"].grid.get_field("cost_center").get_query = function(doc) {
return {
filters: {
filters: {
'company': doc.company,
'group_or_ledger': 'Ledger'
}
}
}
}
@ -396,12 +396,12 @@ cur_frm.cscript.convert_into_recurring_invoice = function(doc, dt, dn) {
var owner_email = doc.owner=="Administrator"
? frappe.user_info("Administrator").email
: doc.owner;
doc.notification_email_address = $.map([cstr(owner_email),
cstr(doc.contact_email)], function(v) { return v || null; }).join(", ");
doc.repeat_on_day_of_month = frappe.datetime.str_to_obj(doc.posting_date).getDate();
}
refresh_many(["notification_email_address", "repeat_on_day_of_month"]);
}

View File

@ -65,6 +65,7 @@ class SalesInvoice(SellingController):
self.is_opening = 'No'
self.set_aging_date()
frappe.get_doc("Account", self.debit_to).validate_due_date(self.posting_date, self.due_date)
self.set_against_income_account()
self.validate_c_form()
self.validate_time_logs_are_submitted()
@ -464,6 +465,10 @@ class SalesInvoice(SellingController):
make_gl_entries(gl_entries, cancel=(self.docstatus == 2),
update_outstanding=update_outstanding, merge_entries=False)
if update_outstanding == "No":
from erpnext.accounts.doctype.gl_entry.gl_entry import update_outstanding_amt
update_outstanding_amt(self.debit_to, self.doctype, self.name)
if repost_future_gle and cint(self.update_stock) \
and cint(frappe.defaults.get_global_default("auto_accounting_for_stock")):
items, warehouse_account = self.get_items_and_warehouse_accounts()

View File

@ -10,7 +10,7 @@ from erpnext.accounts.utils import validate_expense_against_budget
class StockAccountInvalidTransaction(frappe.ValidationError): pass
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
update_outstanding='Yes'):
if gl_map:
if not cancel:
@ -18,11 +18,11 @@ def make_gl_entries(gl_map, cancel=False, adv_adj=False, merge_entries=True,
save_entries(gl_map, adv_adj, update_outstanding)
else:
delete_gl_entries(gl_map, adv_adj=adv_adj, update_outstanding=update_outstanding)
def process_gl_map(gl_map, merge_entries=True):
if merge_entries:
gl_map = merge_similar_entries(gl_map)
for entry in gl_map:
# toggle debit, credit if negative entry
if flt(entry.debit) < 0:
@ -33,11 +33,11 @@ def process_gl_map(gl_map, merge_entries=True):
entry.credit = 0.0
return gl_map
def merge_similar_entries(gl_map):
merged_gl_map = []
for entry in gl_map:
# if there is already an entry in this account then just add it
# if there is already an entry in this account then just add it
# to that entry
same_head = check_if_in_list(entry, merged_gl_map)
if same_head:
@ -45,7 +45,7 @@ def merge_similar_entries(gl_map):
same_head.credit = flt(same_head.credit) + flt(entry.credit)
else:
merged_gl_map.append(entry)
# filter zero debit and credit entries
merged_gl_map = filter(lambda x: flt(x.debit)!=0 or flt(x.credit)!=0, merged_gl_map)
return merged_gl_map
@ -61,20 +61,20 @@ def check_if_in_list(gle, gl_map):
def save_entries(gl_map, adv_adj, update_outstanding):
validate_account_for_auto_accounting_for_stock(gl_map)
total_debit = total_credit = 0.0
for entry in gl_map:
make_entry(entry, adv_adj, update_outstanding)
# check against budget
validate_expense_against_budget(entry)
# update total debit / credit
total_debit += flt(entry.debit)
total_credit += flt(entry.credit)
validate_total_debit_credit(total_debit, total_credit)
def make_entry(args, adv_adj, update_outstanding):
args.update({"doctype": "GL Entry"})
gle = frappe.get_doc(args)
@ -82,45 +82,44 @@ def make_entry(args, adv_adj, update_outstanding):
gle.insert()
gle.run_method("on_update_with_args", adv_adj, update_outstanding)
gle.submit()
def validate_total_debit_credit(total_debit, total_credit):
if abs(total_debit - total_credit) > 0.005:
frappe.throw(_("Debit and Credit not equal for this voucher: Diff (Debit) is ") +
cstr(total_debit - total_credit))
def validate_account_for_auto_accounting_for_stock(gl_map):
if gl_map[0].voucher_type=="Journal Voucher":
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
aii_accounts = [d[0] for d in frappe.db.sql("""select name from tabAccount
where account_type = 'Warehouse' and ifnull(master_name, '')!=''""")]
for entry in gl_map:
if entry.account in aii_accounts:
frappe.throw(_("Account") + ": " + entry.account +
_(" can only be debited/credited through Stock transactions"),
frappe.throw(_("Account") + ": " + entry.account +
_(" can only be debited/credited through Stock transactions"),
StockAccountInvalidTransaction)
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
def delete_gl_entries(gl_entries=None, voucher_type=None, voucher_no=None,
adv_adj=False, update_outstanding="Yes"):
from erpnext.accounts.doctype.gl_entry.gl_entry import validate_balance_type, \
check_freezing_date, update_outstanding_amt, validate_frozen_account
if not gl_entries:
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
gl_entries = frappe.db.sql("""select * from `tabGL Entry`
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no), as_dict=True)
if gl_entries:
check_freezing_date(gl_entries[0]["posting_date"], adv_adj)
frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
frappe.db.sql("""delete from `tabGL Entry` where voucher_type=%s and voucher_no=%s""",
(voucher_type or gl_entries[0]["voucher_type"], voucher_no or gl_entries[0]["voucher_no"]))
for entry in gl_entries:
validate_frozen_account(entry["account"], adv_adj)
validate_balance_type(entry["account"], adv_adj)
validate_expense_against_budget(entry)
if entry.get("against_voucher") and entry.get("against_voucher_type") != "POS" \
and update_outstanding == 'Yes':
update_outstanding_amt(entry["account"], entry.get("against_voucher_type"),
entry.get("against_voucher"), on_cancel=True)
if entry.get("against_voucher") and update_outstanding == 'Yes':
update_outstanding_amt(entry["account"], entry.get("against_voucher_type"),
entry.get("against_voucher"), on_cancel=True)

View File

@ -36,10 +36,11 @@ def employee_query(doctype, txt, searchfield, start, page_len, filters):
or employee_name like "%(txt)s")
%(mcond)s
order by
case when name like "%(txt)s" then 0 else 1 end,
case when employee_name like "%(txt)s" then 0 else 1 end,
name
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
if(locate("%(_txt)s", employee_name), locate("%(_txt)s", item_name), 99999),
name, employee_name
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
'_txt': txt.replace("%", ""),
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
# searches for leads which are not converted
@ -52,11 +53,12 @@ def lead_query(doctype, txt, searchfield, start, page_len, filters):
or company_name like "%(txt)s")
%(mcond)s
order by
case when name like "%(txt)s" then 0 else 1 end,
case when lead_name like "%(txt)s" then 0 else 1 end,
case when company_name like "%(txt)s" then 0 else 1 end,
lead_name asc
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
if(locate("%(_txt)s", lead_name), locate("%(_txt)s", name), 99999),
if(locate("%(_txt)s", company_name), locate("%(_txt)s", name), 99999),
name, lead_name
limit %(start)s, %(page_len)s""" % {'key': searchfield, 'txt': "%%%s%%" % txt,
'_txt': txt.replace("%", ""),
'mcond':get_match_cond(doctype), 'start': start, 'page_len': page_len})
# searches for customer
@ -76,11 +78,12 @@ def customer_query(doctype, txt, searchfield, start, page_len, filters):
or customer_name like "%(txt)s")
%(mcond)s
order by
case when name like "%(txt)s" then 0 else 1 end,
case when customer_name like "%(txt)s" then 0 else 1 end,
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
if(locate("%(_txt)s", customer_name), locate("%(_txt)s", name), 99999),
name, customer_name
limit %(start)s, %(page_len)s""" % {'field': fields,'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype),
'txt': "%%%s%%" % txt, '_txt': txt.replace("%", ""),
'mcond':get_match_cond(doctype),
'start': start, 'page_len': page_len})
# searches for supplier
@ -98,11 +101,12 @@ def supplier_query(doctype, txt, searchfield, start, page_len, filters):
or supplier_name like "%(txt)s")
%(mcond)s
order by
case when name like "%(txt)s" then 0 else 1 end,
case when supplier_name like "%(txt)s" then 0 else 1 end,
if(locate("%(_txt)s", name), locate("%(_txt)s", name), 99999),
if(locate("%(_txt)s", supplier_name), locate("%(_txt)s", name), 99999),
name, supplier_name
limit %(start)s, %(page_len)s """ % {'field': fields,'key': searchfield,
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype), 'start': start,
'txt': "%%%s%%" % txt, '_txt': txt.replace("%", ""),
'mcond':get_match_cond(doctype), 'start': start,
'page_len': page_len})
def tax_account_query(doctype, txt, searchfield, start, page_len, filters):
@ -141,12 +145,17 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
and (tabItem.`{key}` LIKE %(txt)s
or tabItem.item_name LIKE %(txt)s)
{fcond} {mcond}
order by
if(locate(%(_txt)s, name), locate(%(_txt)s, name), 99999),
if(locate(%(_txt)s, item_name), locate(%(_txt)s, item_name), 99999),
name, item_name
limit %(start)s, %(page_len)s """.format(key=searchfield,
fcond=get_filters_cond(doctype, filters, conditions),
mcond=get_match_cond(doctype)),
{
"today": nowdate(),
"txt": "%%%s%%" % txt,
"_txt": txt.replace("%", ""),
"start": start,
"page_len": page_len
})

View File

@ -6,10 +6,10 @@ import frappe
from frappe.utils import cstr, flt, nowdate
from frappe import _
from frappe.model.document import Document
class OverProductionError(frappe.ValidationError): pass
from frappe.model.document import Document
class StockOverProductionError(frappe.ValidationError): pass
class ProductionOrder(Document):
@ -89,21 +89,41 @@ class ProductionOrder(Document):
frappe.msgprint(_("Production Order status is {0}").format(status))
def update_status(self, status):
if status == 'Stopped':
frappe.db.set(self, 'status', cstr(status))
else:
if flt(self.qty) == flt(self.produced_qty):
frappe.db.set(self, 'status', 'Completed')
if flt(self.qty) > flt(self.produced_qty):
frappe.db.set(self, 'status', 'In Process')
if flt(self.produced_qty) == 0:
frappe.db.set(self, 'status', 'Submitted')
def update_status(self, status=None):
if not status:
status = self.status
if status != 'Stopped':
stock_entries = frappe._dict(frappe.db.sql("""select purpose, sum(fg_completed_qty)
from `tabStock Entry` where production_order=%s and docstatus=1
group by purpose""", self.name))
status = "Submitted"
if stock_entries:
status = "In Process"
produced_qty = stock_entries.get("Manufacture/Repack")
if flt(produced_qty) == flt(self.qty):
status = "Completed"
if status != self.status:
self.db_set("status", status)
def update_produced_qty(self):
produced_qty = frappe.db.sql("""select sum(fg_completed_qty)
from `tabStock Entry` where production_order=%s and docstatus=1
and purpose='Manufacture/Repack'""", self.name)
produced_qty = flt(produced_qty[0][0]) if produced_qty else 0
if produced_qty > self.qty:
frappe.throw(_("Cannot manufacture more than the planned Quantity to Manufacture ({0}) in Production Order: {1}").format(self.qty, self.name), StockOverProductionError)
self.db_set("produced_qty", produced_qty)
def on_submit(self):
if not self.wip_warehouse:
frappe.throw(_("WIP Warehouse required before Submit"))
frappe.throw(_("Work-in-Progress Warehouse is required before Submit"))
if not self.fg_warehouse:
frappe.throw(_("For Warehouse is required before Submit"))
frappe.db.set(self,'status', 'Submitted')
self.update_planned_qty(self.qty)

View File

@ -49,7 +49,7 @@ class TestProductionOrder(unittest.TestCase):
return pro_doc.name
def test_over_production(self):
from erpnext.stock.doctype.stock_entry.stock_entry import StockOverProductionError
from erpnext.manufacturing.doctype.production_order.production_order import StockOverProductionError
pro_order = self.test_planned_qty()
stock_entry = make_stock_entry(pro_order, "Manufacture/Repack")

View File

@ -24,8 +24,10 @@ $.extend(erpnext.queries, {
return { query: "erpnext.controllers.queries.account_query" };
},
item: function() {
return { query: "erpnext.controllers.queries.item_query" };
item: function(filters) {
var args = { query: "erpnext.controllers.queries.item_query" };
if(filters) args["filters"] = filters;
return args;
},
bom: function() {
@ -38,25 +40,25 @@ $.extend(erpnext.queries, {
customer_filter: function(doc) {
if(!doc.customer) {
frappe.throw(__("Please specify a") + " " +
frappe.throw(__("Please specify a") + " " +
__(frappe.meta.get_label(doc.doctype, "customer", doc.name)));
}
return { filters: { customer: doc.customer } };
},
supplier_filter: function(doc) {
if(!doc.supplier) {
frappe.throw(__("Please specify a") + " " +
frappe.throw(__("Please specify a") + " " +
__(frappe.meta.get_label(doc.doctype, "supplier", doc.name)));
}
return { filters: { supplier: doc.supplier } };
},
lead_filter: function(doc) {
if(!doc.lead) {
frappe.throw(__("Please specify a") + " " +
frappe.throw(__("Please specify a") + " " +
__(frappe.meta.get_label(doc.doctype, "lead", doc.name)));
}
@ -66,4 +68,4 @@ $.extend(erpnext.queries, {
not_a_group_filter: function() {
return { filters: { is_group: "No" } };
},
});
});

View File

@ -189,7 +189,7 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
},
validate: function() {
this.calculate_taxes_and_totals();
this.calculate_taxes_and_totals(false);
},
company: function() {
@ -299,7 +299,8 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
this.calculate_taxes_and_totals();
},
tax_rate: function(doc, cdt, cdn) {
// tax rate
rate: function(doc, cdt, cdn) {
this.calculate_taxes_and_totals();
},
@ -372,7 +373,6 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
var on_previous_row_error = function(row_range) {
var msg = __("For row {0} in {1}. To include {2} in Item rate, rows {3} must also be included",
[tax.idx, __(tax.doctype), tax.charge_type, row_range])
frappe.throw(msg);
};
@ -680,14 +680,14 @@ erpnext.TransactionController = erpnext.stock.StockController.extend({
});
},
calculate_total_advance: function(parenttype, advance_parentfield) {
calculate_total_advance: function(parenttype, advance_parentfield, update_paid_amount) {
if(this.frm.doc.doctype == parenttype && this.frm.doc.docstatus < 2) {
var advance_doclist = this.frm.doc[advance_parentfield] || [];
this.frm.doc.total_advance = flt(frappe.utils.sum(
$.map(advance_doclist, function(adv) { return adv.allocated_amount })
), precision("total_advance"));
this.calculate_outstanding_amount();
this.calculate_outstanding_amount(update_paid_amount);
}
},

View File

@ -235,9 +235,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
}
},
calculate_taxes_and_totals: function() {
calculate_taxes_and_totals: function(update_paid_amount) {
this._super();
this.calculate_total_advance("Sales Invoice", "advance_adjustment_details");
this.calculate_total_advance("Sales Invoice", "advance_adjustment_details", update_paid_amount);
this.calculate_commission();
this.calculate_contribution();
@ -398,7 +398,7 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
return grand_total_for_discount_amount;
},
calculate_outstanding_amount: function() {
calculate_outstanding_amount: function(update_paid_amount) {
// NOTE:
// paid_amount and write_off_amount is only for POS Invoice
// total_advance is only for non POS Invoice
@ -408,7 +408,9 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
var total_amount_to_pay = this.frm.doc.grand_total - this.frm.doc.write_off_amount
- this.frm.doc.total_advance;
if(this.frm.doc.is_pos) {
if(!this.frm.doc.paid_amount) this.frm.doc.paid_amount = flt(total_amount_to_pay);
if(!this.frm.doc.paid_amount || update_paid_amount===undefined || update_paid_amount) {
this.frm.doc.paid_amount = flt(total_amount_to_pay);
}
} else {
this.frm.doc.paid_amount = 0
}

View File

@ -58,13 +58,14 @@ class LandedCostWizard(Document):
ch.rate = amt
ch.tax_amount = amt
ch.docstatus = 1
ch.save(1)
ch.db_insert()
else: # overwrite if exists
matched_row[0].rate = amt
matched_row[0].tax_amount = amt
matched_row[0].cost_center = lc.cost_center
pr_doc.run_method("validate")
pr_doc._validate_mandatory()
for d in pr_doc.get_all_children():
d.db_update()

View File

@ -8,3 +8,9 @@ cur_frm.add_fetch("item_code", "item_name", "item_name")
cur_frm.add_fetch("item_code", "description", "description")
cur_frm.add_fetch("item_code", "item_group", "item_group")
cur_frm.add_fetch("item_code", "brand", "brand")
cur_frm.cscript.onload = function() {
cur_frm.set_query("item_code", function() {
return erpnext.queries.item({"is_stock_item": "Yes", "has_serial_no": "Yes"})
});
}

View File

@ -18,7 +18,6 @@ class NotUpdateStockError(frappe.ValidationError): pass
class StockOverReturnError(frappe.ValidationError): pass
class IncorrectValuationRateError(frappe.ValidationError): pass
class DuplicateEntryForProductionOrderError(frappe.ValidationError): pass
class StockOverProductionError(frappe.ValidationError): pass
from erpnext.controllers.stock_controller import StockController
@ -314,24 +313,11 @@ class StockEntry(StockController):
if self.production_order:
pro_doc = frappe.get_doc("Production Order", self.production_order)
_validate_production_order(pro_doc)
self.update_produced_qty(pro_doc)
pro_doc.run_method("update_status")
if self.purpose == "Manufacture/Repack":
pro_doc.run_method("update_produced_qty")
self.update_planned_qty(pro_doc)
def update_produced_qty(self, pro_doc):
if self.purpose == "Manufacture/Repack":
produced_qty = flt(pro_doc.produced_qty) + \
(self.docstatus==1 and 1 or -1 ) * flt(self.fg_completed_qty)
if produced_qty > flt(pro_doc.qty):
frappe.throw(_("Production Order") + ": " + self.production_order + "\n" +
_("Total Manufactured Qty can not be greater than Planned qty to manufacture")
+ "(%s/%s)" % (produced_qty, flt(pro_doc.qty)), StockOverProductionError)
status = 'Completed' if flt(produced_qty) >= flt(pro_doc.qty) else 'In Process'
frappe.db.sql("""update `tabProduction Order` set status=%s, produced_qty=%s
where name=%s""", (status, produced_qty, self.production_order))
def update_planned_qty(self, pro_doc):
from erpnext.stock.utils import update_bin
update_bin({

View File

@ -3,20 +3,20 @@
frappe.provide("erpnext.support");
frappe.ui.form.on_change("Customer Issue", "customer", function(frm) {
frappe.ui.form.on_change("Customer Issue", "customer", function(frm) {
erpnext.utils.get_party_details(frm) });
frappe.ui.form.on_change("Customer Issue", "customer_address",
frappe.ui.form.on_change("Customer Issue", "customer_address",
erpnext.utils.get_address_display);
frappe.ui.form.on_change("Customer Issue", "contact_person",
erpnext.utils.get_contact_details);
frappe.ui.form.on_change("Customer Issue", "contact_person",
erpnext.utils.get_contact_details);
erpnext.support.CustomerIssue = frappe.ui.form.Controller.extend({
refresh: function() {
if((cur_frm.doc.status=='Open' || cur_frm.doc.status == 'Work In Progress')) {
cur_frm.add_custom_button(__('Make Maintenance Visit'), this.make_maintenance_visit)
}
},
},
make_maintenance_visit: function() {
frappe.model.open_mapped_doc({
method: "erpnext.support.doctype.customer_issue.customer_issue.make_maintenance_visit",
@ -28,8 +28,8 @@ erpnext.support.CustomerIssue = frappe.ui.form.Controller.extend({
$.extend(cur_frm.cscript, new erpnext.support.CustomerIssue({frm: cur_frm}));
cur_frm.cscript.onload = function(doc,cdt,cdn){
if(!doc.status)
set_multiple(dt,dn,{status:'Open'});
if(!doc.status)
set_multiple(dt,dn,{status:'Open'});
}
cur_frm.fields_dict['customer_address'].get_query = function(doc, cdt, cdn) {
@ -66,7 +66,6 @@ cur_frm.add_fetch('serial_no', 'warranty_expiry_date', 'warranty_expiry_date');
cur_frm.add_fetch('serial_no', 'amc_expiry_date', 'amc_expiry_date');
cur_frm.add_fetch('serial_no', 'customer', 'customer');
cur_frm.add_fetch('serial_no', 'customer_name', 'customer_name');
cur_frm.add_fetch('serial_no', 'delivery_address', 'customer_address');
cur_frm.add_fetch('item_code', 'item_name', 'item_name');
cur_frm.add_fetch('item_code', 'description', 'description');
@ -74,14 +73,14 @@ cur_frm.fields_dict['item_code'].get_query = function(doc, cdt, cdn) {
if(doc.serial_no) {
return{
filters:{ 'serial_no': doc.serial_no}
}
}
}
else{
return{
filters:[
['Item', 'docstatus', '!=', 2]
]
}
}
}
}