Merge branch 'master' of https://github.com/frappe/erpnext.git into Brand-Item-Defaults

# Conflicts:
#	erpnext/setup/doctype/brand/brand.json
#	erpnext/stock/get_item_details.py
This commit is contained in:
Saif Ur Rehman
2019-02-01 17:05:46 +05:00
498 changed files with 26744 additions and 23544 deletions

View File

@@ -1,43 +1,37 @@
from __future__ import unicode_literals
import frappe
from frappe.model.db_query import DatabaseQuery
@frappe.whitelist()
def get_data(item_code=None, warehouse=None, item_group=None,
start=0, sort_by='actual_qty', sort_order='desc'):
'''Return data to render the item dashboard'''
conditions = []
values = []
filters = []
if item_code:
conditions.append('b.item_code=%s')
values.append(item_code)
filters.append(['item_code', '=', item_code])
if warehouse:
conditions.append('b.warehouse=%s')
values.append(warehouse)
filters.append(['warehouse', '=', warehouse])
if item_group:
conditions.append('i.item_group=%s')
values.append(item_group)
filters.append(['item_group', '=', item_group])
try:
# check if user has any restrictions based on user permissions on warehouse
if DatabaseQuery('Warehouse', user=frappe.session.user).build_match_conditions():
filters.append(['warehouse', 'in', [w.name for w in frappe.get_list('Warehouse')]])
except frappe.PermissionError:
# user does not have access on warehouse
return []
if conditions:
conditions = ' and ' + ' and '.join(conditions)
else:
conditions = ''
return frappe.db.sql('''
select
b.item_code, b.warehouse, b.projected_qty, b.reserved_qty,
b.reserved_qty_for_production, b.reserved_qty_for_sub_contract, b.actual_qty, b.valuation_rate, i.item_name
from
tabBin b, tabItem i
where
b.item_code = i.name
and
(b.projected_qty != 0 or b.reserved_qty != 0 or b.reserved_qty_for_production != 0
or b.reserved_qty_for_sub_contract != 0 or b.actual_qty != 0)
{conditions}
order by
{sort_by} {sort_order}
limit
{start}, 21
'''.format(conditions=conditions, sort_by=sort_by, sort_order=sort_order,
start=start), values, as_dict=True)
return frappe.db.get_all('Bin', fields=['item_code', 'warehouse', 'projected_qty',
'reserved_qty', 'reserved_qty_for_production', 'reserved_qty_for_sub_contract', 'actual_qty', 'valuation_rate'],
or_filters={
'projected_qty': ['!=', 0],
'reserved_qty': ['!=', 0],
'reserved_qty_for_production': ['!=', 0],
'reserved_qty_for_sub_contract': ['!=', 0],
'actual_qty': ['!=', 0],
},
filters=filters,
order_by=sort_by + ' ' + sort_order,
limit_start=start,
limit_page_length='21')

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
from __future__ import unicode_literals
from frappe import _
def get_data():

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -15,6 +16,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -45,6 +47,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -80,6 +83,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -114,6 +118,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -143,6 +148,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -173,6 +179,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -204,6 +211,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -238,6 +246,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -268,6 +277,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -299,6 +309,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -331,6 +342,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -361,6 +373,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -395,6 +408,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -430,6 +444,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -459,6 +474,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -491,6 +507,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -522,6 +539,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -553,6 +571,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -583,6 +602,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -618,6 +638,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -653,6 +674,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -684,6 +706,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -717,6 +740,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -749,6 +773,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -782,6 +807,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -812,6 +838,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -847,6 +874,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -875,10 +903,12 @@
"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,
@@ -912,6 +942,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -941,6 +972,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -976,6 +1008,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1011,6 +1044,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1040,6 +1074,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1075,6 +1110,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1110,6 +1146,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1141,6 +1178,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1171,6 +1209,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1203,6 +1242,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1235,6 +1275,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1265,6 +1306,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1297,6 +1339,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1329,6 +1372,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -1360,6 +1404,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1391,6 +1436,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1422,6 +1468,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1452,6 +1499,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1484,6 +1532,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1514,6 +1563,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1549,6 +1599,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1583,6 +1634,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1616,6 +1668,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1646,6 +1699,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1679,6 +1733,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -1713,6 +1768,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -1747,6 +1803,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1779,6 +1836,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1813,6 +1871,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1848,6 +1907,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1880,6 +1940,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1909,6 +1970,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1941,6 +2003,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1974,6 +2037,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2005,6 +2069,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2036,6 +2101,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2067,6 +2133,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2101,6 +2168,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2132,6 +2200,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2166,6 +2235,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2198,6 +2268,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -2239,7 +2310,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-08-07 05:18:26.132899",
"modified": "2019-01-07 16:51:53.322875",
"modified_by": "Administrator",
"module": "Stock",
"name": "Delivery Note Item",
@@ -2252,5 +2323,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,4 @@
from __future__ import unicode_literals
from frappe import _
def get_data():

