Merge remote-tracking branch 'frappe/develop' into wip-4.1

This commit is contained in:
Anand Doshi 2014-06-17 14:58:18 +05:30
commit 5780163fb7
18 changed files with 137 additions and 37 deletions

View File

@ -7,8 +7,10 @@ frappe.listview_settings['Sales Invoice'] = {
add_columns: [{"content":"Percent Paid", width:"10%", type:"bar-graph",
label: "Payment Received"}],
prepare_data: function(data) {
data["Percent Paid"] = (data.docstatus===1 && flt(data.grand_total))
? (((flt(data.grand_total) - flt(data.outstanding_amount)) / flt(data.grand_total)) * 100)
: 0;
if (data.docstatus === 1) {
data["Percent Paid"] = flt(data.grand_total)
? (((flt(data.grand_total) - flt(data.outstanding_amount)) / flt(data.grand_total)) * 100)
: 100.0;
}
}
};

View File

@ -206,11 +206,11 @@ erpnext.FinancialAnalytics = erpnext.AccountTreeGrid.extend({
if(me.pl_or_bs=='Balance Sheet') {
$.each(me.data, function(i, ac) {
if((ac.rgt - ac.lft)==1 && ac.report_type=='Balance Sheet') {
var opening = 0;
var opening = flt(ac["opening_dr"]) - flt(ac["opening_cr"]);
//if(opening) throw opening;
$.each(me.columns, function(i, col) {
if(col.formatter==me.currency_formatter) {
if(col.balance_type=="Dr") {
if(col.balance_type=="Dr" && !in_list(["opening_dr", "opening_cr"], col.field)) {
opening = opening + flt(ac[col.date + "_dr"]) -
flt(ac[col.date + "_cr"]);
me.set_debit_or_credit(ac, col.date, opening);

View File

@ -52,9 +52,8 @@ class BuyingController(StockController):
validate_warehouse_company(w, self.company)
def validate_stock_or_nonstock_items(self):
if not self.get_stock_items():
tax_for_valuation = [d.account_head for d in
self.get("other_charges")
if self.meta.get_field("other_charges") and not self.get_stock_items():
tax_for_valuation = [d.account_head for d in self.get("other_charges")
if d.category in ["Valuation", "Valuation and Total"]]
if tax_for_valuation:
frappe.throw(_("Tax Category can not be 'Valuation' or 'Valuation and Total' as all items are non-stock items"))

View File

@ -141,7 +141,7 @@ def item_query(doctype, txt, searchfield, start, page_len, filters):
concat(substr(tabItem.description, 1, 40), "..."), description) as decription
from tabItem
where tabItem.docstatus < 2
and (ifnull(tabItem.end_of_life, '') = '' or tabItem.end_of_life > %(today)s)
and (tabItem.end_of_life is null or tabItem.end_of_life > %(today)s)
and (tabItem.`{key}` LIKE %(txt)s
or tabItem.item_name LIKE %(txt)s)
{fcond} {mcond}
@ -236,13 +236,21 @@ def get_batch_no(doctype, txt, searchfield, start, page_len, filters):
'page_len': page_len})
def get_account_list(doctype, txt, searchfield, start, page_len, filters):
if isinstance(filters, dict):
if not filters.get("group_or_ledger"):
filters["group_or_ledger"] = "Ledger"
elif isinstance(filters, list):
if "group_or_ledger" not in [d[0] for d in filters]:
filters.append(["Account", "group_or_ledger", "=", "Ledger"])
filter_list = []
return frappe.widgets.reportview.execute("Account", filters = filters,
if isinstance(filters, dict):
for key, val in filters.items():
if isinstance(val, (list, tuple)):
filter_list.append([doctype, key, val[0], val[1]])
else:
filter_list.append([doctype, key, "=", val])
if "group_or_ledger" not in [d[1] for d in filter_list]:
filter_list.append(["Account", "group_or_ledger", "=", "Ledger"])
if searchfield and txt:
filter_list.append([doctype, searchfield, "like", "%%%s%%" % txt])
return frappe.widgets.reportview.execute("Account", filters = filter_list,
fields = ["name", "parent_account"],
limit_start=start, limit_page_length=page_len, as_list=True)

View File

@ -19,7 +19,7 @@ class SellingController(StockController):
if frappe.db.get_value('Sales Email Settings', None, 'extract_emails'):
return frappe.db.get_value('Sales Email Settings', None, 'email_id')
else:
return frappe.session.user
return comm.sender or frappe.session.user
def set_missing_values(self, for_validate=False):
super(SellingController, self).set_missing_values(for_validate)

View File

@ -128,7 +128,7 @@ class SalaryManager(Document):
for ss in ss_list:
ss_obj = frappe.get_doc("Salary Slip",ss[0])
try:
frappe.db.set(ss_obj, 'email_check', cint(self.send_mail))
frappe.db.set(ss_obj, 'email_check', cint(self.send_email))
if cint(self.send_email) == 1:
ss_obj.send_mail_funct()

View File

@ -58,3 +58,6 @@ execute:frappe.reset_perms("Stock Ledger Entry") #2014-06-09
erpnext.patches.v4_0.create_custom_fields_for_india_specific_fields
erpnext.patches.v4_0.save_default_letterhead
erpnext.patches.v4_0.update_custom_print_formats_for_renamed_fields
erpnext.patches.v4_0.update_other_charges_in_custom_purchase_print_formats
erpnext.patches.v4_0.create_price_list_if_missing
execute:frappe.db.sql("update `tabItem` set end_of_life=null where end_of_life='0000-00-00'") #2014-06-16

View File

@ -27,7 +27,9 @@ def update_hr_permissions():
# save employees to run on_update events
for employee in frappe.db.sql_list("""select name from `tabEmployee` where docstatus < 2"""):
try:
frappe.get_doc("Employee", employee).save()
emp = frappe.get_doc("Employee", employee)
emp.ignore_mandatory = True
emp.save()
except EmployeeUserDisabledError:
pass

View File

@ -0,0 +1,35 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
from frappe import _
from frappe.utils.nestedset import get_root_of
def execute():
# setup not complete
if not frappe.db.sql("""select name from tabCompany limit 1"""):
return
if "shopping_cart" in frappe.get_installed_apps():
frappe.reload_doc("shopping_cart", "doctype", "shopping_cart_settings")
if not frappe.db.sql("select name from `tabPrice List` where buying=1"):
create_price_list(_("Standard Buying"), buying=1)
if not frappe.db.sql("select name from `tabPrice List` where selling=1"):
create_price_list(_("Standard Selling"), selling=1)
def create_price_list(pl_name, buying=0, selling=0):
price_list = frappe.get_doc({
"doctype": "Price List",
"price_list_name": pl_name,
"enabled": 1,
"buying": buying,
"selling": selling,
"currency": frappe.db.get_default("currency"),
"valid_for_territories": [{
"territory": get_root_of("Territory")
}]
})
price_list.insert()

View File

@ -28,6 +28,7 @@ def map_outgoing_email_settings(email_settings):
outgoing_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
outgoing_email_settings._fix_numeric_types()
outgoing_email_settings.save()
def map_support_email_settings(email_settings):
@ -47,6 +48,7 @@ def map_support_email_settings(email_settings):
support_email_settings.set(to_fieldname, email_settings.get(from_fieldname))
support_email_settings._fix_numeric_types()
support_email_settings.save()
def get_email_settings():

View File

@ -0,0 +1,12 @@
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import re
def execute():
for name, html in frappe.db.sql("""select name, html from `tabPrint Format`
where standard = 'No' and html like '%%purchase\\_tax\\_details%%'"""):
html = re.sub(r"\bpurchase_tax_details\b", "other_charges", html)
frappe.db.set_value("Print Format", name, "html", html)

View File

@ -118,10 +118,10 @@ cur_frm.fields_dict['transporter_name'].get_query = function(doc) {
}
cur_frm.cscript['Make Packing Slip'] = function() {
n = frappe.model.make_new_doc_and_get_name('Packing Slip');
ps = locals["Packing Slip"][n];
ps.delivery_note = cur_frm.doc.name;
loaddoc('Packing Slip', n);
frappe.model.open_mapped_doc({
method: "erpnext.stock.doctype.delivery_note.delivery_note.make_packing_slip",
frm: cur_frm
})
}
var set_print_hide= function(doc, cdt, cdn){

View File

@ -68,13 +68,14 @@ class DeliveryNote(SellingController):
self.validate_for_items()
self.validate_warehouse()
self.validate_uom_is_integer("stock_uom", "qty")
self.update_current_stock()
self.validate_with_previous_doc()
from erpnext.stock.doctype.packed_item.packed_item import make_packing_list
make_packing_list(self, 'delivery_note_details')
self.status = 'Draft'
self.update_current_stock()
if not self.status: self.status = 'Draft'
if not self.installation_status: self.installation_status = 'Not Installed'
def validate_with_previous_doc(self):
@ -133,14 +134,17 @@ class DeliveryNote(SellingController):
def update_current_stock(self):
for d in self.get('delivery_note_details'):
bin = frappe.db.sql("select actual_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
if self._action != "update_after_submit":
for d in self.get('delivery_note_details'):
d.actual_qty = frappe.db.get_value("Bin", {"item_code": d.item_code,
"warehouse": d.warehouse}, "actual_qty")
for d in self.get('packing_details'):
bin = frappe.db.sql("select actual_qty, projected_qty from `tabBin` where item_code = %s and warehouse = %s", (d.item_code, d.warehouse), as_dict = 1)
d.actual_qty = bin and flt(bin[0]['actual_qty']) or 0
d.projected_qty = bin and flt(bin[0]['projected_qty']) or 0
for d in self.get('packing_details'):
bin_qty = frappe.db.get_value("Bin", {"item_code": d.item_code,
"warehouse": d.warehouse}, ["actual_qty", "projected_qty"], as_dict=True)
if bin_qty:
d.actual_qty = flt(bin_qty.actual_qty)
d.projected_qty = flt(bin_qty.projected_qty)
def on_submit(self):
self.validate_packed_qty()
@ -346,3 +350,19 @@ def make_installation_note(source_name, target_doc=None):
}, target_doc)
return doclist
@frappe.whitelist()
def make_packing_slip(source_name, target_doc=None):
doclist = get_mapped_doc("Delivery Note", source_name, {
"Delivery Note": {
"doctype": "Packing Slip",
"field_map": {
"name": "delivery_note"
},
"validation": {
"docstatus": ["=", 0]
}
}
}, target_doc)
return doclist

View File

@ -48,7 +48,7 @@ class MaterialRequest(BuyingController):
def validate_schedule_date(self):
for d in self.get('indent_details'):
if d.schedule_date < self.transaction_date:
if d.schedule_date and d.schedule_date < self.transaction_date:
frappe.throw(_("Expected Date cannot be before Material Request Date"))
# Validate

View File

@ -18,7 +18,7 @@ cur_frm.fields_dict['item_details'].grid.get_field('item_code').get_query =
cur_frm.cscript.onload_post_render = function(doc, cdt, cdn) {
if(doc.delivery_note && doc.__islocal) {
cur_frm.cscript.get_items(doc, cdt, cdn);
cur_frm.cscript.get_items(doc, cdt, cdn);
}
}

View File

@ -51,6 +51,7 @@ class PriceList(Document):
if self.name == b.get(price_list_fieldname):
b.set(price_list_fieldname, None)
b.ignore_permissions = True
b.save()
for module in ["Selling", "Buying"]:

View File

@ -70,6 +70,9 @@ class StockEntry(StockController):
def set_transfer_qty(self):
for item in self.get("mtn_details"):
if not flt(item.qty):
frappe.throw(_("Row {0}: Qty is mandatory").format(item.idx))
item.transfer_qty = flt(item.qty * item.conversion_factor, self.precision("transfer_qty", item))
def validate_item(self):
@ -191,6 +194,11 @@ class StockEntry(StockController):
raw_material_cost = 0.0
if not self.posting_date or not self.posting_time:
frappe.throw(_("Posting date and posting time is mandatory"))
allow_negative_stock = frappe.db.get_value("Stock Settings", None, "allow_negative_stock")
for d in self.get('mtn_details'):
args = frappe._dict({
"item_code": d.item_code,
@ -200,13 +208,21 @@ class StockEntry(StockController):
"qty": d.s_warehouse and -1*d.transfer_qty or d.transfer_qty,
"serial_no": d.serial_no
})
# get actual stock at source warehouse
d.actual_qty = get_previous_sle(args).get("qty_after_transaction") or 0
if d.s_warehouse and not allow_negative_stock and d.actual_qty <= d.transfer_qty:
frappe.throw(_("""Row {0}: Qty not avalable in warehouse {1} on {2} {3}.
Available Qty: {4}, Transfer Qty: {5}""").format(d.idx, d.s_warehouse,
self.posting_date, self.posting_time, d.actual_qty, d.transfer_qty))
# get incoming rate
if not d.bom_no:
if not flt(d.incoming_rate):
d.incoming_rate = self.get_incoming_rate(args)
if not flt(d.incoming_rate) or d.s_warehouse or self.purpose == "Sales Return":
incoming_rate = self.get_incoming_rate(args)
if incoming_rate:
d.incoming_rate = incoming_rate
d.amount = flt(d.transfer_qty) * flt(d.incoming_rate)
raw_material_cost += flt(d.amount)

View File

@ -255,7 +255,7 @@ def apply_pricing_rule(args):
args = frappe._dict(args)
out = frappe._dict()
if not args.get("item_code"): return
if args.get("doctype") == "Material Request" or not args.get("item_code"): return out
if not args.get("item_group") or not args.get("brand"):
args.item_group, args.brand = frappe.db.get_value("Item",