Merge branch 'frappe:develop' into get_incoming_rate_zero_in_rate_fix
This commit is contained in:
commit
bbd44e6e7e
@ -22,4 +22,4 @@ erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
|
|||||||
erpnext/patches/ @deepeshgarg007
|
erpnext/patches/ @deepeshgarg007
|
||||||
|
|
||||||
.github/ @deepeshgarg007
|
.github/ @deepeshgarg007
|
||||||
pyproject.toml @ankush
|
pyproject.toml @phot0n
|
||||||
|
|||||||
@ -184,6 +184,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"default": "0",
|
"default": "0",
|
||||||
|
"description": "Payment Terms from orders will be fetched into the invoices as is",
|
||||||
"fieldname": "automatically_fetch_payment_terms",
|
"fieldname": "automatically_fetch_payment_terms",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Automatically Fetch Payment Terms from Order"
|
"label": "Automatically Fetch Payment Terms from Order"
|
||||||
@ -375,7 +376,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-03-28 09:50:20.375233",
|
"modified": "2023-04-14 17:22:03.680886",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
|
|||||||
@ -1754,7 +1754,12 @@ def get_payment_entry(
|
|||||||
if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
|
if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
|
||||||
frappe.msgprint(_("{0} is on hold till {1}").format(doc.name, doc.release_date))
|
frappe.msgprint(_("{0} is on hold till {1}").format(doc.name, doc.release_date))
|
||||||
else:
|
else:
|
||||||
if doc.doctype in ("Sales Invoice", "Purchase Invoice") and frappe.get_cached_value(
|
if doc.doctype in (
|
||||||
|
"Sales Invoice",
|
||||||
|
"Purchase Invoice",
|
||||||
|
"Purchase Order",
|
||||||
|
"Sales Order",
|
||||||
|
) and frappe.get_cached_value(
|
||||||
"Payment Terms Template",
|
"Payment Terms Template",
|
||||||
doc.payment_terms_template,
|
doc.payment_terms_template,
|
||||||
"allocate_payment_based_on_payment_terms",
|
"allocate_payment_based_on_payment_terms",
|
||||||
|
|||||||
@ -495,6 +495,7 @@
|
|||||||
"allow_bulk_edit": 1,
|
"allow_bulk_edit": 1,
|
||||||
"fieldname": "items",
|
"fieldname": "items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
|
"label": "Items",
|
||||||
"oldfieldname": "po_details",
|
"oldfieldname": "po_details",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Purchase Order Item",
|
"options": "Purchase Order Item",
|
||||||
@ -1100,8 +1101,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "before_items_section",
|
"fieldname": "before_items_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hide_border": 1,
|
"hide_border": 1
|
||||||
"label": "Items"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "items_col_break",
|
"fieldname": "items_col_break",
|
||||||
@ -1271,7 +1271,7 @@
|
|||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-01-28 18:59:16.322824",
|
"modified": "2023-04-14 16:42:29.448464",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
|
|||||||
@ -310,7 +310,6 @@
|
|||||||
"fieldname": "items_section",
|
"fieldname": "items_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hide_border": 1,
|
"hide_border": 1,
|
||||||
"label": "Items",
|
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"options": "fa fa-shopping-cart"
|
"options": "fa fa-shopping-cart"
|
||||||
},
|
},
|
||||||
@ -318,6 +317,7 @@
|
|||||||
"allow_bulk_edit": 1,
|
"allow_bulk_edit": 1,
|
||||||
"fieldname": "items",
|
"fieldname": "items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
|
"label": "Items",
|
||||||
"oldfieldname": "po_details",
|
"oldfieldname": "po_details",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Supplier Quotation Item",
|
"options": "Supplier Quotation Item",
|
||||||
@ -844,7 +844,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-12-12 18:35:39.740974",
|
"modified": "2023-04-14 16:43:41.714832",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Supplier Quotation",
|
"name": "Supplier Quotation",
|
||||||
|
|||||||
@ -273,8 +273,8 @@ class AccountsController(TransactionBase):
|
|||||||
self.validate_payment_schedule_dates()
|
self.validate_payment_schedule_dates()
|
||||||
self.set_due_date()
|
self.set_due_date()
|
||||||
self.set_payment_schedule()
|
self.set_payment_schedule()
|
||||||
self.validate_payment_schedule_amount()
|
|
||||||
if not self.get("ignore_default_payment_terms_template"):
|
if not self.get("ignore_default_payment_terms_template"):
|
||||||
|
self.validate_payment_schedule_amount()
|
||||||
self.validate_due_date()
|
self.validate_due_date()
|
||||||
self.validate_advance_entries()
|
self.validate_advance_entries()
|
||||||
|
|
||||||
@ -1607,6 +1607,7 @@ class AccountsController(TransactionBase):
|
|||||||
|
|
||||||
base_grand_total = self.get("base_rounded_total") or self.base_grand_total
|
base_grand_total = self.get("base_rounded_total") or self.base_grand_total
|
||||||
grand_total = self.get("rounded_total") or self.grand_total
|
grand_total = self.get("rounded_total") or self.grand_total
|
||||||
|
automatically_fetch_payment_terms = 0
|
||||||
|
|
||||||
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
if self.doctype in ("Sales Invoice", "Purchase Invoice"):
|
||||||
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
base_grand_total = base_grand_total - flt(self.base_write_off_amount)
|
||||||
@ -1652,19 +1653,20 @@ class AccountsController(TransactionBase):
|
|||||||
)
|
)
|
||||||
self.append("payment_schedule", data)
|
self.append("payment_schedule", data)
|
||||||
|
|
||||||
for d in self.get("payment_schedule"):
|
if not automatically_fetch_payment_terms:
|
||||||
if d.invoice_portion:
|
for d in self.get("payment_schedule"):
|
||||||
d.payment_amount = flt(
|
if d.invoice_portion:
|
||||||
grand_total * flt(d.invoice_portion / 100), d.precision("payment_amount")
|
d.payment_amount = flt(
|
||||||
)
|
grand_total * flt(d.invoice_portion / 100), d.precision("payment_amount")
|
||||||
d.base_payment_amount = flt(
|
)
|
||||||
base_grand_total * flt(d.invoice_portion / 100), d.precision("base_payment_amount")
|
d.base_payment_amount = flt(
|
||||||
)
|
base_grand_total * flt(d.invoice_portion / 100), d.precision("base_payment_amount")
|
||||||
d.outstanding = d.payment_amount
|
)
|
||||||
elif not d.invoice_portion:
|
d.outstanding = d.payment_amount
|
||||||
d.base_payment_amount = flt(
|
elif not d.invoice_portion:
|
||||||
d.payment_amount * self.get("conversion_rate"), d.precision("base_payment_amount")
|
d.base_payment_amount = flt(
|
||||||
)
|
d.payment_amount * self.get("conversion_rate"), d.precision("base_payment_amount")
|
||||||
|
)
|
||||||
|
|
||||||
def get_order_details(self):
|
def get_order_details(self):
|
||||||
if self.doctype == "Sales Invoice":
|
if self.doctype == "Sales Invoice":
|
||||||
@ -1717,6 +1719,10 @@ class AccountsController(TransactionBase):
|
|||||||
"invoice_portion": schedule.invoice_portion,
|
"invoice_portion": schedule.invoice_portion,
|
||||||
"mode_of_payment": schedule.mode_of_payment,
|
"mode_of_payment": schedule.mode_of_payment,
|
||||||
"description": schedule.description,
|
"description": schedule.description,
|
||||||
|
"payment_amount": schedule.payment_amount,
|
||||||
|
"base_payment_amount": schedule.base_payment_amount,
|
||||||
|
"outstanding": schedule.outstanding,
|
||||||
|
"paid_amount": schedule.paid_amount,
|
||||||
}
|
}
|
||||||
|
|
||||||
if schedule.discount_type == "Percentage":
|
if schedule.discount_type == "Percentage":
|
||||||
|
|||||||
@ -859,6 +859,8 @@ def is_reposting_pending():
|
|||||||
|
|
||||||
def future_sle_exists(args, sl_entries=None):
|
def future_sle_exists(args, sl_entries=None):
|
||||||
key = (args.voucher_type, args.voucher_no)
|
key = (args.voucher_type, args.voucher_no)
|
||||||
|
if not hasattr(frappe.local, "future_sle"):
|
||||||
|
frappe.local.future_sle = {}
|
||||||
|
|
||||||
if validate_future_sle_not_exists(args, key, sl_entries):
|
if validate_future_sle_not_exists(args, key, sl_entries):
|
||||||
return False
|
return False
|
||||||
@ -892,6 +894,9 @@ def future_sle_exists(args, sl_entries=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
for d in data:
|
for d in data:
|
||||||
|
if key not in frappe.local.future_sle:
|
||||||
|
frappe.local.future_sle[key] = frappe._dict({})
|
||||||
|
|
||||||
frappe.local.future_sle[key][(d.item_code, d.warehouse)] = d.total_row
|
frappe.local.future_sle[key][(d.item_code, d.warehouse)] = d.total_row
|
||||||
|
|
||||||
return len(data)
|
return len(data)
|
||||||
@ -903,6 +908,9 @@ def validate_future_sle_not_exists(args, key, sl_entries=None):
|
|||||||
item_key = (args.get("item_code"), args.get("warehouse"))
|
item_key = (args.get("item_code"), args.get("warehouse"))
|
||||||
|
|
||||||
if not sl_entries and hasattr(frappe.local, "future_sle"):
|
if not sl_entries and hasattr(frappe.local, "future_sle"):
|
||||||
|
if key not in frappe.local.future_sle:
|
||||||
|
return False
|
||||||
|
|
||||||
if not frappe.local.future_sle.get(key) or (
|
if not frappe.local.future_sle.get(key) or (
|
||||||
item_key and item_key not in frappe.local.future_sle.get(key)
|
item_key and item_key not in frappe.local.future_sle.get(key)
|
||||||
):
|
):
|
||||||
@ -910,11 +918,8 @@ def validate_future_sle_not_exists(args, key, sl_entries=None):
|
|||||||
|
|
||||||
|
|
||||||
def get_cached_data(args, key):
|
def get_cached_data(args, key):
|
||||||
if not hasattr(frappe.local, "future_sle"):
|
|
||||||
frappe.local.future_sle = {}
|
|
||||||
|
|
||||||
if key not in frappe.local.future_sle:
|
if key not in frappe.local.future_sle:
|
||||||
frappe.local.future_sle[key] = frappe._dict({})
|
return False
|
||||||
|
|
||||||
if args.get("item_code"):
|
if args.get("item_code"):
|
||||||
item_key = (args.get("item_code"), args.get("warehouse"))
|
item_key = (args.get("item_code"), args.get("warehouse"))
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
"actions": [],
|
"actions": [],
|
||||||
"allow_events_in_timeline": 1,
|
"allow_events_in_timeline": 1,
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
|
"allow_rename": 1,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
"creation": "2022-02-08 13:14:41.083327",
|
"creation": "2022-02-08 13:14:41.083327",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
@ -515,7 +516,7 @@
|
|||||||
"idx": 5,
|
"idx": 5,
|
||||||
"image_field": "image",
|
"image_field": "image",
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-01-24 18:20:05.044791",
|
"modified": "2023-04-14 18:20:05.044791",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "CRM",
|
"module": "CRM",
|
||||||
"name": "Lead",
|
"name": "Lead",
|
||||||
|
|||||||
@ -315,6 +315,7 @@ class WebsiteItem(WebsiteGenerator):
|
|||||||
self.item_code, skip_quotation_creation=True
|
self.item_code, skip_quotation_creation=True
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
def copy_specification_from_item_group(self):
|
def copy_specification_from_item_group(self):
|
||||||
self.set("website_specifications", [])
|
self.set("website_specifications", [])
|
||||||
if self.item_group:
|
if self.item_group:
|
||||||
|
|||||||
@ -1920,7 +1920,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
}
|
}
|
||||||
|
|
||||||
prompt_user_for_reference_date(){
|
prompt_user_for_reference_date(){
|
||||||
var me = this;
|
let me = this;
|
||||||
frappe.prompt({
|
frappe.prompt({
|
||||||
label: __("Cheque/Reference Date"),
|
label: __("Cheque/Reference Date"),
|
||||||
fieldname: "reference_date",
|
fieldname: "reference_date",
|
||||||
@ -1947,7 +1947,7 @@ erpnext.TransactionController = class TransactionController extends erpnext.taxe
|
|||||||
let has_payment_schedule = this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length;
|
let has_payment_schedule = this.frm.doc.payment_schedule && this.frm.doc.payment_schedule.length;
|
||||||
if(!is_eligible || !has_payment_schedule) return false;
|
if(!is_eligible || !has_payment_schedule) return false;
|
||||||
|
|
||||||
let has_discount = this.frm.doc.payment_schedule.some(row => row.discount_date);
|
let has_discount = this.frm.doc.payment_schedule.some(row => row.discount);
|
||||||
return has_discount;
|
return has_discount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -416,7 +416,6 @@
|
|||||||
"fieldname": "items_section",
|
"fieldname": "items_section",
|
||||||
"fieldtype": "Section Break",
|
"fieldtype": "Section Break",
|
||||||
"hide_border": 1,
|
"hide_border": 1,
|
||||||
"label": "Items",
|
|
||||||
"oldfieldtype": "Section Break",
|
"oldfieldtype": "Section Break",
|
||||||
"options": "fa fa-shopping-cart"
|
"options": "fa fa-shopping-cart"
|
||||||
},
|
},
|
||||||
@ -424,6 +423,7 @@
|
|||||||
"allow_bulk_edit": 1,
|
"allow_bulk_edit": 1,
|
||||||
"fieldname": "items",
|
"fieldname": "items",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
|
"label": "Items",
|
||||||
"oldfieldname": "quotation_details",
|
"oldfieldname": "quotation_details",
|
||||||
"oldfieldtype": "Table",
|
"oldfieldtype": "Table",
|
||||||
"options": "Quotation Item",
|
"options": "Quotation Item",
|
||||||
@ -1072,7 +1072,7 @@
|
|||||||
"idx": 82,
|
"idx": 82,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-12-12 18:32:28.671332",
|
"modified": "2023-04-14 16:50:44.550098",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Quotation",
|
"name": "Quotation",
|
||||||
|
|||||||
@ -704,7 +704,7 @@
|
|||||||
"type": "Link"
|
"type": "Link"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-04-26 13:29:55.087240",
|
"modified": "2023-04-16 13:29:55.087240",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Selling",
|
"name": "Selling",
|
||||||
|
|||||||
@ -161,7 +161,7 @@ def add_standard_navbar_items():
|
|||||||
{
|
{
|
||||||
"item_label": "User Forum",
|
"item_label": "User Forum",
|
||||||
"item_type": "Route",
|
"item_type": "Route",
|
||||||
"route": "https://discuss.erpnext.com",
|
"route": "https://discuss.frappe.io",
|
||||||
"is_standard": 1,
|
"is_standard": 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -571,24 +571,33 @@ class StockReconciliation(StockController):
|
|||||||
self._cancel()
|
self._cancel()
|
||||||
|
|
||||||
def recalculate_current_qty(self, item_code, batch_no):
|
def recalculate_current_qty(self, item_code, batch_no):
|
||||||
|
from erpnext.stock.stock_ledger import get_valuation_rate
|
||||||
|
|
||||||
|
sl_entries = []
|
||||||
for row in self.items:
|
for row in self.items:
|
||||||
if not (row.item_code == item_code and row.batch_no == batch_no):
|
if not (row.item_code == item_code and row.batch_no == batch_no):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
row.current_qty = get_batch_qty_for_stock_reco(
|
current_qty = get_batch_qty_for_stock_reco(
|
||||||
item_code, row.warehouse, batch_no, self.posting_date, self.posting_time, self.name
|
item_code, row.warehouse, batch_no, self.posting_date, self.posting_time, self.name
|
||||||
)
|
)
|
||||||
|
|
||||||
qty, val_rate = get_stock_balance(
|
precesion = row.precision("current_qty")
|
||||||
item_code,
|
if flt(current_qty, precesion) == flt(row.current_qty, precesion):
|
||||||
row.warehouse,
|
continue
|
||||||
self.posting_date,
|
|
||||||
self.posting_time,
|
val_rate = get_valuation_rate(
|
||||||
with_valuation_rate=True,
|
item_code, row.warehouse, self.doctype, self.name, company=self.company, batch_no=batch_no
|
||||||
)
|
)
|
||||||
|
|
||||||
row.current_valuation_rate = val_rate
|
row.current_valuation_rate = val_rate
|
||||||
|
if not row.current_qty and current_qty:
|
||||||
|
sle = self.get_sle_for_items(row)
|
||||||
|
sle.actual_qty = current_qty * -1
|
||||||
|
sle.valuation_rate = val_rate
|
||||||
|
sl_entries.append(sle)
|
||||||
|
|
||||||
|
row.current_qty = current_qty
|
||||||
row.db_set(
|
row.db_set(
|
||||||
{
|
{
|
||||||
"current_qty": row.current_qty,
|
"current_qty": row.current_qty,
|
||||||
@ -597,6 +606,9 @@ class StockReconciliation(StockController):
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if sl_entries:
|
||||||
|
self.make_sl_entries(sl_entries)
|
||||||
|
|
||||||
|
|
||||||
def get_batch_qty_for_stock_reco(
|
def get_batch_qty_for_stock_reco(
|
||||||
item_code, warehouse, batch_no, posting_date, posting_time, voucher_no
|
item_code, warehouse, batch_no, posting_date, posting_time, voucher_no
|
||||||
|
|||||||
@ -11,6 +11,13 @@ frappe.query_reports["Warehouse Wise Stock Balance"] = {
|
|||||||
"options": "Company",
|
"options": "Company",
|
||||||
"reqd": 1,
|
"reqd": 1,
|
||||||
"default": frappe.defaults.get_user_default("Company")
|
"default": frappe.defaults.get_user_default("Company")
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname":"show_disabled_warehouses",
|
||||||
|
"label": __("Show Disabled Warehouses"),
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"default": 0
|
||||||
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"initial_depth": 3,
|
"initial_depth": 3,
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from frappe.query_builder.functions import Sum
|
|||||||
class StockBalanceFilter(TypedDict):
|
class StockBalanceFilter(TypedDict):
|
||||||
company: Optional[str]
|
company: Optional[str]
|
||||||
warehouse: Optional[str]
|
warehouse: Optional[str]
|
||||||
|
show_disabled_warehouses: Optional[int]
|
||||||
|
|
||||||
|
|
||||||
SLEntry = Dict[str, Any]
|
SLEntry = Dict[str, Any]
|
||||||
@ -18,7 +19,7 @@ SLEntry = Dict[str, Any]
|
|||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
columns, data = [], []
|
columns, data = [], []
|
||||||
columns = get_columns()
|
columns = get_columns(filters)
|
||||||
data = get_data(filters)
|
data = get_data(filters)
|
||||||
|
|
||||||
return columns, data
|
return columns, data
|
||||||
@ -42,10 +43,14 @@ def get_warehouse_wise_balance(filters: StockBalanceFilter) -> List[SLEntry]:
|
|||||||
|
|
||||||
|
|
||||||
def get_warehouses(report_filters: StockBalanceFilter):
|
def get_warehouses(report_filters: StockBalanceFilter):
|
||||||
|
filters = {"company": report_filters.company, "disabled": 0}
|
||||||
|
if report_filters.get("show_disabled_warehouses"):
|
||||||
|
filters["disabled"] = ("in", [0, report_filters.show_disabled_warehouses])
|
||||||
|
|
||||||
return frappe.get_all(
|
return frappe.get_all(
|
||||||
"Warehouse",
|
"Warehouse",
|
||||||
fields=["name", "parent_warehouse", "is_group"],
|
fields=["name", "parent_warehouse", "is_group", "disabled"],
|
||||||
filters={"company": report_filters.company},
|
filters=filters,
|
||||||
order_by="lft",
|
order_by="lft",
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -90,8 +95,8 @@ def set_balance_in_parent(warehouses):
|
|||||||
update_balance(warehouse, warehouse.stock_balance)
|
update_balance(warehouse, warehouse.stock_balance)
|
||||||
|
|
||||||
|
|
||||||
def get_columns():
|
def get_columns(filters: StockBalanceFilter) -> List[Dict]:
|
||||||
return [
|
columns = [
|
||||||
{
|
{
|
||||||
"label": _("Warehouse"),
|
"label": _("Warehouse"),
|
||||||
"fieldname": "name",
|
"fieldname": "name",
|
||||||
@ -101,3 +106,15 @@ def get_columns():
|
|||||||
},
|
},
|
||||||
{"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150},
|
{"label": _("Stock Balance"), "fieldname": "stock_balance", "fieldtype": "Float", "width": 150},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
if filters.get("show_disabled_warehouses"):
|
||||||
|
columns.append(
|
||||||
|
{
|
||||||
|
"label": _("Warehouse Disabled?"),
|
||||||
|
"fieldname": "disabled",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"width": 200,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return columns
|
||||||
|
|||||||
@ -544,6 +544,14 @@ class update_entries_after(object):
|
|||||||
if not self.args.get("sle_id"):
|
if not self.args.get("sle_id"):
|
||||||
self.get_dynamic_incoming_outgoing_rate(sle)
|
self.get_dynamic_incoming_outgoing_rate(sle)
|
||||||
|
|
||||||
|
if (
|
||||||
|
sle.voucher_type == "Stock Reconciliation"
|
||||||
|
and sle.batch_no
|
||||||
|
and sle.voucher_detail_no
|
||||||
|
and sle.actual_qty < 0
|
||||||
|
):
|
||||||
|
self.reset_actual_qty_for_stock_reco(sle)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
|
sle.voucher_type in ["Purchase Receipt", "Purchase Invoice"]
|
||||||
and sle.voucher_detail_no
|
and sle.voucher_detail_no
|
||||||
@ -605,6 +613,16 @@ class update_entries_after(object):
|
|||||||
if not self.args.get("sle_id"):
|
if not self.args.get("sle_id"):
|
||||||
self.update_outgoing_rate_on_transaction(sle)
|
self.update_outgoing_rate_on_transaction(sle)
|
||||||
|
|
||||||
|
def reset_actual_qty_for_stock_reco(self, sle):
|
||||||
|
current_qty = frappe.get_cached_value(
|
||||||
|
"Stock Reconciliation Item", sle.voucher_detail_no, "current_qty"
|
||||||
|
)
|
||||||
|
|
||||||
|
if current_qty:
|
||||||
|
sle.actual_qty = current_qty * -1
|
||||||
|
elif current_qty == 0:
|
||||||
|
sle.is_cancelled = 1
|
||||||
|
|
||||||
def validate_negative_stock(self, sle):
|
def validate_negative_stock(self, sle):
|
||||||
"""
|
"""
|
||||||
validate negative stock for entries current datetime onwards
|
validate negative stock for entries current datetime onwards
|
||||||
@ -1369,12 +1387,7 @@ def update_qty_in_future_sle(args, allow_negative_stock=False):
|
|||||||
|
|
||||||
def regenerate_sle_for_batch_stock_reco(detail):
|
def regenerate_sle_for_batch_stock_reco(detail):
|
||||||
doc = frappe.get_cached_doc("Stock Reconciliation", detail.voucher_no)
|
doc = frappe.get_cached_doc("Stock Reconciliation", detail.voucher_no)
|
||||||
doc.docstatus = 2
|
|
||||||
doc.update_stock_ledger()
|
|
||||||
|
|
||||||
doc.recalculate_current_qty(detail.item_code, detail.batch_no)
|
doc.recalculate_current_qty(detail.item_code, detail.batch_no)
|
||||||
doc.docstatus = 1
|
|
||||||
doc.update_stock_ledger()
|
|
||||||
doc.repost_future_sle_and_gle()
|
doc.repost_future_sle_and_gle()
|
||||||
|
|
||||||
|
|
||||||
@ -1401,34 +1414,52 @@ def get_stock_reco_qty_shift(args):
|
|||||||
return stock_reco_qty_shift
|
return stock_reco_qty_shift
|
||||||
|
|
||||||
|
|
||||||
def get_next_stock_reco(args):
|
def get_next_stock_reco(kwargs):
|
||||||
"""Returns next nearest stock reconciliaton's details."""
|
"""Returns next nearest stock reconciliaton's details."""
|
||||||
|
|
||||||
return frappe.db.sql(
|
sle = frappe.qb.DocType("Stock Ledger Entry")
|
||||||
"""
|
|
||||||
select
|
query = (
|
||||||
name, posting_date, posting_time, creation, voucher_no, item_code, batch_no, actual_qty
|
frappe.qb.from_(sle)
|
||||||
from
|
.select(
|
||||||
`tabStock Ledger Entry`
|
sle.name,
|
||||||
where
|
sle.posting_date,
|
||||||
item_code = %(item_code)s
|
sle.posting_time,
|
||||||
and warehouse = %(warehouse)s
|
sle.creation,
|
||||||
and voucher_type = 'Stock Reconciliation'
|
sle.voucher_no,
|
||||||
and voucher_no != %(voucher_no)s
|
sle.item_code,
|
||||||
and is_cancelled = 0
|
sle.batch_no,
|
||||||
and (timestamp(posting_date, posting_time) > timestamp(%(posting_date)s, %(posting_time)s)
|
sle.actual_qty,
|
||||||
or (
|
)
|
||||||
timestamp(posting_date, posting_time) = timestamp(%(posting_date)s, %(posting_time)s)
|
.where(
|
||||||
and creation > %(creation)s
|
(sle.item_code == kwargs.get("item_code"))
|
||||||
|
& (sle.warehouse == kwargs.get("warehouse"))
|
||||||
|
& (sle.voucher_type == "Stock Reconciliation")
|
||||||
|
& (sle.voucher_no != kwargs.get("voucher_no"))
|
||||||
|
& (sle.is_cancelled == 0)
|
||||||
|
& (
|
||||||
|
(
|
||||||
|
CombineDatetime(sle.posting_date, sle.posting_time)
|
||||||
|
> CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
|
||||||
|
| (
|
||||||
|
(
|
||||||
|
CombineDatetime(sle.posting_date, sle.posting_time)
|
||||||
|
== CombineDatetime(kwargs.get("posting_date"), kwargs.get("posting_time"))
|
||||||
|
)
|
||||||
|
& (sle.creation > kwargs.get("creation"))
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
order by timestamp(posting_date, posting_time) asc, creation asc
|
)
|
||||||
limit 1
|
.orderby(CombineDatetime(sle.posting_date, sle.posting_time))
|
||||||
""",
|
.orderby(sle.creation)
|
||||||
args,
|
|
||||||
as_dict=1,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if kwargs.get("batch_no"):
|
||||||
|
query.where(sle.batch_no == kwargs.get("batch_no"))
|
||||||
|
|
||||||
|
return query.run(as_dict=True)
|
||||||
|
|
||||||
|
|
||||||
def get_datetime_limit_condition(detail):
|
def get_datetime_limit_condition(detail):
|
||||||
return f"""
|
return f"""
|
||||||
|
|||||||
@ -11,7 +11,10 @@
|
|||||||
|
|
||||||
<div class="product-price">
|
<div class="product-price">
|
||||||
<!-- Final Price -->
|
<!-- Final Price -->
|
||||||
{{ price_info.formatted_price_sales_uom }}
|
<span itemprop="offers" itemscope itemtype="https://schema.org/Offer">
|
||||||
|
<span itemprop="price" content="{{ price_info.price_list_rate }}">{{ price_info.formatted_price_sales_uom }}</span>
|
||||||
|
<span style="display:none;" itemprop="priceCurrency" content="{{ price_info.currency }}">{{ price_info.currency }}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
<!-- Striked Price and Discount -->
|
<!-- Striked Price and Discount -->
|
||||||
{% if price_info.formatted_mrp %}
|
{% if price_info.formatted_mrp %}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user