View File

@@ -378,7 +378,7 @@ def make_item_variant():
test_records = frappe.get_test_records('Item')
def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None):
def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None, opening_stock=None):
if not frappe.db.exists("Item", item_code):
item = frappe.new_doc("Item")
item.item_code = item_code
@@ -386,6 +386,7 @@ def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None)
item.description = item_code
item.item_group = "All Item Groups"
item.is_stock_item = is_stock_item or 1
item.opening_stock = opening_stock or 0
item.valuation_rate = valuation_rate or 0.0
item.append("item_defaults", {
"default_warehouse": warehouse or '_Test Warehouse - _TC',

View File

@@ -1,6 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest

View File

@@ -1,3 +1,4 @@
from __future__ import unicode_literals
from frappe import _

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -1244,7 +1245,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-06-15 13:09:57.819520",
"modified": "2019-01-07 16:57:19.927892",
"modified_by": "Administrator",
"module": "Stock",
"name": "Material Request Item",
@@ -1256,5 +1257,6 @@
"show_name_in_global_search": 0,
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -1,3 +1,4 @@
from __future__ import unicode_literals
from frappe import _
def get_data():

View File

@@ -1,8 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import unittest
import frappe, erpnext
import frappe.defaults
@@ -352,7 +351,7 @@ class TestPurchaseReceipt(unittest.TestCase):
set_perpetual_inventory(1, "_Test Company")
pr = make_purchase_receipt(cost_center=cost_center)
stock_in_hand_account = get_inventory_account(pr.company, pr.get("items")[0].warehouse)
gl_entries = get_gl_entries("Purchase Receipt", pr.name)

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -14,6 +15,7 @@
"fields": [
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -45,6 +47,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -75,6 +78,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -110,6 +114,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -141,6 +146,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -171,6 +177,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -203,6 +210,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -234,6 +242,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -268,6 +277,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -297,6 +307,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -328,6 +339,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -360,6 +372,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -390,6 +403,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -424,6 +438,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -458,6 +473,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -492,6 +508,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -522,6 +539,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -558,6 +576,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -593,6 +612,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -628,6 +648,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -661,6 +682,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -695,6 +717,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -725,6 +748,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -756,6 +780,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -787,6 +812,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -815,10 +841,12 @@
"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,
@@ -848,6 +876,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -879,6 +908,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -908,6 +938,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -943,6 +974,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -976,6 +1008,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1005,6 +1038,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1040,6 +1074,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1075,6 +1110,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1106,6 +1142,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1136,6 +1173,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1168,6 +1206,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1200,6 +1239,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1230,6 +1270,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1262,6 +1303,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1294,6 +1336,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 1,
@@ -1325,6 +1368,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1356,6 +1400,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1387,6 +1432,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1417,6 +1463,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1449,6 +1496,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1479,6 +1527,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 1,
"collapsible": 0,
@@ -1514,6 +1563,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1549,6 +1599,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1583,6 +1634,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1613,6 +1665,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1644,6 +1697,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1677,6 +1731,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1710,6 +1765,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1745,6 +1801,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1777,6 +1834,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1811,6 +1869,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1841,6 +1900,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1873,6 +1933,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1906,6 +1967,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1937,6 +1999,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1967,6 +2030,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -1997,6 +2061,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2028,6 +2093,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2061,6 +2127,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2095,6 +2162,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2124,6 +2192,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2155,6 +2224,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2187,6 +2257,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2219,6 +2290,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2251,6 +2323,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -2282,6 +2355,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2315,6 +2389,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2349,6 +2424,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2384,6 +2460,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2419,6 +2496,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -2454,6 +2532,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
@@ -2487,6 +2566,7 @@
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 1,
"bold": 0,
"collapsible": 0,
@@ -2528,7 +2608,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-08-09 06:56:45.396664",
"modified": "2019-01-07 16:51:59.002215",
"modified_by": "Administrator",
"module": "Stock",
"name": "Purchase Receipt Item",
@@ -2541,5 +2621,6 @@
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 0,
"track_seen": 0
}
"track_seen": 0,
"track_views": 0
}

View File

@@ -1,12 +1,13 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe
import unittest
from frappe.utils import nowdate
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.controllers.stock_controller import QualityInspectionRejectedError, QualityInspectionRequiredError
from erpnext.controllers.stock_controller import QualityInspectionRejectedError, QualityInspectionRequiredError, QualityInspectionNotSubmittedError
# test_records = frappe.get_test_records('Quality Inspection')
@@ -19,7 +20,7 @@ class TestQualityInspection(unittest.TestCase):
dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
self.assertRaises(QualityInspectionRequiredError, dn.submit)
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected")
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, status="Rejected", submit=True)
dn.reload()
self.assertRaises(QualityInspectionRejectedError, dn.submit)
@@ -27,6 +28,12 @@ class TestQualityInspection(unittest.TestCase):
dn.reload()
dn.submit()
def test_qa_not_submit(self):
dn = create_delivery_note(item_code="_Test Item with QA", do_not_submit=True)
qa = create_quality_inspection(reference_type="Delivery Note", reference_name=dn.name, submit = False)
dn.items[0].quality_inspection = qa.name
self.assertRaises(QualityInspectionNotSubmittedError, dn.submit)
def create_quality_inspection(**args):
args = frappe._dict(args)
qa = frappe.new_doc("Quality Inspection")
@@ -42,6 +49,7 @@ def create_quality_inspection(**args):
"status": args.status
})
qa.save()
qa.submit()
if args.submit:
qa.submit()
return qa

