Merge branch 'develop' into healthcare_refactor
This commit is contained in:
commit
b95a794e51
@ -663,4 +663,5 @@ erpnext.patches.v12_0.move_bank_account_swift_number_to_bank
|
||||
erpnext.patches.v12_0.rename_bank_reconciliation_fields # 2020-01-22
|
||||
erpnext.patches.v12_0.set_received_qty_in_material_request_as_per_stock_uom
|
||||
erpnext.patches.v12_0.recalculate_requested_qty_in_bin
|
||||
erpnext.patches.v12_0.update_healthcare_refactored_changes
|
||||
erpnext.patches.v12_0.update_healthcare_refactored_changes
|
||||
erpnext.patches.v12_0.set_total_batch_quantity
|
||||
|
@ -3,10 +3,10 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from erpnext.regional.india.setup import update_address_template
|
||||
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||
|
||||
def execute():
|
||||
if frappe.db.get_value('Company', {'country': 'India'}, 'name'):
|
||||
address_template = frappe.db.get_value('Address Template', 'India', 'template')
|
||||
if not address_template or "gstin" not in address_template:
|
||||
update_address_template()
|
||||
set_up_address_templates(default_country='India')
|
||||
|
11
erpnext/patches/v12_0/set_total_batch_quantity.py
Normal file
11
erpnext/patches/v12_0/set_total_batch_quantity.py
Normal file
@ -0,0 +1,11 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
frappe.reload_doc("stock", "doctype", "batch")
|
||||
|
||||
for batch in frappe.get_all("Batch", fields=["name", "batch_id"]):
|
||||
batch_qty = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"docstatus": 1, "batch_no": batch.batch_id, "is_cancelled": "No"},
|
||||
"sum(actual_qty)") or 0.0
|
||||
frappe.db.set_value("Batch", batch.name, "batch_qty", batch_qty, update_modified=False)
|
@ -1,7 +1,8 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
|
||||
from erpnext.regional.india.setup import update_address_template
|
||||
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||
|
||||
|
||||
def execute():
|
||||
company = frappe.get_all('Company', filters = {'country': 'India'})
|
||||
@ -10,9 +11,10 @@ def execute():
|
||||
|
||||
update_existing_custom_fields()
|
||||
add_custom_fields()
|
||||
update_address_template()
|
||||
set_up_address_templates(default_country='India')
|
||||
frappe.reload_doc("regional", "print_format", "gst_tax_invoice")
|
||||
|
||||
|
||||
def update_existing_custom_fields():
|
||||
frappe.db.sql("""update `tabCustom Field` set label = 'HSN/SAC'
|
||||
where fieldname='gst_hsn_code' and label='GST HSN Code'
|
||||
@ -34,6 +36,7 @@ def update_existing_custom_fields():
|
||||
where fieldname='gst_hsn_code' and dt in ('Sales Invoice Item', 'Purchase Invoice Item')
|
||||
""")
|
||||
|
||||
|
||||
def add_custom_fields():
|
||||
hsn_sac_field = dict(fieldname='gst_hsn_code', label='HSN/SAC',
|
||||
fieldtype='Data', options='item_code.gst_hsn_code', insert_after='description')
|
||||
|
18
erpnext/regional/address_template/README.md
Normal file
18
erpnext/regional/address_template/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
To add an **Address Template** for your country, place a new file in this directory:
|
||||
|
||||
* File name: `your_country.html` (lower case with underscores)
|
||||
* File content: a [Jinja Template](http://jinja.pocoo.org/docs/templates/).
|
||||
|
||||
All the fields of **Address** (including Custom Fields, if any) will be available to the template. Example:
|
||||
|
||||
```jinja
|
||||
{{ address_line1 }}<br>
|
||||
{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
|
||||
{{ city }}<br>
|
||||
{% if state %}{{ state }}<br>{% endif -%}
|
||||
{% if pincode %} PIN: {{ pincode }}<br>{% endif -%}
|
||||
{{ country }}<br>
|
||||
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
|
||||
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
|
||||
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
|
||||
```
|
0
erpnext/regional/address_template/__init__.py
Normal file
0
erpnext/regional/address_template/__init__.py
Normal file
53
erpnext/regional/address_template/setup.py
Normal file
53
erpnext/regional/address_template/setup.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""Import Address Templates from ./templates directory."""
|
||||
import os
|
||||
import frappe
|
||||
|
||||
def set_up_address_templates(default_country=None):
|
||||
for country, html in get_address_templates():
|
||||
is_default = 1 if country == default_country else 0
|
||||
update_address_template(country, html, is_default)
|
||||
|
||||
def get_address_templates():
|
||||
"""
|
||||
Return country and path for all HTML files in this directory.
|
||||
|
||||
Returns a list of dicts.
|
||||
"""
|
||||
def country(file_name):
|
||||
"""Convert 'united_states.html' to 'United States'."""
|
||||
suffix_pos = file_name.find(".html")
|
||||
country_snake_case = file_name[:suffix_pos]
|
||||
country_title_case = " ".join(country_snake_case.split("_")).title()
|
||||
return country_title_case
|
||||
|
||||
def get_file_content(file_name):
|
||||
"""Convert 'united_states.html' to '/path/to/united_states.html'."""
|
||||
full_path = os.path.join(template_dir, file_name)
|
||||
with open(full_path, "r") as f:
|
||||
content = f.read()
|
||||
return content
|
||||
|
||||
dir_name = os.path.dirname(__file__)
|
||||
template_dir = os.path.join(dir_name, "templates")
|
||||
file_names = os.listdir(template_dir)
|
||||
html_files = [file for file in file_names if file.endswith(".html")]
|
||||
|
||||
return [(country(file_name), get_file_content(file_name)) for file_name in html_files]
|
||||
|
||||
|
||||
def update_address_template(country, html, is_default=0):
|
||||
"""Update existing Address Template or create a new one."""
|
||||
if not frappe.db.exists("Country", country):
|
||||
frappe.log_error("Country {} for regional Address Template does not exist.".format(country))
|
||||
return
|
||||
|
||||
if frappe.db.exists("Address Template", country):
|
||||
frappe.db.set_value("Address Template", country, "template", html)
|
||||
frappe.db.set_value("Address Template", country, "is_default", is_default)
|
||||
else:
|
||||
frappe.get_doc(dict(
|
||||
doctype="Address Template",
|
||||
country=country,
|
||||
is_default=is_default,
|
||||
template=html
|
||||
)).insert()
|
@ -6,4 +6,4 @@
|
||||
{% if phone %}Phone: {{ phone }}<br>{% endif -%}
|
||||
{% if fax %}Fax: {{ fax }}<br>{% endif -%}
|
||||
{% if email_id %}Email: {{ email_id }}<br>{% endif -%}
|
||||
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
|
||||
{% if gstin %}GSTIN: {{ gstin }}<br>{% endif -%}
|
@ -0,0 +1,45 @@
|
||||
from __future__ import unicode_literals
|
||||
from unittest import TestCase
|
||||
|
||||
import frappe
|
||||
from erpnext.regional.address_template.setup import get_address_templates
|
||||
from erpnext.regional.address_template.setup import update_address_template
|
||||
|
||||
def ensure_country(country):
|
||||
if frappe.db.exists("Country", country):
|
||||
return frappe.get_doc("Country", country)
|
||||
else:
|
||||
c = frappe.get_doc({
|
||||
"doctype": "Country",
|
||||
"country_name": country
|
||||
})
|
||||
c.insert()
|
||||
return c
|
||||
|
||||
class TestRegionalAddressTemplate(TestCase):
|
||||
def test_get_address_templates(self):
|
||||
"""Get the countries and paths from the templates directory."""
|
||||
templates = get_address_templates()
|
||||
self.assertIsInstance(templates, list)
|
||||
self.assertIsInstance(templates[0], tuple)
|
||||
|
||||
def test_create_address_template(self):
|
||||
"""Create a new Address Template."""
|
||||
country = ensure_country("Germany")
|
||||
update_address_template(country.name, "TEST")
|
||||
doc = frappe.get_doc("Address Template", country.name)
|
||||
self.assertEqual(doc.template, "TEST")
|
||||
|
||||
def test_update_address_template(self):
|
||||
"""Update an existing Address Template."""
|
||||
country = ensure_country("Germany")
|
||||
if not frappe.db.exists("Address Template", country.name):
|
||||
template = frappe.get_doc({
|
||||
"doctype": "Address Template",
|
||||
"country": country.name,
|
||||
"template": "EXISTING"
|
||||
}).insert()
|
||||
|
||||
update_address_template(country.name, "NEW")
|
||||
doc = frappe.get_doc("Address Template", country.name)
|
||||
self.assertEqual(doc.template, "NEW")
|
@ -3,29 +3,4 @@ import frappe
|
||||
|
||||
|
||||
def setup(company=None, patch=True):
|
||||
if not patch:
|
||||
update_address_template()
|
||||
|
||||
|
||||
def update_address_template():
|
||||
"""
|
||||
Read address template from file. Update existing Address Template or create a
|
||||
new one.
|
||||
"""
|
||||
dir_name = os.path.dirname(__file__)
|
||||
template_path = os.path.join(dir_name, 'address_template.html')
|
||||
|
||||
with open(template_path, 'r') as template_file:
|
||||
template_html = template_file.read()
|
||||
|
||||
address_template = frappe.db.get_value('Address Template', 'Germany')
|
||||
|
||||
if address_template:
|
||||
frappe.db.set_value('Address Template', 'Germany', 'template', template_html)
|
||||
else:
|
||||
# make new html template for Germany
|
||||
frappe.get_doc(dict(
|
||||
doctype='Address Template',
|
||||
country='Germany',
|
||||
template=template_html
|
||||
)).insert()
|
||||
pass
|
||||
|
@ -13,7 +13,6 @@ from frappe.utils import today
|
||||
def setup(company=None, patch=True):
|
||||
setup_company_independent_fixtures()
|
||||
if not patch:
|
||||
update_address_template()
|
||||
make_fixtures(company)
|
||||
|
||||
# TODO: for all countries
|
||||
@ -24,21 +23,6 @@ def setup_company_independent_fixtures():
|
||||
frappe.enqueue('erpnext.regional.india.setup.add_hsn_sac_codes', now=frappe.flags.in_test)
|
||||
add_print_formats()
|
||||
|
||||
def update_address_template():
|
||||
with open(os.path.join(os.path.dirname(__file__), 'address_template.html'), 'r') as f:
|
||||
html = f.read()
|
||||
|
||||
address_template = frappe.db.get_value('Address Template', 'India')
|
||||
if address_template:
|
||||
frappe.db.set_value('Address Template', 'India', 'template', html)
|
||||
else:
|
||||
# make new html template for India
|
||||
frappe.get_doc(dict(
|
||||
doctype='Address Template',
|
||||
country='India',
|
||||
template=html
|
||||
)).insert()
|
||||
|
||||
def add_hsn_sac_codes():
|
||||
# HSN codes
|
||||
with open(os.path.join(os.path.dirname(__file__), 'hsn_code_data.json'), 'r') as f:
|
||||
|
@ -5,12 +5,9 @@ from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.custom.doctype.custom_field.custom_field import create_custom_fields
|
||||
|
||||
|
||||
def setup(company=None, patch=True):
|
||||
make_custom_fields()
|
||||
add_print_formats()
|
||||
update_address_template()
|
||||
|
||||
|
||||
def make_custom_fields():
|
||||
custom_fields = {
|
||||
@ -21,22 +18,7 @@ def make_custom_fields():
|
||||
}
|
||||
create_custom_fields(custom_fields)
|
||||
|
||||
|
||||
def add_print_formats():
|
||||
frappe.reload_doc("regional", "print_format", "irs_1099_form")
|
||||
frappe.db.sql(""" update `tabPrint Format` set disabled = 0 where
|
||||
name in('IRS 1099 Form') """)
|
||||
|
||||
|
||||
def update_address_template():
|
||||
html = """{{ address_line1 }}<br>
|
||||
{% if address_line2 %}{{ address_line2 }}<br>{% endif -%}
|
||||
{{ city }}, {% if state %}{{ state }}{% endif -%}{% if pincode %} {{ pincode }}<br>{% endif -%}
|
||||
{% if country != "United States" %}{{ country|upper }}{% endif -%}
|
||||
"""
|
||||
|
||||
address_template = frappe.db.get_value('Address Template', 'United States')
|
||||
if address_template:
|
||||
frappe.db.set_value('Address Template', 'United States', 'template', html)
|
||||
else:
|
||||
frappe.get_doc(dict(doctype='Address Template', country='United States', template=html)).insert()
|
||||
|
@ -8,9 +8,11 @@ import frappe, os, json
|
||||
from frappe import _
|
||||
from frappe.desk.page.setup_wizard.setup_wizard import make_records
|
||||
from frappe.utils import cstr, getdate
|
||||
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||
from frappe.desk.doctype.global_search_settings.global_search_settings import update_global_search_doctypes
|
||||
|
||||
from erpnext.accounts.doctype.account.account import RootNotEditable
|
||||
from erpnext.regional.address_template.setup import set_up_address_templates
|
||||
|
||||
default_lead_sources = ["Existing Customer", "Reference", "Advertisement",
|
||||
"Cold Calling", "Exhibition", "Supplier Reference", "Mass Mailing",
|
||||
"Customer's Vendor", "Campaign", "Walk In"]
|
||||
@ -30,7 +32,7 @@ def install(country=None):
|
||||
{ 'doctype': 'Domain', 'domain': 'Agriculture'},
|
||||
{ 'doctype': 'Domain', 'domain': 'Non Profit'},
|
||||
|
||||
# address template
|
||||
# ensure at least an empty Address Template exists for this Country
|
||||
{'doctype':"Address Template", "country": country},
|
||||
|
||||
# item group
|
||||
@ -269,12 +271,11 @@ def install(country=None):
|
||||
|
||||
# Records for the Supplier Scorecard
|
||||
from erpnext.buying.doctype.supplier_scorecard.supplier_scorecard import make_default_records
|
||||
|
||||
make_default_records()
|
||||
|
||||
make_records(records)
|
||||
|
||||
set_up_address_templates(default_country=country)
|
||||
set_more_defaults()
|
||||
|
||||
update_global_search_doctypes()
|
||||
|
||||
# path = frappe.get_app_path('erpnext', 'regional', frappe.scrub(country))
|
||||
|
@ -1,554 +1,194 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:batch_id",
|
||||
"beta": 0,
|
||||
"creation": "2013-03-05 14:50:38",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"sb_disabled",
|
||||
"disabled",
|
||||
"sb_batch",
|
||||
"batch_id",
|
||||
"item",
|
||||
"item_name",
|
||||
"image",
|
||||
"parent_batch",
|
||||
"manufacturing_date",
|
||||
"column_break_3",
|
||||
"batch_qty",
|
||||
"stock_uom",
|
||||
"expiry_date",
|
||||
"source",
|
||||
"supplier",
|
||||
"column_break_9",
|
||||
"reference_doctype",
|
||||
"reference_name",
|
||||
"section_break_7",
|
||||
"description"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.__islocal",
|
||||
"fieldname": "batch_id",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Batch ID",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "batch_id",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "item",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Item",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "item",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Item",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "image",
|
||||
"fieldtype": "Attach Image",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "image",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"label": "image"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "eval:doc.parent_batch",
|
||||
"fieldname": "parent_batch",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Parent Batch",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Batch",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Disabled",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Today",
|
||||
"fieldname": "manufacturing_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Manufacturing Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"label": "Manufacturing Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_3",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "expiry_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Expiry Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "expiry_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"oldfieldtype": "Date"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "source",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Source",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"label": "Source"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "supplier",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Supplier",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Supplier",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_9",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference_doctype",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Source Document Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "DocType",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference_name",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Source Document Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "reference_doctype",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_7",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Batch Description",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "description",
|
||||
"oldfieldtype": "Small Text",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": "300px"
|
||||
},
|
||||
{
|
||||
"fieldname": "sb_disabled",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "sb_batch",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Batch Details"
|
||||
},
|
||||
{
|
||||
"fetch_from": "item.item_name",
|
||||
"fieldname": "item_name",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Item Name",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "batch_qty",
|
||||
"fieldtype": "Float",
|
||||
"in_list_view": 1,
|
||||
"label": "Batch Quantity",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fetch_from": "item.stock_uom",
|
||||
"fieldname": "stock_uom",
|
||||
"fieldtype": "Link",
|
||||
"label": "Batch UOM",
|
||||
"options": "UOM",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-archive",
|
||||
"idx": 1,
|
||||
"image_field": "image",
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 5,
|
||||
"modified": "2018-08-29 06:28:57.985997",
|
||||
"modified": "2019-10-03 22:38:45.104056",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Batch",
|
||||
"owner": "harshada@webnotestech.com",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 1,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Item Manager",
|
||||
"set_user_permissions": 1,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "item",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"title_field": "batch_id"
|
||||
}
|
27
erpnext/stock/doctype/batch/batch_dashboard.py
Normal file
27
erpnext/stock/doctype/batch/batch_dashboard.py
Normal file
@ -0,0 +1,27 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from frappe import _
|
||||
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'batch_no',
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Buy'),
|
||||
'items': ['Purchase Invoice', 'Purchase Receipt']
|
||||
},
|
||||
{
|
||||
'label': _('Sell'),
|
||||
'items': ['Sales Invoice', 'Delivery Note']
|
||||
},
|
||||
{
|
||||
'label': _('Move'),
|
||||
'items': ['Stock Entry']
|
||||
},
|
||||
{
|
||||
'label': _('Quality'),
|
||||
'items': ['Quality Inspection']
|
||||
}
|
||||
]
|
||||
}
|
@ -1,12 +1,14 @@
|
||||
frappe.listview_settings['Batch'] = {
|
||||
add_fields: ["item", "expiry_date"],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date, frappe.datetime.nowdate()) <= 0) {
|
||||
return [__("Expired"), "red", "expiry_date,>=,Today"]
|
||||
} else if(doc.expiry_date) {
|
||||
return [__("Not Expired"), "green", "expiry_date,<,Today"]
|
||||
add_fields: ["item", "expiry_date", "batch_qty", "disabled"],
|
||||
get_indicator: (doc) => {
|
||||
if (doc.disabled) {
|
||||
return [__("Disabled"), "darkgrey", "disabled,=,1"];
|
||||
} else if (!doc.batch_qty) {
|
||||
return [__("Empty"), "darkgrey", "batch_qty,=,0|disabled,=,0"];
|
||||
} else if (doc.expiry_date && frappe.datetime.get_diff(doc.expiry_date, frappe.datetime.nowdate()) <= 0) {
|
||||
return [__("Expired"), "red", "expiry_date,not in,|expiry_date,<=,Today|batch_qty,>,0|disabled,=,0"]
|
||||
} else {
|
||||
return ["Not Set", "darkgrey", ""];
|
||||
}
|
||||
return [__("Active"), "green", "batch_qty,>,0|disabled,=,0"];
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ from frappe.exceptions import ValidationError
|
||||
import unittest
|
||||
|
||||
from erpnext.stock.doctype.batch.batch import get_batch_qty, UnableToSelectBatchError, get_batch_no
|
||||
from frappe.utils import cint
|
||||
from frappe.utils import cint, flt
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
|
||||
|
||||
class TestBatch(unittest.TestCase):
|
||||
@ -35,12 +35,13 @@ class TestBatch(unittest.TestCase):
|
||||
receipt = frappe.get_doc(dict(
|
||||
doctype='Purchase Receipt',
|
||||
supplier='_Test Supplier',
|
||||
company='_Test Company',
|
||||
items=[
|
||||
dict(
|
||||
item_code='ITEM-BATCH-1',
|
||||
qty=batch_qty,
|
||||
rate=10,
|
||||
warehouse= 'Stores - WP'
|
||||
warehouse= 'Stores - _TC'
|
||||
)
|
||||
]
|
||||
)).insert()
|
||||
@ -175,6 +176,18 @@ class TestBatch(unittest.TestCase):
|
||||
|
||||
self.assertEqual(get_batch_qty('batch a', '_Test Warehouse - _TC'), 90)
|
||||
|
||||
def test_total_batch_qty(self):
|
||||
self.make_batch_item('ITEM-BATCH-3')
|
||||
existing_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty"))
|
||||
stock_entry = self.make_new_batch_and_entry('ITEM-BATCH-3', 'B100', '_Test Warehouse - _TC')
|
||||
|
||||
current_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty"))
|
||||
self.assertEqual(current_batch_qty, existing_batch_qty + 90)
|
||||
|
||||
stock_entry.cancel()
|
||||
current_batch_qty = flt(frappe.db.get_value("Batch", "B100", "batch_qty"))
|
||||
self.assertEqual(current_batch_qty, existing_batch_qty)
|
||||
|
||||
@classmethod
|
||||
def make_new_batch_and_entry(cls, item_name, batch_name, warehouse):
|
||||
'''Make a new stock entry for given target warehouse and batch name of item'''
|
||||
@ -208,6 +221,8 @@ class TestBatch(unittest.TestCase):
|
||||
stock_entry.insert()
|
||||
stock_entry.submit()
|
||||
|
||||
return stock_entry
|
||||
|
||||
def test_batch_name_with_naming_series(self):
|
||||
stock_settings = frappe.get_single('Stock Settings')
|
||||
use_naming_series = cint(stock_settings.use_naming_series)
|
||||
|
@ -37,11 +37,19 @@ class StockLedgerEntry(Document):
|
||||
def on_submit(self):
|
||||
self.check_stock_frozen_date()
|
||||
self.actual_amt_check()
|
||||
self.calculate_batch_qty()
|
||||
|
||||
if not self.get("via_landed_cost_voucher"):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import process_serial_no
|
||||
process_serial_no(self)
|
||||
|
||||
def calculate_batch_qty(self):
|
||||
if self.batch_no:
|
||||
batch_qty = frappe.db.get_value("Stock Ledger Entry",
|
||||
{"docstatus": 1, "batch_no": self.batch_no, "is_cancelled": "No"},
|
||||
"sum(actual_qty)") or 0
|
||||
frappe.db.set_value("Batch", self.batch_no, "batch_qty", batch_qty)
|
||||
|
||||
#check for item quantity available in stock
|
||||
def actual_amt_check(self):
|
||||
if self.batch_no and not self.get("allow_negative_stock"):
|
||||
@ -139,4 +147,3 @@ def on_doctype_update():
|
||||
|
||||
frappe.db.add_index("Stock Ledger Entry", ["voucher_no", "voucher_type"])
|
||||
frappe.db.add_index("Stock Ledger Entry", ["batch_no", "item_code", "warehouse"])
|
||||
|
||||
|
@ -488,12 +488,14 @@ def get_stock_balance_for(item_code, warehouse,
|
||||
["has_serial_no", "has_batch_no"], as_dict=1)
|
||||
|
||||
serial_nos = ""
|
||||
if item_dict.get("has_serial_no"):
|
||||
qty, rate, serial_nos = get_qty_rate_for_serial_nos(item_code,
|
||||
warehouse, posting_date, posting_time, item_dict)
|
||||
with_serial_no = True if item_dict.get("has_serial_no") else False
|
||||
data = get_stock_balance(item_code, warehouse, posting_date, posting_time,
|
||||
with_valuation_rate=with_valuation_rate, with_serial_no=with_serial_no)
|
||||
|
||||
if with_serial_no:
|
||||
qty, rate, serial_nos = data
|
||||
else:
|
||||
qty, rate = get_stock_balance(item_code, warehouse,
|
||||
posting_date, posting_time, with_valuation_rate=with_valuation_rate)
|
||||
qty, rate = data
|
||||
|
||||
if item_dict.get("has_batch_no"):
|
||||
qty = get_batch_qty(batch_no, warehouse) or 0
|
||||
@ -504,28 +506,6 @@ def get_stock_balance_for(item_code, warehouse,
|
||||
'serial_nos': serial_nos
|
||||
}
|
||||
|
||||
def get_qty_rate_for_serial_nos(item_code, warehouse, posting_date, posting_time, item_dict):
|
||||
args = {
|
||||
"item_code": item_code,
|
||||
"warehouse": warehouse,
|
||||
"posting_date": posting_date,
|
||||
"posting_time": posting_time,
|
||||
}
|
||||
|
||||
serial_nos_list = [serial_no.get("name")
|
||||
for serial_no in get_available_serial_nos(args)]
|
||||
|
||||
qty = len(serial_nos_list)
|
||||
serial_nos = '\n'.join(serial_nos_list)
|
||||
args.update({
|
||||
'qty': qty,
|
||||
"serial_nos": serial_nos
|
||||
})
|
||||
|
||||
rate = get_incoming_rate(args, raise_error_if_no_rate=False) or 0
|
||||
|
||||
return qty, rate, serial_nos
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_difference_account(purpose, company):
|
||||
if purpose == 'Stock Reconciliation':
|
||||
|
@ -35,7 +35,7 @@ def get_data(report_filters):
|
||||
gl_data = voucher_wise_gl_data.get(key) or {}
|
||||
d.account_value = gl_data.get("account_value", 0)
|
||||
d.difference_value = (d.stock_value - d.account_value)
|
||||
if abs(d.difference_value) > 1.0/10 ** currency_precision:
|
||||
if abs(d.difference_value) > 0.1:
|
||||
data.append(d)
|
||||
|
||||
return data
|
||||
|
@ -74,7 +74,8 @@ def get_stock_value_on(warehouse=None, posting_date=None, item_code=None):
|
||||
return sum(sle_map.values())
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None, with_valuation_rate=False):
|
||||
def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None,
|
||||
with_valuation_rate=False, with_serial_no=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)"""
|
||||
@ -84,17 +85,51 @@ def get_stock_balance(item_code, warehouse, posting_date=None, posting_time=None
|
||||
if not posting_date: posting_date = nowdate()
|
||||
if not posting_time: posting_time = nowtime()
|
||||
|
||||
last_entry = get_previous_sle({
|
||||
args = {
|
||||
"item_code": item_code,
|
||||
"warehouse":warehouse,
|
||||
"posting_date": posting_date,
|
||||
"posting_time": posting_time })
|
||||
"posting_time": posting_time
|
||||
}
|
||||
|
||||
last_entry = get_previous_sle(args)
|
||||
|
||||
if with_valuation_rate:
|
||||
return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0)
|
||||
if with_serial_no:
|
||||
serial_nos = last_entry.get("serial_no")
|
||||
|
||||
if (serial_nos and
|
||||
len(get_serial_nos_data(serial_nos)) < last_entry.qty_after_transaction):
|
||||
serial_nos = get_serial_nos_data_after_transactions(args)
|
||||
|
||||
return ((last_entry.qty_after_transaction, last_entry.valuation_rate, serial_nos)
|
||||
if last_entry else (0.0, 0.0, 0.0))
|
||||
else:
|
||||
return (last_entry.qty_after_transaction, last_entry.valuation_rate) if last_entry else (0.0, 0.0)
|
||||
else:
|
||||
return last_entry.qty_after_transaction if last_entry else 0.0
|
||||
|
||||
def get_serial_nos_data_after_transactions(args):
|
||||
serial_nos = []
|
||||
data = frappe.db.sql(""" SELECT serial_no, actual_qty
|
||||
FROM `tabStock Ledger Entry`
|
||||
WHERE
|
||||
item_code = %(item_code)s and warehouse = %(warehouse)s
|
||||
and timestamp(posting_date, posting_time) < timestamp(%(posting_date)s, %(posting_time)s)
|
||||
order by posting_date, posting_time asc """, args, as_dict=1)
|
||||
|
||||
for d in data:
|
||||
if d.actual_qty > 0:
|
||||
serial_nos.extend(get_serial_nos_data(d.serial_no))
|
||||
else:
|
||||
serial_nos = list(set(serial_nos) - set(get_serial_nos_data(d.serial_no)))
|
||||
|
||||
return '\n'.join(serial_nos)
|
||||
|
||||
def get_serial_nos_data(serial_nos):
|
||||
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
|
||||
return get_serial_nos(serial_nos)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_latest_stock_qty(item_code, warehouse=None):
|
||||
values, condition = [item_code], ""
|
||||
|
Loading…
x
Reference in New Issue
Block a user