Merge branch 'develop' into email-digest
This commit is contained in:
commit
f52f2b2f17
@ -293,6 +293,11 @@ def validate_accounts(file_name):
|
||||
accounts_dict = {}
|
||||
for account in accounts:
|
||||
accounts_dict.setdefault(account["account_name"], account)
|
||||
if not hasattr(account, "parent_account"):
|
||||
msg = _("Please make sure the file you are using has 'Parent Account' column present in the header.")
|
||||
msg += "<br><br>"
|
||||
msg += _("Alternatively, you can download the template and fill your data in.")
|
||||
frappe.throw(msg, title=_("Parent Account Missing"))
|
||||
if account["parent_account"] and accounts_dict.get(account["parent_account"]):
|
||||
accounts_dict[account["parent_account"]]["is_group"] = 1
|
||||
|
||||
|
@ -260,7 +260,10 @@ doc_events = {
|
||||
"erpnext.regional.italy.utils.sales_invoice_on_cancel",
|
||||
"erpnext.erpnext_integrations.taxjar_integration.delete_transaction"
|
||||
],
|
||||
"on_trash": "erpnext.regional.check_deletion_permission"
|
||||
"on_trash": "erpnext.regional.check_deletion_permission",
|
||||
"validate": [
|
||||
"erpnext.regional.india.utils.validate_document_name"
|
||||
]
|
||||
},
|
||||
"Purchase Invoice": {
|
||||
"validate": [
|
||||
@ -282,9 +285,6 @@ doc_events = {
|
||||
('Sales Invoice', 'Sales Order', 'Delivery Note', 'Purchase Invoice', 'Purchase Order', 'Purchase Receipt'): {
|
||||
'validate': ['erpnext.regional.india.utils.set_place_of_supply']
|
||||
},
|
||||
('Sales Invoice', 'Purchase Invoice'): {
|
||||
'validate': ['erpnext.regional.india.utils.validate_document_name']
|
||||
},
|
||||
"Contact": {
|
||||
"on_trash": "erpnext.support.doctype.issue.issue.update_issue",
|
||||
"after_insert": "erpnext.telephony.doctype.call_log.call_log.link_existing_conversations",
|
||||
|
@ -15,6 +15,7 @@
|
||||
"hide_custom": 0,
|
||||
"icon": "hr",
|
||||
"idx": 0,
|
||||
"is_default": 0,
|
||||
"is_standard": 1,
|
||||
"label": "HR",
|
||||
"links": [
|
||||
@ -226,42 +227,12 @@
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Application",
|
||||
"link_to": "Leave Application",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Allocation",
|
||||
"link_to": "Leave Allocation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Leave Type",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Policy",
|
||||
"link_to": "Leave Policy",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Period",
|
||||
"link_to": "Leave Period",
|
||||
"label": "Holiday List",
|
||||
"link_to": "Holiday List",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
@ -280,8 +251,28 @@
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Holiday List",
|
||||
"link_to": "Holiday List",
|
||||
"label": "Leave Period",
|
||||
"link_to": "Leave Period",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Leave Type",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Policy",
|
||||
"link_to": "Leave Policy",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Leave Policy",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Policy Assignment",
|
||||
"link_to": "Leave Policy Assignment",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
@ -290,8 +281,18 @@
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Compensatory Leave Request",
|
||||
"link_to": "Compensatory Leave Request",
|
||||
"label": "Leave Application",
|
||||
"link_to": "Leave Application",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Leave Allocation",
|
||||
"link_to": "Leave Allocation",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
@ -317,12 +318,12 @@
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Leave Application",
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Leave Balance",
|
||||
"link_to": "Employee Leave Balance",
|
||||
"link_type": "Report",
|
||||
"is_query_report": 0,
|
||||
"label": "Compensatory Leave Request",
|
||||
"link_to": "Compensatory Leave Request",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
@ -383,16 +384,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Attendance",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Monthly Attendance Sheet",
|
||||
"link_to": "Monthly Attendance Sheet",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -420,6 +411,15 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Travel Request",
|
||||
"link_to": "Travel Request",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -464,6 +464,15 @@
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Driver",
|
||||
"link_to": "Driver",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "",
|
||||
"hidden": 0,
|
||||
@ -541,6 +550,24 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Appointment Letter",
|
||||
"link_to": "Appointment Letter",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Appointment Letter Template",
|
||||
"link_to": "Appointment Letter Template",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -625,33 +652,6 @@
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Reports",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Birthday",
|
||||
"link_to": "Employee Birthday",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employees working on a holiday",
|
||||
"link_to": "Employees working on a holiday",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
@ -702,7 +702,74 @@
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Tax and Benefits",
|
||||
"label": "Key Reports",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
{
|
||||
"dependencies": "Attendance",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Monthly Attendance Sheet",
|
||||
"link_to": "Monthly Attendance Sheet",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Staffing Plan",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Recruitment Analytics",
|
||||
"link_to": "Recruitment Analytics",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Analytics",
|
||||
"link_to": "Employee Analytics",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Leave Balance",
|
||||
"link_to": "Employee Leave Balance",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Leave Balance Summary",
|
||||
"link_to": "Employee Leave Balance Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee Advance",
|
||||
"hidden": 0,
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Advance Summary",
|
||||
"link_to": "Employee Advance Summary",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Other Reports",
|
||||
"onboard": 0,
|
||||
"type": "Card Break"
|
||||
},
|
||||
@ -710,74 +777,44 @@
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Tax Exemption Declaration",
|
||||
"link_to": "Employee Tax Exemption Declaration",
|
||||
"link_type": "DocType",
|
||||
"label": "Employee Information",
|
||||
"link_to": "Employee Information",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Tax Exemption Proof Submission",
|
||||
"link_to": "Employee Tax Exemption Proof Submission",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee, Payroll Period",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Other Income",
|
||||
"link_to": "Employee Other Income",
|
||||
"link_type": "DocType",
|
||||
"is_query_report": 1,
|
||||
"label": "Employee Birthday",
|
||||
"link_to": "Employee Birthday",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Benefit Application",
|
||||
"link_to": "Employee Benefit Application",
|
||||
"link_type": "DocType",
|
||||
"is_query_report": 1,
|
||||
"label": "Employees Working on a Holiday",
|
||||
"link_to": "Employees working on a holiday",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"dependencies": "Daily Work Summary",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Benefit Claim",
|
||||
"link_to": "Employee Benefit Claim",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Tax Exemption Category",
|
||||
"link_to": "Employee Tax Exemption Category",
|
||||
"link_type": "DocType",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Employee",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Employee Tax Exemption Sub Category",
|
||||
"link_to": "Employee Tax Exemption Sub Category",
|
||||
"link_type": "DocType",
|
||||
"is_query_report": 1,
|
||||
"label": "Daily Work Summary Replies",
|
||||
"link_to": "Daily Work Summary Replies",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2021-01-21 13:38:38.941001",
|
||||
"modified": "2021-03-24 17:35:21.483297",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "HR",
|
||||
|
@ -5,7 +5,7 @@
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import frappe
|
||||
from frappe.utils import cstr
|
||||
from frappe.utils import cstr, flt
|
||||
from frappe.test_runner import make_test_records
|
||||
from erpnext.stock.doctype.stock_reconciliation.test_stock_reconciliation import create_stock_reconciliation
|
||||
from erpnext.manufacturing.doctype.bom_update_tool.bom_update_tool import update_cost
|
||||
@ -81,15 +81,27 @@ class TestBOM(unittest.TestCase):
|
||||
bom = frappe.copy_doc(test_records[2])
|
||||
bom.insert()
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.operating_cost, 100)
|
||||
self.assertEqual(bom.raw_material_cost, 351.68)
|
||||
self.assertEqual(bom.total_cost, 451.68)
|
||||
raw_material_cost = 0.0
|
||||
op_cost = 0.0
|
||||
|
||||
for op_row in bom.operations:
|
||||
op_cost += op_row.operating_cost
|
||||
|
||||
for row in bom.items:
|
||||
raw_material_cost += row.amount
|
||||
|
||||
base_raw_material_cost = raw_material_cost * flt(bom.conversion_rate, bom.precision("conversion_rate"))
|
||||
base_op_cost = op_cost * flt(bom.conversion_rate, bom.precision("conversion_rate"))
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.base_operating_cost, 6000)
|
||||
self.assertEqual(bom.base_raw_material_cost, 21100.80)
|
||||
self.assertEqual(bom.base_total_cost, 27100.80)
|
||||
self.assertEqual(bom.operating_cost, op_cost)
|
||||
self.assertEqual(bom.raw_material_cost, raw_material_cost)
|
||||
self.assertEqual(bom.total_cost, raw_material_cost + op_cost)
|
||||
|
||||
# test amounts in selected currency
|
||||
self.assertEqual(bom.base_operating_cost, base_op_cost)
|
||||
self.assertEqual(bom.base_raw_material_cost, base_raw_material_cost)
|
||||
self.assertEqual(bom.base_total_cost, base_raw_material_cost + base_op_cost)
|
||||
|
||||
def test_bom_cost_multi_uom_multi_currency_based_on_price_list(self):
|
||||
frappe.db.set_value("Price List", "_Test Price List", "price_not_uom_dependent", 1)
|
||||
|
@ -47,6 +47,8 @@ class JobCard(Document):
|
||||
if d.completed_qty:
|
||||
self.total_completed_qty += d.completed_qty
|
||||
|
||||
self.total_completed_qty = flt(self.total_completed_qty, self.precision("total_completed_qty"))
|
||||
|
||||
def get_overlap_for(self, args, check_next_available_slot=False):
|
||||
production_capacity = 1
|
||||
|
||||
|
@ -33,12 +33,16 @@ class TestProject(unittest.TestCase):
|
||||
|
||||
def test_project_template_having_parent_child_tasks(self):
|
||||
project_name = "Test Project with Template - Tasks with Parent-Child Relation"
|
||||
|
||||
if frappe.db.get_value('Project', {'project_name': project_name}, 'name'):
|
||||
project_name = frappe.db.get_value('Project', {'project_name': project_name}, 'name')
|
||||
|
||||
frappe.db.sql(""" delete from tabTask where project = %s """, project_name)
|
||||
frappe.delete_doc('Project', project_name)
|
||||
|
||||
task1 = task_exists("Test Template Task Parent")
|
||||
if not task1:
|
||||
task1 = create_task(subject="Test Template Task Parent", is_group=1, is_template=1, begin=1, duration=4)
|
||||
task1 = create_task(subject="Test Template Task Parent", is_group=1, is_template=1, begin=1, duration=10)
|
||||
|
||||
task2 = task_exists("Test Template Task Child 1")
|
||||
if not task2:
|
||||
@ -53,7 +57,7 @@ class TestProject(unittest.TestCase):
|
||||
tasks = frappe.get_all('Task', ['subject','exp_end_date','depends_on_tasks', 'name', 'parent_task'], dict(project=project.name), order_by='creation asc')
|
||||
|
||||
self.assertEqual(tasks[0].subject, 'Test Template Task Parent')
|
||||
self.assertEqual(getdate(tasks[0].exp_end_date), calculate_end_date(project, 1, 4))
|
||||
self.assertEqual(getdate(tasks[0].exp_end_date), calculate_end_date(project, 1, 10))
|
||||
|
||||
self.assertEqual(tasks[1].subject, 'Test Template Task Child 1')
|
||||
self.assertEqual(getdate(tasks[1].exp_end_date), calculate_end_date(project, 1, 3))
|
||||
|
@ -737,26 +737,32 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
this.frm.trigger("item_code", cdt, cdn);
|
||||
}
|
||||
else {
|
||||
var valid_serial_nos = [];
|
||||
var serialnos = [];
|
||||
// Replacing all occurences of comma with carriage return
|
||||
item.serial_no = item.serial_no.replace(/,/g, '\n');
|
||||
item.conversion_factor = item.conversion_factor || 1;
|
||||
refresh_field("serial_no", item.name, item.parentfield);
|
||||
if (!doc.is_return && cint(frappe.user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
|
||||
setTimeout(() => {
|
||||
me.update_qty(cdt, cdn);
|
||||
}, 10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
update_qty: function(cdt, cdn) {
|
||||
var valid_serial_nos = [];
|
||||
var serialnos = [];
|
||||
var item = frappe.get_doc(cdt, cdn);
|
||||
serialnos = item.serial_no.split("\n");
|
||||
for (var i = 0; i < serialnos.length; i++) {
|
||||
if (serialnos[i] != "") {
|
||||
valid_serial_nos.push(serialnos[i]);
|
||||
}
|
||||
}
|
||||
item.conversion_factor = item.conversion_factor || 1;
|
||||
|
||||
refresh_field("serial_no", item.name, item.parentfield);
|
||||
if(!doc.is_return && cint(user_defaults.set_qty_in_transactions_based_on_serial_no_input)) {
|
||||
frappe.model.set_value(item.doctype, item.name,
|
||||
"qty", valid_serial_nos.length / item.conversion_factor);
|
||||
frappe.model.set_value(item.doctype, item.name, "stock_qty", valid_serial_nos.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
|
@ -787,6 +787,8 @@ class GSPConnector():
|
||||
|
||||
self.invoice.irn = res.get('Irn')
|
||||
self.invoice.ewaybill = res.get('EwbNo')
|
||||
self.invoice.ack_no = res.get('AckNo')
|
||||
self.invoice.ack_date = res.get('AckDt')
|
||||
self.invoice.signed_einvoice = dec_signed_invoice
|
||||
self.invoice.signed_qr_code = res.get('SignedQRCode')
|
||||
|
||||
|
@ -17,7 +17,7 @@ frappe.ui.form.on('Global Defaults', {
|
||||
method: "frappe.client.get_list",
|
||||
args: {
|
||||
doctype: "UOM Conversion Factor",
|
||||
filters: { "category": "Length" },
|
||||
filters: { "category": __("Length") },
|
||||
fields: ["to_uom"],
|
||||
limit_page_length: 500
|
||||
},
|
||||
|
@ -17,19 +17,22 @@ erpnext.stock.ItemDashboard = Class.extend({
|
||||
this.result = this.content.find('.result');
|
||||
|
||||
this.content.on('click', '.btn-move', function () {
|
||||
handle_move_add($(this), "Move")
|
||||
handle_move_add($(this), "Move");
|
||||
});
|
||||
|
||||
this.content.on('click', '.btn-add', function () {
|
||||
handle_move_add($(this), "Add")
|
||||
handle_move_add($(this), "Add");
|
||||
});
|
||||
|
||||
this.content.on('click', '.btn-edit', function () {
|
||||
let item = unescape($(this).attr('data-item'));
|
||||
let warehouse = unescape($(this).attr('data-warehouse'));
|
||||
let company = unescape($(this).attr('data-company'));
|
||||
frappe.db.get_value('Putaway Rule',
|
||||
{'item_code': item, 'warehouse': warehouse, 'company': company}, 'name', (r) => {
|
||||
frappe.db.get_value('Putaway Rule', {
|
||||
'item_code': item,
|
||||
'warehouse': warehouse,
|
||||
'company': company
|
||||
}, 'name', (r) => {
|
||||
frappe.set_route("Form", "Putaway Rule", r.name);
|
||||
});
|
||||
});
|
||||
@ -46,10 +49,13 @@ erpnext.stock.ItemDashboard = Class.extend({
|
||||
} else {
|
||||
if (action === "Add") {
|
||||
let rate = unescape($(this).attr('data-rate'));
|
||||
erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function() { me.refresh(); });
|
||||
}
|
||||
else {
|
||||
erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function() { me.refresh(); });
|
||||
erpnext.stock.move_item(item, null, warehouse, actual_qty, rate, function () {
|
||||
me.refresh();
|
||||
});
|
||||
} else {
|
||||
erpnext.stock.move_item(item, warehouse, null, actual_qty, null, function () {
|
||||
me.refresh();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -64,7 +70,7 @@ erpnext.stock.ItemDashboard = Class.extend({
|
||||
row.s_warehouse = warehouse;
|
||||
|
||||
frappe.set_route('Form', doc.doctype, doc.name);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
// more
|
||||
@ -188,18 +194,42 @@ erpnext.stock.ItemDashboard = Class.extend({
|
||||
erpnext.stock.move_item = function (item, source, target, actual_qty, rate, callback) {
|
||||
var dialog = new frappe.ui.Dialog({
|
||||
title: target ? __('Add Item') : __('Move Item'),
|
||||
fields: [
|
||||
{fieldname: 'item_code', label: __('Item'),
|
||||
fieldtype: 'Link', options: 'Item', read_only: 1},
|
||||
{fieldname: 'source', label: __('Source Warehouse'),
|
||||
fieldtype: 'Link', options: 'Warehouse', read_only: 1},
|
||||
{fieldname: 'target', label: __('Target Warehouse'),
|
||||
fieldtype: 'Link', options: 'Warehouse', reqd: 1},
|
||||
{fieldname: 'qty', label: __('Quantity'), reqd: 1,
|
||||
fieldtype: 'Float', description: __('Available {0}', [actual_qty]) },
|
||||
{fieldname: 'rate', label: __('Rate'), fieldtype: 'Currency', hidden: 1 },
|
||||
fields: [{
|
||||
fieldname: 'item_code',
|
||||
label: __('Item'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Item',
|
||||
read_only: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'source',
|
||||
label: __('Source Warehouse'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Warehouse',
|
||||
read_only: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'target',
|
||||
label: __('Target Warehouse'),
|
||||
fieldtype: 'Link',
|
||||
options: 'Warehouse',
|
||||
reqd: 1
|
||||
},
|
||||
{
|
||||
fieldname: 'qty',
|
||||
label: __('Quantity'),
|
||||
reqd: 1,
|
||||
fieldtype: 'Float',
|
||||
description: __('Available {0}', [actual_qty])
|
||||
},
|
||||
{
|
||||
fieldname: 'rate',
|
||||
label: __('Rate'),
|
||||
fieldtype: 'Currency',
|
||||
hidden: 1
|
||||
},
|
||||
],
|
||||
})
|
||||
});
|
||||
dialog.show();
|
||||
dialog.get_field('item_code').set_input(item);
|
||||
|
||||
@ -248,8 +278,8 @@ erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callb
|
||||
});
|
||||
});
|
||||
|
||||
$('<p style="margin-left: 10px;"><a class="link-open text-muted small">'
|
||||
+ __("Add more items or open full form") + '</a></p>')
|
||||
$('<p style="margin-left: 10px;"><a class="link-open text-muted small">' +
|
||||
__("Add more items or open full form") + '</a></p>')
|
||||
.appendTo(dialog.body)
|
||||
.find('.link-open')
|
||||
.on('click', function () {
|
||||
@ -266,6 +296,6 @@ erpnext.stock.move_item = function(item, source, target, actual_qty, rate, callb
|
||||
row.transfer_qty = dialog.get_value('qty');
|
||||
row.basic_rate = dialog.get_value('rate');
|
||||
frappe.set_route('Form', doc.doctype, doc.name);
|
||||
})
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -2,6 +2,7 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
from frappe.model.db_query import DatabaseQuery
|
||||
from frappe.utils import flt, cint
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_data(item_code=None, warehouse=None, item_group=None,
|
||||
@ -42,11 +43,20 @@ def get_data(item_code=None, warehouse=None, item_group=None,
|
||||
limit_start=start,
|
||||
limit_page_length='21')
|
||||
|
||||
precision = cint(frappe.db.get_single_value("System Settings", "float_precision"))
|
||||
|
||||
for item in items:
|
||||
item.update({
|
||||
'item_name': frappe.get_cached_value("Item", item.item_code, 'item_name'),
|
||||
'disable_quick_entry': frappe.get_cached_value("Item", item.item_code, 'has_batch_no')
|
||||
or frappe.get_cached_value("Item", item.item_code, 'has_serial_no'),
|
||||
'item_name': frappe.get_cached_value(
|
||||
"Item", item.item_code, 'item_name'),
|
||||
'disable_quick_entry': frappe.get_cached_value(
|
||||
"Item", item.item_code, 'has_batch_no')
|
||||
or frappe.get_cached_value(
|
||||
"Item", item.item_code, 'has_serial_no'),
|
||||
'projected_qty': flt(item.projected_qty, precision),
|
||||
'reserved_qty': flt(item.reserved_qty, precision),
|
||||
'reserved_qty_for_production': flt(item.reserved_qty_for_production, precision),
|
||||
'reserved_qty_for_sub_contract': flt(item.reserved_qty_for_sub_contract, precision),
|
||||
'actual_qty': flt(item.actual_qty, precision),
|
||||
})
|
||||
|
||||
return items
|
||||
|
@ -494,7 +494,8 @@ 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, is_customer_provided_item=None, customer=None, is_purchase_item=None, opening_stock=None):
|
||||
def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None, is_customer_provided_item=None,
|
||||
customer=None, is_purchase_item=None, opening_stock=None, company=None):
|
||||
if not frappe.db.exists("Item", item_code):
|
||||
item = frappe.new_doc("Item")
|
||||
item.item_code = item_code
|
||||
@ -509,7 +510,7 @@ def create_item(item_code, is_stock_item=None, valuation_rate=0, warehouse=None,
|
||||
item.customer = customer or ''
|
||||
item.append("item_defaults", {
|
||||
"default_warehouse": warehouse or '_Test Warehouse - _TC',
|
||||
"company": "_Test Company"
|
||||
"company": company or "_Test Company"
|
||||
})
|
||||
item.save()
|
||||
else:
|
||||
|
@ -346,7 +346,7 @@ def create_delivery_note(source_name, target_doc=None):
|
||||
|
||||
if dn_item:
|
||||
dn_item.warehouse = location.warehouse
|
||||
dn_item.qty = location.picked_qty
|
||||
dn_item.qty = flt(location.picked_qty) / (flt(location.conversion_factor) or 1)
|
||||
dn_item.batch_no = location.batch_no
|
||||
dn_item.serial_no = location.serial_no
|
||||
|
||||
|
@ -9,6 +9,7 @@ test_dependencies = ['Item', 'Sales Invoice', 'Stock Entry', 'Batch']
|
||||
|
||||
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import make_purchase_receipt
|
||||
from erpnext.stock.doctype.item.test_item import create_item
|
||||
from erpnext.stock.doctype.pick_list.pick_list import create_delivery_note
|
||||
from erpnext.stock.doctype.stock_reconciliation.stock_reconciliation \
|
||||
import EmptyStockReconciliationItemsError
|
||||
|
||||
@ -291,6 +292,61 @@ class TestPickList(unittest.TestCase):
|
||||
self.assertEqual(pick_list.locations[1].qty, 5)
|
||||
self.assertEqual(pick_list.locations[1].sales_order_item, sales_order.items[0].name)
|
||||
|
||||
def test_pick_list_for_items_with_multiple_UOM(self):
|
||||
purchase_receipt = make_purchase_receipt(item_code="_Test Item", qty=10)
|
||||
purchase_receipt.submit()
|
||||
|
||||
sales_order = frappe.get_doc({
|
||||
'doctype': 'Sales Order',
|
||||
'customer': '_Test Customer',
|
||||
'company': '_Test Company',
|
||||
'items': [{
|
||||
'item_code': '_Test Item',
|
||||
'qty': 1,
|
||||
'conversion_factor': 5,
|
||||
'delivery_date': frappe.utils.today()
|
||||
}, {
|
||||
'item_code': '_Test Item',
|
||||
'qty': 1,
|
||||
'conversion_factor': 1,
|
||||
'delivery_date': frappe.utils.today()
|
||||
}],
|
||||
}).insert()
|
||||
sales_order.submit()
|
||||
|
||||
pick_list = frappe.get_doc({
|
||||
'doctype': 'Pick List',
|
||||
'company': '_Test Company',
|
||||
'customer': '_Test Customer',
|
||||
'items_based_on': 'Sales Order',
|
||||
'locations': [{
|
||||
'item_code': '_Test Item',
|
||||
'qty': 1,
|
||||
'stock_qty': 5,
|
||||
'conversion_factor': 5,
|
||||
'sales_order': sales_order.name,
|
||||
'sales_order_item': sales_order.items[0].name ,
|
||||
}, {
|
||||
'item_code': '_Test Item',
|
||||
'qty': 1,
|
||||
'stock_qty': 1,
|
||||
'conversion_factor': 1,
|
||||
'sales_order': sales_order.name,
|
||||
'sales_order_item': sales_order.items[1].name ,
|
||||
}]
|
||||
})
|
||||
pick_list.set_item_locations()
|
||||
pick_list.submit()
|
||||
|
||||
delivery_note = create_delivery_note(pick_list.name)
|
||||
|
||||
self.assertEqual(pick_list.locations[0].qty, delivery_note.items[0].qty)
|
||||
self.assertEqual(pick_list.locations[1].qty, delivery_note.items[1].qty)
|
||||
self.assertEqual(sales_order.items[0].conversion_factor, delivery_note.items[0].conversion_factor)
|
||||
|
||||
pick_list.cancel()
|
||||
sales_order.cancel()
|
||||
purchase_receipt.cancel()
|
||||
|
||||
# def test_pick_list_skips_items_in_expired_batch(self):
|
||||
# pass
|
||||
|
@ -179,11 +179,15 @@ class TestStockEntry(unittest.TestCase):
|
||||
def test_material_transfer_gl_entry(self):
|
||||
company = frappe.db.get_value('Warehouse', 'Stores - TCP1', 'company')
|
||||
|
||||
mtn = make_stock_entry(item_code="_Test Item", source="Stores - TCP1",
|
||||
item_code = 'Hand Sanitizer - 001'
|
||||
create_item(item_code =item_code, is_stock_item = 1,
|
||||
is_purchase_item=1, opening_stock=1000, valuation_rate=10, company=company, warehouse="Stores - TCP1")
|
||||
|
||||
mtn = make_stock_entry(item_code=item_code, source="Stores - TCP1",
|
||||
target="Finished Goods - TCP1", qty=45, company=company)
|
||||
|
||||
self.check_stock_ledger_entries("Stock Entry", mtn.name,
|
||||
[["_Test Item", "Stores - TCP1", -45.0], ["_Test Item", "Finished Goods - TCP1", 45.0]])
|
||||
[[item_code, "Stores - TCP1", -45.0], [item_code, "Finished Goods - TCP1", 45.0]])
|
||||
|
||||
source_warehouse_account = get_inventory_account(mtn.company, mtn.get("items")[0].s_warehouse)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user