mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-06 21:59:13 +00:00
Merge branch 'version-13-hotfix' into mergify/bp/version-13-hotfix/pr-33901
This commit is contained in:
@@ -1,7 +1,6 @@
|
|||||||
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
||||||
# License: GNU General Public License v3. See license.txt
|
# License: GNU General Public License v3. See license.txt
|
||||||
|
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import math
|
import math
|
||||||
|
|
||||||
@@ -316,6 +315,8 @@ class SalarySlip(TransactionBase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
working_days = date_diff(self.end_date, self.start_date) + 1
|
working_days = date_diff(self.end_date, self.start_date) + 1
|
||||||
|
working_days_list = [add_days(self.start_date, i) for i in range(working_days)]
|
||||||
|
|
||||||
if for_preview:
|
if for_preview:
|
||||||
self.total_working_days = working_days
|
self.total_working_days = working_days
|
||||||
self.payment_days = working_days
|
self.payment_days = working_days
|
||||||
@@ -325,6 +326,8 @@ class SalarySlip(TransactionBase):
|
|||||||
|
|
||||||
if not cint(include_holidays_in_total_working_days):
|
if not cint(include_holidays_in_total_working_days):
|
||||||
working_days -= len(holidays)
|
working_days -= len(holidays)
|
||||||
|
working_days_list = [cstr(day) for day in working_days_list if cstr(day) not in holidays]
|
||||||
|
|
||||||
if working_days < 0:
|
if working_days < 0:
|
||||||
frappe.throw(_("There are more holidays than working days this month."))
|
frappe.throw(_("There are more holidays than working days this month."))
|
||||||
|
|
||||||
@@ -335,7 +338,7 @@ class SalarySlip(TransactionBase):
|
|||||||
actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays)
|
actual_lwp, absent = self.calculate_lwp_ppl_and_absent_days_based_on_attendance(holidays)
|
||||||
self.absent_days = absent
|
self.absent_days = absent
|
||||||
else:
|
else:
|
||||||
actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days)
|
actual_lwp = self.calculate_lwp_or_ppl_based_on_leave_application(holidays, working_days_list)
|
||||||
|
|
||||||
if not lwp:
|
if not lwp:
|
||||||
lwp = actual_lwp
|
lwp = actual_lwp
|
||||||
@@ -458,16 +461,15 @@ class SalarySlip(TransactionBase):
|
|||||||
def get_holidays_for_employee(self, start_date, end_date):
|
def get_holidays_for_employee(self, start_date, end_date):
|
||||||
return get_holiday_dates_for_employee(self.employee, start_date, end_date)
|
return get_holiday_dates_for_employee(self.employee, start_date, end_date)
|
||||||
|
|
||||||
def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days):
|
def calculate_lwp_or_ppl_based_on_leave_application(self, holidays, working_days_list):
|
||||||
lwp = 0
|
lwp = 0
|
||||||
holidays = "','".join(holidays)
|
|
||||||
daily_wages_fraction_for_half_day = (
|
daily_wages_fraction_for_half_day = (
|
||||||
flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
|
flt(frappe.db.get_value("Payroll Settings", None, "daily_wages_fraction_for_half_day")) or 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
for d in range(working_days):
|
for d in working_days_list:
|
||||||
date = add_days(cstr(getdate(self.start_date)), d)
|
leave = get_lwp_or_ppl_for_date(d, self.employee, holidays)
|
||||||
leave = get_lwp_or_ppl_for_date(date, self.employee, holidays)
|
|
||||||
|
|
||||||
if leave:
|
if leave:
|
||||||
equivalent_lwp_count = 0
|
equivalent_lwp_count = 0
|
||||||
|
|||||||
@@ -84,11 +84,15 @@ erpnext.selling.QuotationController = erpnext.selling.SellingController.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) {
|
if (doc.docstatus == 1 && !["Lost", "Ordered"].includes(doc.status)) {
|
||||||
this.frm.add_custom_button(
|
if (frappe.boot.sysdefaults.allow_sales_order_creation_for_expired_quotation
|
||||||
__("Sales Order"),
|
|| (!doc.valid_till)
|
||||||
this.frm.cscript["Make Sales Order"],
|
|| frappe.datetime.get_diff(doc.valid_till, frappe.datetime.get_today()) >= 0) {
|
||||||
__("Create")
|
this.frm.add_custom_button(
|
||||||
);
|
__("Sales Order"),
|
||||||
|
this.frm.cscript["Make Sales Order"],
|
||||||
|
__("Create")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if(doc.status!=="Ordered") {
|
if(doc.status!=="Ordered") {
|
||||||
this.frm.add_custom_button(__('Set as Lost'), () => {
|
this.frm.add_custom_button(__('Set as Lost'), () => {
|
||||||
|
|||||||
@@ -192,6 +192,17 @@ def get_list_context(context=None):
|
|||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_sales_order(source_name: str, target_doc=None):
|
def make_sales_order(source_name: str, target_doc=None):
|
||||||
|
if not frappe.db.get_singles_value(
|
||||||
|
"Selling Settings", "allow_sales_order_creation_for_expired_quotation"
|
||||||
|
):
|
||||||
|
quotation = frappe.db.get_value(
|
||||||
|
"Quotation", source_name, ["transaction_date", "valid_till"], as_dict=1
|
||||||
|
)
|
||||||
|
if quotation.valid_till and (
|
||||||
|
quotation.valid_till < quotation.transaction_date or quotation.valid_till < getdate(nowdate())
|
||||||
|
):
|
||||||
|
frappe.throw(_("Validity period of this quotation has ended."))
|
||||||
|
|
||||||
return _make_sales_order(source_name, target_doc)
|
return _make_sales_order(source_name, target_doc)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -126,11 +126,21 @@ class TestQuotation(FrappeTestCase):
|
|||||||
def test_so_from_expired_quotation(self):
|
def test_so_from_expired_quotation(self):
|
||||||
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
from erpnext.selling.doctype.quotation.quotation import make_sales_order
|
||||||
|
|
||||||
|
frappe.db.set_single_value(
|
||||||
|
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 0
|
||||||
|
)
|
||||||
|
|
||||||
quotation = frappe.copy_doc(test_records[0])
|
quotation = frappe.copy_doc(test_records[0])
|
||||||
quotation.valid_till = add_days(nowdate(), -1)
|
quotation.valid_till = add_days(nowdate(), -1)
|
||||||
quotation.insert()
|
quotation.insert()
|
||||||
quotation.submit()
|
quotation.submit()
|
||||||
|
|
||||||
|
self.assertRaises(frappe.ValidationError, make_sales_order, quotation.name)
|
||||||
|
|
||||||
|
frappe.db.set_single_value(
|
||||||
|
"Selling Settings", "allow_sales_order_creation_for_expired_quotation", 1
|
||||||
|
)
|
||||||
|
|
||||||
make_sales_order(quotation.name)
|
make_sales_order(quotation.name)
|
||||||
|
|
||||||
def test_shopping_cart_without_website_item(self):
|
def test_shopping_cart_without_website_item(self):
|
||||||
|
|||||||
@@ -32,7 +32,8 @@
|
|||||||
"sales_update_frequency",
|
"sales_update_frequency",
|
||||||
"allow_multiple_items",
|
"allow_multiple_items",
|
||||||
"allow_against_multiple_purchase_orders",
|
"allow_against_multiple_purchase_orders",
|
||||||
"hide_tax_id"
|
"hide_tax_id",
|
||||||
|
"allow_sales_order_creation_for_expired_quotation"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -199,6 +200,12 @@
|
|||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
"label": "Contract Naming By",
|
"label": "Contract Naming By",
|
||||||
"options": "Party Name\nNaming Series"
|
"options": "Party Name\nNaming Series"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"default": "0",
|
||||||
|
"fieldname": "allow_sales_order_creation_for_expired_quotation",
|
||||||
|
"fieldtype": "Check",
|
||||||
|
"label": "Allow Sales Order Creation For Expired Quotation"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-cog",
|
"icon": "fa fa-cog",
|
||||||
@@ -206,7 +213,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2022-03-28 12:18:06.768403",
|
"modified": "2023-02-04 12:37:53.380857",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Selling Settings",
|
"name": "Selling Settings",
|
||||||
|
|||||||
@@ -26,6 +26,12 @@ def boot_session(bootinfo):
|
|||||||
frappe.db.get_single_value("Selling Settings", "default_valid_till")
|
frappe.db.get_single_value("Selling Settings", "default_valid_till")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
bootinfo.sysdefaults.allow_sales_order_creation_for_expired_quotation = cint(
|
||||||
|
frappe.db.get_single_value(
|
||||||
|
"Selling Settings", "allow_sales_order_creation_for_expired_quotation"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# if no company, show a dialog box to create a new company
|
# if no company, show a dialog box to create a new company
|
||||||
bootinfo.customer_count = frappe.db.sql("""SELECT count(*) FROM `tabCustomer`""")[0][0]
|
bootinfo.customer_count = frappe.db.sql("""SELECT count(*) FROM `tabCustomer`""")[0][0]
|
||||||
|
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ def get_reserved_qty(item_code, warehouse):
|
|||||||
and parenttype="Sales Order"
|
and parenttype="Sales Order"
|
||||||
and item_code != parent_item
|
and item_code != parent_item
|
||||||
and exists (select * from `tabSales Order` so
|
and exists (select * from `tabSales Order` so
|
||||||
where name = dnpi_in.parent and docstatus = 1 and status != 'Closed')
|
where name = dnpi_in.parent and docstatus = 1 and status not in ('On Hold', 'Closed'))
|
||||||
) dnpi)
|
) dnpi)
|
||||||
union
|
union
|
||||||
(select stock_qty as dnpi_qty, qty as so_item_qty,
|
(select stock_qty as dnpi_qty, qty as so_item_qty,
|
||||||
@@ -132,7 +132,7 @@ def get_reserved_qty(item_code, warehouse):
|
|||||||
and (so_item.delivered_by_supplier is null or so_item.delivered_by_supplier = 0)
|
and (so_item.delivered_by_supplier is null or so_item.delivered_by_supplier = 0)
|
||||||
and exists(select * from `tabSales Order` so
|
and exists(select * from `tabSales Order` so
|
||||||
where so.name = so_item.parent and so.docstatus = 1
|
where so.name = so_item.parent and so.docstatus = 1
|
||||||
and so.status != 'Closed'))
|
and so.status not in ('On Hold', 'Closed')))
|
||||||
) tab
|
) tab
|
||||||
where
|
where
|
||||||
so_item_qty >= so_item_delivered_qty
|
so_item_qty >= so_item_delivered_qty
|
||||||
|
|||||||
Reference in New Issue
Block a user