mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-08 15:42:52 +00:00
[stock reco] added items table
This commit is contained in:
@@ -5,6 +5,26 @@ frappe.require("assets/erpnext/js/controllers/stock_controller.js");
|
|||||||
frappe.require("assets/erpnext/js/utils.js");
|
frappe.require("assets/erpnext/js/utils.js");
|
||||||
frappe.provide("erpnext.stock");
|
frappe.provide("erpnext.stock");
|
||||||
|
|
||||||
|
frappe.ui.form.on("Stock Reconciliation", "get_items", function(frm) {
|
||||||
|
frappe.prompt({label:"Warehouse", fieldtype:"Link", options:"Warehouse", reqd: 1},
|
||||||
|
function(data) {
|
||||||
|
frappe.call({
|
||||||
|
method:"erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.get_items",
|
||||||
|
args: {warehouse: data.warehouse},
|
||||||
|
callback: function(r) {
|
||||||
|
var items = [];
|
||||||
|
frm.clear_table("items");
|
||||||
|
for(var i=0; i< r.message.length; i++) {
|
||||||
|
var d = frm.add_child("items");
|
||||||
|
$.extend(d, r.message[i]);
|
||||||
|
}
|
||||||
|
frm.refresh_field("items");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
||||||
onload: function() {
|
onload: function() {
|
||||||
this.set_default_expense_account();
|
this.set_default_expense_account();
|
||||||
@@ -31,6 +51,8 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
|||||||
|
|
||||||
setup: function() {
|
setup: function() {
|
||||||
var me = this;
|
var me = this;
|
||||||
|
this.frm.get_field("items").grid.allow_build_edit();
|
||||||
|
|
||||||
if (sys_defaults.auto_accounting_for_stock) {
|
if (sys_defaults.auto_accounting_for_stock) {
|
||||||
this.frm.add_fetch("company", "stock_adjustment_account", "expense_account");
|
this.frm.add_fetch("company", "stock_adjustment_account", "expense_account");
|
||||||
this.frm.add_fetch("company", "cost_center", "cost_center");
|
this.frm.add_fetch("company", "cost_center", "cost_center");
|
||||||
@@ -55,108 +77,29 @@ erpnext.stock.StockReconciliation = erpnext.stock.StockController.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
refresh: function() {
|
refresh: function() {
|
||||||
if(this.frm.doc.docstatus===0) {
|
//
|
||||||
this.show_download_template();
|
|
||||||
this.show_upload();
|
|
||||||
if(this.frm.doc.reconciliation_json) {
|
|
||||||
this.frm.set_intro(__("You can submit this Stock Reconciliation."));
|
|
||||||
} else {
|
|
||||||
this.frm.set_intro(__("Download the Template, fill appropriate data and attach the modified file."));
|
|
||||||
}
|
|
||||||
} else if(this.frm.doc.docstatus == 1) {
|
|
||||||
this.frm.set_intro(__("Cancelling this Stock Reconciliation will nullify its effect."));
|
|
||||||
this.show_stock_ledger();
|
|
||||||
this.show_general_ledger();
|
|
||||||
} else {
|
|
||||||
this.frm.set_intro("");
|
|
||||||
}
|
|
||||||
this.show_reconciliation_data();
|
|
||||||
this.show_download_reconciliation_data();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
show_download_template: function() {
|
// show_download_template: function() {
|
||||||
var me = this;
|
// var me = this;
|
||||||
this.frm.add_custom_button(__("Download Template"), function() {
|
// this.frm.add_custom_button(__("Download Template"), function() {
|
||||||
this.title = __("Stock Reconcilation Template");
|
// this.title = __("Stock Reconcilation Template");
|
||||||
frappe.tools.downloadify([[__("Stock Reconciliation")],
|
// frappe.tools.downloadify([[__("Stock Reconciliation")],
|
||||||
["----"],
|
// ["----"],
|
||||||
[__("Stock Reconciliation can be used to update the stock on a particular date, usually as per physical inventory.")],
|
// [__("Stock Reconciliation can be used to update the stock on a particular date, usually as per physical inventory.")],
|
||||||
[__("When submitted, the system creates difference entries to set the given stock and valuation on this date.")],
|
// [__("When submitted, the system creates difference entries to set the given stock and valuation on this date.")],
|
||||||
[__("It can also be used to create opening stock entries and to fix stock value.")],
|
// [__("It can also be used to create opening stock entries and to fix stock value.")],
|
||||||
["----"],
|
// ["----"],
|
||||||
[__("Notes:")],
|
// [__("Notes:")],
|
||||||
[__("Item Code and Warehouse should already exist.")],
|
// [__("Item Code and Warehouse should already exist.")],
|
||||||
[__("You can update either Quantity or Valuation Rate or both.")],
|
// [__("You can update either Quantity or Valuation Rate or both.")],
|
||||||
[__("If no change in either Quantity or Valuation Rate, leave the cell blank.")],
|
// [__("If no change in either Quantity or Valuation Rate, leave the cell blank.")],
|
||||||
["----"],
|
// ["----"],
|
||||||
["Item Code", "Warehouse", "Quantity", "Valuation Rate"]], null, this);
|
// ["Item Code", "Warehouse", "Quantity", "Valuation Rate"]], null, this);
|
||||||
return false;
|
// return false;
|
||||||
}, "icon-download");
|
// }, "icon-download");
|
||||||
},
|
// },
|
||||||
|
|
||||||
show_upload: function() {
|
|
||||||
var me = this;
|
|
||||||
var $wrapper = $(cur_frm.fields_dict.upload_html.wrapper).empty();
|
|
||||||
|
|
||||||
// upload
|
|
||||||
frappe.upload.make({
|
|
||||||
parent: $wrapper,
|
|
||||||
args: {
|
|
||||||
method: 'erpnext.stock.doctype.stock_reconciliation.stock_reconciliation.upload'
|
|
||||||
},
|
|
||||||
sample_url: "e.g. http://example.com/somefile.csv",
|
|
||||||
callback: function(attachment, r) {
|
|
||||||
me.frm.set_value("reconciliation_json", JSON.stringify(r.message));
|
|
||||||
me.show_reconciliation_data();
|
|
||||||
me.frm.save();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// rename button
|
|
||||||
$wrapper.find('form input[type="submit"]')
|
|
||||||
.attr('value', 'Upload')
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
show_download_reconciliation_data: function() {
|
|
||||||
var me = this;
|
|
||||||
if(this.frm.doc.reconciliation_json) {
|
|
||||||
this.frm.add_custom_button(__("Download Reconcilation Data"), function() {
|
|
||||||
this.title = __("Stock Reconcilation Data");
|
|
||||||
frappe.tools.downloadify(JSON.parse(me.frm.doc.reconciliation_json), null, this);
|
|
||||||
return false;
|
|
||||||
}, "icon-download", "btn-default");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
show_reconciliation_data: function() {
|
|
||||||
var $wrapper = $(cur_frm.fields_dict.reconciliation_html.wrapper).empty();
|
|
||||||
if(this.frm.doc.reconciliation_json) {
|
|
||||||
var reconciliation_data = JSON.parse(this.frm.doc.reconciliation_json);
|
|
||||||
|
|
||||||
var _make = function(data, header) {
|
|
||||||
var result = "";
|
|
||||||
|
|
||||||
var _render = header
|
|
||||||
? function(col) { return "<th>" + col + "</th>"; }
|
|
||||||
: function(col) { return "<td>" + col + "</td>"; };
|
|
||||||
|
|
||||||
$.each(data, function(i, row) {
|
|
||||||
result += "<tr>"
|
|
||||||
+ $.map(row, _render).join("")
|
|
||||||
+ "</tr>";
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
|
|
||||||
var $reconciliation_table = $("<div style='overflow-x: auto;'>\
|
|
||||||
<table class='table table-striped table-bordered'>\
|
|
||||||
<thead>" + _make([reconciliation_data[0]], true) + "</thead>\
|
|
||||||
<tbody>" + _make(reconciliation_data.splice(1)) + "</tbody>\
|
|
||||||
</table>\
|
|
||||||
</div>").appendTo($wrapper);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
cur_frm.cscript = new erpnext.stock.StockReconciliation({frm: cur_frm});
|
cur_frm.cscript = new erpnext.stock.StockReconciliation({frm: cur_frm});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 1,
|
"allow_copy": 0,
|
||||||
"autoname": "SR/.######",
|
"autoname": "SR/.######",
|
||||||
"creation": "2013-03-28 10:35:31",
|
"creation": "2013-03-28 10:35:31",
|
||||||
"description": "This tool helps you to update or fix the quantity and valuation of stock in the system. It is typically used to synchronise the system values and what actually exists in your warehouses.",
|
"description": "This tool helps you to update or fix the quantity and valuation of stock in the system. It is typically used to synchronise the system values and what actually exists in your warehouses.",
|
||||||
@@ -31,6 +31,14 @@
|
|||||||
"read_only": 0,
|
"read_only": 0,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||||
|
"fieldname": "expense_account",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"label": "Difference Account",
|
||||||
|
"options": "Account",
|
||||||
|
"permlevel": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -42,6 +50,11 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "col1",
|
||||||
|
"fieldtype": "Column Break",
|
||||||
|
"permlevel": 0
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
@@ -59,14 +72,6 @@
|
|||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
|
||||||
"fieldname": "expense_account",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Difference Account",
|
|
||||||
"options": "Account",
|
|
||||||
"permlevel": 0
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
"depends_on": "eval:cint(sys_defaults.auto_accounting_for_stock)",
|
||||||
"fieldname": "cost_center",
|
"fieldname": "cost_center",
|
||||||
@@ -76,9 +81,31 @@
|
|||||||
"permlevel": 0
|
"permlevel": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "col1",
|
"fieldname": "sb9",
|
||||||
"fieldtype": "Column Break",
|
"fieldtype": "Section Break",
|
||||||
"permlevel": 0
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "items",
|
||||||
|
"fieldtype": "Table",
|
||||||
|
"label": "Items",
|
||||||
|
"options": "Stock Reconciliation Item",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "get_items",
|
||||||
|
"fieldtype": "Button",
|
||||||
|
"label": "Get Items",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "section_break_9",
|
||||||
|
"fieldtype": "Section Break",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "upload_html",
|
"fieldname": "upload_html",
|
||||||
@@ -119,7 +146,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"max_attachments": 1,
|
"max_attachments": 1,
|
||||||
"modified": "2015-02-05 05:11:47.153367",
|
"modified": "2015-02-17 02:09:17.483016",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Stock",
|
"module": "Stock",
|
||||||
"name": "Stock Reconciliation",
|
"name": "Stock Reconciliation",
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe
|
import frappe
|
||||||
import frappe.defaults
|
import frappe.defaults
|
||||||
import json
|
|
||||||
from frappe import msgprint, _
|
from frappe import msgprint, _
|
||||||
from frappe.utils import cstr, flt, cint
|
from frappe.utils import cstr, flt, cint
|
||||||
from erpnext.stock.stock_ledger import update_entries_after
|
from erpnext.stock.stock_ledger import update_entries_after
|
||||||
@@ -28,61 +27,41 @@ class StockReconciliation(StockController):
|
|||||||
self.make_gl_entries_on_cancel()
|
self.make_gl_entries_on_cancel()
|
||||||
|
|
||||||
def validate_data(self):
|
def validate_data(self):
|
||||||
if not self.reconciliation_json:
|
|
||||||
return
|
|
||||||
|
|
||||||
data = json.loads(self.reconciliation_json)
|
|
||||||
|
|
||||||
# strip out extra columns (if any)
|
|
||||||
data = [row[:4] for row in data]
|
|
||||||
|
|
||||||
if self.head_row not in data:
|
|
||||||
msgprint(_("""Wrong Template: Unable to find head row."""),
|
|
||||||
raise_exception=1)
|
|
||||||
|
|
||||||
# remove the help part and save the json
|
|
||||||
head_row_no = 0
|
|
||||||
if data.index(self.head_row) != 0:
|
|
||||||
head_row_no = data.index(self.head_row)
|
|
||||||
data = data[head_row_no:]
|
|
||||||
self.reconciliation_json = json.dumps(data)
|
|
||||||
|
|
||||||
def _get_msg(row_num, msg):
|
def _get_msg(row_num, msg):
|
||||||
return _("Row # {0}: ").format(row_num+head_row_no+2) + msg
|
return _("Row # {0}: ").format(row_num+1) + msg
|
||||||
|
|
||||||
self.validation_messages = []
|
self.validation_messages = []
|
||||||
item_warehouse_combinations = []
|
item_warehouse_combinations = []
|
||||||
|
|
||||||
# validate no of rows
|
# validate no of rows
|
||||||
rows = data[1:]
|
rows = self.items
|
||||||
if len(rows) > 100:
|
if len(rows) > 100:
|
||||||
msgprint(_("""Sorry! We can only allow upto 100 rows for Stock Reconciliation."""),
|
frappe.throw(_("""Max 100 rows for Stock Reconciliation."""))
|
||||||
raise_exception=True)
|
|
||||||
for row_num, row in enumerate(rows):
|
for row_num, row in enumerate(rows):
|
||||||
# find duplicates
|
# find duplicates
|
||||||
if [row[0], row[1]] in item_warehouse_combinations:
|
if [row.item_code, row.warehouse] in item_warehouse_combinations:
|
||||||
self.validation_messages.append(_get_msg(row_num, _("Duplicate entry")))
|
self.validation_messages.append(_get_msg(row_num, _("Duplicate entry")))
|
||||||
else:
|
else:
|
||||||
item_warehouse_combinations.append([row[0], row[1]])
|
item_warehouse_combinations.append([row.item_code, row.warehouse])
|
||||||
|
|
||||||
self.validate_item(row[0], row_num+head_row_no+2)
|
self.validate_item(row.item_code, row_num+1)
|
||||||
|
|
||||||
# validate warehouse
|
# validate warehouse
|
||||||
if not frappe.db.get_value("Warehouse", row[1]):
|
if not frappe.db.get_value("Warehouse", row.warehouse):
|
||||||
self.validation_messages.append(_get_msg(row_num, _("Warehouse not found in the system")))
|
self.validation_messages.append(_get_msg(row_num, _("Warehouse not found in the system")))
|
||||||
|
|
||||||
# if both not specified
|
# if both not specified
|
||||||
if row[2] in ["", None] and row[3] in ["", None]:
|
if row.qty in ["", None] and row.valuation_rate in ["", None]:
|
||||||
self.validation_messages.append(_get_msg(row_num,
|
self.validation_messages.append(_get_msg(row_num,
|
||||||
_("Please specify either Quantity or Valuation Rate or both")))
|
_("Please specify either Quantity or Valuation Rate or both")))
|
||||||
|
|
||||||
# do not allow negative quantity
|
# do not allow negative quantity
|
||||||
if flt(row[2]) < 0:
|
if flt(row.qty) < 0:
|
||||||
self.validation_messages.append(_get_msg(row_num,
|
self.validation_messages.append(_get_msg(row_num,
|
||||||
_("Negative Quantity is not allowed")))
|
_("Negative Quantity is not allowed")))
|
||||||
|
|
||||||
# do not allow negative valuation
|
# do not allow negative valuation
|
||||||
if flt(row[3]) < 0:
|
if flt(row.valuation_rate) < 0:
|
||||||
self.validation_messages.append(_get_msg(row_num,
|
self.validation_messages.append(_get_msg(row_num,
|
||||||
_("Negative Valuation Rate is not allowed")))
|
_("Negative Valuation Rate is not allowed")))
|
||||||
|
|
||||||
@@ -129,16 +108,7 @@ class StockReconciliation(StockController):
|
|||||||
and create stock ledger entries based on the difference"""
|
and create stock ledger entries based on the difference"""
|
||||||
from erpnext.stock.stock_ledger import get_previous_sle
|
from erpnext.stock.stock_ledger import get_previous_sle
|
||||||
|
|
||||||
row_template = ["item_code", "warehouse", "qty", "valuation_rate"]
|
for row in self.items:
|
||||||
|
|
||||||
if not self.reconciliation_json:
|
|
||||||
msgprint(_("""Stock Reconciliation file not uploaded"""), raise_exception=1)
|
|
||||||
|
|
||||||
data = json.loads(self.reconciliation_json)
|
|
||||||
for row_num, row in enumerate(data[data.index(self.head_row)+1:]):
|
|
||||||
row = frappe._dict(zip(row_template, row))
|
|
||||||
row["row_num"] = row_num
|
|
||||||
|
|
||||||
if row.qty in ("", None) or row.valuation_rate in ("", None):
|
if row.qty in ("", None) or row.valuation_rate in ("", None):
|
||||||
previous_sle = get_previous_sle({
|
previous_sle = get_previous_sle({
|
||||||
"item_code": row.item_code,
|
"item_code": row.item_code,
|
||||||
@@ -216,7 +186,14 @@ class StockReconciliation(StockController):
|
|||||||
frappe.throw(_("Difference Account must be a 'Liability' type account, since this Stock Reconciliation is an Opening Entry"))
|
frappe.throw(_("Difference Account must be a 'Liability' type account, since this Stock Reconciliation is an Opening Entry"))
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def upload():
|
def get_items(warehouse):
|
||||||
from frappe.utils.csvutils import read_csv_content_from_uploaded_file
|
from erpnext.stock.utils import get_stock_balance
|
||||||
csv_content = read_csv_content_from_uploaded_file()
|
items = frappe.get_list("Item", fields=["name"], filters=
|
||||||
return filter(lambda x: x and any(x), csv_content)
|
{"is_stock_item": "Yes", "has_serial_no": "No", "has_batch_no": "No"})
|
||||||
|
for item in items:
|
||||||
|
item.item_code = item.name
|
||||||
|
item.warehouse = warehouse
|
||||||
|
del item["name"]
|
||||||
|
item.qty, item.valuation_rate = get_stock_balance(item.name, warehouse, with_valuation_rate=True)
|
||||||
|
|
||||||
|
return items
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
{
|
||||||
|
"allow_copy": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
|
"creation": "2015-02-17 01:06:05.072764",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
|
"doctype": "DocType",
|
||||||
|
"document_type": "Other",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"fieldname": "item_code",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Item Code",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Item",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"fieldname": "warehouse",
|
||||||
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Warehouse",
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Warehouse",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"description": "Leave blank if no change",
|
||||||
|
"fieldname": "qty",
|
||||||
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Quantity",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"description": "Leave blank if no change",
|
||||||
|
"fieldname": "valuation_rate",
|
||||||
|
"fieldtype": "Currency",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_list_view": 1,
|
||||||
|
"label": "Valuation Rate",
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"in_create": 0,
|
||||||
|
"in_dialog": 0,
|
||||||
|
"is_submittable": 0,
|
||||||
|
"issingle": 0,
|
||||||
|
"istable": 1,
|
||||||
|
"modified": "2015-02-17 01:07:50.200649",
|
||||||
|
"modified_by": "Administrator",
|
||||||
|
"module": "Stock",
|
||||||
|
"name": "Stock Reconciliation Item",
|
||||||
|
"name_case": "",
|
||||||
|
"owner": "Administrator",
|
||||||
|
"permissions": [],
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"sort_field": "modified",
|
||||||
|
"sort_order": "DESC"
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2013, Web Notes Technologies Pvt. Ltd. and Contributors and contributors
|
||||||
|
# For license information, please see license.txt
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
import frappe
|
||||||
|
from frappe.model.document import Document
|
||||||
|
|
||||||
|
class StockReconciliationItem(Document):
|
||||||
|
pass
|
||||||
@@ -34,19 +34,22 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
|||||||
|
|
||||||
return sum(sle_map.values())
|
return sum(sle_map.values())
|
||||||
|
|
||||||
def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None):
|
def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None, with_valuation_rate=False):
|
||||||
|
"""Returns stock balance quantity at given warehouse on given posting date or current date.
|
||||||
|
|
||||||
|
If `with_valuation_rate` is True, will return tuple (qty, rate)"""
|
||||||
if not posting_date: posting_date = nowdate()
|
if not posting_date: posting_date = nowdate()
|
||||||
if not posting_time: posting_time = nowtime()
|
if not posting_time: posting_time = nowtime()
|
||||||
last_entry = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
|
last_entry = frappe.db.sql("""select qty_after_transaction, valuation_rate from `tabStock Ledger Entry`
|
||||||
where item_code=%s and warehouse=%s
|
where item_code=%s and warehouse=%s
|
||||||
and timestamp(posting_date, posting_time) < timestamp(%s, %s)
|
and timestamp(posting_date, posting_time) < timestamp(%s, %s)
|
||||||
order by timestamp(posting_date, posting_time) limit 1""",
|
order by timestamp(posting_date, posting_time) limit 1""",
|
||||||
(item_code, warehouse, posting_date, posting_time))
|
(item_code, warehouse, posting_date, posting_time))
|
||||||
|
|
||||||
if last_entry:
|
if with_valuation_rate:
|
||||||
return last_entry[0][0]
|
return (last_entry[0][0], last_entry[0][1]) if last_entry else (0.0, 0.0)
|
||||||
else:
|
else:
|
||||||
return 0.0
|
return last_entry[0][0] if last_entry else 0.0
|
||||||
|
|
||||||
def get_latest_stock_balance():
|
def get_latest_stock_balance():
|
||||||
bin_map = {}
|
bin_map = {}
|
||||||
|
|||||||
Reference in New Issue
Block a user