View File

@@ -139,7 +139,7 @@ class SerialNo(StockController):
order by posting_date desc, posting_time desc, name desc""",
("%%%s%%" % self.name, self.item_code), as_dict=1):
if self.name.upper() in get_serial_nos(sle.serial_no):
if sle.actual_qty > 0:
if cint(sle.actual_qty) > 0:
sle_dict.setdefault("incoming", []).append(sle)
else:
sle_dict.setdefault("outgoing", []).append(sle)
@@ -218,7 +218,7 @@ def validate_serial_no(sle, item_det):
frappe.throw(_("Serial No {0} does not belong to Item {1}").format(serial_no,
sle.item_code), SerialNoItemError)
if sle.actual_qty > 0 and has_duplicate_serial_no(sr, sle):
if cint(sle.actual_qty) > 0 and has_duplicate_serial_no(sr, sle):
frappe.throw(_("Serial No {0} has already been received").format(serial_no),
SerialNoDuplicateError)
@@ -228,7 +228,7 @@ def validate_serial_no(sle, item_det):
if return_against and return_against != sr.delivery_document_no:
frappe.throw(_("Serial no {0} has been already returned").format(sr.name))
if sle.actual_qty < 0:
if cint(sle.actual_qty) < 0:
if sr.warehouse!=sle.warehouse:
frappe.throw(_("Serial No {0} does not belong to Warehouse {1}").format(serial_no,
sle.warehouse), SerialNoWarehouseError)
@@ -279,16 +279,16 @@ def validate_serial_no(sle, item_det):
"parent": sales_invoice, "item_code": sle.item_code}, "sales_order")
if sales_order and get_reserved_qty_for_so(sales_order, sle.item_code):
validate_so_serial_no(sr, sales_order)
elif sle.actual_qty < 0:
elif cint(sle.actual_qty) < 0:
# transfer out
frappe.throw(_("Serial No {0} not in stock").format(serial_no), SerialNoNotExistsError)
elif sle.actual_qty < 0 or not item_det.serial_no_series:
elif cint(sle.actual_qty) < 0 or not item_det.serial_no_series:
frappe.throw(_("Serial Nos Required for Serialized Item {0}").format(sle.item_code),
SerialNoRequiredError)
elif serial_nos:
for serial_no in serial_nos:
sr = frappe.db.get_value("Serial No", serial_no, ["name", "warehouse"], as_dict=1)
if sr and sle.actual_qty < 0 and sr.warehouse != sle.warehouse:
if sr and cint(sle.actual_qty) < 0 and sr.warehouse != sle.warehouse:
frappe.throw(_("Cannot cancel {0} {1} because Serial No {2} does not belong to the warehouse {3}")
.format(sle.voucher_type, sle.voucher_no, serial_no, sle.warehouse))
@@ -302,6 +302,9 @@ def has_duplicate_serial_no(sn, sle):
if sn.warehouse:
return True
if sn.company != sle.company:
return False
status = False
if sn.purchase_document_no:
if sle.voucher_type in ['Purchase Receipt', 'Stock Entry', "Purchase Invoice"] and \
@@ -320,7 +323,7 @@ def allow_serial_nos_with_different_item(sle_serial_no, sle):
in Manufacture / Repack type Stock Entry
"""
allow_serial_nos = False
if sle.voucher_type=="Stock Entry" and sle.actual_qty > 0:
if sle.voucher_type=="Stock Entry" and cint(sle.actual_qty) > 0:
stock_entry = frappe.get_doc("Stock Entry", sle.voucher_no)
if stock_entry.purpose in ("Repack", "Manufacture"):
for d in stock_entry.get("items"):
@@ -332,7 +335,7 @@ def allow_serial_nos_with_different_item(sle_serial_no, sle):
return allow_serial_nos
def update_serial_nos(sle, item_det):
if sle.is_cancelled == "No" and not sle.serial_no and sle.actual_qty > 0 \
if sle.is_cancelled == "No" and not sle.serial_no and cint(sle.actual_qty) > 0 \
and item_det.has_serial_no == 1 and item_det.serial_no_series:
serial_nos = get_auto_serial_nos(item_det.serial_no_series, sle.actual_qty)
frappe.db.set(sle, "serial_no", serial_nos)
@@ -357,6 +360,7 @@ def auto_make_serial_nos(args):
sr.warehouse = args.get('warehouse') if args.get('actual_qty', 0) > 0 else None
sr.batch_no = args.get('batch_no')
sr.location = args.get('location')
sr.company = args.get('company')
if sr.sales_order and args.get('voucher_type') == "Stock Entry" \
and not args.get('actual_qty', 0) > 0:
sr.sales_order = None

