Merge branch 'hotfix'
This commit is contained in:
commit
4d185f3541
@ -4,7 +4,7 @@ import inspect
|
||||
import frappe
|
||||
from erpnext.hooks import regional_overrides
|
||||
|
||||
__version__ = '8.6.4'
|
||||
__version__ = '8.6.5'
|
||||
|
||||
def get_default_company(user=None):
|
||||
'''Get default company for user'''
|
||||
|
@ -721,38 +721,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "tc_name",
|
||||
"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": "Terms and Conditions",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "tc_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Terms and Conditions",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -782,39 +750,6 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Territory",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "territory",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -847,6 +782,38 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "tc_name",
|
||||
"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": "Terms and Conditions",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "tc_name",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Terms and Conditions",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -910,6 +877,129 @@
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "customer_details",
|
||||
"fieldtype": "Section Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "New Customer Details",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "",
|
||||
"fieldname": "territory",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Territory",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "territory",
|
||||
"oldfieldtype": "Link",
|
||||
"options": "Territory",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_31",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "customer_group",
|
||||
"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": "Customer Group",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer Group",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
@ -1201,7 +1291,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-06-16 17:04:33.165676",
|
||||
"modified": "2017-07-28 03:40:03.253088",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Profile",
|
||||
|
@ -14,6 +14,7 @@ class POSProfile(Document):
|
||||
self.check_for_duplicate()
|
||||
self.validate_all_link_fields()
|
||||
self.validate_duplicate_groups()
|
||||
self.validate_customer_territory_group()
|
||||
|
||||
def check_for_duplicate(self):
|
||||
res = frappe.db.sql("""select name, user from `tabPOS Profile`
|
||||
@ -48,6 +49,13 @@ class POSProfile(Document):
|
||||
if len(customer_groups) != len(set(customer_groups)):
|
||||
frappe.throw(_("Duplicate customer group found in the cutomer group table"), title = "Duplicate Customer Group")
|
||||
|
||||
def validate_customer_territory_group(self):
|
||||
if not self.territory:
|
||||
frappe.throw(_("Territory is Required in POS Profile"), title="Mandatory Field")
|
||||
|
||||
if not self.customer_group:
|
||||
frappe.throw(_("Customer Group is Required in POS Profile"), title="Mandatory Field")
|
||||
|
||||
def before_save(self):
|
||||
set_account_for_mode_of_payment(self)
|
||||
|
||||
|
23
erpnext/accounts/doctype/pos_profile/test_pos_profile.js
Normal file
23
erpnext/accounts/doctype/pos_profile/test_pos_profile.js
Normal file
@ -0,0 +1,23 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: POS Profile", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially('POS Profile', [
|
||||
// insert a new POS Profile
|
||||
() => frappe.tests.make([
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -42,6 +42,7 @@ def make_pos_profile():
|
||||
"naming_series": "_T-POS Profile-",
|
||||
"selling_price_list": "_Test Price List",
|
||||
"territory": "_Test Territory",
|
||||
"customer_group": frappe.db.get_value('Customer Group', {'is_group': 0}, 'name'),
|
||||
"warehouse": "_Test Warehouse - _TC",
|
||||
"write_off_account": "_Test Write Off - _TC",
|
||||
"write_off_cost_center": "_Test Write Off Cost Center - _TC"
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe, json
|
||||
from frappe import _
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.setup.utils import get_exchange_rate
|
||||
from frappe.core.doctype.communication.email import make
|
||||
@ -20,6 +21,7 @@ def get_pos_data():
|
||||
|
||||
if pos_profile.get('name'):
|
||||
pos_profile = frappe.get_doc('POS Profile', pos_profile.get('name'))
|
||||
pos_profile.validate()
|
||||
|
||||
company_data = get_company_data(doc.company)
|
||||
update_pos_profile_data(doc, pos_profile, company_data)
|
||||
@ -378,13 +380,27 @@ def add_customer(data):
|
||||
customer_doc.customer_name = data.get('full_name') or data.get('customer')
|
||||
customer_doc.customer_pos_id = data.get('customer_pos_id')
|
||||
customer_doc.customer_type = 'Company'
|
||||
customer_doc.customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
|
||||
customer_doc.territory = frappe.db.get_single_value('Selling Settings', 'territory')
|
||||
customer_doc.customer_group = get_customer_group(data)
|
||||
customer_doc.territory = get_territory(data)
|
||||
customer_doc.flags.ignore_mandatory = True
|
||||
customer_doc.save(ignore_permissions = True)
|
||||
frappe.db.commit()
|
||||
return customer_doc.name
|
||||
|
||||
def get_territory(data):
|
||||
if data.get('territory'):
|
||||
return data.get('territory')
|
||||
|
||||
return frappe.db.get_single_value('Selling Settings',
|
||||
'territory') or _('All Territories')
|
||||
|
||||
def get_customer_group(data):
|
||||
if data.get('customer_group'):
|
||||
return data.get('customer_group')
|
||||
|
||||
return frappe.db.get_single_value('Selling Settings',
|
||||
'customer_group') or frappe.db.get_value('Customer Group', {'is_group': 0}, 'name')
|
||||
|
||||
def make_contact(args,customer):
|
||||
if args.get('email_id') or args.get('phone'):
|
||||
name = frappe.db.get_value('Dynamic Link',
|
||||
|
@ -979,6 +979,8 @@ erpnext.pos.PointOfSale = erpnext.taxes_and_totals.extend({
|
||||
get_prompt_details: function() {
|
||||
this.prompt_details = this.customer_doc.get_values();
|
||||
this.prompt_details['country'] = this.pos_profile_data.country;
|
||||
this.prompt_details['territory'] = this.pos_profile_data["territory"];
|
||||
this.prompt_details['customer_group'] = this.pos_profile_data["customer_group"];
|
||||
this.prompt_details['customer_pos_id'] = this.customer_doc.fields_dict.customer_pos_id.value;
|
||||
return JSON.stringify(this.prompt_details)
|
||||
},
|
||||
|
@ -273,6 +273,7 @@ def get_due_date(posting_date, party_type, party, company):
|
||||
return due_date
|
||||
|
||||
def get_credit_days(party_type, party, company):
|
||||
credit_days = 0
|
||||
if party_type and party:
|
||||
if party_type == "Customer":
|
||||
credit_days_based_on, credit_days, customer_group = \
|
||||
@ -282,10 +283,10 @@ def get_credit_days(party_type, party, company):
|
||||
frappe.db.get_value(party_type, party, ["credit_days_based_on", "credit_days", "supplier_type"])
|
||||
|
||||
if not credit_days_based_on:
|
||||
if party_type == "Customer":
|
||||
if party_type == "Customer" and customer_group:
|
||||
credit_days_based_on, credit_days = \
|
||||
frappe.db.get_value("Customer Group", customer_group, ["credit_days_based_on", "credit_days"])
|
||||
else:
|
||||
elif party_type == "Supplier" and supplier_type:
|
||||
credit_days_based_on, credit_days = \
|
||||
frappe.db.get_value("Supplier Type", supplier_type, ["credit_days_based_on", "credit_days"])
|
||||
|
||||
|
@ -27,8 +27,7 @@ def test_recurring_document(obj, test_records):
|
||||
base_doc.set(date_field, today)
|
||||
|
||||
if base_doc.doctype == "Sales Order":
|
||||
for d in base_doc.get("items"):
|
||||
d.set("delivery_date", add_days(today, 15))
|
||||
base_doc.set("delivery_date", add_days(today, 15))
|
||||
|
||||
# monthly
|
||||
doc1 = frappe.copy_doc(base_doc)
|
||||
|
@ -118,8 +118,7 @@ def make_sales_order():
|
||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||
so = frappe.get_doc(make_sales_order(q))
|
||||
so.transaction_date = frappe.flags.current_date
|
||||
for d in so.get("items"):
|
||||
d.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
|
||||
so.delivery_date = frappe.utils.add_days(frappe.flags.current_date, 10)
|
||||
so.insert()
|
||||
frappe.db.commit()
|
||||
so.submit()
|
||||
|
@ -273,7 +273,7 @@ class ProductionOrder(Document):
|
||||
timesheets = []
|
||||
plan_days = frappe.db.get_single_value("Manufacturing Settings", "capacity_planning_for_days") or 30
|
||||
|
||||
timesheet = make_timesheet(self.name)
|
||||
timesheet = make_timesheet(self.name, self.company)
|
||||
timesheet.set('time_logs', [])
|
||||
|
||||
for i, d in enumerate(self.operations):
|
||||
@ -575,10 +575,11 @@ def get_events(start, end, filters=None):
|
||||
return data
|
||||
|
||||
@frappe.whitelist()
|
||||
def make_timesheet(production_order):
|
||||
def make_timesheet(production_order, company):
|
||||
timesheet = frappe.new_doc("Timesheet")
|
||||
timesheet.employee = ""
|
||||
timesheet.production_order = production_order
|
||||
timesheet.company = company
|
||||
return timesheet
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -87,6 +87,7 @@ class TestProductionOrder(unittest.TestCase):
|
||||
|
||||
name = frappe.db.get_value('Timesheet', {'production_order': prod_order.name}, 'name')
|
||||
time_sheet_doc = frappe.get_doc('Timesheet', name)
|
||||
self.assertEqual(prod_order.company, time_sheet_doc.company)
|
||||
time_sheet_doc.submit()
|
||||
|
||||
|
||||
@ -107,7 +108,7 @@ class TestProductionOrder(unittest.TestCase):
|
||||
self.assertEqual(prod_order.operations[0].actual_operation_time, 60)
|
||||
self.assertEqual(prod_order.operations[0].actual_operating_cost, 100)
|
||||
|
||||
time_sheet_doc1 = make_timesheet(prod_order.name)
|
||||
time_sheet_doc1 = make_timesheet(prod_order.name, prod_order.company)
|
||||
self.assertEqual(len(time_sheet_doc1.get('time_logs')), 0)
|
||||
|
||||
time_sheet_doc.cancel()
|
||||
|
@ -422,5 +422,7 @@ erpnext.patches.v8_1.add_indexes_in_transaction_doctypes
|
||||
erpnext.patches.v8_3.set_restrict_to_domain_for_module_def
|
||||
erpnext.patches.v8_1.update_expense_claim_status
|
||||
erpnext.patches.v8_3.update_company_total_sales
|
||||
erpnext.patches.v8_1.set_delivery_date_in_so_item
|
||||
erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
|
||||
erpnext.patches.v8_1.set_delivery_date_in_so_item #2017-07-28
|
||||
erpnext.patches.v8_5.fix_tax_breakup_for_non_invoice_docs
|
||||
erpnext.patches.v8_5.update_customer_group_in_POS_profile
|
||||
erpnext.patches.v8_6.update_timesheet_company_from_PO
|
@ -4,10 +4,18 @@ def execute():
|
||||
frappe.reload_doctype("Sales Order")
|
||||
frappe.reload_doctype("Sales Order Item")
|
||||
|
||||
frappe.db.sql("""update `tabSales Order` set final_delivery_date = delivery_date where docstatus=1""")
|
||||
if "final_delivery_date" in frappe.db.get_table_columns("Sales Order"):
|
||||
frappe.db.sql("""
|
||||
update `tabSales Order`
|
||||
set delivery_date = final_delivery_date
|
||||
where (delivery_date is null or delivery_date = '' or delivery_date = '0000-00-00')
|
||||
and order_type = 'Sales'""")
|
||||
|
||||
frappe.db.sql("""
|
||||
update `tabSales Order` so, `tabSales Order Item` so_item
|
||||
set so_item.delivery_date = so.delivery_date
|
||||
where so.name = so_item.parent
|
||||
and so.order_type = 'Sales'
|
||||
and (so_item.delivery_date is null or so_item.delivery_date = ''
|
||||
or so_item.delivery_date = '0000-00-00')
|
||||
""")
|
@ -0,0 +1,8 @@
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype('POS Profile')
|
||||
customer_group = frappe.db.get_single_value('Selling Settings', 'customer_group')
|
||||
if customer_group:
|
||||
frappe.db.sql(""" update `tabPOS Profile`
|
||||
set customer_group = %s where customer_group is null """, (customer_group))
|
0
erpnext/patches/v8_6/__init__.py
Normal file
0
erpnext/patches/v8_6/__init__.py
Normal file
15
erpnext/patches/v8_6/update_timesheet_company_from_PO.py
Normal file
15
erpnext/patches/v8_6/update_timesheet_company_from_PO.py
Normal file
@ -0,0 +1,15 @@
|
||||
# Copyright (c) 2017, Frappe and Contributors
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
|
||||
def execute():
|
||||
frappe.reload_doctype('Timesheet')
|
||||
company = frappe.get_all('Company')
|
||||
|
||||
#Check more than one company exists
|
||||
if len(company) > 1:
|
||||
frappe.db.sql(""" update `tabTimesheet` set `tabTimesheet`.company =
|
||||
(select company from `tabProduction Order` where name = `tabTimesheet`.production_order)
|
||||
where production_order is not null and production_order !=''""")
|
@ -14,8 +14,8 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
|
||||
|
||||
class TestTimesheet(unittest.TestCase):
|
||||
def test_timesheet_billing_amount(self):
|
||||
salary_structure = make_salary_structure("_T-Employee-0001")
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
|
||||
make_salary_structure("_T-Employee-0001")
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
|
||||
|
||||
self.assertEquals(timesheet.total_hours, 2)
|
||||
self.assertEquals(timesheet.total_billable_hours, 2)
|
||||
@ -23,6 +23,16 @@ class TestTimesheet(unittest.TestCase):
|
||||
self.assertEquals(timesheet.time_logs[0].billing_amount, 100)
|
||||
self.assertEquals(timesheet.total_billable_amount, 100)
|
||||
|
||||
def test_timesheet_billing_amount_not_billable(self):
|
||||
make_salary_structure("_T-Employee-0001")
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=0)
|
||||
|
||||
self.assertEquals(timesheet.total_hours, 2)
|
||||
self.assertEquals(timesheet.total_billable_hours, 0)
|
||||
self.assertEquals(timesheet.time_logs[0].billing_rate, 0)
|
||||
self.assertEquals(timesheet.time_logs[0].billing_amount, 0)
|
||||
self.assertEquals(timesheet.total_billable_amount, 0)
|
||||
|
||||
def test_salary_slip_from_timesheet(self):
|
||||
salary_structure = make_salary_structure("_T-Employee-0001")
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable=1)
|
||||
@ -43,7 +53,7 @@ class TestTimesheet(unittest.TestCase):
|
||||
self.assertEquals(timesheet.status, 'Submitted')
|
||||
|
||||
def test_sales_invoice_from_timesheet(self):
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate = True, billable = 1)
|
||||
timesheet = make_timesheet("_T-Employee-0001", simulate=True, billable=1)
|
||||
sales_invoice = make_sales_invoice(timesheet.name)
|
||||
sales_invoice.customer = "_Test Customer"
|
||||
sales_invoice.due_date = nowdate()
|
||||
|
@ -105,7 +105,9 @@ frappe.ui.form.on("Timesheet Detail", {
|
||||
},
|
||||
|
||||
billable: function(frm, cdt, cdn) {
|
||||
calculate_billing_costing_amount(frm, cdt, cdn)
|
||||
update_billing_hours(frm, cdt, cdn);
|
||||
update_time_rates(frm, cdt, cdn);
|
||||
calculate_billing_costing_amount(frm, cdt, cdn);
|
||||
},
|
||||
|
||||
activity_type: function(frm, cdt, cdn) {
|
||||
@ -148,8 +150,21 @@ var calculate_end_time = function(frm, cdt, cdn) {
|
||||
}
|
||||
}
|
||||
|
||||
var update_billing_hours = function(frm, cdt, cdn){
|
||||
var child = locals[cdt][cdn];
|
||||
if(!child.billable) frappe.model.set_value(cdt, cdn, 'billing_hours', 0.0);
|
||||
}
|
||||
|
||||
var update_time_rates = function(frm, cdt, cdn){
|
||||
var child = locals[cdt][cdn];
|
||||
if(!child.billable){
|
||||
frappe.model.set_value(cdt, cdn, 'billing_rate', 0.0);
|
||||
frappe.model.set_value(cdt, cdn, 'costing_rate', 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
var calculate_billing_costing_amount = function(frm, cdt, cdn){
|
||||
var child = locals[cdt][cdn]
|
||||
var child = locals[cdt][cdn];
|
||||
var billing_amount = 0.0;
|
||||
var costing_amount = 0.0;
|
||||
|
||||
@ -160,7 +175,7 @@ var calculate_billing_costing_amount = function(frm, cdt, cdn){
|
||||
|
||||
frappe.model.set_value(cdt, cdn, 'billing_amount', billing_amount);
|
||||
frappe.model.set_value(cdt, cdn, 'costing_amount', costing_amount);
|
||||
calculate_time_and_amount(frm)
|
||||
calculate_time_and_amount(frm);
|
||||
}
|
||||
|
||||
var calculate_time_and_amount = function(frm) {
|
||||
|
@ -46,6 +46,7 @@ class Timesheet(Document):
|
||||
|
||||
for d in self.get("time_logs"):
|
||||
self.update_billing_hours(d)
|
||||
self.update_time_rates(d)
|
||||
|
||||
self.total_hours += flt(d.hours)
|
||||
if d.billable:
|
||||
@ -61,8 +62,11 @@ class Timesheet(Document):
|
||||
self.per_billed = (self.total_billed_amount * 100) / self.total_billable_amount
|
||||
|
||||
def update_billing_hours(self, args):
|
||||
if cint(args.billing_hours) == 0:
|
||||
args.billing_hours = args.hours
|
||||
if args.billable:
|
||||
if flt(args.billing_hours) == 0.0:
|
||||
args.billing_hours = args.hours
|
||||
else:
|
||||
args.billing_hours = 0
|
||||
|
||||
def set_status(self):
|
||||
self.status = {
|
||||
@ -263,13 +267,19 @@ class Timesheet(Document):
|
||||
for data in self.time_logs:
|
||||
if data.activity_type and data.billable:
|
||||
rate = get_activity_cost(self.employee, data.activity_type)
|
||||
hours = data.billing_hours or 0
|
||||
hours = data.billing_hours or 0
|
||||
if rate:
|
||||
data.billing_rate = flt(rate.get('billing_rate')) if flt(data.billing_rate) == 0 else data.billing_rate
|
||||
data.costing_rate = flt(rate.get('costing_rate')) if flt(data.costing_rate) == 0 else data.costing_rate
|
||||
data.billing_amount = data.billing_rate * hours
|
||||
data.costing_amount = data.costing_rate * hours
|
||||
|
||||
def update_time_rates(self, ts_detail):
|
||||
if not ts_detail.billable:
|
||||
ts_detail.billing_rate = 0.0
|
||||
ts_detail.costing_rate = 0.0
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_projectwise_timesheet_data(project, parent=None):
|
||||
cond = ''
|
||||
|
@ -27,8 +27,7 @@ class TestQuotation(unittest.TestCase):
|
||||
self.assertEquals(sales_order.get("items")[0].prevdoc_docname, quotation.name)
|
||||
self.assertEquals(sales_order.customer, "_Test Customer")
|
||||
|
||||
for d in sales_order.get("items"):
|
||||
d.delivery_date = "2014-01-01"
|
||||
sales_order.delivery_date = "2014-01-01"
|
||||
sales_order.naming_series = "_T-Quotation-"
|
||||
sales_order.transaction_date = "2013-05-12"
|
||||
sales_order.insert()
|
||||
@ -54,8 +53,7 @@ class TestQuotation(unittest.TestCase):
|
||||
sales_order = make_sales_order(quotation.name)
|
||||
sales_order.naming_series = "_T-Quotation-"
|
||||
sales_order.transaction_date = "2016-01-01"
|
||||
for d in sales_order.get("items"):
|
||||
d.delivery_date = "2016-01-02"
|
||||
sales_order.delivery_date = "2016-01-02"
|
||||
|
||||
sales_order.insert()
|
||||
|
||||
|
@ -34,11 +34,20 @@ frappe.ui.form.on("Sales Order", {
|
||||
|
||||
erpnext.queries.setup_warehouse_query(frm);
|
||||
},
|
||||
|
||||
delivery_date: function(frm) {
|
||||
$.each(frm.doc.items || [], function(i, d) {
|
||||
if(!d.delivery_date) d.delivery_date = frm.doc.delivery_date;
|
||||
});
|
||||
refresh_field("items");
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.on("Sales Order Item", {
|
||||
delivery_date: function(frm, cdt, cdn) {
|
||||
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
|
||||
if(!frm.doc.delivery_date) {
|
||||
erpnext.utils.copy_value_in_all_row(frm.doc, cdt, cdn, "items", "delivery_date");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@ -416,8 +425,13 @@ erpnext.selling.SalesOrderController = erpnext.selling.SellingController.extend(
|
||||
|
||||
items_add: function(doc, cdt, cdn) {
|
||||
var row = frappe.get_doc(cdt, cdn);
|
||||
this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]);
|
||||
if(doc.delivery_date) {
|
||||
row.delivery_date = doc.delivery_date;
|
||||
refresh_field("delivery_date", cdn, "items");
|
||||
} else {
|
||||
this.frm.script_manager.copy_from_first_row("items", row, ["delivery_date"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
|
||||
$.extend(cur_frm.cscript, new erpnext.selling.SalesOrderController({frm: cur_frm}));
|
@ -367,23 +367,23 @@
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "final_delivery_date",
|
||||
"fieldname": "delivery_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 1,
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Final Delivery Date",
|
||||
"label": "Delivery Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
@ -3659,7 +3659,7 @@
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-07-25 13:45:02.965353",
|
||||
"modified": "2017-07-28 14:03:33.373347",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
@ -101,20 +101,20 @@ class SalesOrder(SellingController):
|
||||
super(SalesOrder, self).validate_order_type()
|
||||
|
||||
def validate_delivery_date(self):
|
||||
self.final_delivery_date = None
|
||||
if self.order_type == 'Sales':
|
||||
for d in self.get("items"):
|
||||
if not d.delivery_date:
|
||||
frappe.throw(_("Row #{0}: Please enter Delivery Date against item {1}")
|
||||
.format(d.idx, d.item_code))
|
||||
if not self.delivery_date:
|
||||
self.delivery_date = max([d.delivery_date for d in self.get("items")])
|
||||
|
||||
if getdate(self.transaction_date) > getdate(d.delivery_date):
|
||||
frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"),
|
||||
indicator='orange', title=_('Warning'))
|
||||
|
||||
if not self.final_delivery_date or \
|
||||
(d.delivery_date and getdate(d.delivery_date) > getdate(self.final_delivery_date)):
|
||||
self.final_delivery_date = d.delivery_date
|
||||
if self.delivery_date:
|
||||
for d in self.get("items"):
|
||||
if not d.delivery_date:
|
||||
d.delivery_date = self.delivery_date
|
||||
|
||||
if getdate(self.transaction_date) > getdate(d.delivery_date):
|
||||
frappe.msgprint(_("Expected Delivery Date should be after Sales Order Date"),
|
||||
indicator='orange', title=_('Warning'))
|
||||
else:
|
||||
frappe.throw(_("Please enter Delivery Date"))
|
||||
|
||||
self.validate_sales_mntc_quotation()
|
||||
|
||||
@ -347,6 +347,9 @@ class SalesOrder(SellingController):
|
||||
|
||||
def on_recurring(self, reference_doc):
|
||||
mcount = month_map[reference_doc.recurring_type]
|
||||
self.set("delivery_date", get_next_date(reference_doc.delivery_date, mcount,
|
||||
cint(reference_doc.repeat_on_day_of_month)))
|
||||
|
||||
for d in self.get("items"):
|
||||
reference_delivery_date = frappe.db.get_value("Sales Order Item",
|
||||
{"parent": reference_doc.name, "item_code": d.item_code, "idx": d.idx}, "delivery_date")
|
||||
|
@ -1,14 +1,14 @@
|
||||
frappe.listview_settings['Sales Order'] = {
|
||||
add_fields: ["base_grand_total", "customer_name", "currency", "final_delivery_date",
|
||||
add_fields: ["base_grand_total", "customer_name", "currency", "delivery_date",
|
||||
"per_delivered", "per_billed", "status", "order_type", "name"],
|
||||
get_indicator: function(doc) {
|
||||
if(doc.status==="Closed"){
|
||||
return [__("Closed"), "green", "status,=,Closed"];
|
||||
|
||||
} else if (doc.order_type !== "Maintenance"
|
||||
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.final_delivery_date) < 0) {
|
||||
&& flt(doc.per_delivered, 2) < 100 && frappe.datetime.get_diff(doc.delivery_date) < 0) {
|
||||
// to bill & overdue
|
||||
return [__("Overdue"), "red", "per_delivered,<,100|final_delivery_date,<,Today|status,!=,Closed"];
|
||||
return [__("Overdue"), "red", "per_delivered,<,100|delivery_date,<,Today|status,!=,Closed"];
|
||||
|
||||
} else if (doc.order_type !== "Maintenance"
|
||||
&& flt(doc.per_delivered, 2) < 100 && doc.status!=="Closed") {
|
||||
|
59
erpnext/selling/doctype/sales_order/test_sales_order.js
Normal file
59
erpnext/selling/doctype/sales_order/test_sales_order.js
Normal file
@ -0,0 +1,59 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Sales Order", function (assert) {
|
||||
assert.expect(2);
|
||||
let done = assert.async();
|
||||
let delivery_date = frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Sales Order
|
||||
() => {
|
||||
return frappe.tests.make('Sales Order', [
|
||||
{customer: "Test Customer 1"},
|
||||
{delivery_date: delivery_date},
|
||||
{order_type: 'Sales'},
|
||||
{items: [
|
||||
[
|
||||
{"item_code": "Test Product 1"},
|
||||
{"qty": 5},
|
||||
{'rate': 100},
|
||||
]]
|
||||
}
|
||||
])
|
||||
},
|
||||
() => {
|
||||
assert.ok(cur_frm.doc.items[0].delivery_date == delivery_date);
|
||||
},
|
||||
() => frappe.timeout(1),
|
||||
// make SO without delivery date in parent,
|
||||
// parent delivery date should be set based on final delivery date entered in item
|
||||
() => {
|
||||
return frappe.tests.make('Sales Order', [
|
||||
{customer: "Test Customer 1"},
|
||||
{order_type: 'Sales'},
|
||||
{items: [
|
||||
[
|
||||
{"item_code": "Test Product 1"},
|
||||
{"qty": 5},
|
||||
{'rate': 100},
|
||||
{'delivery_date': delivery_date}
|
||||
],
|
||||
[
|
||||
{"item_code": "Test Product 2"},
|
||||
{"qty": 5},
|
||||
{'rate': 100},
|
||||
{'delivery_date': frappe.datetime.add_days(delivery_date, 5)}
|
||||
]]
|
||||
}
|
||||
])
|
||||
},
|
||||
() => cur_frm.save(),
|
||||
() => frappe.timeout(1),
|
||||
() => {
|
||||
assert.ok(cur_frm.doc.delivery_date == frappe.datetime.add_days(delivery_date, 5));
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
});
|
@ -532,8 +532,7 @@ def make_sales_order(**args):
|
||||
"rate": args.rate or 100
|
||||
})
|
||||
|
||||
for d in so.get("items"):
|
||||
d.delivery_date = add_days(so.transaction_date, 10)
|
||||
so.delivery_date = add_days(so.transaction_date, 10)
|
||||
|
||||
if not args.do_not_save:
|
||||
so.insert()
|
||||
|
@ -220,7 +220,7 @@
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide": 1,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
@ -1963,7 +1963,7 @@
|
||||
"istable": 1,
|
||||
"max_attachments": 0,
|
||||
"menu_index": 0,
|
||||
"modified": "2017-07-18 18:26:36.870342",
|
||||
"modified": "2017-07-28 14:04:04.289428",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order Item",
|
||||
|
@ -2,4 +2,5 @@ erpnext/tests/ui/make_fixtures.js #long
|
||||
erpnext/accounts/doctype/account/test_account.js
|
||||
erpnext/crm/doctype/lead/test_lead.js
|
||||
erpnext/crm/doctype/opportunity/test_opportunity.js
|
||||
erpnext/selling/doctype/quotation/test_quotation.js
|
||||
erpnext/selling/doctype/quotation/test_quotation.js
|
||||
erpnext/selling/doctype/sales_order/test_sales_order.js
|
Loading…
x
Reference in New Issue
Block a user