Merge remote-tracking branch 'frappe/develop' into wip-4.1
This commit is contained in:
commit
5780163fb7
@ -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;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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"))
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
35
erpnext/patches/v4_0/create_price_list_if_missing.py
Normal file
35
erpnext/patches/v4_0/create_price_list_if_missing.py
Normal 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()
|
@ -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():
|
||||
|
@ -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)
|
@ -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){
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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"]:
|
||||
|
@ -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)
|
||||
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user