commit
f749302d25
@ -197,9 +197,9 @@ class StockController(AccountsController):
|
||||
sl_dict.update(args)
|
||||
return sl_dict
|
||||
|
||||
def make_sl_entries(self, sl_entries, is_amended=None):
|
||||
def make_sl_entries(self, sl_entries, is_amended=None, allow_negative_stock=False):
|
||||
from erpnext.stock.stock_ledger import make_sl_entries
|
||||
make_sl_entries(sl_entries, is_amended)
|
||||
make_sl_entries(sl_entries, is_amended, allow_negative_stock)
|
||||
|
||||
def make_gl_entries_on_cancel(self):
|
||||
if frappe.db.sql("""select name from `tabGL Entry` where voucher_type=%s
|
||||
|
@ -91,3 +91,4 @@ erpnext.patches.v4_2.update_requested_and_ordered_qty
|
||||
execute:frappe.delete_doc("DocType", "Contact Control")
|
||||
erpnext.patches.v4_2.recalculate_bom_costs
|
||||
erpnext.patches.v4_2.discount_amount
|
||||
erpnext.patches.v4_2.update_landed_cost_voucher
|
||||
|
10
erpnext/patches/v4_2/update_landed_cost_voucher.py
Normal file
10
erpnext/patches/v4_2/update_landed_cost_voucher.py
Normal file
@ -0,0 +1,10 @@
|
||||
# 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
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "landed_cost_voucher")
|
||||
frappe.db.sql("""update `tabLanded Cost Voucher` set distribute_charges_based_on = 'Amount'
|
||||
where docstatus=1""")
|
@ -723,7 +723,7 @@
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "status",
|
||||
"oldfieldtype": "Select",
|
||||
"options": "Draft\nSubmitted\nOrdered\nLost\nCancelled",
|
||||
"options": "Draft\nSubmitted\nOrdered\nLost\nCancelled\nOpen\nReplied",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1,
|
||||
@ -842,7 +842,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"max_attachments": 1,
|
||||
"modified": "2015-01-12 16:57:14.706270",
|
||||
"modified": "2015-01-21 11:24:08.210880",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Quotation",
|
||||
|
@ -23,7 +23,7 @@ class Bin(Document):
|
||||
if (not getattr(self, f, None)) or (not self.get(f)):
|
||||
self.set(f, 0.0)
|
||||
|
||||
def update_stock(self, args):
|
||||
def update_stock(self, args, allow_negative_stock=False):
|
||||
self.update_qty(args)
|
||||
|
||||
if args.get("actual_qty") or args.get("voucher_type") == "Stock Reconciliation":
|
||||
@ -38,7 +38,7 @@ class Bin(Document):
|
||||
"warehouse": self.warehouse,
|
||||
"posting_date": args.get("posting_date"),
|
||||
"posting_time": args.get("posting_time")
|
||||
})
|
||||
}, allow_negative_stock=allow_negative_stock)
|
||||
|
||||
def update_qty(self, args):
|
||||
# update the stock values (for current quantities)
|
||||
|
@ -18,17 +18,6 @@
|
||||
"permlevel": 0,
|
||||
"width": "50%"
|
||||
},
|
||||
{
|
||||
"fieldname": "account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Account",
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 0,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "amount",
|
||||
"fieldtype": "Currency",
|
||||
@ -40,7 +29,7 @@
|
||||
}
|
||||
],
|
||||
"istable": 1,
|
||||
"modified": "2014-08-08 13:12:02.594698",
|
||||
"modified": "2015-01-21 11:51:33.964438",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Landed Cost Taxes and Charges",
|
||||
|
@ -5,10 +5,10 @@
|
||||
frappe.provide("erpnext.stock");
|
||||
frappe.require("assets/erpnext/js/controllers/stock_controller.js");
|
||||
|
||||
erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
setup: function() {
|
||||
var me = this;
|
||||
this.frm.fields_dict.landed_cost_purchase_receipts.grid.get_field('purchase_receipt').get_query =
|
||||
this.frm.fields_dict.landed_cost_purchase_receipts.grid.get_field('purchase_receipt').get_query =
|
||||
function() {
|
||||
if(!me.frm.doc.company) msgprint(__("Please enter company first"));
|
||||
return {
|
||||
@ -18,53 +18,44 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
this.frm.fields_dict.landed_cost_taxes_and_charges.grid.get_field('account').get_query = function() {
|
||||
if(!me.frm.doc.company) msgprint(__("Please enter company first"));
|
||||
return {
|
||||
filters:[
|
||||
['Account', 'group_or_ledger', '=', 'Ledger'],
|
||||
['Account', 'account_type', 'in', ['Tax', 'Chargeable', 'Expense Account']],
|
||||
['Account', 'company', '=', me.frm.doc.company]
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
this.frm.add_fetch("purchase_receipt", "supplier", "supplier");
|
||||
this.frm.add_fetch("purchase_receipt", "posting_date", "posting_date");
|
||||
this.frm.add_fetch("purchase_receipt", "grand_total", "grand_total");
|
||||
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
|
||||
refresh: function() {
|
||||
var help_content = ['<table class="table table-bordered" style="background-color: #f9f9f9;">',
|
||||
'<tr><td>',
|
||||
'<h4><i class="icon-hand-right"></i> ',
|
||||
__('Notes'),
|
||||
':</h4>',
|
||||
'<ul>',
|
||||
'<li>',
|
||||
__("Charges will be distributed proportionately based on item amount"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Remove item if charges is not applicable to that item"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Charges are updated in Purchase Receipt against each item"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Item valuation rate is recalculated considering landed cost voucher amount"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Stock Ledger Entries and GL Entries are reposted for the selected Purchase Receipts"),
|
||||
'</li>',
|
||||
'</ul>',
|
||||
'</td></tr>',
|
||||
'</table>'].join("\n");
|
||||
var help_content = [
|
||||
'<br><br>',
|
||||
'<table class="table table-bordered" style="background-color: #f9f9f9;">',
|
||||
'<tr><td>',
|
||||
'<h4><i class="icon-hand-right"></i> ',
|
||||
__('Notes'),
|
||||
':</h4>',
|
||||
'<ul>',
|
||||
'<li>',
|
||||
__("Charges will be distributed proportionately based on item qty or amount, as per your selection"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Remove item if charges is not applicable to that item"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Charges are updated in Purchase Receipt against each item"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Item valuation rate is recalculated considering landed cost voucher amount"),
|
||||
'</li>',
|
||||
'<li>',
|
||||
__("Stock Ledger Entries and GL Entries are reposted for the selected Purchase Receipts"),
|
||||
'</li>',
|
||||
'</ul>',
|
||||
'</td></tr>',
|
||||
'</table>'].join("\n");
|
||||
|
||||
set_field_options("landed_cost_help", help_content);
|
||||
},
|
||||
|
||||
|
||||
get_items_from_purchase_receipts: function() {
|
||||
var me = this;
|
||||
if(!this.frm.doc.landed_cost_purchase_receipts.length) {
|
||||
@ -75,13 +66,13 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
method: "get_items_from_purchase_receipts"
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
|
||||
amount: function() {
|
||||
this.set_total_taxes_and_charges();
|
||||
this.set_applicable_charges_for_item();
|
||||
},
|
||||
|
||||
|
||||
set_total_taxes_and_charges: function() {
|
||||
total_taxes_and_charges = 0.0;
|
||||
$.each(this.frm.doc.landed_cost_taxes_and_charges, function(i, d) {
|
||||
@ -89,7 +80,7 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
});
|
||||
cur_frm.set_value("total_taxes_and_charges", total_taxes_and_charges);
|
||||
},
|
||||
|
||||
|
||||
set_applicable_charges_for_item: function() {
|
||||
var me = this;
|
||||
if(this.frm.doc.landed_cost_taxes_and_charges.length) {
|
||||
@ -97,14 +88,14 @@ erpnext.stock.LandedCostVoucher = erpnext.stock.StockController.extend({
|
||||
$.each(this.frm.doc.landed_cost_items, function(i, d) {
|
||||
total_item_cost += flt(d.amount)
|
||||
});
|
||||
|
||||
|
||||
$.each(this.frm.doc.landed_cost_items, function(i, item) {
|
||||
item.applicable_charges = flt(item.amount) * flt(me.frm.doc.total_taxes_and_charges) / flt(total_item_cost)
|
||||
});
|
||||
refresh_field("landed_cost_items");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
cur_frm.script_manager.make(erpnext.stock.LandedCostVoucher);
|
||||
cur_frm.script_manager.make(erpnext.stock.LandedCostVoucher);
|
||||
|
@ -44,6 +44,13 @@
|
||||
"options": "Landed Cost Taxes and Charges",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "sec_break1",
|
||||
"fieldtype": "Section Break",
|
||||
"options": "Simple",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "total_taxes_and_charges",
|
||||
"fieldtype": "Currency",
|
||||
@ -53,13 +60,6 @@
|
||||
"read_only": 1,
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "landed_cost_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Landed Cost Help",
|
||||
"options": "",
|
||||
"permlevel": 0
|
||||
},
|
||||
{
|
||||
"fieldname": "amended_from",
|
||||
"fieldtype": "Link",
|
||||
@ -69,11 +69,40 @@
|
||||
"permlevel": 0,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "col_break1",
|
||||
"fieldtype": "Column Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"default": "Amount",
|
||||
"fieldname": "distribute_charges_based_on",
|
||||
"fieldtype": "Select",
|
||||
"label": "Distribute Charges Based On",
|
||||
"options": "\nQty\nAmount",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "sec_break2",
|
||||
"fieldtype": "Section Break",
|
||||
"permlevel": 0,
|
||||
"precision": ""
|
||||
},
|
||||
{
|
||||
"fieldname": "landed_cost_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Landed Cost Help",
|
||||
"options": "",
|
||||
"permlevel": 0
|
||||
}
|
||||
],
|
||||
"icon": "icon-usd",
|
||||
"is_submittable": 1,
|
||||
"modified": "2014-09-01 12:05:46.834513",
|
||||
"modified": "2015-01-21 11:56:37.698326",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Landed Cost Voucher",
|
||||
|
@ -7,9 +7,6 @@ from frappe import _
|
||||
from frappe.utils import flt
|
||||
from frappe.model.document import Document
|
||||
|
||||
from erpnext.stock.utils import get_valuation_method
|
||||
from erpnext.stock.stock_ledger import get_previous_sle
|
||||
|
||||
class LandedCostVoucher(Document):
|
||||
def get_items_from_purchase_receipts(self):
|
||||
self.set("landed_cost_items", [])
|
||||
@ -69,10 +66,11 @@ class LandedCostVoucher(Document):
|
||||
self.total_taxes_and_charges = sum([flt(d.amount) for d in self.get("landed_cost_taxes_and_charges")])
|
||||
|
||||
def set_applicable_charges_for_item(self):
|
||||
total_item_cost = sum([flt(d.amount) for d in self.get("landed_cost_items")])
|
||||
based_on = self.distribute_charges_based_on.lower()
|
||||
total = sum([flt(d.get(based_on)) for d in self.get("landed_cost_items")])
|
||||
|
||||
for item in self.get("landed_cost_items"):
|
||||
item.applicable_charges = flt(item.amount) * flt(self.total_taxes_and_charges) / flt(total_item_cost)
|
||||
item.applicable_charges = flt(item.get(based_on)) * flt(self.total_taxes_and_charges) / flt(total)
|
||||
|
||||
def on_submit(self):
|
||||
self.update_landed_cost()
|
||||
@ -92,12 +90,12 @@ class LandedCostVoucher(Document):
|
||||
pr.update_valuation_rate("purchase_receipt_details")
|
||||
|
||||
# save will update landed_cost_voucher_amount and voucher_amount in PR,
|
||||
# as those fields are ellowed to edit after submit
|
||||
# as those fields are allowed to edit after submit
|
||||
pr.save()
|
||||
|
||||
# update stock & gl entries for cancelled state of PR
|
||||
pr.docstatus = 2
|
||||
pr.update_stock_ledger()
|
||||
pr.update_stock_ledger(allow_negative_stock=True)
|
||||
pr.make_gl_entries_on_cancel()
|
||||
|
||||
# update stock & gl entries for submit state of PR
|
||||
|
@ -129,7 +129,7 @@ class PurchaseReceipt(BuyingController):
|
||||
if not d.prevdoc_docname:
|
||||
frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
|
||||
|
||||
def update_stock_ledger(self):
|
||||
def update_stock_ledger(self, allow_negative_stock=False):
|
||||
sl_entries = []
|
||||
stock_items = self.get_stock_items()
|
||||
|
||||
@ -153,7 +153,7 @@ class PurchaseReceipt(BuyingController):
|
||||
}))
|
||||
|
||||
self.bk_flush_supp_wh(sl_entries)
|
||||
self.make_sl_entries(sl_entries)
|
||||
self.make_sl_entries(sl_entries, allow_negative_stock=allow_negative_stock)
|
||||
|
||||
def update_ordered_qty(self):
|
||||
po_map = {}
|
||||
|
@ -14,7 +14,7 @@ class NegativeStockError(frappe.ValidationError): pass
|
||||
_exceptions = frappe.local('stockledger_exceptions')
|
||||
# _exceptions = []
|
||||
|
||||
def make_sl_entries(sl_entries, is_amended=None):
|
||||
def make_sl_entries(sl_entries, is_amended=None, allow_negative_stock=False):
|
||||
if sl_entries:
|
||||
from erpnext.stock.utils import update_bin
|
||||
|
||||
@ -35,7 +35,7 @@ def make_sl_entries(sl_entries, is_amended=None):
|
||||
"sle_id": sle_id,
|
||||
"is_amended": is_amended
|
||||
})
|
||||
update_bin(args)
|
||||
update_bin(args, allow_negative_stock)
|
||||
|
||||
if cancel:
|
||||
delete_cancelled_entry(sl_entries[0].get('voucher_type'), sl_entries[0].get('voucher_no'))
|
||||
@ -58,7 +58,7 @@ def delete_cancelled_entry(voucher_type, voucher_no):
|
||||
frappe.db.sql("""delete from `tabStock Ledger Entry`
|
||||
where voucher_type=%s and voucher_no=%s""", (voucher_type, voucher_no))
|
||||
|
||||
def update_entries_after(args, allow_zero_rate=False, verbose=1):
|
||||
def update_entries_after(args, allow_zero_rate=False, allow_negative_stock=False, verbose=1):
|
||||
"""
|
||||
update valution rate and qty after transaction
|
||||
from the current time-bucket onwards
|
||||
@ -73,6 +73,9 @@ def update_entries_after(args, allow_zero_rate=False, verbose=1):
|
||||
if not _exceptions:
|
||||
frappe.local.stockledger_exceptions = []
|
||||
|
||||
if not allow_negative_stock:
|
||||
allow_negative_stock = cint(frappe.db.get_default("allow_negative_stock"))
|
||||
|
||||
previous_sle = get_sle_before_datetime(args)
|
||||
|
||||
qty_after_transaction = flt(previous_sle.get("qty_after_transaction"))
|
||||
@ -87,7 +90,7 @@ def update_entries_after(args, allow_zero_rate=False, verbose=1):
|
||||
stock_value_difference = 0.0
|
||||
|
||||
for sle in entries_to_fix:
|
||||
if sle.serial_no or not cint(frappe.db.get_default("allow_negative_stock")):
|
||||
if sle.serial_no or not allow_negative_stock:
|
||||
# validate negative stock for serialized items, fifo valuation
|
||||
# or when negative stock is not allowed for moving average
|
||||
if not validate_negative_stock(qty_after_transaction, sle):
|
||||
|
@ -52,11 +52,11 @@ def get_bin(item_code, warehouse):
|
||||
bin_obj.ignore_permissions = True
|
||||
return bin_obj
|
||||
|
||||
def update_bin(args):
|
||||
def update_bin(args, allow_negative_stock=False):
|
||||
is_stock_item = frappe.db.get_value('Item', args.get("item_code"), 'is_stock_item')
|
||||
if is_stock_item == 'Yes':
|
||||
bin = get_bin(args.get("item_code"), args.get("warehouse"))
|
||||
bin.update_stock(args)
|
||||
bin.update_stock(args, allow_negative_stock)
|
||||
return bin
|
||||
else:
|
||||
frappe.msgprint(_("Item {0} ignored since it is not a stock item").format(args.get("item_code")))
|
||||
|
Loading…
x
Reference in New Issue
Block a user