View File

@@ -7,6 +7,12 @@
from __future__ import unicode_literals
import frappe, unittest
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
from erpnext.stock.doctype.delivery_note.test_delivery_note import create_delivery_note
from erpnext.stock.doctype.serial_no.serial_no import get_serial_nos
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
test_dependencies = ["Item"]
test_records = frappe.get_test_records('Serial No')
@@ -29,3 +35,21 @@ class TestSerialNo(unittest.TestCase):
sr.warehouse = "_Test Warehouse - _TC"
self.assertTrue(SerialNoCannotCannotChangeError, sr.save)
def test_inter_company_transfer(self):
se = make_serialized_item(target_warehouse="_Test Warehouse - _TC")
serial_nos = get_serial_nos(se.get("items")[0].serial_no)
create_delivery_note(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0])
wh = create_warehouse("_Test Warehouse", company="_Test Company 1")
make_purchase_receipt(item_code="_Test Serialized Item With Series", qty=1, serial_no=serial_nos[0],
company="_Test Company 1", warehouse=wh)
serial_no = frappe.db.get_value("Serial No", serial_nos[0], ["warehouse", "company"], as_dict=1)
self.assertEqual(serial_no.warehouse, wh)
self.assertEqual(serial_no.company, "_Test Company 1")
def tearDown(self):
frappe.db.rollback()

