chore: release v13 (#37245)
* feat: provision to make reposting entries from Stock and Account Value Comparison Report (backport #35365) (#37171) * feat: provision to make reposting entries from Stock and Account Value Comparison Report (cherry picked from commit7b818e9d34) * fix: `linter` * fix(ux): throw if no row selected to create repost entries --------- Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com> Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com> * fix: incorrect stock ledger entries in DN (backport #36944) (#37067) * fix: incorrect stock ledger entries in DN (#36944) (cherry picked from commit0e83190c19) # Conflicts: # erpnext/stock/doctype/delivery_note/delivery_note.json * chore: fix conflicts --------- Co-authored-by: rohitwaghchaure <rohitw1991@gmail.com> * feat: `Stock Ledger Variance` report (backport #37165) (#37184) feat: `Stock Ledger Variance` report (#37165) * feat: `Stock Ledger Variance` report * refactor: `get_data()` (cherry picked from commitacda72d616) Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com> * fix: Update `advance_paid` in SO/PO after unlinking from advance entry (cherry picked from commit426350eee6) * test: Impact on SO of advance PE submit and unlinking/replacement by SI (cherry picked from commit8a4954d713) --------- Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> Co-authored-by: Rohit Waghchaure <rohitw1991@gmail.com> Co-authored-by: s-aga-r <sagarsharma.s312@gmail.com> Co-authored-by: marination <maricadsouza221197@gmail.com> Co-authored-by: ruthra kumar <ruthra@erpnext.com>
This commit is contained in:
@@ -1783,6 +1783,10 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
)
|
||||
|
||||
def test_outstanding_amount_after_advance_payment_entry_cancellation(self):
|
||||
"""Test impact of advance PE submission/cancellation on SI and SO."""
|
||||
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||
|
||||
sales_order = make_sales_order(item_code="138-CMS Shoe", qty=1, price_list_rate=500)
|
||||
pe = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Payment Entry",
|
||||
@@ -1802,10 +1806,25 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"paid_to": "_Test Cash - _TC",
|
||||
}
|
||||
)
|
||||
pe.append(
|
||||
"references",
|
||||
{
|
||||
"reference_doctype": "Sales Order",
|
||||
"reference_name": sales_order.name,
|
||||
"total_amount": sales_order.grand_total,
|
||||
"outstanding_amount": sales_order.grand_total,
|
||||
"allocated_amount": 300,
|
||||
},
|
||||
)
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
sales_order.reload()
|
||||
self.assertEqual(sales_order.advance_paid, 300)
|
||||
|
||||
si = frappe.copy_doc(test_records[0])
|
||||
si.items[0].sales_order = sales_order.name
|
||||
si.items[0].so_detail = sales_order.get("items")[0].name
|
||||
si.is_pos = 0
|
||||
si.append(
|
||||
"advances",
|
||||
@@ -1813,6 +1832,7 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
"doctype": "Sales Invoice Advance",
|
||||
"reference_type": "Payment Entry",
|
||||
"reference_name": pe.name,
|
||||
"reference_row": pe.references[0].name,
|
||||
"advance_amount": 300,
|
||||
"allocated_amount": 300,
|
||||
"remarks": pe.remarks,
|
||||
@@ -1821,7 +1841,13 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
si.insert()
|
||||
si.submit()
|
||||
|
||||
si.load_from_db()
|
||||
si.reload()
|
||||
pe.reload()
|
||||
sales_order.reload()
|
||||
|
||||
# Check if SO is unlinked/replaced by SI in PE & if SO advance paid is 0
|
||||
self.assertEqual(pe.references[0].reference_name, si.name)
|
||||
self.assertEqual(sales_order.advance_paid, 0.0)
|
||||
|
||||
# check outstanding after advance allocation
|
||||
self.assertEqual(
|
||||
@@ -1829,11 +1855,9 @@ class TestSalesInvoice(unittest.TestCase):
|
||||
flt(si.rounded_total - si.total_advance, si.precision("outstanding_amount")),
|
||||
)
|
||||
|
||||
# added to avoid Document has been modified exception
|
||||
pe = frappe.get_doc("Payment Entry", pe.name)
|
||||
pe.cancel()
|
||||
si.reload()
|
||||
|
||||
si.load_from_db()
|
||||
# check outstanding after advance cancellation
|
||||
self.assertEqual(
|
||||
flt(si.outstanding_amount),
|
||||
|
||||
@@ -537,6 +537,10 @@ def update_reference_in_journal_entry(d, journal_entry, do_not_save=False):
|
||||
"""
|
||||
jv_detail = journal_entry.get("accounts", {"name": d["voucher_detail_no"]})[0]
|
||||
|
||||
# Update Advance Paid in SO/PO since they might be getting unlinked
|
||||
if jv_detail.get("reference_type") in ("Sales Order", "Purchase Order"):
|
||||
frappe.get_doc(jv_detail.reference_type, jv_detail.reference_name).set_total_advance_paid()
|
||||
|
||||
if flt(d["unadjusted_amount"]) - flt(d["allocated_amount"]) != 0:
|
||||
# adjust the unreconciled balance
|
||||
amount_in_account_currency = flt(d["unadjusted_amount"]) - flt(d["allocated_amount"])
|
||||
@@ -596,6 +600,13 @@ def update_reference_in_payment_entry(d, payment_entry, do_not_save=False):
|
||||
|
||||
if d.voucher_detail_no:
|
||||
existing_row = payment_entry.get("references", {"name": d["voucher_detail_no"]})[0]
|
||||
|
||||
# Update Advance Paid in SO/PO since they are getting unlinked
|
||||
if existing_row.get("reference_doctype") in ("Sales Order", "Purchase Order"):
|
||||
frappe.get_doc(
|
||||
existing_row.reference_doctype, existing_row.reference_name
|
||||
).set_total_advance_paid()
|
||||
|
||||
original_row = existing_row.as_dict().copy()
|
||||
existing_row.update(reference_details)
|
||||
|
||||
|
||||
@@ -1268,6 +1268,7 @@
|
||||
"depends_on": "eval: doc.is_internal_customer",
|
||||
"fieldname": "set_target_warehouse",
|
||||
"fieldtype": "Link",
|
||||
"ignore_user_permissions": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Set Target Warehouse",
|
||||
"no_copy": 1,
|
||||
@@ -1335,7 +1336,7 @@
|
||||
"idx": 146,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2022-09-16 17:46:17.701904",
|
||||
"modified": "2023-09-04 14:15:28.363184",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
@@ -1405,4 +1406,4 @@
|
||||
"title_field": "title",
|
||||
"track_changes": 1,
|
||||
"track_seen": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,43 @@ frappe.query_reports["Stock and Account Value Comparison"] = {
|
||||
"fieldtype": "Date",
|
||||
"default": frappe.datetime.get_today(),
|
||||
},
|
||||
]
|
||||
],
|
||||
|
||||
get_datatable_options(options) {
|
||||
return Object.assign(options, {
|
||||
checkboxColumn: true,
|
||||
});
|
||||
},
|
||||
|
||||
onload(report) {
|
||||
report.page.add_inner_button(__("Create Reposting Entries"), function() {
|
||||
let message = `
|
||||
<div>
|
||||
<p>
|
||||
Reposting Entries will change the value of
|
||||
accounts Stock In Hand, and Stock Expenses
|
||||
in the Trial Balance report and will also change
|
||||
the Balance Value in the Stock Balance report.
|
||||
</p>
|
||||
<p>Are you sure you want to create Reposting Entries?</p>
|
||||
</div>`;
|
||||
let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
|
||||
let selected_rows = indexes.map(i => frappe.query_report.data[i]);
|
||||
|
||||
if (!selected_rows.length) {
|
||||
frappe.throw(__("Please select rows to create Reposting Entries"));
|
||||
}
|
||||
|
||||
frappe.confirm(__(message), () => {
|
||||
frappe.call({
|
||||
method: "erpnext.stock.report.stock_and_account_value_comparison.stock_and_account_value_comparison.create_reposting_entries",
|
||||
args: {
|
||||
rows: selected_rows,
|
||||
company: frappe.query_report.get_filter_values().company
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import get_link_to_form, parse_json
|
||||
|
||||
import erpnext
|
||||
from erpnext.accounts.utils import get_currency_precision, get_stock_accounts
|
||||
@@ -134,3 +135,35 @@ def get_columns(filters):
|
||||
"width": "120",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_reposting_entries(rows, company):
|
||||
if isinstance(rows, str):
|
||||
rows = parse_json(rows)
|
||||
|
||||
entries = []
|
||||
for row in rows:
|
||||
row = frappe._dict(row)
|
||||
|
||||
try:
|
||||
doc = frappe.get_doc(
|
||||
{
|
||||
"doctype": "Repost Item Valuation",
|
||||
"based_on": "Transaction",
|
||||
"status": "Queued",
|
||||
"voucher_type": row.voucher_type,
|
||||
"voucher_no": row.voucher_no,
|
||||
"posting_date": row.posting_date,
|
||||
"company": company,
|
||||
"allow_nagative_stock": 1,
|
||||
}
|
||||
).submit()
|
||||
|
||||
entries.append(get_link_to_form("Repost Item Valuation", doc.name))
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
if entries:
|
||||
entries = ", ".join(entries)
|
||||
frappe.msgprint(_("Reposting entries created: {0}").format(entries))
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
const DIFFERENCE_FIELD_NAMES = [
|
||||
"difference_in_qty",
|
||||
"fifo_qty_diff",
|
||||
"fifo_value_diff",
|
||||
"fifo_valuation_diff",
|
||||
"valuation_diff",
|
||||
"fifo_difference_diff",
|
||||
"diff_value_diff"
|
||||
];
|
||||
|
||||
frappe.query_reports["Stock Ledger Variance"] = {
|
||||
"filters": [
|
||||
{
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"label": "Item",
|
||||
"options": "Item",
|
||||
get_query: function() {
|
||||
return {
|
||||
filters: {is_stock_item: 1, has_serial_no: 0}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": "Warehouse",
|
||||
"options": "Warehouse",
|
||||
get_query: function() {
|
||||
return {
|
||||
filters: {is_group: 0, disabled: 0}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"fieldname": "difference_in",
|
||||
"fieldtype": "Select",
|
||||
"label": "Difference In",
|
||||
"options": [
|
||||
"",
|
||||
"Qty",
|
||||
"Value",
|
||||
"Valuation",
|
||||
],
|
||||
},
|
||||
{
|
||||
"fieldname": "include_disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Include Disabled",
|
||||
}
|
||||
],
|
||||
|
||||
formatter (value, row, column, data, default_formatter) {
|
||||
value = default_formatter(value, row, column, data);
|
||||
|
||||
if (DIFFERENCE_FIELD_NAMES.includes(column.fieldname) && Math.abs(data[column.fieldname]) > 0.001) {
|
||||
value = "<span style='color:red'>" + value + "</span>";
|
||||
}
|
||||
|
||||
return value;
|
||||
},
|
||||
|
||||
get_datatable_options(options) {
|
||||
return Object.assign(options, {
|
||||
checkboxColumn: true,
|
||||
});
|
||||
},
|
||||
|
||||
onload(report) {
|
||||
report.page.add_inner_button(__('Create Reposting Entries'), () => {
|
||||
let message = `
|
||||
<div>
|
||||
<p>
|
||||
Reposting Entries will change the value of
|
||||
accounts Stock In Hand, and Stock Expenses
|
||||
in the Trial Balance report and will also change
|
||||
the Balance Value in the Stock Balance report.
|
||||
</p>
|
||||
<p>Are you sure you want to create Reposting Entries?</p>
|
||||
</div>`;
|
||||
let indexes = frappe.query_report.datatable.rowmanager.getCheckedRows();
|
||||
let selected_rows = indexes.map(i => frappe.query_report.data[i]);
|
||||
|
||||
if (!selected_rows.length) {
|
||||
frappe.throw(__("Please select rows to create Reposting Entries"));
|
||||
}
|
||||
|
||||
frappe.confirm(__(message), () => {
|
||||
frappe.call({
|
||||
method: 'erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check.create_reposting_entries',
|
||||
args: {
|
||||
rows: selected_rows,
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"columns": [],
|
||||
"creation": "2023-09-20 10:44:19.414449",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"letterhead": null,
|
||||
"modified": "2023-09-20 10:44:19.414449",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Ledger Variance",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Stock Ledger Entry",
|
||||
"report_name": "Stock Ledger Variance",
|
||||
"report_type": "Script Report",
|
||||
"roles": []
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import cint, flt
|
||||
|
||||
from erpnext.stock.report.stock_ledger_invariant_check.stock_ledger_invariant_check import (
|
||||
get_data as stock_ledger_invariant_check,
|
||||
)
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
columns, data = [], []
|
||||
|
||||
filters = frappe._dict(filters or {})
|
||||
columns = get_columns()
|
||||
data = get_data(filters)
|
||||
|
||||
return columns, data
|
||||
|
||||
|
||||
def get_columns():
|
||||
return [
|
||||
{
|
||||
"fieldname": "name",
|
||||
"fieldtype": "Link",
|
||||
"label": _("Stock Ledger Entry"),
|
||||
"options": "Stock Ledger Entry",
|
||||
},
|
||||
{
|
||||
"fieldname": "posting_date",
|
||||
"fieldtype": "Data",
|
||||
"label": _("Posting Date"),
|
||||
},
|
||||
{
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Data",
|
||||
"label": _("Posting Time"),
|
||||
},
|
||||
{
|
||||
"fieldname": "creation",
|
||||
"fieldtype": "Data",
|
||||
"label": _("Creation"),
|
||||
},
|
||||
{
|
||||
"fieldname": "item_code",
|
||||
"fieldtype": "Link",
|
||||
"label": _("Item"),
|
||||
"options": "Item",
|
||||
},
|
||||
{
|
||||
"fieldname": "warehouse",
|
||||
"fieldtype": "Link",
|
||||
"label": _("Warehouse"),
|
||||
"options": "Warehouse",
|
||||
},
|
||||
{
|
||||
"fieldname": "voucher_type",
|
||||
"fieldtype": "Link",
|
||||
"label": _("Voucher Type"),
|
||||
"options": "DocType",
|
||||
},
|
||||
{
|
||||
"fieldname": "voucher_no",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": _("Voucher No"),
|
||||
"options": "voucher_type",
|
||||
},
|
||||
{
|
||||
"fieldname": "batch_no",
|
||||
"fieldtype": "Link",
|
||||
"label": _("Batch"),
|
||||
"options": "Batch",
|
||||
},
|
||||
{
|
||||
"fieldname": "use_batchwise_valuation",
|
||||
"fieldtype": "Check",
|
||||
"label": _("Batchwise Valuation"),
|
||||
},
|
||||
{
|
||||
"fieldname": "actual_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": _("Qty Change"),
|
||||
},
|
||||
{
|
||||
"fieldname": "incoming_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": _("Incoming Rate"),
|
||||
},
|
||||
{
|
||||
"fieldname": "consumption_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": _("Consumption Rate"),
|
||||
},
|
||||
{
|
||||
"fieldname": "qty_after_transaction",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(A) Qty After Transaction"),
|
||||
},
|
||||
{
|
||||
"fieldname": "expected_qty_after_transaction",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(B) Expected Qty After Transaction"),
|
||||
},
|
||||
{
|
||||
"fieldname": "difference_in_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": _("A - B"),
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_queue",
|
||||
"fieldtype": "Data",
|
||||
"label": _("FIFO/LIFO Queue"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_queue_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(C) Total Qty in Queue"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_qty_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("A - C"),
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_value",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(D) Balance Stock Value"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_stock_value",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(E) Balance Stock Value in Queue"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_value_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("D - E"),
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_value_difference",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(F) Change in Stock Value"),
|
||||
},
|
||||
{
|
||||
"fieldname": "stock_value_from_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(G) Sum of Change in Stock Value"),
|
||||
},
|
||||
{
|
||||
"fieldname": "diff_value_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("G - D"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_stock_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(H) Change in Stock Value (FIFO Queue)"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_difference_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("H - F"),
|
||||
},
|
||||
{
|
||||
"fieldname": "valuation_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(I) Valuation Rate"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_valuation_rate",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(J) Valuation Rate as per FIFO"),
|
||||
},
|
||||
{
|
||||
"fieldname": "fifo_valuation_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("I - J"),
|
||||
},
|
||||
{
|
||||
"fieldname": "balance_value_by_qty",
|
||||
"fieldtype": "Float",
|
||||
"label": _("(K) Valuation = Value (D) ÷ Qty (A)"),
|
||||
},
|
||||
{
|
||||
"fieldname": "valuation_diff",
|
||||
"fieldtype": "Float",
|
||||
"label": _("I - K"),
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def get_data(filters=None):
|
||||
filters = frappe._dict(filters or {})
|
||||
item_warehouse_map = get_item_warehouse_combinations(filters)
|
||||
|
||||
data = []
|
||||
if item_warehouse_map:
|
||||
precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
|
||||
|
||||
for item_warehouse in item_warehouse_map:
|
||||
report_data = stock_ledger_invariant_check(item_warehouse)
|
||||
|
||||
if not report_data:
|
||||
continue
|
||||
|
||||
for row in report_data:
|
||||
if has_difference(row, precision, filters.difference_in):
|
||||
data.append(add_item_warehouse_details(row, item_warehouse))
|
||||
break
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_item_warehouse_combinations(filters: dict = None) -> dict:
|
||||
filters = frappe._dict(filters or {})
|
||||
|
||||
bin = frappe.qb.DocType("Bin")
|
||||
item = frappe.qb.DocType("Item")
|
||||
warehouse = frappe.qb.DocType("Warehouse")
|
||||
|
||||
query = (
|
||||
frappe.qb.from_(bin)
|
||||
.inner_join(item)
|
||||
.on(bin.item_code == item.name)
|
||||
.inner_join(warehouse)
|
||||
.on(bin.warehouse == warehouse.name)
|
||||
.select(
|
||||
bin.item_code,
|
||||
bin.warehouse,
|
||||
)
|
||||
.where((item.is_stock_item == 1) & (item.has_serial_no == 0) & (warehouse.is_group == 0))
|
||||
)
|
||||
|
||||
if filters.item_code:
|
||||
query = query.where(item.name == filters.item_code)
|
||||
if filters.warehouse:
|
||||
query = query.where(warehouse.name == filters.warehouse)
|
||||
if not filters.include_disabled:
|
||||
query = query.where((item.disabled == 0) & (warehouse.disabled == 0))
|
||||
|
||||
return query.run(as_dict=1)
|
||||
|
||||
|
||||
def has_difference(row, precision, difference_in):
|
||||
has_qty_difference = flt(row.difference_in_qty, precision) or flt(row.fifo_qty_diff, precision)
|
||||
has_value_difference = (
|
||||
flt(row.diff_value_diff, precision)
|
||||
or flt(row.fifo_value_diff, precision)
|
||||
or flt(row.fifo_difference_diff, precision)
|
||||
)
|
||||
has_valuation_difference = flt(row.valuation_diff, precision) or flt(
|
||||
row.fifo_valuation_diff, precision
|
||||
)
|
||||
|
||||
if difference_in == "Qty" and has_qty_difference:
|
||||
return True
|
||||
elif difference_in == "Value" and has_value_difference:
|
||||
return True
|
||||
elif difference_in == "Valuation" and has_valuation_difference:
|
||||
return True
|
||||
elif difference_in not in ["Qty", "Value", "Valuation"] and (
|
||||
has_qty_difference or has_value_difference or has_valuation_difference
|
||||
):
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def add_item_warehouse_details(row, item_warehouse):
|
||||
row.update(
|
||||
{
|
||||
"item_code": item_warehouse.item_code,
|
||||
"warehouse": item_warehouse.warehouse,
|
||||
}
|
||||
)
|
||||
|
||||
return row
|
||||
Reference in New Issue
Block a user