Merged develop into v5
This commit is contained in:
commit
a1bf43b1a6
@ -18,17 +18,17 @@ class CForm(Document):
|
|||||||
`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
|
`tabSales Invoice` where name = %s and docstatus = 1""", d.invoice_no)
|
||||||
|
|
||||||
if inv and inv[0][0] != 'Yes':
|
if inv and inv[0][0] != 'Yes':
|
||||||
frappe.throw("C-form is not applicable for Invoice: %s" % d.invoice_no)
|
frappe.throw("C-form is not applicable for Invoice: {0}".format(d.invoice_no))
|
||||||
|
|
||||||
elif inv and inv[0][1] and inv[0][1] != self.name:
|
elif inv and inv[0][1] and inv[0][1] != self.name:
|
||||||
frappe.throw("""Invoice %s is tagged in another C-form: %s.
|
frappe.throw("""Invoice {0} is tagged in another C-form: {1}.
|
||||||
If you want to change C-form no for this invoice,
|
If you want to change C-form no for this invoice,
|
||||||
please remove invoice no from the previous c-form and then try again""" %
|
please remove invoice no from the previous c-form and then try again"""\
|
||||||
(d.invoice_no, inv[0][1]))
|
.format(d.invoice_no, inv[0][1]))
|
||||||
|
|
||||||
elif not inv:
|
elif not inv:
|
||||||
frappe.throw("Row %s: Invoice %s is invalid, it might be cancelled / does not exist. \
|
frappe.throw("Row {0}: Invoice {1} is invalid, it might be cancelled / does not exist. \
|
||||||
Please enter a valid Invoice" % d.idx, d.invoice_no)
|
Please enter a valid Invoice".format(d.idx, d.invoice_no))
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
""" Update C-Form No on invoices"""
|
""" Update C-Form No on invoices"""
|
||||||
|
@ -230,7 +230,7 @@ cur_frm.cscript.hide_fields = function(doc) {
|
|||||||
cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_normal, true);
|
cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_normal, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse']
|
item_flds_stock = ['serial_no', 'batch_no', 'actual_qty', 'expense_account', 'warehouse', 'expense_account', 'warehouse']
|
||||||
cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_stock,
|
cur_frm.fields_dict['items'].grid.set_column_disp(item_flds_stock,
|
||||||
(cint(doc.update_stock)==1 ? true : false));
|
(cint(doc.update_stock)==1 ? true : false));
|
||||||
|
|
||||||
|
@ -613,7 +613,6 @@ def get_income_account(doctype, txt, searchfield, start, page_len, filters):
|
|||||||
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
|
%(mcond)s""" % {'company': filters['company'], 'key': searchfield,
|
||||||
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
|
'txt': "%%%s%%" % txt, 'mcond':get_match_cond(doctype)})
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_delivery_note(source_name, target_doc=None):
|
def make_delivery_note(source_name, target_doc=None):
|
||||||
def set_missing_values(source, target):
|
def set_missing_values(source, target):
|
||||||
|
@ -391,6 +391,19 @@
|
|||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"fieldname": "actual_batch_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Available Batch Qty at Warehouse",
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_width": "150px",
|
||||||
|
"read_only": 1,
|
||||||
|
"width": "150px"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "actual_qty",
|
"fieldname": "actual_qty",
|
||||||
@ -491,7 +504,7 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-02-23 15:55:23.143072",
|
"modified": "2015-03-10 14:56:45.641026",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice Item",
|
"name": "Sales Invoice Item",
|
||||||
|
@ -119,6 +119,8 @@ class AccountsController(TransactionBase):
|
|||||||
if item.get("item_code"):
|
if item.get("item_code"):
|
||||||
args = parent_dict.copy()
|
args = parent_dict.copy()
|
||||||
args.update(item.as_dict())
|
args.update(item.as_dict())
|
||||||
|
if not args.get("transaction_date"):
|
||||||
|
args["transaction_date"] = args.get("posting_date")
|
||||||
ret = get_item_details(args)
|
ret = get_item_details(args)
|
||||||
|
|
||||||
for fieldname, value in ret.items():
|
for fieldname, value in ret.items():
|
||||||
@ -165,7 +167,6 @@ class AccountsController(TransactionBase):
|
|||||||
if frappe.db.get_value(taxes_and_charges_doctype, self.taxes_and_charges, "disabled"):
|
if frappe.db.get_value(taxes_and_charges_doctype, self.taxes_and_charges, "disabled"):
|
||||||
frappe.throw(_("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges))
|
frappe.throw(_("{0} '{1}' is disabled").format(taxes_and_charges_doctype, self.taxes_and_charges))
|
||||||
|
|
||||||
|
|
||||||
def get_gl_dict(self, args):
|
def get_gl_dict(self, args):
|
||||||
"""this method populates the common properties of a gl entry record"""
|
"""this method populates the common properties of a gl entry record"""
|
||||||
gl_dict = frappe._dict({
|
gl_dict = frappe._dict({
|
||||||
|
@ -31,6 +31,7 @@ class calculate_taxes_and_totals(object):
|
|||||||
self.determine_exclusive_rate()
|
self.determine_exclusive_rate()
|
||||||
self.calculate_net_total()
|
self.calculate_net_total()
|
||||||
self.calculate_taxes()
|
self.calculate_taxes()
|
||||||
|
self.manipulate_grand_total_for_inclusive_tax()
|
||||||
self.calculate_totals()
|
self.calculate_totals()
|
||||||
self._cleanup()
|
self._cleanup()
|
||||||
|
|
||||||
@ -282,6 +283,21 @@ class calculate_taxes_and_totals(object):
|
|||||||
|
|
||||||
self._set_in_company_currency(tax, ["total", "tax_amount_after_discount_amount"])
|
self._set_in_company_currency(tax, ["total", "tax_amount_after_discount_amount"])
|
||||||
|
|
||||||
|
def manipulate_grand_total_for_inclusive_tax(self):
|
||||||
|
# if fully inclusive taxes and diff
|
||||||
|
if self.doc.get("taxes") and all(cint(t.included_in_print_rate) for t in self.doc.get("taxes")):
|
||||||
|
|
||||||
|
last_tax = self.doc.get("taxes")[-1]
|
||||||
|
|
||||||
|
diff = self.doc.net_total - flt(last_tax.total / self.doc.conversion_rate,
|
||||||
|
self.precision("grand_total_export"))
|
||||||
|
|
||||||
|
if diff and abs(diff) <= (2.0 / 10**last_tax.precision("tax_amount")):
|
||||||
|
adjustment_amount = flt(diff * self.doc.conversion_rate, last_tax.precision("tax_amount"))
|
||||||
|
last_tax.tax_amount += adjustment_amount
|
||||||
|
last_tax.tax_amount_after_discount_amount += adjustment_amount
|
||||||
|
last_tax.total += adjustment_amount
|
||||||
|
|
||||||
def calculate_totals(self):
|
def calculate_totals(self):
|
||||||
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total
|
self.doc.grand_total = flt(self.doc.get("taxes")[-1].total
|
||||||
if self.doc.get("taxes") else self.doc.net_total)
|
if self.doc.get("taxes") else self.doc.net_total)
|
||||||
|
@ -131,3 +131,5 @@ erpnext.patches.v5_0.update_account_types
|
|||||||
erpnext.patches.v5_0.update_sms_sender
|
erpnext.patches.v5_0.update_sms_sender
|
||||||
erpnext.patches.v5_0.set_appraisal_remarks
|
erpnext.patches.v5_0.set_appraisal_remarks
|
||||||
erpnext.patches.v5_0.update_time_log_title
|
erpnext.patches.v5_0.update_time_log_title
|
||||||
|
erpnext.patches.v4_2.repost_reserved_qty
|
||||||
|
erpnext.patches.v4_2.repost_sle_for_si_with_no_warehouse
|
||||||
|
12
erpnext/patches/v4_2/repost_reserved_qty.py
Normal file
12
erpnext/patches/v4_2/repost_reserved_qty.py
Normal 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
|
||||||
|
from erpnext.utilities.repost_stock import update_bin_qty, get_reserved_qty
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
for item_code, warehouse in frappe.db.sql("select item_code, warehouse from tabBin where ifnull(reserved_qty, 0) < 0"):
|
||||||
|
update_bin_qty(item_code, warehouse, {
|
||||||
|
"reserved_qty": get_reserved_qty(item_code, warehouse)
|
||||||
|
})
|
34
erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
Normal file
34
erpnext/patches/v4_2/repost_sle_for_si_with_no_warehouse.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# 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 erpnext.stock.stock_ledger import NegativeStockError
|
||||||
|
|
||||||
|
def execute():
|
||||||
|
si_list = frappe.db.sql("""select distinct si.name
|
||||||
|
from `tabSales Invoice Item` si_item, `tabSales Invoice` si
|
||||||
|
where si.name = si_item.parent and si.modified > '2015-02-16' and si.docstatus=1
|
||||||
|
and ifnull(si_item.warehouse, '') = '' and ifnull(si.update_stock, 0) = 1
|
||||||
|
order by posting_date, posting_time""", as_dict=1)
|
||||||
|
|
||||||
|
failed_list = []
|
||||||
|
for si in si_list:
|
||||||
|
try:
|
||||||
|
si_doc = frappe.get_doc("Sales Invoice", si.name)
|
||||||
|
si_doc.docstatus = 2
|
||||||
|
si_doc.on_cancel()
|
||||||
|
|
||||||
|
si_doc.docstatus = 1
|
||||||
|
si_doc.set_missing_item_details()
|
||||||
|
si_doc.on_submit()
|
||||||
|
frappe.db.commit()
|
||||||
|
except:
|
||||||
|
failed_list.append(si.name)
|
||||||
|
frappe.local.stockledger_exceptions = None
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
print "Failed to repost: ", failed_list
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -33,6 +33,7 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({
|
|||||||
this.determine_exclusive_rate();
|
this.determine_exclusive_rate();
|
||||||
this.calculate_net_total();
|
this.calculate_net_total();
|
||||||
this.calculate_taxes();
|
this.calculate_taxes();
|
||||||
|
this.manipulate_grand_total_for_inclusive_tax();
|
||||||
this.calculate_totals();
|
this.calculate_totals();
|
||||||
this._cleanup();
|
this._cleanup();
|
||||||
this.show_item_wise_taxes();
|
this.show_item_wise_taxes();
|
||||||
@ -320,6 +321,31 @@ erpnext.taxes_and_totals = erpnext.stock.StockController.extend({
|
|||||||
tax.total = flt(tax.total + discount_amount_loss, precision("total", tax));
|
tax.total = flt(tax.total + discount_amount_loss, precision("total", tax));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
manipulate_grand_total_for_inclusive_tax: function() {
|
||||||
|
var me = this;
|
||||||
|
// if fully inclusive taxes and diff
|
||||||
|
if (this.frm.doc["taxes"].length) {
|
||||||
|
var all_inclusive = frappe.utils.all(this.frm.doc["taxes"].map(function(d) {
|
||||||
|
return cint(d.included_in_print_rate);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (all_inclusive) {
|
||||||
|
var last_tax = me.frm.doc["taxes"].slice(-1)[0];
|
||||||
|
|
||||||
|
var diff = me.frm.doc.net_total
|
||||||
|
- flt(last_tax.total / me.frm.doc.conversion_rate, precision("grand_total"));
|
||||||
|
|
||||||
|
if ( diff && Math.abs(diff) <= (2.0 / Math.pow(10, last_tax.precision("tax_amount"))) ) {
|
||||||
|
var adjustment_amount = flt(diff * me.frm.doc.conversion_rate,
|
||||||
|
last_tax.precision("tax_amount"));
|
||||||
|
last_tax.tax_amount += adjustment_amount;
|
||||||
|
last_tax.tax_amount_after_discount += adjustment_amount;
|
||||||
|
last_tax.total += adjustment_amount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
calculate_totals: function() {
|
calculate_totals: function() {
|
||||||
// Changing sequence can cause roundiing issue and on-screen discrepency
|
// Changing sequence can cause roundiing issue and on-screen discrepency
|
||||||
var me = this;
|
var me = this;
|
||||||
|
@ -109,7 +109,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
|||||||
order_type: me.frm.doc.order_type,
|
order_type: me.frm.doc.order_type,
|
||||||
is_pos: cint(me.frm.doc.is_pos),
|
is_pos: cint(me.frm.doc.is_pos),
|
||||||
is_subcontracted: me.frm.doc.is_subcontracted,
|
is_subcontracted: me.frm.doc.is_subcontracted,
|
||||||
transaction_date: me.frm.doc.transaction_date,
|
transaction_date: me.frm.doc.transaction_date || me.frm.doc.posting_date,
|
||||||
ignore_pricing_rule: me.frm.doc.ignore_pricing_rule,
|
ignore_pricing_rule: me.frm.doc.ignore_pricing_rule,
|
||||||
doctype: item.doctype,
|
doctype: item.doctype,
|
||||||
name: item.name,
|
name: item.name,
|
||||||
|
@ -190,6 +190,8 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
warehouse: function(doc, cdt, cdn) {
|
warehouse: function(doc, cdt, cdn) {
|
||||||
|
var me = this;
|
||||||
|
this.batch_no(doc, cdt, cdn);
|
||||||
var item = frappe.get_doc(cdt, cdn);
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
if(item.item_code && item.warehouse) {
|
if(item.item_code && item.warehouse) {
|
||||||
return this.frm.call({
|
return this.frm.call({
|
||||||
@ -277,6 +279,21 @@ erpnext.selling.SellingController = erpnext.TransactionController.extend({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
batch_no: function(doc, cdt, cdn) {
|
||||||
|
var me = this;
|
||||||
|
var item = frappe.get_doc(cdt, cdn);
|
||||||
|
return this.frm.call({
|
||||||
|
method: "erpnext.stock.get_item_details.get_batch_qty",
|
||||||
|
child: item,
|
||||||
|
args: {
|
||||||
|
"batch_no": item.batch_no,
|
||||||
|
"warehouse": item.warehouse,
|
||||||
|
"item_code": item.item_code
|
||||||
|
},
|
||||||
|
"fieldname": "actual_batch_qty"
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
set_dynamic_labels: function() {
|
set_dynamic_labels: function() {
|
||||||
this._super();
|
this._super();
|
||||||
this.set_sales_bom_help(this.frm.doc);
|
this.set_sales_bom_help(this.frm.doc);
|
||||||
|
@ -395,6 +395,19 @@
|
|||||||
"fieldtype": "Column Break",
|
"fieldtype": "Column Break",
|
||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 1,
|
||||||
|
"fieldname": "actual_batch_qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"label": "Available Batch Qty at Warehouse",
|
||||||
|
"no_copy": 1,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 1,
|
||||||
|
"print_width": "150px",
|
||||||
|
"read_only": 1,
|
||||||
|
"width": "150px"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
"allow_on_submit": 1,
|
||||||
"fieldname": "actual_qty",
|
"fieldname": "actual_qty",
|
||||||
@ -508,7 +521,7 @@
|
|||||||
],
|
],
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"modified": "2015-02-23 15:51:20.772564",
|
"modified": "2015-03-10 12:21:17.028911",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Delivery Note Item",
|
"name": "Delivery Note Item",
|
||||||
|
@ -304,6 +304,15 @@ def get_serial_nos_by_fifo(args, item_doc):
|
|||||||
"qty": cint(args.qty)
|
"qty": cint(args.qty)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
def get_actual_batch_qty(batch_no,warehouse,item_code):
|
||||||
|
actual_batch_qty = 0
|
||||||
|
if batch_no:
|
||||||
|
actual_batch_qty = flt(frappe.db.sql("""select sum(actual_qty)
|
||||||
|
from `tabStock Ledger Entry`
|
||||||
|
where warehouse=%s and item_code=%s and batch_no=%s""",
|
||||||
|
(warehouse, item_code, batch_no))[0][0])
|
||||||
|
return actual_batch_qty
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_conversion_factor(item_code, uom):
|
def get_conversion_factor(item_code, uom):
|
||||||
variant_of = frappe.db.get_value("Item", item_code, "variant_of")
|
variant_of = frappe.db.get_value("Item", item_code, "variant_of")
|
||||||
@ -324,6 +333,12 @@ def get_available_qty(item_code, warehouse):
|
|||||||
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
return frappe.db.get_value("Bin", {"item_code": item_code, "warehouse": warehouse},
|
||||||
["projected_qty", "actual_qty"], as_dict=True) or {}
|
["projected_qty", "actual_qty"], as_dict=True) or {}
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def get_batch_qty(batch_no,warehouse,item_code):
|
||||||
|
actual_batch_qty = get_actual_batch_qty(batch_no,warehouse,item_code)
|
||||||
|
if batch_no:
|
||||||
|
return {'actual_batch_qty': actual_batch_qty}
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def apply_price_list(args):
|
def apply_price_list(args):
|
||||||
"""
|
"""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user