View File

@@ -1,6 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
from __future__ import unicode_literals
import frappe, erpnext
from frappe.utils import cint, flt

View File

@@ -1,5 +1,6 @@
{
"allow_copy": 0,
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
@@ -1549,7 +1550,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
"modified": "2018-05-30 20:06:00.623763",
"modified": "2019-01-07 16:58:58.769285",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Entry Detail",
@@ -1561,5 +1562,6 @@
"show_name_in_global_search": 0,
"sort_order": "ASC",
"track_changes": 0,
"track_seen": 0
"track_seen": 0,
"track_views": 0
}

View File

@@ -31,7 +31,7 @@ class StockLedgerEntry(Document):
self.check_stock_frozen_date()
self.actual_amt_check()
if not self.get("via_landed_cost_voucher"):
if not self.get("via_landed_cost_voucher") and self.voucher_type != 'Stock Reconciliation':
from erpnext.stock.doctype.serial_no.serial_no import process_serial_no
process_serial_no(self)
@@ -132,4 +132,4 @@ 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"])

View File

@@ -271,27 +271,39 @@ class StockReconciliation(StockController):
@frappe.whitelist()
def get_items(warehouse, posting_date, posting_time, company):
items = frappe.db.sql('''select i.name, i.item_name from `tabItem` i, `tabBin` bin where i.name=bin.item_code
and i.disabled=0 and bin.warehouse=%s''', (warehouse), as_dict=True)
lft, rgt = frappe.db.get_value("Warehouse", warehouse, ["lft", "rgt"])
items = frappe.db.sql("""
select i.name, i.item_name, bin.warehouse
from tabBin bin, tabItem i
where i.name=bin.item_code and i.disabled=0
and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=bin.warehouse)
""", (lft, rgt))
items += frappe.db.sql('''select i.name, i.item_name from `tabItem` i, `tabItem Default` id where i.name = id.parent
and i.is_stock_item=1 and i.has_serial_no=0 and i.has_batch_no=0 and i.has_variants=0 and i.disabled=0
and id.default_warehouse=%s and id.company=%s group by i.name''', (warehouse, company), as_dict=True)
items += frappe.db.sql("""
select i.name, i.item_name, id.default_warehouse
from tabItem i, `tabItem Default` id
where i.name = id.parent
and exists(select name from `tabWarehouse` where lft >= %s and rgt <= %s and name=id.default_warehouse)
and i.is_stock_item = 1 and i.has_serial_no = 0 and i.has_batch_no = 0
and i.has_variants = 0 and i.disabled = 0 and id.company=%s
group by i.name
""", (lft, rgt, company))
res = []
for item in items:
qty, rate = get_stock_balance(item.name, warehouse, posting_date, posting_time,
for d in set(items):
stock_bal = get_stock_balance(d[0], d[2], posting_date, posting_time,
with_valuation_rate=True)
res.append({
"item_code": item.name,
"warehouse": warehouse,
"qty": qty,
"item_name": item.item_name,
"valuation_rate": rate,
"current_qty": qty,
"current_valuation_rate": rate
})
if frappe.db.get_value("Item", d[0], "disabled") == 0:
res.append({
"item_code": d[0],
"warehouse": d[2],
"qty": stock_bal[0],
"item_name": d[1],
"valuation_rate": stock_bal[1],
"current_qty": stock_bal[0],
"current_valuation_rate": stock_bal[1]
})
return res

View File

@@ -10,7 +10,9 @@ from frappe.utils import flt, nowdate, nowtime
from erpnext.accounts.utils import get_stock_and_account_difference
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import set_perpetual_inventory
from erpnext.stock.stock_ledger import get_previous_sle, update_entries_after
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation import EmptyStockReconciliationItemsError, get_items
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.stock.doctype.item.test_item import create_item
class TestStockReconciliation(unittest.TestCase):
def setUp(self):
@@ -79,6 +81,19 @@ class TestStockReconciliation(unittest.TestCase):
set_perpetual_inventory(0)
def test_get_items(self):
create_warehouse("_Test Warehouse Group 1", {"is_group": 1})
create_warehouse("_Test Warehouse Ledger 1",
{"is_group": 0, "parent_warehouse": "_Test Warehouse Group 1 - _TC"})
create_item("_Test Stock Reco Item", is_stock_item=1, valuation_rate=100,
warehouse="_Test Warehouse Ledger 1 - _TC", opening_stock=100)
items = get_items("_Test Warehouse Group 1 - _TC", nowdate(), nowtime(), "_Test Company")
self.assertEqual(["_Test Stock Reco Item", "_Test Warehouse Ledger 1 - _TC", 100],
[items[0]["item_code"], items[0]["warehouse"], items[0]["qty"]])
def insert_existing_sle(self):
from erpnext.stock.doctype.stock_entry.test_stock_entry import make_stock_entry

View File

@@ -8,6 +8,7 @@ from erpnext import set_perpetual_inventory
from frappe.test_runner import make_test_records
from erpnext.accounts.doctype.account.test_account import get_inventory_account, create_account
import erpnext
import frappe
import unittest
test_records = frappe.get_test_records('Warehouse')
@@ -90,19 +91,28 @@ class TestWarehouse(unittest.TestCase):
self.assertTrue(frappe.db.get_value("Warehouse",
filters={"account": "Test Warehouse for Merging 2 - _TC"}))
def create_warehouse(warehouse_name):
if not frappe.db.exists("Warehouse", warehouse_name + " - _TC"):
def create_warehouse(warehouse_name, properties=None, company=None):
if not company:
company = "_Test Company"
warehouse_id = erpnext.encode_company_abbr(warehouse_name, company)
if not frappe.db.exists("Warehouse", warehouse_id):
w = frappe.new_doc("Warehouse")
w.warehouse_name = warehouse_name
w.parent_warehouse = "_Test Warehouse Group - _TC"
w.company = "_Test Company"
w.company = company
make_account_for_warehouse(warehouse_name, w)
w.account = warehouse_name + " - _TC"
w.account = warehouse_id
if properties:
w.update(properties)
w.save()
return w.name
else:
return warehouse_id
def make_account_for_warehouse(warehouse_name, warehouse_obj):
if not frappe.db.exists("Account", warehouse_name + " - _TC"):
parent_account = frappe.db.get_value('Account',
parent_account = frappe.db.get_value('Account',
{'company': warehouse_obj.company, 'is_group':1, 'account_type': 'Stock'},'name')
account = create_account(account_name=warehouse_name, \
account_type="Stock", parent_account= parent_account, company=warehouse_obj.company)

View File

@@ -37,6 +37,7 @@ def get_item_details(args):
"is_subcontracted": "Yes" / "No",
"ignore_pricing_rule": 0/1
"project": ""
"set_warehouse": ""
}
"""
args = process_args(args)
@@ -190,7 +191,6 @@ def get_basic_details(args, item):
"project": "",
barcode: "",
serial_no: "",
warehouse: "",
currency: "",
update_stock: "",
price_list: "",
@@ -221,7 +221,7 @@ def get_basic_details(args, item):
item_group_defaults = get_item_group_defaults(item.name, args.company)
brand_defaults = get_brand_defaults(item.name, args.company)
warehouse = user_default_warehouse or item_defaults.get("default_warehouse") or\
warehouse = args.get("set_warehouse") or user_default_warehouse or item_defaults.get("default_warehouse") or\
item_group_defaults.get("default_warehouse") or brand_defaults.get("default_warehouse") or args.warehouse
if args.get('doctype') == "Material Request" and not args.get('material_request_type'):
@@ -275,7 +275,7 @@ def get_basic_details(args, item):
"transaction_date": args.get("transaction_date")
})
if item.enable_deferred_revenue:
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
out.update(calculate_service_end_date(args, item))
# calculate conversion factor
@@ -283,7 +283,7 @@ def get_basic_details(args, item):
out.conversion_factor = 1.0
else:
out.conversion_factor = args.conversion_factor or \
get_conversion_factor(item.item_code, args.uom).get("conversion_factor") or 1.0
get_conversion_factor(item.item_code, args.uom).get("conversion_factor")
args.conversion_factor = out.conversion_factor
out.stock_qty = out.qty * out.conversion_factor
@@ -312,9 +312,15 @@ def calculate_service_end_date(args, item=None):
if not item:
item = frappe.get_cached_doc("Item", args.item_code)
enable_deferred = "enable_deferred_revenue" if args.doctype=="Sales Invoice" else "enable_deferred_expense"
no_of_months = "no_of_months" if args.doctype=="Sales Invoice" else "no_of_months_exp"
account = "deferred_revenue_account" if args.doctype=="Sales Invoice" else "deferred_expense_account"
doctype = args.get("parenttype") or args.get("doctype")
if doctype == "Sales Invoice":
enable_deferred = "enable_deferred_revenue"
no_of_months = "no_of_months"
account = "deferred_revenue_account"
else:
enable_deferred = "enable_deferred_expense"
no_of_months = "no_of_months_exp"
account = "deferred_expense_account"
service_start_date = args.service_start_date if args.service_start_date else args.transaction_date
service_end_date = add_months(service_start_date, item.get(no_of_months))
@@ -340,7 +346,7 @@ def get_default_expense_account(args, item, item_group, brand):
or args.expense_account)
def get_default_deferred_account(args, item, fieldname=None):
if item.enable_deferred_revenue:
if item.get("enable_deferred_revenue") or item.get("enable_deferred_expense"):
return (item.get(fieldname)
or args.get(fieldname)
or frappe.get_cached_value('Company', args.company, "default_"+fieldname))
@@ -369,22 +375,24 @@ def get_price_list_rate(args, item_doc, out):
meta = frappe.get_meta(args.parenttype or args.doctype)
if meta.get_field("currency") or args.get('currency'):
pl_details = get_price_list_currency_and_exchange_rate(args)
args.update(pl_details)
validate_price_list(args)
if meta.get_field("currency") and args.price_list:
validate_conversion_rate(args, meta)
price_list_rate = get_price_list_rate_for(args, item_doc.name) or 0
# variant
if not price_list_rate and item_doc.variant_of:
price_list_rate = get_price_list_rate_for(args, item_doc.variant_of)
# insert in database
if not price_list_rate:
if args.price_list and args.rate:
insert_item_price(args)
return {}
# variant
if not price_list_rate and item_doc.variant_of:
price_list_rate = get_price_list_rate_for(args, item_doc.variant_of)
out.price_list_rate = flt(price_list_rate) * flt(args.plc_conversion_rate) \
/ flt(args.conversion_rate)
@@ -421,7 +429,7 @@ def insert_item_price(args):
frappe.msgprint(_("Item Price added for {0} in Price List {1}").format(args.item_code,
args.price_list), alert=True)
def get_item_price(args, item_code):
def get_item_price(args, item_code, ignore_party=False):
"""
Get name, price_list_rate from Item Price based on conditions
Check if the Derised qty is within the increment of the packing list.
@@ -431,17 +439,19 @@ def get_item_price(args, item_code):
"""
args['item_code'] = item_code
conditions = "where (customer is null or customer = '') and (supplier is null or supplier = '')"
if args.get("customer"):
conditions = "where customer=%(customer)s"
if args.get("supplier"):
conditions = "where supplier=%(supplier)s"
conditions += """ and item_code=%(item_code)s
conditions = """where item_code=%(item_code)s
and price_list=%(price_list)s
and ifnull(uom, '') in ('', %(uom)s)"""
if not ignore_party:
if args.get("customer"):
conditions += " and customer=%(customer)s"
elif args.get("supplier"):
conditions += " and supplier=%(supplier)s"
else:
conditions += " and (customer is null or customer = '') and (supplier is null or supplier = '')"
if args.get('min_qty'):
conditions += " and ifnull(min_qty, 0) <= %(min_qty)s"
@@ -487,10 +497,10 @@ def get_price_list_rate_for(args, item_code):
for field in ["customer", "supplier", "min_qty"]:
del item_price_args[field]
general_price_list_rate = get_item_price(item_price_args, item_code)
general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
if not general_price_list_rate and args.get("uom") != args.get("stock_uom"):
item_price_args["args"] = args.get("stock_uom")
general_price_list_rate = get_item_price(item_price_args, item_code)
general_price_list_rate = get_item_price(item_price_args, item_code, ignore_party=args.get("ignore_party"))
if general_price_list_rate:
item_price_data = general_price_list_rate
@@ -553,9 +563,10 @@ def validate_conversion_rate(args, meta):
validate_conversion_rate(args.price_list_currency, args.plc_conversion_rate,
meta.get_label("plc_conversion_rate"), args.company)
args.plc_conversion_rate = flt(args.plc_conversion_rate,
get_field_precision(meta.get_field("plc_conversion_rate"),
frappe._dict({"fields": args})))
if meta.get_field("plc_conversion_rate"):
args.plc_conversion_rate = flt(args.plc_conversion_rate,
get_field_precision(meta.get_field("plc_conversion_rate"),
frappe._dict({"fields": args})))
def get_party_item_code(args, item_doc, out):
if args.transaction_type=="selling" and args.customer:
@@ -656,7 +667,7 @@ def get_conversion_factor(item_code, uom):
if not conversion_factor:
stock_uom = frappe.db.get_value("Item", item_code, "stock_uom")
conversion_factor = get_uom_conv_factor(uom, stock_uom)
return {"conversion_factor": conversion_factor}
return {"conversion_factor": conversion_factor or 1.0}
@frappe.whitelist()
def get_projected_qty(item_code, warehouse):
@@ -791,7 +802,7 @@ def get_price_list_uom_dependant(price_list):
if not result:
throw(_("Price List {0} is disabled or does not exist").format(price_list))
return result.price_not_uom_dependant
return not result.price_not_uom_dependant
def get_price_list_currency_and_exchange_rate(args):

View File

@@ -1,6 +1,7 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
from __future__ import unicode_literals
import frappe
import erpnext
from frappe.utils import flt, nowdate, add_days, cint
@@ -138,7 +139,7 @@ def create_material_request(material_requests):
if request_type == 'Purchase':
uom = item.purchase_uom or item.stock_uom
if uom != item.stock_uom:
conversion_factor = frappe.db.get_value("UOM Conversion Detail",
conversion_factor = frappe.db.get_value("UOM Conversion Detail",
{'parent': item.name, 'uom': uom}, 'conversion_factor') or 1.0
mr.append("items", {

View File

@@ -110,16 +110,22 @@ def get_item_details(items, sl_entries, include_uom):
cf_field = cf_join = ""
if include_uom:
cf_field = ", ucd.conversion_factor"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom=%(include_uom)s"
cf_join = "left join `tabUOM Conversion Detail` ucd on ucd.parent=item.name and ucd.uom='%s'" \
% frappe.db.escape(include_uom)
for item in frappe.db.sql("""
select item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom{cf_field}
from `tabItem` item
{cf_join}
where item.name in ({names})
""".format(cf_field=cf_field, cf_join=cf_join, names=', '.join(['"' + frappe.db.escape(i, percent=False) + '"' for i in items])),
{"include_uom": include_uom}, as_dict=1):
item_details.setdefault(item.name, item)
item_codes = ', '.join(['"' + frappe.db.escape(i, percent=False) + '"' for i in items])
res = frappe.db.sql("""
select
item.name, item.item_name, item.description, item.item_group, item.brand, item.stock_uom {cf_field}
from
`tabItem` item
{cf_join}
where
item.name in ({item_codes})
""".format(cf_field=cf_field, cf_join=cf_join, item_codes=item_codes), as_dict=1)
for item in res:
item_details.setdefault(item.name, item)
return item_details

View File

@@ -257,7 +257,7 @@ def repost_all_stock_vouchers():
doc.update_stock_ledger()
doc.make_gl_entries(repost_future_gle=False)
frappe.db.commit()
except Exception as e:
except Exception:
print(frappe.get_traceback())
rejected.append([voucher_type, voucher_no])
frappe.db.rollback()