Merge pull request #16358 from adityahase/naming-series
feat(naming): Deferred naming for SLE and GL Entry
This commit is contained in:
commit
bace4d3e6d
File diff suppressed because it is too large
Load Diff
@ -6,14 +6,21 @@ import frappe, erpnext
|
|||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import flt, fmt_money, getdate, formatdate
|
from frappe.utils import flt, fmt_money, getdate, formatdate
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.model.naming import set_name_from_naming_options
|
||||||
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
|
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
|
||||||
from erpnext.accounts.utils import get_account_currency
|
from erpnext.accounts.utils import get_account_currency
|
||||||
from erpnext.accounts.utils import get_fiscal_year
|
from erpnext.accounts.utils import get_fiscal_year
|
||||||
from erpnext.exceptions import InvalidAccountCurrency
|
from erpnext.exceptions import InvalidAccountCurrency
|
||||||
|
|
||||||
exclude_from_linked_with = True
|
exclude_from_linked_with = True
|
||||||
|
|
||||||
class GLEntry(Document):
|
class GLEntry(Document):
|
||||||
|
def autoname(self):
|
||||||
|
"""
|
||||||
|
Temporarily name doc for fast insertion
|
||||||
|
name will be changed using autoname options (in a scheduled job)
|
||||||
|
"""
|
||||||
|
self.name = frappe.generate_hash(txt="", length=10)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.flags.ignore_submit_comment = True
|
self.flags.ignore_submit_comment = True
|
||||||
self.check_mandatory()
|
self.check_mandatory()
|
||||||
@ -230,3 +237,17 @@ def update_against_account(voucher_type, voucher_no):
|
|||||||
|
|
||||||
if d.against != new_against:
|
if d.against != new_against:
|
||||||
frappe.db.set_value("GL Entry", d.name, "against", new_against)
|
frappe.db.set_value("GL Entry", d.name, "against", new_against)
|
||||||
|
|
||||||
|
|
||||||
|
def rename_gle_sle_docs():
|
||||||
|
for doctype in ["GL Entry", "Stock Ledger Entry"]:
|
||||||
|
rename_temporarily_named_docs(doctype)
|
||||||
|
|
||||||
|
def rename_temporarily_named_docs(doctype):
|
||||||
|
"""Rename temporarily named docs using autoname options"""
|
||||||
|
docs_to_rename = frappe.get_all(doctype, {"to_rename": "1"}, order_by="creation")
|
||||||
|
for doc in docs_to_rename:
|
||||||
|
oldname = doc.name
|
||||||
|
set_name_from_naming_options(frappe.get_meta(doctype).autoname, doc)
|
||||||
|
newname = doc.name
|
||||||
|
frappe.db.sql("""UPDATE `tab{}` SET name = %s, to_rename = 0 where name = %s""".format(doctype), (newname, oldname))
|
||||||
|
|||||||
@ -3,7 +3,9 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import frappe, unittest
|
import frappe, unittest
|
||||||
|
from frappe.model.naming import parse_naming_series
|
||||||
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
|
||||||
|
from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs
|
||||||
|
|
||||||
class TestGLEntry(unittest.TestCase):
|
class TestGLEntry(unittest.TestCase):
|
||||||
def test_round_off_entry(self):
|
def test_round_off_entry(self):
|
||||||
@ -23,3 +25,32 @@ class TestGLEntry(unittest.TestCase):
|
|||||||
and debit = 0 and credit = '.01'""", jv.name)
|
and debit = 0 and credit = '.01'""", jv.name)
|
||||||
|
|
||||||
self.assertTrue(round_off_entry)
|
self.assertTrue(round_off_entry)
|
||||||
|
|
||||||
|
def test_rename_entries(self):
|
||||||
|
je = make_journal_entry("_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", 100, submit=True)
|
||||||
|
rename_gle_sle_docs()
|
||||||
|
naming_series = parse_naming_series(parts=frappe.get_meta("GL Entry").autoname.split(".")[:-1])
|
||||||
|
|
||||||
|
je = make_journal_entry("_Test Account Cost for Goods Sold - _TC", "_Test Bank - _TC", 100, submit=True)
|
||||||
|
|
||||||
|
gl_entries = frappe.get_all("GL Entry",
|
||||||
|
fields=["name", "to_rename"],
|
||||||
|
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
|
||||||
|
order_by="creation"
|
||||||
|
)
|
||||||
|
self.assertTrue(all(entry.to_rename == 1 for entry in gl_entries))
|
||||||
|
old_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
|
||||||
|
|
||||||
|
rename_gle_sle_docs()
|
||||||
|
|
||||||
|
new_gl_entries = frappe.get_all("GL Entry",
|
||||||
|
fields=["name", "to_rename"],
|
||||||
|
filters={"voucher_type": "Journal Entry", "voucher_no": je.name},
|
||||||
|
order_by="creation"
|
||||||
|
)
|
||||||
|
self.assertTrue(all(entry.to_rename == 0 for entry in new_gl_entries))
|
||||||
|
|
||||||
|
self.assertTrue(all(new.name != old.name for new, old in zip(gl_entries, new_gl_entries)))
|
||||||
|
|
||||||
|
new_naming_series_current_value = frappe.db.sql("SELECT current from tabSeries where name = %s", naming_series)[0][0]
|
||||||
|
self.assertEquals(old_naming_series_current_value + 2, new_naming_series_current_value)
|
||||||
|
|||||||
@ -729,7 +729,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
# check gl entries
|
# check gl entries
|
||||||
gl_entries = frappe.db.sql("""select account, debit, credit
|
gl_entries = frappe.db.sql("""select account, debit, credit
|
||||||
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
from `tabGL Entry` where voucher_type='Sales Invoice' and voucher_no=%s
|
||||||
order by account asc, debit asc""", si.name, as_dict=1)
|
order by account asc, debit asc, credit asc""", si.name, as_dict=1)
|
||||||
self.assertTrue(gl_entries)
|
self.assertTrue(gl_entries)
|
||||||
|
|
||||||
stock_in_hand = get_inventory_account('_Test Company')
|
stock_in_hand = get_inventory_account('_Test Company')
|
||||||
@ -762,7 +762,7 @@ class TestSalesInvoice(unittest.TestCase):
|
|||||||
set_perpetual_inventory(0)
|
set_perpetual_inventory(0)
|
||||||
|
|
||||||
frappe.db.sql("delete from `tabPOS Profile`")
|
frappe.db.sql("delete from `tabPOS Profile`")
|
||||||
|
|
||||||
def test_pos_si_without_payment(self):
|
def test_pos_si_without_payment(self):
|
||||||
set_perpetual_inventory()
|
set_perpetual_inventory()
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
|
|||||||
@ -329,7 +329,7 @@ class GrossProfitGenerator(object):
|
|||||||
where company=%(company)s
|
where company=%(company)s
|
||||||
order by
|
order by
|
||||||
item_code desc, warehouse desc, posting_date desc,
|
item_code desc, warehouse desc, posting_date desc,
|
||||||
posting_time desc, name desc""", self.filters, as_dict=True)
|
posting_time desc, creation desc""", self.filters, as_dict=True)
|
||||||
self.sle = {}
|
self.sle = {}
|
||||||
for r in res:
|
for r in res:
|
||||||
if (r.item_code, r.warehouse) not in self.sle:
|
if (r.item_code, r.warehouse) not in self.sle:
|
||||||
|
|||||||
@ -655,7 +655,7 @@ def get_outstanding_invoices(party_type, party, account, condition=None):
|
|||||||
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
|
or (voucher_type not in ('Journal Entry', 'Payment Entry')))
|
||||||
group by voucher_type, voucher_no
|
group by voucher_type, voucher_no
|
||||||
having (invoice_amount - payment_amount) > 0.005
|
having (invoice_amount - payment_amount) > 0.005
|
||||||
order by posting_date, name""".format(
|
order by posting_date, creation""".format(
|
||||||
dr_or_cr=dr_or_cr,
|
dr_or_cr=dr_or_cr,
|
||||||
invoice = invoice,
|
invoice = invoice,
|
||||||
payment_dr_or_cr=payment_dr_or_cr,
|
payment_dr_or_cr=payment_dr_or_cr,
|
||||||
|
|||||||
@ -179,7 +179,7 @@ class SellingController(StockController):
|
|||||||
last_valuation_rate = frappe.db.sql("""
|
last_valuation_rate = frappe.db.sql("""
|
||||||
SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
|
SELECT valuation_rate FROM `tabStock Ledger Entry` WHERE item_code = %s
|
||||||
AND warehouse = %s AND valuation_rate > 0
|
AND warehouse = %s AND valuation_rate > 0
|
||||||
ORDER BY posting_date DESC, posting_time DESC, name DESC LIMIT 1
|
ORDER BY posting_date DESC, posting_time DESC, creation DESC LIMIT 1
|
||||||
""", (it.item_code, it.warehouse))
|
""", (it.item_code, it.warehouse))
|
||||||
if last_valuation_rate:
|
if last_valuation_rate:
|
||||||
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
|
last_valuation_rate_in_sales_uom = last_valuation_rate[0][0] / (it.conversion_factor or 1)
|
||||||
|
|||||||
@ -413,7 +413,7 @@ def get_future_stock_vouchers(posting_date, posting_time, for_warehouses=None, f
|
|||||||
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
for d in frappe.db.sql("""select distinct sle.voucher_type, sle.voucher_no
|
||||||
from `tabStock Ledger Entry` sle
|
from `tabStock Ledger Entry` sle
|
||||||
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
|
where timestamp(sle.posting_date, sle.posting_time) >= timestamp(%s, %s) {condition}
|
||||||
order by timestamp(sle.posting_date, sle.posting_time) asc, name asc""".format(condition=condition),
|
order by timestamp(sle.posting_date, sle.posting_time) asc, creation asc""".format(condition=condition),
|
||||||
tuple([posting_date, posting_time] + values), as_dict=True):
|
tuple([posting_date, posting_time] + values), as_dict=True):
|
||||||
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
|
future_stock_vouchers.append([d.voucher_type, d.voucher_no])
|
||||||
|
|
||||||
|
|||||||
@ -235,7 +235,9 @@ scheduler_events = {
|
|||||||
"hourly": [
|
"hourly": [
|
||||||
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
'erpnext.hr.doctype.daily_work_summary_group.daily_work_summary_group.trigger_emails',
|
||||||
"erpnext.accounts.doctype.subscription.subscription.process_all",
|
"erpnext.accounts.doctype.subscription.subscription.process_all",
|
||||||
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details"
|
"erpnext.erpnext_integrations.doctype.amazon_mws_settings.amazon_mws_settings.schedule_get_order_details",
|
||||||
|
"erpnext.accounts.doctype.gl_entry.gl_entry.rename_gle_sle_docs",
|
||||||
|
|
||||||
],
|
],
|
||||||
"daily": [
|
"daily": [
|
||||||
"erpnext.stock.reorder_item.reorder_item",
|
"erpnext.stock.reorder_item.reorder_item",
|
||||||
|
|||||||
@ -272,7 +272,7 @@ class BOM(WebsiteGenerator):
|
|||||||
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
||||||
from `tabStock Ledger Entry`
|
from `tabStock Ledger Entry`
|
||||||
where item_code = %s and valuation_rate > 0
|
where item_code = %s and valuation_rate > 0
|
||||||
order by posting_date desc, posting_time desc, name desc limit 1""", args['item_code'])
|
order by posting_date desc, posting_time desc, creation desc limit 1""", args['item_code'])
|
||||||
|
|
||||||
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
|
valuation_rate = flt(last_valuation_rate[0][0]) if last_valuation_rate else 0
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ data_map = {
|
|||||||
"actual_qty as qty", "voucher_type", "voucher_no", "project",
|
"actual_qty as qty", "voucher_type", "voucher_no", "project",
|
||||||
"incoming_rate as incoming_rate", "stock_uom", "serial_no",
|
"incoming_rate as incoming_rate", "stock_uom", "serial_no",
|
||||||
"qty_after_transaction", "valuation_rate"],
|
"qty_after_transaction", "valuation_rate"],
|
||||||
"order_by": "posting_date, posting_time, name",
|
"order_by": "posting_date, posting_time, creation",
|
||||||
"links": {
|
"links": {
|
||||||
"item_code": ["Item", "name"],
|
"item_code": ["Item", "name"],
|
||||||
"warehouse": ["Warehouse", "name"],
|
"warehouse": ["Warehouse", "name"],
|
||||||
|
|||||||
@ -60,7 +60,7 @@ class Bin(Document):
|
|||||||
select * from `tabStock Ledger Entry`
|
select * from `tabStock Ledger Entry`
|
||||||
where item_code = %s
|
where item_code = %s
|
||||||
and warehouse = %s
|
and warehouse = %s
|
||||||
order by timestamp(posting_date, posting_time) asc, name asc
|
order by timestamp(posting_date, posting_time) asc, creation asc
|
||||||
limit 1
|
limit 1
|
||||||
""", (self.item_code, self.warehouse), as_dict=1)
|
""", (self.item_code, self.warehouse), as_dict=1)
|
||||||
return sle and sle[0] or None
|
return sle and sle[0] or None
|
||||||
|
|||||||
@ -136,7 +136,7 @@ class SerialNo(StockController):
|
|||||||
sle_dict = {}
|
sle_dict = {}
|
||||||
for sle in frappe.db.sql("""select * from `tabStock Ledger Entry`
|
for sle in frappe.db.sql("""select * from `tabStock Ledger Entry`
|
||||||
where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'
|
where serial_no like %s and item_code=%s and ifnull(is_cancelled, 'No')='No'
|
||||||
order by posting_date desc, posting_time desc, name desc""",
|
order by posting_date desc, posting_time desc, creation desc""",
|
||||||
("%%%s%%" % self.name, self.item_code), as_dict=1):
|
("%%%s%%" % self.name, self.item_code), as_dict=1):
|
||||||
if self.name.upper() in get_serial_nos(sle.serial_no):
|
if self.name.upper() in get_serial_nos(sle.serial_no):
|
||||||
if cint(sle.actual_qty) > 0:
|
if cint(sle.actual_qty) > 0:
|
||||||
|
|||||||
@ -27,7 +27,7 @@ def get_sle(**args):
|
|||||||
values.append(value)
|
values.append(value)
|
||||||
|
|
||||||
return frappe.db.sql("""select * from `tabStock Ledger Entry` %s
|
return frappe.db.sql("""select * from `tabStock Ledger Entry` %s
|
||||||
order by timestamp(posting_date, posting_time) desc, name desc limit 1"""% condition,
|
order by timestamp(posting_date, posting_time) desc, creation desc limit 1"""% condition,
|
||||||
values, as_dict=1)
|
values, as_dict=1)
|
||||||
|
|
||||||
class TestStockEntry(unittest.TestCase):
|
class TestStockEntry(unittest.TestCase):
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,13 @@ class StockFreezeError(frappe.ValidationError): pass
|
|||||||
exclude_from_linked_with = True
|
exclude_from_linked_with = True
|
||||||
|
|
||||||
class StockLedgerEntry(Document):
|
class StockLedgerEntry(Document):
|
||||||
|
def autoname(self):
|
||||||
|
"""
|
||||||
|
Temporarily name doc for fast insertion
|
||||||
|
name will be changed using autoname options (in a scheduled job)
|
||||||
|
"""
|
||||||
|
self.name = frappe.generate_hash(txt="", length=10)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.flags.ignore_submit_comment = True
|
self.flags.ignore_submit_comment = True
|
||||||
from erpnext.stock.utils import validate_warehouse_company
|
from erpnext.stock.utils import validate_warehouse_company
|
||||||
|
|||||||
@ -81,7 +81,7 @@ def get_stock_ledger_entries(filters):
|
|||||||
company = %(company)s and
|
company = %(company)s and
|
||||||
posting_date <= %(to_date)s
|
posting_date <= %(to_date)s
|
||||||
{sle_conditions}
|
{sle_conditions}
|
||||||
order by posting_date, posting_time, sle.name"""\
|
order by posting_date, posting_time, sle.creation"""\
|
||||||
.format(item_conditions=get_item_conditions(filters),
|
.format(item_conditions=get_item_conditions(filters),
|
||||||
sle_conditions=get_sle_conditions(filters)), filters, as_dict=True)
|
sle_conditions=get_sle_conditions(filters)), filters, as_dict=True)
|
||||||
|
|
||||||
|
|||||||
@ -130,7 +130,7 @@ def get_stock_ledger_entries(filters, items):
|
|||||||
from
|
from
|
||||||
`tabStock Ledger Entry` sle force index (posting_sort_index)
|
`tabStock Ledger Entry` sle force index (posting_sort_index)
|
||||||
where sle.docstatus < 2 %s %s
|
where sle.docstatus < 2 %s %s
|
||||||
order by sle.posting_date, sle.posting_time, sle.name""" %
|
order by sle.posting_date, sle.posting_time, sle.creation""" %
|
||||||
(item_conditions_sql, conditions), as_dict=1)
|
(item_conditions_sql, conditions), as_dict=1)
|
||||||
|
|
||||||
def get_item_warehouse_map(filters, sle):
|
def get_item_warehouse_map(filters, sle):
|
||||||
|
|||||||
@ -77,7 +77,7 @@ def get_stock_ledger_entries(filters, items):
|
|||||||
posting_date between %(from_date)s and %(to_date)s
|
posting_date between %(from_date)s and %(to_date)s
|
||||||
{sle_conditions}
|
{sle_conditions}
|
||||||
{item_conditions_sql}
|
{item_conditions_sql}
|
||||||
order by posting_date asc, posting_time asc, name asc"""\
|
order by posting_date asc, posting_time asc, creation asc"""\
|
||||||
.format(
|
.format(
|
||||||
sle_conditions=get_sle_conditions(filters),
|
sle_conditions=get_sle_conditions(filters),
|
||||||
item_conditions_sql = item_conditions_sql
|
item_conditions_sql = item_conditions_sql
|
||||||
|
|||||||
@ -59,7 +59,7 @@ def repost_actual_qty(item_code, warehouse, allow_zero_rate=False):
|
|||||||
def get_balance_qty_from_sle(item_code, warehouse):
|
def get_balance_qty_from_sle(item_code, warehouse):
|
||||||
balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
|
balance_qty = frappe.db.sql("""select qty_after_transaction from `tabStock Ledger Entry`
|
||||||
where item_code=%s and warehouse=%s and is_cancelled='No'
|
where item_code=%s and warehouse=%s and is_cancelled='No'
|
||||||
order by posting_date desc, posting_time desc, name desc
|
order by posting_date desc, posting_time desc, creation desc
|
||||||
limit 1""", (item_code, warehouse))
|
limit 1""", (item_code, warehouse))
|
||||||
|
|
||||||
return flt(balance_qty[0][0]) if balance_qty else 0.0
|
return flt(balance_qty[0][0]) if balance_qty else 0.0
|
||||||
@ -235,7 +235,7 @@ def repost_all_stock_vouchers():
|
|||||||
vouchers = frappe.db.sql("""select distinct voucher_type, voucher_no
|
vouchers = frappe.db.sql("""select distinct voucher_type, voucher_no
|
||||||
from `tabStock Ledger Entry` sle
|
from `tabStock Ledger Entry` sle
|
||||||
where voucher_type != "Serial No" and sle.warehouse in (%s)
|
where voucher_type != "Serial No" and sle.warehouse in (%s)
|
||||||
order by posting_date, posting_time, name""" %
|
order by posting_date, posting_time, creation""" %
|
||||||
', '.join(['%s']*len(warehouses_with_account)), tuple(warehouses_with_account))
|
', '.join(['%s']*len(warehouses_with_account)), tuple(warehouses_with_account))
|
||||||
|
|
||||||
rejected = []
|
rejected = []
|
||||||
|
|||||||
@ -432,7 +432,7 @@ def get_stock_ledger_entries(previous_sle, operator=None, order="desc", limit=No
|
|||||||
where item_code = %%(item_code)s
|
where item_code = %%(item_code)s
|
||||||
and ifnull(is_cancelled, 'No')='No'
|
and ifnull(is_cancelled, 'No')='No'
|
||||||
%(conditions)s
|
%(conditions)s
|
||||||
order by timestamp(posting_date, posting_time) %(order)s, name %(order)s
|
order by timestamp(posting_date, posting_time) %(order)s, creation %(order)s
|
||||||
%(limit)s %(for_update)s""" % {
|
%(limit)s %(for_update)s""" % {
|
||||||
"conditions": conditions,
|
"conditions": conditions,
|
||||||
"limit": limit or "",
|
"limit": limit or "",
|
||||||
@ -450,14 +450,14 @@ def get_valuation_rate(item_code, warehouse, voucher_type, voucher_no,
|
|||||||
from `tabStock Ledger Entry`
|
from `tabStock Ledger Entry`
|
||||||
where item_code = %s and warehouse = %s
|
where item_code = %s and warehouse = %s
|
||||||
and valuation_rate >= 0
|
and valuation_rate >= 0
|
||||||
order by posting_date desc, posting_time desc, name desc limit 1""", (item_code, warehouse))
|
order by posting_date desc, posting_time desc, creation desc limit 1""", (item_code, warehouse))
|
||||||
|
|
||||||
if not last_valuation_rate:
|
if not last_valuation_rate:
|
||||||
# Get valuation rate from last sle for the item against any warehouse
|
# Get valuation rate from last sle for the item against any warehouse
|
||||||
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
last_valuation_rate = frappe.db.sql("""select valuation_rate
|
||||||
from `tabStock Ledger Entry`
|
from `tabStock Ledger Entry`
|
||||||
where item_code = %s and valuation_rate > 0
|
where item_code = %s and valuation_rate > 0
|
||||||
order by posting_date desc, posting_time desc, name desc limit 1""", item_code)
|
order by posting_date desc, posting_time desc, creation desc limit 1""", item_code)
|
||||||
|
|
||||||
if last_valuation_rate:
|
if last_valuation_rate:
|
||||||
return flt(last_valuation_rate[0][0]) # as there is previous records, it might come with zero rate
|
return flt(last_valuation_rate[0][0]) # as there is previous records, it might come with zero rate
|
||||||
|
|||||||
@ -62,7 +62,7 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
|||||||
SELECT item_code, stock_value, name, warehouse
|
SELECT item_code, stock_value, name, warehouse
|
||||||
FROM `tabStock Ledger Entry` sle
|
FROM `tabStock Ledger Entry` sle
|
||||||
WHERE posting_date <= %s {0}
|
WHERE posting_date <= %s {0}
|
||||||
ORDER BY timestamp(posting_date, posting_time) DESC, name DESC
|
ORDER BY timestamp(posting_date, posting_time) DESC, creation DESC
|
||||||
""".format(condition), values, as_dict=1)
|
""".format(condition), values, as_dict=1)
|
||||||
|
|
||||||
sle_map = {}
|
sle_map = {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user