Merge branch 'develop' into feat_taxjar

This commit is contained in:
Deepesh Garg 2020-06-27 18:51:48 +05:30 committed by GitHub
commit a4b9fc74aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 273 additions and 358 deletions

View File

@ -188,14 +188,15 @@ frappe.ui.form.on('Invoice Discounting', {
},
show_general_ledger: (frm) => {
if(frm.doc.docstatus===1) {
if(frm.doc.docstatus > 0) {
cur_frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
company: frm.doc.company,
group_by: "Group by Voucher (Consolidated)"
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));

View File

@ -13,15 +13,16 @@ frappe.ui.form.on("Journal Entry", {
refresh: function(frm) {
erpnext.toggle_naming_series();
if(frm.doc.docstatus==1) {
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
"finance_book": frm.doc.finance_book,
"group_by_voucher": 0
"group_by": '',
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __('View'));

View File

@ -280,7 +280,7 @@
"idx": 1,
"istable": 1,
"links": [],
"modified": "2020-06-18 14:06:54.833738",
"modified": "2020-06-24 14:06:54.833738",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Journal Entry Account",

View File

@ -234,14 +234,15 @@ frappe.ui.form.on('Payment Entry', {
},
show_general_ledger: function(frm) {
if(frm.doc.docstatus==1) {
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Ledger'), function() {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
group_by: ""
"group_by": "",
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, "fa fa-table");

View File

@ -25,9 +25,10 @@ frappe.ui.form.on('Period Closing Voucher', {
frappe.route_options = {
"voucher_no": frm.doc.name,
"from_date": frm.doc.posting_date,
"to_date": frm.doc.posting_date,
"to_date": moment(frm.doc.modified).format('YYYY-MM-DD'),
"company": frm.doc.company,
group_by_voucher: 0
"group_by": "",
"show_cancelled_entries": frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, "fa fa-table");

View File

@ -408,6 +408,8 @@ class Asset(AccountsController):
row.expected_value_after_useful_life = asset_value_after_full_schedule
def validate_cancellation(self):
if self.status in ("In Maintenance", "Out of Order"):
frappe.throw(_("There are active maintenance or repairs against the asset. You must complete all of them before cancelling the asset."))
if self.status not in ("Submitted", "Partially Depreciated", "Fully Depreciated"):
frappe.throw(_("Asset cannot be cancelled, as it is already {0}").format(self.status))

View File

@ -51,7 +51,7 @@ class RequestforQuotation(BuyingController):
def validate_email_id(self, args):
if not args.email_id:
frappe.throw(_("Row {0}: For supplier {0} Email Address is required to send email").format(args.idx, args.supplier))
frappe.throw(_("Row {0}: For Supplier {0}, Email Address is Required to Send Email").format(args.idx, args.supplier))
def on_submit(self):
frappe.db.set(self, 'status', 'Submitted')
@ -154,7 +154,7 @@ class RequestforQuotation(BuyingController):
sender=sender,attachments = attachments, send_email=True,
doctype=self.doctype, name=self.name)["name"]
frappe.msgprint(_("Email sent to supplier {0}").format(data.supplier))
frappe.msgprint(_("Email Sent to Supplier {0}").format(data.supplier))
def get_attachments(self):
attachments = [d.name for d in get_attachments(self.doctype, self.name)]
@ -193,7 +193,7 @@ def send_supplier_emails(rfq_name):
def check_portal_enabled(reference_doctype):
if not frappe.db.get_value('Portal Menu Item',
{'reference_doctype': reference_doctype}, 'enabled'):
frappe.throw(_("Request for Quotation is disabled to access from portal, for more check portal settings."))
frappe.throw(_("The Access to Request for Quotation From Portal is Disabled. To Allow Access, Enable it in Portal Settings."))
def get_list_context(context=None):
from erpnext.controllers.website_list_for_contact import get_list_context
@ -259,7 +259,7 @@ def create_supplier_quotation(doc):
sq_doc.flags.ignore_permissions = True
sq_doc.run_method("set_missing_values")
sq_doc.save()
frappe.msgprint(_("Supplier Quotation {0} created").format(sq_doc.name))
frappe.msgprint(_("Supplier Quotation {0} Created").format(sq_doc.name))
return sq_doc.name
except Exception:
return None

View File

@ -33,7 +33,7 @@ def validate_filters(filters):
frappe.throw(_("{0} is mandatory").format(f))
if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")):
frappe.throw(_("Fiscal Year: {0} does not exists").format(filters.get("fiscal_year")))
frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year")))
if filters.get("based_on") == filters.get("group_by"):
frappe.throw(_("'Based On' and 'Group By' can not be same"))

View File

@ -55,14 +55,15 @@ frappe.ui.form.on("Fees", {
frm.set_df_property('posting_date', 'read_only', 1);
frm.set_df_property('posting_time', 'read_only', 1);
}
if(frm.doc.docstatus===1) {
if(frm.doc.docstatus > 0) {
frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
from_date: frm.doc.posting_date,
to_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
company: frm.doc.company,
group_by_voucher: false
group_by: '',
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2013-05-13 14:04:03",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2017-11-10 19:42:36.457449",
"modified": "2020-06-24 17:16:40.251116",
"modified_by": "Administrator",
"module": "Education",
"name": "Absent Student Report",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Student Attendance",
"report_name": "Absent Student Report",
"report_type": "Script Report",

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-11-09 15:07:30.404428",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-11-28 18:35:44.903665",
"modified": "2020-06-24 17:16:02.027410",
"modified_by": "Administrator",
"module": "Education",
"name": "Assessment Plan Status",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Assessment Plan",
"report_name": "Assessment Plan Status",
"report_type": "Script Report",

View File

@ -1,17 +1,19 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-05-05 14:46:13.776133",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2018-02-08 15:11:24.904628",
"modified": "2020-06-24 17:15:15.477530",
"modified_by": "Administrator",
"module": "Education",
"name": "Course wise Assessment Report",
"owner": "Administrator",
"prepared_report": 0,
"query": "",
"ref_doctype": "Assessment Result",
"report_name": "Course wise Assessment Report",
"report_type": "Script Report",

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2018-01-22 17:04:43.412054",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2019-02-08 15:11:35.339434",
"modified": "2020-06-24 17:13:35.373756",
"modified_by": "Administrator",
"module": "Education",
"name": "Final Assessment Grades",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Assessment Result",
"report_name": "Final Assessment Grades",
"report_type": "Script Report",

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2017-03-27 17:47:16.831433",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 0,
"is_standard": "Yes",
"modified": "2017-11-10 19:42:30.300729",
"modified": "2020-06-24 17:16:50.639488",
"modified_by": "Administrator",
"module": "Education",
"name": "Student and Guardian Contact Details",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Program Enrollment",
"report_name": "Student and Guardian Contact Details",
"report_type": "Script Report",

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2016-11-28 22:07:03.859124",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 2,
"is_standard": "Yes",
"modified": "2017-11-10 19:41:12.328346",
"modified": "2020-06-24 17:16:59.823709",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Batch-Wise Attendance",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Student Attendance",
"report_name": "Student Batch-Wise Attendance",
"report_type": "Script Report",

View File

@ -1,12 +1,13 @@
{
"add_total_row": 0,
"creation": "2016-06-22 02:58:41.024538",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2018-12-17 16:46:46.176620",
"modified": "2020-06-24 17:14:39.452551",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Fee Collection",

View File

@ -1,17 +1,18 @@
{
"add_total_row": 0,
"apply_user_permissions": 1,
"creation": "2013-05-13 14:04:03",
"disable_prepared_report": 0,
"disabled": 0,
"docstatus": 0,
"doctype": "Report",
"idx": 3,
"is_standard": "Yes",
"modified": "2017-11-10 19:42:43.376658",
"modified": "2020-06-24 17:16:13.307053",
"modified_by": "Administrator",
"module": "Education",
"name": "Student Monthly Attendance Sheet",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Student Attendance",
"report_name": "Student Monthly Attendance Sheet",
"report_type": "Script Report",

View File

@ -213,12 +213,15 @@ frappe.ui.form.on("Expense Claim", {
refresh: function(frm) {
frm.trigger("toggle_fields");
if(frm.doc.docstatus === 1 && frm.doc.approval_status !== "Rejected") {
if(frm.doc.docstatus > 0 && frm.doc.approval_status !== "Rejected") {
frm.add_custom_button(__('Accounting Ledger'), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
company: frm.doc.company,
group_by_voucher: false
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
group_by: '',
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));

View File

@ -9,12 +9,15 @@ frappe.ui.form.on(cur_frm.doctype, {
}
if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual'].includes(frm.doc.doctype)
&& frm.doc.docstatus == 1) {
&& frm.doc.docstatus > 0) {
frm.add_custom_button(__("Accounting Ledger"), function() {
frappe.route_options = {
voucher_no: frm.doc.name,
company: frm.doc.company
company: frm.doc.company,
from_date: frm.doc.posting_date,
to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
show_cancelled_entries: frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");

View File

@ -98,11 +98,17 @@ class ProductionPlan(Document):
elif self.get_items_from == "Material Request":
self.get_mr_items()
def get_so_mr_list(self, field, table):
"""Returns a list of Sales Orders or Material Requests from the respective tables"""
so_mr_list = [d.get(field) for d in self.get(table) if d.get(field)]
return so_mr_list
def get_so_items(self):
so_list = [d.sales_order for d in self.sales_orders if d.sales_order]
if not so_list:
msgprint(_("Please enter Sales Orders in the above table"))
return []
# Check for empty table or empty rows
if not self.get("sales_orders") or not self.get_so_mr_list("sales_order", "sales_orders"):
frappe.throw(_("Please fill the Sales Orders table"), title=_("Sales Orders Required"))
so_list = self.get_so_mr_list("sales_order", "sales_orders")
item_condition = ""
if self.item_code:
@ -134,10 +140,11 @@ class ProductionPlan(Document):
self.calculate_total_planned_qty()
def get_mr_items(self):
mr_list = [d.material_request for d in self.material_requests if d.material_request]
if not mr_list:
msgprint(_("Please enter Material Requests in the above table"))
return []
# Check for empty table or empty rows
if not self.get("material_requests") or not self.get_so_mr_list("material_request", "material_requests"):
frappe.throw(_("Please fill the Material Requests table"), title=_("Material Requests Required"))
mr_list = self.get_so_mr_list("material_request", "material_requests")
item_condition = ""
if self.item_code:
@ -635,9 +642,12 @@ def get_items_for_material_requests(doc, warehouses=None):
warehouse_list = None
doc['mr_items'] = []
po_items = doc.get('po_items') if doc.get('po_items') else doc.get('items')
if not po_items:
frappe.throw(_("Items are required to pull the raw materials which is associated with it."))
# Check for empty table or empty rows
if not po_items or not [row.get('item_code') for row in po_items if row.get('item_code')]:
frappe.throw(_("Items to Manufacture are required to pull the Raw Materials associated with it."),
title=_("Items Required"))
company = doc.get('company')
ignore_existing_ordered_qty = doc.get('ignore_existing_ordered_qty')

View File

@ -381,7 +381,6 @@
{
"fieldname": "earning",
"fieldtype": "Column Break",
"label": "Earning",
"oldfieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1,
@ -400,7 +399,6 @@
{
"fieldname": "deduction",
"fieldtype": "Column Break",
"label": "Deduction",
"oldfieldtype": "Column Break",
"show_days": 1,
"show_seconds": 1,
@ -616,7 +614,7 @@
"idx": 9,
"is_submittable": 1,
"links": [],
"modified": "2020-06-22 14:42:43.921828",
"modified": "2020-06-25 14:42:43.921828",
"modified_by": "Administrator",
"module": "Payroll",
"name": "Salary Slip",

View File

@ -239,13 +239,12 @@ def get_next_attribute_and_values(item_code, selected_attributes):
if exact_match:
data = get_product_info_for_website(exact_match[0])
product_info = data.product_info
product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
if not data.cart_settings.show_price:
product_info = None
else:
product_info = None
product_info["allow_items_not_in_stock"] = cint(data.cart_settings.allow_items_not_in_stock)
return {
'next_attribute': next_attribute,
'valid_options_for_attributes': valid_options_for_attributes,

View File

@ -140,52 +140,6 @@ class TestTimesheet(unittest.TestCase):
settings.ignore_employee_time_overlap = initial_setting
settings.save()
def test_timesheet_std_working_hours(self):
emp = make_employee("test_employee_6@salary.com")
company = frappe.get_doc('Company', "_Test Company")
company.standard_working_hours = 8
company.save()
timesheet = frappe.new_doc("Timesheet")
timesheet.employee = emp
timesheet.company = '_Test Company'
timesheet.append(
'time_logs',
{
"activity_type": "_Test Activity Type",
"from_time": now_datetime(),
"to_time": now_datetime() + datetime.timedelta(days= 4)
}
)
timesheet.save()
ts = frappe.get_doc('Timesheet', timesheet.name)
self.assertEqual(ts.total_hours, 32)
ts.submit()
ts.cancel()
company = frappe.get_doc('Company', "_Test Company")
company.standard_working_hours = 0
company.save()
timesheet = frappe.new_doc("Timesheet")
timesheet.employee = emp
timesheet.company = '_Test Company'
timesheet.append(
'time_logs',
{
"activity_type": "_Test Activity Type",
"from_time": now_datetime(),
"to_time": now_datetime() + datetime.timedelta(days= 4)
}
)
timesheet.save()
ts = frappe.get_doc('Timesheet', timesheet.name)
self.assertEqual(ts.total_hours, 96)
ts.submit()
ts.cancel()
def make_salary_structure_for_timesheet(employee):
salary_structure_name = "Timesheet Salary Structure Test"

View File

@ -162,19 +162,11 @@ frappe.ui.form.on("Timesheet Detail", {
to_time: function(frm, cdt, cdn) {
var child = locals[cdt][cdn];
var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / ( 60 * 60 * 24);
var std_working_hours = 0;
if(frm._setting_hours) return;
var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600;
std_working_hours = time_diff * frappe.working_hours;
if (std_working_hours < hours && std_working_hours > 0) {
frappe.model.set_value(cdt, cdn, "hours", std_working_hours);
} else {
frappe.model.set_value(cdt, cdn, "hours", hours);
}
frappe.model.set_value(cdt, cdn, "hours", hours);
},
time_logs_add: function(frm) {
@ -236,23 +228,12 @@ var calculate_end_time = function(frm, cdt, cdn) {
let d = moment(child.from_time);
if(child.hours) {
var time_diff = (moment(child.to_time).diff(moment(child.from_time),"seconds")) / (60 * 60 * 24);
var std_working_hours = 0;
var hours = moment(child.to_time).diff(moment(child.from_time), "seconds") / 3600;
std_working_hours = time_diff * frappe.working_hours;
if (std_working_hours < hours && std_working_hours > 0) {
frappe.model.set_value(cdt, cdn, "hours", std_working_hours);
frappe.model.set_value(cdt, cdn, "to_time", d.add(hours, "hours").format(frappe.defaultDatetimeFormat));
} else {
d.add(child.hours, "hours");
frm._setting_hours = true;
frappe.model.set_value(cdt, cdn, "to_time",
d.format(frappe.defaultDatetimeFormat)).then(() => {
frm._setting_hours = false;
});
}
d.add(child.hours, "hours");
frm._setting_hours = true;
frappe.model.set_value(cdt, cdn, "to_time",
d.format(frappe.defaultDatetimeFormat)).then(() => {
frm._setting_hours = false;
});
}
};

View File

@ -24,7 +24,6 @@ class Timesheet(Document):
self.set_status()
self.validate_dates()
self.validate_time_logs()
self.calculate_std_hours()
self.update_cost()
self.calculate_total_amounts()
self.calculate_percentage_billed()
@ -91,17 +90,6 @@ class Timesheet(Document):
self.start_date = getdate(start_date)
self.end_date = getdate(end_date)
def calculate_std_hours(self):
std_working_hours = frappe.get_value("Company", self.company, 'standard_working_hours')
for time in self.time_logs:
if time.from_time and time.to_time:
if flt(std_working_hours) and date_diff(time.to_time, time.from_time):
time.hours = flt(std_working_hours) * date_diff(time.to_time, time.from_time)
else:
if not time.hours:
time.hours = time_diff_in_hours(time.to_time, time.from_time)
def before_cancel(self):
self.set_status()

View File

@ -55,8 +55,9 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
frappe.route_options = {
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
company: me.frm.doc.company
to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'),
company: me.frm.doc.company,
show_cancelled_entries: me.frm.doc.docstatus === 2
};
frappe.set_route("query-report", "Stock Ledger");
}, __("View"));
@ -71,9 +72,10 @@ erpnext.stock.StockController = frappe.ui.form.Controller.extend({
frappe.route_options = {
voucher_no: me.frm.doc.name,
from_date: me.frm.doc.posting_date,
to_date: me.frm.doc.posting_date,
to_date: moment(me.frm.doc.modified).format('YYYY-MM-DD'),
company: me.frm.doc.company,
group_by: "Group by Voucher (Consolidated)"
group_by: "Group by Voucher (Consolidated)",
show_cancelled_entries: me.frm.doc.docstatus === 2
};
frappe.set_route("query-report", "General Ledger");
}, __("View"));

View File

@ -388,8 +388,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
credit_controller_users = get_users_with_role(credit_controller_role or "Sales Master Manager")
# form a list of emails and names to show to the user
credit_controller_users_list = [user for user in credit_controller_users if frappe.db.exists("Employee", {"prefered_email": user})]
credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users_list]
credit_controller_users = [get_formatted_email(user).replace("<", "(").replace(">", ")") for user in credit_controller_users]
if not credit_controller_users:
frappe.throw(_("Please contact your administrator to extend the credit limits for {0}.".format(customer)))
@ -409,7 +408,7 @@ def check_credit_limit(customer, company, ignore_outstanding_sales_order=False,
'customer': customer,
'customer_outstanding': customer_outstanding,
'credit_limit': credit_limit,
'credit_controller_users_list': credit_controller_users_list
'credit_controller_users_list': credit_controller_users
}
}
)

View File

@ -22,7 +22,6 @@
"default_letter_head",
"default_holiday_list",
"default_finance_book",
"standard_working_hours",
"default_selling_terms",
"default_buying_terms",
"default_warehouse_for_sales_return",
@ -240,11 +239,6 @@
"label": "Default Holiday List",
"options": "Holiday List"
},
{
"fieldname": "standard_working_hours",
"fieldtype": "Float",
"label": "Standard Working Hours"
},
{
"fieldname": "default_warehouse_for_sales_return",
"fieldtype": "Link",
@ -746,7 +740,7 @@
"image_field": "company_logo",
"is_tree": 1,
"links": [],
"modified": "2020-06-20 11:38:43.178970",
"modified": "2020-06-24 12:45:31.462195",
"modified_by": "Administrator",
"module": "Setup",
"name": "Company",

View File

@ -405,8 +405,8 @@ class EmailDigest(Document):
value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
count(*) from `tabSales Order`
where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed"
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
where (transaction_date <= %(to_date)s) and billing_status != "Fully Billed" and company = %(company)s
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_bill"),
report_type="Report Builder",
@ -430,8 +430,8 @@ class EmailDigest(Document):
value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_delivered/100)),0),
count(*) from `tabSales Order`
where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered"
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
where (transaction_date <= %(to_date)s) and delivery_status != "Fully Delivered" and company = %(company)s
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
label = get_link_to_report('Sales Order', label=self.meta.get_label("sales_orders_to_deliver"),
report_type="Report Builder",
@ -455,8 +455,8 @@ class EmailDigest(Document):
value, count = frappe.db.sql("""select ifnull((sum(grand_total))-(sum(grand_total*per_received/100)),0),
count(*) from `tabPurchase Order`
where (transaction_date <= %(to_date)s) and per_received < 100
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
where (transaction_date <= %(to_date)s) and per_received < 100 and company = %(company)s
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_receive"),
report_type="Report Builder",
@ -480,8 +480,8 @@ class EmailDigest(Document):
value, count = frappe.db.sql("""select ifnull((sum(grand_total)) - (sum(grand_total*per_billed/100)),0),
count(*) from `tabPurchase Order`
where (transaction_date <= %(to_date)s) and per_billed < 100
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date})[0]
where (transaction_date <= %(to_date)s) and per_billed < 100 and company = %(company)s
and status not in ('Closed','Cancelled', 'Completed') """, {"to_date": self.future_to_date, "company": self.company})[0]
label = get_link_to_report('Purchase Order', label=self.meta.get_label("purchase_orders_to_bill"),
report_type="Report Builder",

View File

@ -13,6 +13,12 @@ $.extend(cur_frm.cscript, {
},
enable_checkout: function(){
toggle_mandatory(cur_frm)
},
enabled: function() {
if (cur_frm.doc.enabled === 1) {
cur_frm.doc.show_configure_button = 1;
cur_frm.refresh_field('show_configure_button');
}
}
});

View File

@ -187,7 +187,7 @@ def get_fifo_queue(filters, sle=None):
transferred_item_details[(d.voucher_no, d.name)].append(fifo_queue.pop(0))
else:
# all from current batch
batch[0] -= qty_to_pop
batch[0] = flt(batch[0]) - qty_to_pop
transferred_item_details[(d.voucher_no, d.name)].append([qty_to_pop, batch[1]])
qty_to_pop = 0

View File

@ -79,7 +79,7 @@ frappe.ui.form.on("Issue", {
method: "erpnext.support.doctype.issue.issue.make_task",
frm: frm
});
}, __("Make"));
}, __("Create"));
} else {
if (frm.doc.service_level_agreement) {

View File

@ -79,47 +79,52 @@ class Issue(Document):
def handle_hold_time(self, status):
if self.service_level_agreement:
# set response and resolution variance as None as the issue is on Hold for status as Replied
# set response and resolution variance as None as the issue is on Hold
pause_sla_on = frappe.db.get_all("Pause SLA On Status", fields=["status"],
filters={"parent": self.service_level_agreement})
hold_statuses = [entry.status for entry in pause_sla_on]
update_values = {}
if self.status in hold_statuses and status not in hold_statuses:
update_values['on_hold_since'] = frappe.flags.current_time or now_datetime()
if not self.first_responded_on:
update_values['response_by'] = None
update_values['response_by_variance'] = 0
update_values['resolution_by'] = None
update_values['resolution_by_variance'] = 0
if hold_statuses:
if self.status in hold_statuses and status not in hold_statuses:
update_values['on_hold_since'] = frappe.flags.current_time or now_datetime()
if not self.first_responded_on:
update_values['response_by'] = None
update_values['response_by_variance'] = 0
update_values['resolution_by'] = None
update_values['resolution_by_variance'] = 0
# calculate hold time when status is changed from Replied to any other status
if self.status not in hold_statuses and status in hold_statuses:
hold_time = self.total_hold_time if self.total_hold_time else 0
now_time = frappe.flags.current_time or now_datetime()
update_values['total_hold_time'] = hold_time + time_diff_in_seconds(now_time, self.on_hold_since)
# calculate hold time when status is changed from any hold status to any non-hold status
if self.status not in hold_statuses and status in hold_statuses:
hold_time = self.total_hold_time if self.total_hold_time else 0
now_time = frappe.flags.current_time or now_datetime()
last_hold_time = 0
if self.on_hold_since:
# last_hold_time will be added to the sla variables
last_hold_time = time_diff_in_seconds(now_time, self.on_hold_since)
update_values['total_hold_time'] = hold_time + last_hold_time
# re-calculate SLA variables after issue changes from Replied to Open
# add hold time to SLA variables
if self.status == "Open" and status in hold_statuses:
start_date_time = get_datetime(self.service_level_agreement_creation)
priority = get_priority(self)
now_time = frappe.flags.current_time or now_datetime()
hold_time = time_diff_in_seconds(now_time, self.on_hold_since)
# re-calculate SLA variables after issue changes from any hold status to any non-hold status
# add hold time to SLA variables
start_date_time = get_datetime(self.service_level_agreement_creation)
priority = get_priority(self)
now_time = frappe.flags.current_time or now_datetime()
if not self.first_responded_on:
response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
update_values['response_by'] = add_to_date(response_by, seconds=round(hold_time))
response_by_variance = round(time_diff_in_hours(self.response_by, now_time))
update_values['response_by_variance'] = response_by_variance + (hold_time // 3600)
if not self.first_responded_on:
response_by = get_expected_time_for(parameter="response", service_level=priority, start_date_time=start_date_time)
response_by = add_to_date(response_by, seconds=round(last_hold_time))
response_by_variance = round(time_diff_in_hours(response_by, now_time))
update_values['response_by'] = response_by
update_values['response_by_variance'] = response_by_variance + (last_hold_time // 3600)
resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
update_values['resolution_by'] = add_to_date(resolution_by, seconds=round(hold_time))
resolution_by_variance = round(time_diff_in_hours(self.resolution_by, now_time))
update_values['resolution_by_variance'] = resolution_by_variance + (hold_time // 3600)
update_values['on_hold_since'] = None
resolution_by = get_expected_time_for(parameter="resolution", service_level=priority, start_date_time=start_date_time)
resolution_by = add_to_date(resolution_by, seconds=round(last_hold_time))
resolution_by_variance = round(time_diff_in_hours(resolution_by, now_time))
update_values['resolution_by'] = resolution_by
update_values['resolution_by_variance'] = resolution_by_variance + (last_hold_time // 3600)
update_values['on_hold_since'] = None
self.db_set(update_values)
self.db_set(update_values)
def update_agreement_status(self):
if self.service_level_agreement and self.agreement_fulfilled == "Ongoing":

View File

@ -9,33 +9,6 @@
<p class="hero-subtitle">{{ greeting_subtitle }}</p>
{% endif %}
</div>
<div class="search-container">
<div class="website-search" id="search-container">
<div class="dropdown">
<div class="search-icon">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24"
fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round"
class="feather feather-search">
<circle cx="11" cy="11" r="8"></circle>
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
</svg>
</div>
<input type="search" class="form-control" placeholder="Search the docs (Press ? to focus)" />
<div class="overflow-hidden shadow dropdown-menu w-100">
</div>
</div>
</div>
<button class="navbar-toggler" type="button"
data-toggle="collapse"
data-target="#navbarSupportedContent"
aria-controls="navbarSupportedContent"
aria-expanded="false"
aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
</div>
</div>
</section>
@ -81,21 +54,5 @@
</div>
</section>
{% endif %}
{% endblock %}
{%- block script -%}
<script>
frappe.ready(() => {
frappe.setup_search('#search-container', 'kb');
});
</script>
{%- endblock -%}
{%- block style -%}
<style>
.search-container {
margin-top: 1.2rem;
max-width: 500px;
}
</style>
{%- endblock -%}