mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-08 15:42:52 +00:00
Merge branch 'version-13-hotfix' into fix/delivery-note/billed-amount
This commit is contained in:
@@ -28,14 +28,14 @@
|
|||||||
{
|
{
|
||||||
"columns": 2,
|
"columns": 2,
|
||||||
"fieldname": "single_threshold",
|
"fieldname": "single_threshold",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Single Transaction Threshold"
|
"label": "Single Transaction Threshold"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"columns": 3,
|
"columns": 3,
|
||||||
"fieldname": "cumulative_threshold",
|
"fieldname": "cumulative_threshold",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Float",
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Cumulative Transaction Threshold"
|
"label": "Cumulative Transaction Threshold"
|
||||||
},
|
},
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-08-31 11:42:12.213977",
|
"modified": "2022-01-13 12:04:42.904263",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Tax Withholding Rate",
|
"name": "Tax Withholding Rate",
|
||||||
@@ -68,5 +68,6 @@
|
|||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -121,6 +121,7 @@ class Deferred_Item(object):
|
|||||||
"""
|
"""
|
||||||
simulate future posting by creating dummy gl entries. starts from the last posting date.
|
simulate future posting by creating dummy gl entries. starts from the last posting date.
|
||||||
"""
|
"""
|
||||||
|
if self.service_start_date != self.service_end_date:
|
||||||
if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
|
if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
|
||||||
self.estimate_for_period_list = get_period_list(
|
self.estimate_for_period_list = get_period_list(
|
||||||
self.filters.from_fiscal_year,
|
self.filters.from_fiscal_year,
|
||||||
|
|||||||
@@ -20,3 +20,56 @@ class TestUtils(unittest.TestCase):
|
|||||||
doc.reset_default_field_value("set_warehouse", "items", "warehouse")
|
doc.reset_default_field_value("set_warehouse", "items", "warehouse")
|
||||||
self.assertEqual(doc.set_warehouse, None)
|
self.assertEqual(doc.set_warehouse, None)
|
||||||
|
|
||||||
|
def test_reset_default_field_value_in_mfg_stock_entry(self):
|
||||||
|
# manufacture stock entry with rows having blank source/target wh
|
||||||
|
se = frappe.get_doc(
|
||||||
|
doctype="Stock Entry",
|
||||||
|
purpose="Manufacture",
|
||||||
|
stock_entry_type="Manufacture",
|
||||||
|
company="_Test Company",
|
||||||
|
from_warehouse="_Test Warehouse - _TC",
|
||||||
|
to_warehouse="_Test Warehouse 1 - _TC",
|
||||||
|
items=[
|
||||||
|
frappe._dict(item_code="_Test Item", qty=1, basic_rate=200, s_warehouse="_Test Warehouse - _TC"),
|
||||||
|
frappe._dict(item_code="_Test FG Item", qty=4, t_warehouse="_Test Warehouse 1 - _TC", is_finished_item=1)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
se.save()
|
||||||
|
|
||||||
|
# default fields must be untouched
|
||||||
|
self.assertEqual(se.from_warehouse, "_Test Warehouse - _TC")
|
||||||
|
self.assertEqual(se.to_warehouse, "_Test Warehouse 1 - _TC")
|
||||||
|
|
||||||
|
se.delete()
|
||||||
|
|
||||||
|
def test_reset_default_field_value_in_transfer_stock_entry(self):
|
||||||
|
doc = frappe.get_doc({
|
||||||
|
"doctype": "Stock Entry",
|
||||||
|
"purpose": "Material Receipt",
|
||||||
|
"from_warehouse": "Warehouse 1",
|
||||||
|
"to_warehouse": "Warehouse 2",
|
||||||
|
})
|
||||||
|
|
||||||
|
# Same values
|
||||||
|
doc.items = [
|
||||||
|
{"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
|
||||||
|
{"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
|
||||||
|
{"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"}
|
||||||
|
]
|
||||||
|
|
||||||
|
doc.reset_default_field_value("from_warehouse", "items", "s_warehouse")
|
||||||
|
doc.reset_default_field_value("to_warehouse", "items", "t_warehouse")
|
||||||
|
self.assertEqual(doc.from_warehouse, "Warehouse 1")
|
||||||
|
self.assertEqual(doc.to_warehouse, "Warehouse 2")
|
||||||
|
|
||||||
|
# Mixed values in source wh
|
||||||
|
doc.items = [
|
||||||
|
{"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"},
|
||||||
|
{"s_warehouse": "Warehouse 3", "t_warehouse": "Warehouse 2"},
|
||||||
|
{"s_warehouse": "Warehouse 1", "t_warehouse": "Warehouse 2"}
|
||||||
|
]
|
||||||
|
|
||||||
|
doc.reset_default_field_value("from_warehouse", "items", "s_warehouse")
|
||||||
|
doc.reset_default_field_value("to_warehouse", "items", "t_warehouse")
|
||||||
|
self.assertEqual(doc.from_warehouse, None)
|
||||||
|
self.assertEqual(doc.to_warehouse, "Warehouse 2")
|
||||||
@@ -17,7 +17,10 @@ class TestEmployeeOnboarding(unittest.TestCase):
|
|||||||
def test_employee_onboarding_incomplete_task(self):
|
def test_employee_onboarding_incomplete_task(self):
|
||||||
if frappe.db.exists('Employee Onboarding', {'employee_name': 'Test Researcher'}):
|
if frappe.db.exists('Employee Onboarding', {'employee_name': 'Test Researcher'}):
|
||||||
frappe.delete_doc('Employee Onboarding', {'employee_name': 'Test Researcher'})
|
frappe.delete_doc('Employee Onboarding', {'employee_name': 'Test Researcher'})
|
||||||
_set_up()
|
frappe.db.sql("delete from `tabEmployee Onboarding`")
|
||||||
|
project = "Employee Onboarding : test@researcher.com"
|
||||||
|
frappe.db.sql("delete from tabProject where name=%s", project)
|
||||||
|
frappe.db.sql("delete from tabTask where project=%s", project)
|
||||||
applicant = get_job_applicant()
|
applicant = get_job_applicant()
|
||||||
|
|
||||||
job_offer = create_job_offer(job_applicant=applicant.name)
|
job_offer = create_job_offer(job_applicant=applicant.name)
|
||||||
@@ -42,7 +45,7 @@ class TestEmployeeOnboarding(unittest.TestCase):
|
|||||||
onboarding.submit()
|
onboarding.submit()
|
||||||
|
|
||||||
project_name = frappe.db.get_value("Project", onboarding.project, "project_name")
|
project_name = frappe.db.get_value("Project", onboarding.project, "project_name")
|
||||||
self.assertEqual(project_name, 'Employee Onboarding : Test Researcher - test@researcher.com')
|
self.assertEqual(project_name, 'Employee Onboarding : test@researcher.com')
|
||||||
|
|
||||||
# don't allow making employee if onboarding is not complete
|
# don't allow making employee if onboarding is not complete
|
||||||
self.assertRaises(IncompleteTaskError, make_employee, onboarding.name)
|
self.assertRaises(IncompleteTaskError, make_employee, onboarding.name)
|
||||||
@@ -65,8 +68,8 @@ class TestEmployeeOnboarding(unittest.TestCase):
|
|||||||
self.assertEqual(employee.employee_name, 'Test Researcher')
|
self.assertEqual(employee.employee_name, 'Test Researcher')
|
||||||
|
|
||||||
def get_job_applicant():
|
def get_job_applicant():
|
||||||
if frappe.db.exists('Job Applicant', 'Test Researcher - test@researcher.com'):
|
if frappe.db.exists('Job Applicant', 'test@researcher.com'):
|
||||||
return frappe.get_doc('Job Applicant', 'Test Researcher - test@researcher.com')
|
return frappe.get_doc('Job Applicant', 'test@researcher.com')
|
||||||
applicant = frappe.new_doc('Job Applicant')
|
applicant = frappe.new_doc('Job Applicant')
|
||||||
applicant.applicant_name = 'Test Researcher'
|
applicant.applicant_name = 'Test Researcher'
|
||||||
applicant.email_id = 'test@researcher.com'
|
applicant.email_id = 'test@researcher.com'
|
||||||
|
|||||||
@@ -192,10 +192,11 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-09-29 23:06:10.904260",
|
"modified": "2022-01-12 16:28:53.196881",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Job Applicant",
|
"name": "Job Applicant",
|
||||||
|
"naming_rule": "Expression (old style)",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -210,10 +211,11 @@
|
|||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"search_fields": "applicant_name",
|
"search_fields": "applicant_name, email_id, job_title, phone_number",
|
||||||
"sender_field": "email_id",
|
"sender_field": "email_id",
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
|
"states": [],
|
||||||
"subject_field": "notes",
|
"subject_field": "notes",
|
||||||
"title_field": "applicant_name"
|
"title_field": "applicant_name"
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
|
from frappe.model.naming import append_number_if_name_exists
|
||||||
from frappe.utils import validate_email_address
|
from frappe.utils import validate_email_address
|
||||||
|
|
||||||
from erpnext.hr.doctype.interview.interview import get_interviewers
|
from erpnext.hr.doctype.interview.interview import get_interviewers
|
||||||
@@ -21,10 +22,11 @@ class JobApplicant(Document):
|
|||||||
self.get("__onload").job_offer = job_offer[0].name
|
self.get("__onload").job_offer = job_offer[0].name
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
keys = filter(None, (self.applicant_name, self.email_id, self.job_title))
|
self.name = self.email_id
|
||||||
if not keys:
|
|
||||||
frappe.throw(_("Name or Email is mandatory"), frappe.NameError)
|
# applicant can apply more than once for a different job title or reapply
|
||||||
self.name = " - ".join(keys)
|
if frappe.db.exists("Job Applicant", self.name):
|
||||||
|
self.name = append_number_if_name_exists("Job Applicant", self.name)
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.email_id:
|
if self.email_id:
|
||||||
|
|||||||
@@ -9,7 +9,26 @@ from erpnext.hr.doctype.designation.test_designation import create_designation
|
|||||||
|
|
||||||
|
|
||||||
class TestJobApplicant(unittest.TestCase):
|
class TestJobApplicant(unittest.TestCase):
|
||||||
pass
|
def test_job_applicant_naming(self):
|
||||||
|
applicant = frappe.get_doc({
|
||||||
|
"doctype": "Job Applicant",
|
||||||
|
"status": "Open",
|
||||||
|
"applicant_name": "_Test Applicant",
|
||||||
|
"email_id": "job_applicant_naming@example.com"
|
||||||
|
}).insert()
|
||||||
|
self.assertEqual(applicant.name, 'job_applicant_naming@example.com')
|
||||||
|
|
||||||
|
applicant = frappe.get_doc({
|
||||||
|
"doctype": "Job Applicant",
|
||||||
|
"status": "Open",
|
||||||
|
"applicant_name": "_Test Applicant",
|
||||||
|
"email_id": "job_applicant_naming@example.com"
|
||||||
|
}).insert()
|
||||||
|
self.assertEqual(applicant.name, 'job_applicant_naming@example.com-1')
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
frappe.db.rollback()
|
||||||
|
|
||||||
|
|
||||||
def create_job_applicant(**args):
|
def create_job_applicant(**args):
|
||||||
args = frappe._dict(args)
|
args = frappe._dict(args)
|
||||||
|
|||||||
@@ -1,294 +1,108 @@
|
|||||||
{
|
{
|
||||||
"allow_copy": 0,
|
"actions": [],
|
||||||
"allow_guest_to_view": 0,
|
|
||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"allow_rename": 1,
|
"allow_rename": 1,
|
||||||
"autoname": "HR-LPR-.YYYY.-.#####",
|
"autoname": "HR-LPR-.YYYY.-.#####",
|
||||||
"beta": 0,
|
|
||||||
"creation": "2018-04-13 15:20:52.864288",
|
"creation": "2018-04-13 15:20:52.864288",
|
||||||
"custom": 0,
|
|
||||||
"docstatus": 0,
|
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "",
|
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
|
"field_order": [
|
||||||
|
"from_date",
|
||||||
|
"to_date",
|
||||||
|
"is_active",
|
||||||
|
"column_break_3",
|
||||||
|
"company",
|
||||||
|
"optional_holiday_list"
|
||||||
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "from_date",
|
"fieldname": "from_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "From Date",
|
"label": "From Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"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": 1,
|
|
||||||
"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": "to_date",
|
"fieldname": "to_date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "To Date",
|
"label": "To Date",
|
||||||
"length": 0,
|
"reqd": 1
|
||||||
"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": 1,
|
|
||||||
"search_index": 0,
|
|
||||||
"set_only_once": 0,
|
|
||||||
"translatable": 0,
|
|
||||||
"unique": 0
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
"default": "0",
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "is_active",
|
"fieldname": "is_active",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"hidden": 0,
|
"label": "Is Active"
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 0,
|
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Is Active",
|
|
||||||
"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": "column_break_3",
|
"fieldname": "column_break_3",
|
||||||
"fieldtype": "Column Break",
|
"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": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"hidden": 0,
|
|
||||||
"ignore_user_permissions": 0,
|
|
||||||
"ignore_xss_filter": 0,
|
|
||||||
"in_filter": 0,
|
|
||||||
"in_global_search": 0,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 0,
|
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"length": 0,
|
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
"permlevel": 0,
|
"reqd": 1
|
||||||
"precision": "",
|
|
||||||
"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
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_bulk_edit": 0,
|
|
||||||
"allow_in_quick_entry": 0,
|
|
||||||
"allow_on_submit": 0,
|
|
||||||
"bold": 0,
|
|
||||||
"collapsible": 0,
|
|
||||||
"columns": 0,
|
|
||||||
"fieldname": "optional_holiday_list",
|
"fieldname": "optional_holiday_list",
|
||||||
"fieldtype": "Link",
|
"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": "Holiday List for Optional Leave",
|
"label": "Holiday List for Optional Leave",
|
||||||
"length": 0,
|
"options": "Holiday List"
|
||||||
"no_copy": 0,
|
|
||||||
"options": "Holiday List",
|
|
||||||
"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
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"has_web_view": 0,
|
"links": [],
|
||||||
"hide_heading": 0,
|
"modified": "2022-01-13 13:28:12.951025",
|
||||||
"hide_toolbar": 0,
|
|
||||||
"idx": 0,
|
|
||||||
"image_view": 0,
|
|
||||||
"in_create": 0,
|
|
||||||
"is_submittable": 0,
|
|
||||||
"issingle": 0,
|
|
||||||
"istable": 0,
|
|
||||||
"max_attachments": 0,
|
|
||||||
"modified": "2019-05-30 16:15:43.305502",
|
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Leave Period",
|
"name": "Leave Period",
|
||||||
"name_case": "",
|
"naming_rule": "Expression (old style)",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "HR Manager",
|
"role": "HR Manager",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"amend": 0,
|
|
||||||
"cancel": 0,
|
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
"if_owner": 0,
|
|
||||||
"import": 0,
|
|
||||||
"permlevel": 0,
|
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "HR User",
|
"role": "HR User",
|
||||||
"set_user_permissions": 0,
|
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 0,
|
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"quick_entry": 0,
|
"search_fields": "from_date, to_date, company",
|
||||||
"read_only": 0,
|
|
||||||
"read_only_onload": 0,
|
|
||||||
"show_name_in_global_search": 0,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"track_changes": 1,
|
"states": [],
|
||||||
"track_seen": 0,
|
"track_changes": 1
|
||||||
"track_views": 0
|
|
||||||
}
|
}
|
||||||
@@ -113,10 +113,11 @@
|
|||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-03-01 17:54:01.014509",
|
"modified": "2022-01-13 13:37:11.218882",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "HR",
|
"module": "HR",
|
||||||
"name": "Leave Policy Assignment",
|
"name": "Leave Policy Assignment",
|
||||||
|
"naming_rule": "Expression (old style)",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -164,5 +165,7 @@
|
|||||||
],
|
],
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
|
"states": [],
|
||||||
|
"title_field": "employee_name",
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,16 @@ frappe.listview_settings['Leave Policy Assignment'] = {
|
|||||||
if (cur_dialog.fields_dict.leave_period.value) {
|
if (cur_dialog.fields_dict.leave_period.value) {
|
||||||
me.set_effective_date();
|
me.set_effective_date();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
get_query() {
|
||||||
|
let filters = {"is_active": 1};
|
||||||
|
if (cur_dialog.fields_dict.company.value)
|
||||||
|
filters["company"] = cur_dialog.fields_dict.company.value;
|
||||||
|
|
||||||
|
return {
|
||||||
|
filters: filters
|
||||||
|
};
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldtype: "Column Break"
|
fieldtype: "Column Break"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import add_months, cint, flt, now, today
|
from frappe.utils import add_days, add_months, cint, flt, now, today
|
||||||
|
|
||||||
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
|
from erpnext.manufacturing.doctype.job_card.job_card import JobCardCancelError
|
||||||
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
from erpnext.manufacturing.doctype.production_plan.test_production_plan import make_bom
|
||||||
@@ -12,6 +12,7 @@ from erpnext.manufacturing.doctype.work_order.work_order import (
|
|||||||
OverProductionError,
|
OverProductionError,
|
||||||
StockOverProductionError,
|
StockOverProductionError,
|
||||||
close_work_order,
|
close_work_order,
|
||||||
|
make_job_card,
|
||||||
make_stock_entry,
|
make_stock_entry,
|
||||||
stop_unstop,
|
stop_unstop,
|
||||||
)
|
)
|
||||||
@@ -801,6 +802,34 @@ class TestWorkOrder(ERPNextTestCase):
|
|||||||
if row.is_scrap_item:
|
if row.is_scrap_item:
|
||||||
self.assertEqual(row.qty, 1)
|
self.assertEqual(row.qty, 1)
|
||||||
|
|
||||||
|
# Partial Job Card 1 with qty 10
|
||||||
|
wo_order = make_wo_order_test_record(item=item, company=company, planned_start_date=add_days(now(), 60), qty=20, skip_transfer=1)
|
||||||
|
job_card = frappe.db.get_value('Job Card', {'work_order': wo_order.name}, 'name')
|
||||||
|
update_job_card(job_card, 10)
|
||||||
|
|
||||||
|
stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
|
||||||
|
for row in stock_entry.items:
|
||||||
|
if row.is_scrap_item:
|
||||||
|
self.assertEqual(row.qty, 2)
|
||||||
|
|
||||||
|
# Partial Job Card 2 with qty 10
|
||||||
|
operations = []
|
||||||
|
wo_order.load_from_db()
|
||||||
|
for row in wo_order.operations:
|
||||||
|
n_dict = row.as_dict()
|
||||||
|
n_dict['qty'] = 10
|
||||||
|
n_dict['pending_qty'] = 10
|
||||||
|
operations.append(n_dict)
|
||||||
|
|
||||||
|
make_job_card(wo_order.name, operations)
|
||||||
|
job_card = frappe.db.get_value('Job Card', {'work_order': wo_order.name, 'docstatus': 0}, 'name')
|
||||||
|
update_job_card(job_card, 10)
|
||||||
|
|
||||||
|
stock_entry = frappe.get_doc(make_stock_entry(wo_order.name, "Manufacture", 10))
|
||||||
|
for row in stock_entry.items:
|
||||||
|
if row.is_scrap_item:
|
||||||
|
self.assertEqual(row.qty, 2)
|
||||||
|
|
||||||
def test_close_work_order(self):
|
def test_close_work_order(self):
|
||||||
items = ['Test FG Item for Closed WO', 'Test RM Item 1 for Closed WO',
|
items = ['Test FG Item for Closed WO', 'Test RM Item 1 for Closed WO',
|
||||||
'Test RM Item 2 for Closed WO']
|
'Test RM Item 2 for Closed WO']
|
||||||
@@ -841,7 +870,9 @@ class TestWorkOrder(ERPNextTestCase):
|
|||||||
close_work_order(wo_order, "Closed")
|
close_work_order(wo_order, "Closed")
|
||||||
self.assertEqual(wo_order.get('status'), "Closed")
|
self.assertEqual(wo_order.get('status'), "Closed")
|
||||||
|
|
||||||
def update_job_card(job_card):
|
def update_job_card(job_card, jc_qty=None):
|
||||||
|
employee = frappe.db.get_value('Employee', {'status': 'Active'}, 'name')
|
||||||
|
|
||||||
job_card_doc = frappe.get_doc('Job Card', job_card)
|
job_card_doc = frappe.get_doc('Job Card', job_card)
|
||||||
job_card_doc.set('scrap_items', [
|
job_card_doc.set('scrap_items', [
|
||||||
{
|
{
|
||||||
@@ -854,15 +885,18 @@ def update_job_card(job_card):
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
|
if jc_qty:
|
||||||
|
job_card_doc.for_quantity = jc_qty
|
||||||
|
|
||||||
job_card_doc.append('time_logs', {
|
job_card_doc.append('time_logs', {
|
||||||
'from_time': now(),
|
'from_time': now(),
|
||||||
|
'employee': employee,
|
||||||
'time_in_mins': 60,
|
'time_in_mins': 60,
|
||||||
'completed_qty': job_card_doc.for_quantity
|
'completed_qty': job_card_doc.for_quantity
|
||||||
})
|
})
|
||||||
|
|
||||||
job_card_doc.submit()
|
job_card_doc.submit()
|
||||||
|
|
||||||
|
|
||||||
def get_scrap_item_details(bom_no):
|
def get_scrap_item_details(bom_no):
|
||||||
scrap_items = {}
|
scrap_items = {}
|
||||||
for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
|
for item in frappe.db.sql("""select item_code, stock_qty from `tabBOM Scrap Item`
|
||||||
|
|||||||
@@ -60,6 +60,8 @@ class PayrollEntry(Document):
|
|||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
frappe.delete_doc("Salary Slip", frappe.db.sql_list("""select name from `tabSalary Slip`
|
frappe.delete_doc("Salary Slip", frappe.db.sql_list("""select name from `tabSalary Slip`
|
||||||
where payroll_entry=%s """, (self.name)))
|
where payroll_entry=%s """, (self.name)))
|
||||||
|
self.db_set("salary_slips_created", 0)
|
||||||
|
self.db_set("salary_slips_submitted", 0)
|
||||||
|
|
||||||
def get_emp_list(self):
|
def get_emp_list(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -213,6 +213,9 @@ erpnext.company.setup_queries = function(frm) {
|
|||||||
["default_payroll_payable_account", {"root_type": "Liability"}],
|
["default_payroll_payable_account", {"root_type": "Liability"}],
|
||||||
["round_off_account", {"root_type": "Expense"}],
|
["round_off_account", {"root_type": "Expense"}],
|
||||||
["write_off_account", {"root_type": "Expense"}],
|
["write_off_account", {"root_type": "Expense"}],
|
||||||
|
["default_deferred_expense_account", {}],
|
||||||
|
["default_deferred_revenue_account", {}],
|
||||||
|
["default_expense_claim_payable_account", {}],
|
||||||
["default_discount_account", {}],
|
["default_discount_account", {}],
|
||||||
["discount_allowed_account", {"root_type": "Expense"}],
|
["discount_allowed_account", {"root_type": "Expense"}],
|
||||||
["discount_received_account", {"root_type": "Income"}],
|
["discount_received_account", {"root_type": "Income"}],
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ from collections import defaultdict
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
|
from frappe.utils import cint, comma_or, cstr, flt, format_time, formatdate, getdate, nowdate
|
||||||
from six import iteritems, itervalues, string_types
|
from six import iteritems, itervalues, string_types
|
||||||
|
|
||||||
@@ -86,8 +87,11 @@ class StockEntry(StockController):
|
|||||||
self.validate_warehouse()
|
self.validate_warehouse()
|
||||||
self.validate_work_order()
|
self.validate_work_order()
|
||||||
self.validate_bom()
|
self.validate_bom()
|
||||||
|
|
||||||
|
if self.purpose in ("Manufacture", "Repack"):
|
||||||
self.mark_finished_and_scrap_items()
|
self.mark_finished_and_scrap_items()
|
||||||
self.validate_finished_goods()
|
self.validate_finished_goods()
|
||||||
|
|
||||||
self.validate_with_material_request()
|
self.validate_with_material_request()
|
||||||
self.validate_batch()
|
self.validate_batch()
|
||||||
self.validate_inspection()
|
self.validate_inspection()
|
||||||
@@ -110,6 +114,10 @@ class StockEntry(StockController):
|
|||||||
self.set_actual_qty()
|
self.set_actual_qty()
|
||||||
self.calculate_rate_and_amount()
|
self.calculate_rate_and_amount()
|
||||||
self.validate_putaway_capacity()
|
self.validate_putaway_capacity()
|
||||||
|
|
||||||
|
if not self.get("purpose") == "Manufacture":
|
||||||
|
# ignore scrap item wh difference and empty source/target wh
|
||||||
|
# in Manufacture Entry
|
||||||
self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
|
self.reset_default_field_value("from_warehouse", "items", "s_warehouse")
|
||||||
self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
|
self.reset_default_field_value("to_warehouse", "items", "t_warehouse")
|
||||||
|
|
||||||
@@ -702,7 +710,6 @@ class StockEntry(StockController):
|
|||||||
validate_bom_no(item_code, d.bom_no)
|
validate_bom_no(item_code, d.bom_no)
|
||||||
|
|
||||||
def mark_finished_and_scrap_items(self):
|
def mark_finished_and_scrap_items(self):
|
||||||
if self.purpose in ("Repack", "Manufacture"):
|
|
||||||
if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
|
if any([d.item_code for d in self.items if (d.is_finished_item and d.t_warehouse)]):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -734,9 +741,9 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
def validate_finished_goods(self):
|
def validate_finished_goods(self):
|
||||||
"""
|
"""
|
||||||
1. Check if FG exists
|
1. Check if FG exists (mfg, repack)
|
||||||
2. Check if Multiple FG Items are present
|
2. Check if Multiple FG Items are present (mfg)
|
||||||
3. Check FG Item and Qty against WO if present
|
3. Check FG Item and Qty against WO if present (mfg)
|
||||||
"""
|
"""
|
||||||
production_item, wo_qty, finished_items = None, 0, []
|
production_item, wo_qty, finished_items = None, 0, []
|
||||||
|
|
||||||
@@ -749,8 +756,9 @@ class StockEntry(StockController):
|
|||||||
for d in self.get('items'):
|
for d in self.get('items'):
|
||||||
if d.is_finished_item:
|
if d.is_finished_item:
|
||||||
if not self.work_order:
|
if not self.work_order:
|
||||||
|
# Independent MFG Entry/ Repack Entry, no WO to match against
|
||||||
finished_items.append(d.item_code)
|
finished_items.append(d.item_code)
|
||||||
continue # Independent Manufacture Entry, no WO to match against
|
continue
|
||||||
|
|
||||||
if d.item_code != production_item:
|
if d.item_code != production_item:
|
||||||
frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
|
frappe.throw(_("Finished Item {0} does not match with Work Order {1}")
|
||||||
@@ -763,19 +771,17 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
finished_items.append(d.item_code)
|
finished_items.append(d.item_code)
|
||||||
|
|
||||||
if len(set(finished_items)) > 1:
|
|
||||||
frappe.throw(
|
|
||||||
msg=_("Multiple items cannot be marked as finished item"),
|
|
||||||
title=_("Note"),
|
|
||||||
exc=FinishedGoodError
|
|
||||||
)
|
|
||||||
|
|
||||||
if self.purpose == "Manufacture":
|
|
||||||
if not finished_items:
|
if not finished_items:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
|
msg=_("There must be atleast 1 Finished Good in this Stock Entry").format(self.name),
|
||||||
title=_("Missing Finished Good"),
|
title=_("Missing Finished Good"), exc=FinishedGoodError
|
||||||
exc=FinishedGoodError
|
)
|
||||||
|
|
||||||
|
if self.purpose == "Manufacture":
|
||||||
|
if len(set(finished_items)) > 1:
|
||||||
|
frappe.throw(
|
||||||
|
msg=_("Multiple items cannot be marked as finished item"),
|
||||||
|
title=_("Note"), exc=FinishedGoodError
|
||||||
)
|
)
|
||||||
|
|
||||||
allowance_percentage = flt(
|
allowance_percentage = flt(
|
||||||
@@ -1276,22 +1282,29 @@ class StockEntry(StockController):
|
|||||||
if not self.pro_doc:
|
if not self.pro_doc:
|
||||||
self.set_work_order_details()
|
self.set_work_order_details()
|
||||||
|
|
||||||
scrap_items = frappe.db.sql('''
|
if not self.pro_doc.operations:
|
||||||
SELECT
|
|
||||||
JCSI.item_code, JCSI.item_name, SUM(JCSI.stock_qty) as stock_qty, JCSI.stock_uom, JCSI.description
|
|
||||||
FROM
|
|
||||||
`tabJob Card` JC, `tabJob Card Scrap Item` JCSI
|
|
||||||
WHERE
|
|
||||||
JCSI.parent = JC.name AND JC.docstatus = 1
|
|
||||||
AND JCSI.item_code IS NOT NULL AND JC.work_order = %s
|
|
||||||
GROUP BY
|
|
||||||
JCSI.item_code
|
|
||||||
''', self.work_order, as_dict=1)
|
|
||||||
|
|
||||||
pending_qty = flt(self.pro_doc.qty) - flt(self.pro_doc.produced_qty)
|
|
||||||
if pending_qty <=0:
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
job_card = frappe.qb.DocType('Job Card')
|
||||||
|
job_card_scrap_item = frappe.qb.DocType('Job Card Scrap Item')
|
||||||
|
|
||||||
|
scrap_items = (
|
||||||
|
frappe.qb.from_(job_card)
|
||||||
|
.select(
|
||||||
|
Sum(job_card_scrap_item.stock_qty).as_('stock_qty'),
|
||||||
|
job_card_scrap_item.item_code, job_card_scrap_item.item_name,
|
||||||
|
job_card_scrap_item.description, job_card_scrap_item.stock_uom)
|
||||||
|
.join(job_card_scrap_item)
|
||||||
|
.on(job_card_scrap_item.parent == job_card.name)
|
||||||
|
.where(
|
||||||
|
(job_card_scrap_item.item_code.isnotnull())
|
||||||
|
& (job_card.work_order == self.work_order)
|
||||||
|
& (job_card.docstatus == 1))
|
||||||
|
.groupby(job_card_scrap_item.item_code)
|
||||||
|
).run(as_dict=1)
|
||||||
|
|
||||||
|
pending_qty = flt(self.get_completed_job_card_qty()) - flt(self.pro_doc.produced_qty)
|
||||||
|
|
||||||
used_scrap_items = self.get_used_scrap_items()
|
used_scrap_items = self.get_used_scrap_items()
|
||||||
for row in scrap_items:
|
for row in scrap_items:
|
||||||
row.stock_qty -= flt(used_scrap_items.get(row.item_code))
|
row.stock_qty -= flt(used_scrap_items.get(row.item_code))
|
||||||
@@ -1305,6 +1318,9 @@ class StockEntry(StockController):
|
|||||||
|
|
||||||
return scrap_items
|
return scrap_items
|
||||||
|
|
||||||
|
def get_completed_job_card_qty(self):
|
||||||
|
return flt(min([d.completed_qty for d in self.pro_doc.operations]))
|
||||||
|
|
||||||
def get_used_scrap_items(self):
|
def get_used_scrap_items(self):
|
||||||
used_scrap_items = defaultdict(float)
|
used_scrap_items = defaultdict(float)
|
||||||
data = frappe.get_all(
|
data = frappe.get_all(
|
||||||
|
|||||||
@@ -227,9 +227,47 @@ class TestStockEntry(ERPNextTestCase):
|
|||||||
|
|
||||||
mtn.cancel()
|
mtn.cancel()
|
||||||
|
|
||||||
def test_repack_no_change_in_valuation(self):
|
def test_repack_multiple_fg(self):
|
||||||
company = frappe.db.get_value('Warehouse', '_Test Warehouse - _TC', 'company')
|
"Test `is_finished_item` for one item repacked into two items."
|
||||||
|
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=100, basic_rate=100)
|
||||||
|
|
||||||
|
repack = frappe.copy_doc(test_records[3])
|
||||||
|
repack.posting_date = nowdate()
|
||||||
|
repack.posting_time = nowtime()
|
||||||
|
|
||||||
|
repack.items[0].qty = 100.0
|
||||||
|
repack.items[0].transfer_qty = 100.0
|
||||||
|
repack.items[1].qty = 50.0
|
||||||
|
|
||||||
|
repack.append("items", {
|
||||||
|
"conversion_factor": 1.0,
|
||||||
|
"cost_center": "_Test Cost Center - _TC",
|
||||||
|
"doctype": "Stock Entry Detail",
|
||||||
|
"expense_account": "Stock Adjustment - _TC",
|
||||||
|
"basic_rate": 150,
|
||||||
|
"item_code": "_Test Item 2",
|
||||||
|
"parentfield": "items",
|
||||||
|
"qty": 50.0,
|
||||||
|
"stock_uom": "_Test UOM",
|
||||||
|
"t_warehouse": "_Test Warehouse - _TC",
|
||||||
|
"transfer_qty": 50.0,
|
||||||
|
"uom": "_Test UOM"
|
||||||
|
})
|
||||||
|
repack.set_stock_entry_type()
|
||||||
|
repack.insert()
|
||||||
|
|
||||||
|
self.assertEqual(repack.items[1].is_finished_item, 1)
|
||||||
|
self.assertEqual(repack.items[2].is_finished_item, 1)
|
||||||
|
|
||||||
|
repack.items[1].is_finished_item = 0
|
||||||
|
repack.items[2].is_finished_item = 0
|
||||||
|
|
||||||
|
# must raise error if 0 fg in repack entry
|
||||||
|
self.assertRaises(FinishedGoodError, repack.validate_finished_goods)
|
||||||
|
|
||||||
|
repack.delete() # teardown
|
||||||
|
|
||||||
|
def test_repack_no_change_in_valuation(self):
|
||||||
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
|
make_stock_entry(item_code="_Test Item", target="_Test Warehouse - _TC", qty=50, basic_rate=100)
|
||||||
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
|
make_stock_entry(item_code="_Test Item Home Desktop 100", target="_Test Warehouse - _TC",
|
||||||
qty=50, basic_rate=100)
|
qty=50, basic_rate=100)
|
||||||
|
|||||||
@@ -182,8 +182,6 @@ class TransactionBase(StatusUpdater):
|
|||||||
|
|
||||||
if len(child_table_values) > 1:
|
if len(child_table_values) > 1:
|
||||||
self.set(default_field, None)
|
self.set(default_field, None)
|
||||||
else:
|
|
||||||
self.set(default_field, list(child_table_values)[0])
|
|
||||||
|
|
||||||
def delete_events(ref_type, ref_name):
|
def delete_events(ref_type, ref_name):
|
||||||
events = frappe.db.sql_list(""" SELECT
|
events = frappe.db.sql_list(""" SELECT
|
||||||
|
|||||||
Reference in New Issue
Block a user