mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-02 11:49:10 +00:00
fix: remove duplicate patch
This commit is contained in:
@@ -160,7 +160,7 @@ class Asset(AccountsController):
|
|||||||
if self.calculate_depreciation:
|
if self.calculate_depreciation:
|
||||||
self.set_depreciation_rate()
|
self.set_depreciation_rate()
|
||||||
for d in self.finance_books:
|
for d in self.finance_books:
|
||||||
d.value_after_depreciation = self.value_after_depreciation
|
d.db_set("value_after_depreciation", self.value_after_depreciation)
|
||||||
else:
|
else:
|
||||||
self.finance_books = []
|
self.finance_books = []
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activ
|
|||||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||||
get_asset_depr_schedule_doc,
|
get_asset_depr_schedule_doc,
|
||||||
get_asset_depr_schedule_name,
|
get_asset_depr_schedule_name,
|
||||||
get_temp_asset_depr_schedule_doc,
|
get_temp_depr_schedule_doc,
|
||||||
reschedule_depreciation,
|
reschedule_depreciation,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -874,9 +874,7 @@ def get_value_after_depreciation_on_disposal_date(asset, disposal_date, finance_
|
|||||||
|
|
||||||
row = asset_doc.finance_books[idx - 1]
|
row = asset_doc.finance_books[idx - 1]
|
||||||
|
|
||||||
temp_asset_depreciation_schedule = get_temp_asset_depr_schedule_doc(
|
temp_asset_depreciation_schedule = get_temp_depr_schedule_doc(asset_doc, row, getdate(disposal_date))
|
||||||
asset_doc, row, getdate(disposal_date)
|
|
||||||
)
|
|
||||||
|
|
||||||
accumulated_depr_amount = temp_asset_depreciation_schedule.get("depreciation_schedule")[
|
accumulated_depr_amount = temp_asset_depreciation_schedule.get("depreciation_schedule")[
|
||||||
-1
|
-1
|
||||||
|
|||||||
@@ -107,14 +107,9 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
|
|||||||
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
||||||
|
|
||||||
def update_shift_depr_schedule(self):
|
def update_shift_depr_schedule(self):
|
||||||
if not self.shift_based or self.docstatus != 0:
|
if not self.shift_based or self.docstatus != 0 or self.get("__islocal"):
|
||||||
return
|
return
|
||||||
|
self.create_depreciation_schedule()
|
||||||
asset_doc = frappe.get_doc("Asset", self.asset)
|
|
||||||
fb_row = asset_doc.finance_books[self.finance_book_id - 1]
|
|
||||||
|
|
||||||
self.make_depr_schedule(asset_doc, fb_row)
|
|
||||||
self.set_accumulated_depreciation(asset_doc, fb_row)
|
|
||||||
|
|
||||||
def get_finance_book_row(self, fb_row=None):
|
def get_finance_book_row(self, fb_row=None):
|
||||||
if fb_row:
|
if fb_row:
|
||||||
@@ -144,6 +139,7 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
|
|||||||
self.total_number_of_depreciations = self.fb_row.total_number_of_depreciations
|
self.total_number_of_depreciations = self.fb_row.total_number_of_depreciations
|
||||||
self.frequency_of_depreciation = self.fb_row.frequency_of_depreciation
|
self.frequency_of_depreciation = self.fb_row.frequency_of_depreciation
|
||||||
self.rate_of_depreciation = self.fb_row.get("rate_of_depreciation")
|
self.rate_of_depreciation = self.fb_row.get("rate_of_depreciation")
|
||||||
|
self.value_after_depreciation = self.fb_row.value_after_depreciation
|
||||||
self.expected_value_after_useful_life = self.fb_row.get("expected_value_after_useful_life")
|
self.expected_value_after_useful_life = self.fb_row.get("expected_value_after_useful_life")
|
||||||
self.daily_prorata_based = self.fb_row.get("daily_prorata_based")
|
self.daily_prorata_based = self.fb_row.get("daily_prorata_based")
|
||||||
self.shift_based = self.fb_row.get("shift_based")
|
self.shift_based = self.fb_row.get("shift_based")
|
||||||
@@ -218,50 +214,46 @@ def set_modified_depreciation_rate(asset_doc, row, new_schedule):
|
|||||||
new_schedule.rate_of_depreciation = new_rate_of_depreciation
|
new_schedule.rate_of_depreciation = new_rate_of_depreciation
|
||||||
|
|
||||||
|
|
||||||
|
def get_temp_depr_schedule_doc(asset_doc, fb_row, disposal_date=None, updated_depr_schedule=None):
|
||||||
|
current_schedule = get_current_asset_depr(asset_doc, fb_row)
|
||||||
|
temp_schedule_doc = frappe.copy_doc(current_schedule)
|
||||||
|
|
||||||
def get_temp_asset_depr_schedule_doc(
|
if updated_depr_schedule:
|
||||||
asset_doc,
|
modify_depreciation_dchedule(temp_schedule_doc, updated_depr_schedule)
|
||||||
row,
|
|
||||||
disposal_date=None,
|
temp_schedule_doc.create_depreciation_schedule(fb_row, disposal_date)
|
||||||
date_of_return=None,
|
return temp_schedule_doc
|
||||||
update_asset_finance_book_row=False,
|
|
||||||
new_depr_schedule=None,
|
|
||||||
):
|
def get_current_asset_depr(asset_doc, row):
|
||||||
current_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active", row.finance_book)
|
current_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active", row.finance_book)
|
||||||
|
|
||||||
if not current_schedule:
|
if not current_schedule:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Asset Depreciation Schedule not found for Asset {0} and Finance Book {1}").format(
|
_("Asset Depreciation Schedule not found for Asset {0} and Finance Book {1}").format(
|
||||||
get_link_to_form("Asset", asset_doc.name), row.finance_book
|
get_link_to_form("Asset", asset_doc.name), row.finance_book
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
return current_schedule
|
||||||
|
|
||||||
temp_asset_depr_schedule_doc = frappe.copy_doc(current_schedule)
|
|
||||||
|
|
||||||
if new_depr_schedule:
|
def modify_depreciation_dchedule(temp_schedule_doc, updated_depr_schedule):
|
||||||
temp_asset_depr_schedule_doc.depreciation_schedule = []
|
temp_schedule_doc.depreciation_schedule = []
|
||||||
|
|
||||||
for schedule in new_depr_schedule:
|
for schedule in updated_depr_schedule:
|
||||||
temp_asset_depr_schedule_doc.append(
|
temp_schedule_doc.append(
|
||||||
"depreciation_schedule",
|
"depreciation_schedule",
|
||||||
{
|
{
|
||||||
"schedule_date": schedule.schedule_date,
|
"schedule_date": schedule.schedule_date,
|
||||||
"depreciation_amount": schedule.depreciation_amount,
|
"depreciation_amount": schedule.depreciation_amount,
|
||||||
"accumulated_depreciation_amount": schedule.accumulated_depreciation_amount,
|
"accumulated_depreciation_amount": schedule.accumulated_depreciation_amount,
|
||||||
"journal_entry": schedule.journal_entry,
|
"journal_entry": schedule.journal_entry,
|
||||||
"shift": schedule.shift,
|
"shift": schedule.shift,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
temp_asset_depr_schedule_doc.create_depreciation_schedule(
|
|
||||||
asset_doc,
|
|
||||||
row,
|
|
||||||
disposal_date,
|
|
||||||
date_of_return,
|
|
||||||
update_asset_finance_book_row,
|
|
||||||
)
|
|
||||||
|
|
||||||
return temp_asset_depr_schedule_doc
|
def get_asset_shift_factors_map():
|
||||||
|
return dict(frappe.db.get_all("Asset Shift Factor", ["shift_name", "shift_factor"], as_list=True))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
|
|||||||
depr_schedule = []
|
depr_schedule = []
|
||||||
|
|
||||||
self.schedules_before_clearing = self.get("depreciation_schedule")
|
self.schedules_before_clearing = self.get("depreciation_schedule")
|
||||||
|
|
||||||
for schedule in self.get("depreciation_schedule"):
|
for schedule in self.get("depreciation_schedule"):
|
||||||
if schedule.journal_entry:
|
if schedule.journal_entry:
|
||||||
num_of_depreciations_completed += 1
|
num_of_depreciations_completed += 1
|
||||||
@@ -68,7 +67,6 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
|
|||||||
self.schedule_date = self.get_next_schedule_date(row_idx)
|
self.schedule_date = self.get_next_schedule_date(row_idx)
|
||||||
|
|
||||||
self.depreciation_amount = self.get_depreciation_amount(row_idx)
|
self.depreciation_amount = self.get_depreciation_amount(row_idx)
|
||||||
print(row_idx, self.schedule_date, self.depreciation_amount)
|
|
||||||
|
|
||||||
# if asset is being sold or scrapped
|
# if asset is being sold or scrapped
|
||||||
if self.disposal_date and getdate(self.schedule_date) >= getdate(self.disposal_date):
|
if self.disposal_date and getdate(self.schedule_date) >= getdate(self.disposal_date):
|
||||||
@@ -228,12 +226,8 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
|
|||||||
total_months = cint(self.fb_row.total_number_of_depreciations) * cint(
|
total_months = cint(self.fb_row.total_number_of_depreciations) * cint(
|
||||||
self.fb_row.frequency_of_depreciation
|
self.fb_row.frequency_of_depreciation
|
||||||
) + cint(self.fb_row.increase_in_asset_life)
|
) + cint(self.fb_row.increase_in_asset_life)
|
||||||
depr_booked_for_months = 0
|
|
||||||
last_depr_date = self.get_last_booked_depreciation_date()
|
last_depr_date = self.get_last_booked_depreciation_date()
|
||||||
if last_depr_date:
|
depr_booked_for_months = self.get_booked_depr_for_months_count(last_depr_date)
|
||||||
depr_booked_for_months = date_diff(last_depr_date, self.asset_doc.available_for_use_date) / (
|
|
||||||
365 / 12
|
|
||||||
)
|
|
||||||
|
|
||||||
self.pending_months = total_months - depr_booked_for_months
|
self.pending_months = total_months - depr_booked_for_months
|
||||||
|
|
||||||
@@ -245,9 +239,22 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
|
|||||||
last_depr_date = add_months(
|
last_depr_date = add_months(
|
||||||
self.fb_row.depreciation_start_date, -1 * self.fb_row.frequency_of_depreciation
|
self.fb_row.depreciation_start_date, -1 * self.fb_row.frequency_of_depreciation
|
||||||
)
|
)
|
||||||
|
|
||||||
return last_depr_date
|
return last_depr_date
|
||||||
|
|
||||||
|
def get_booked_depr_for_months_count(self, last_depr_date):
|
||||||
|
depr_booked_for_months = 0
|
||||||
|
if last_depr_date:
|
||||||
|
asset_used_for_months = self.fb_row.frequency_of_depreciation * (
|
||||||
|
1 + self.asset_doc.opening_number_of_booked_depreciations
|
||||||
|
)
|
||||||
|
computed_available_for_use_date = add_days(
|
||||||
|
add_months(self.fb_row.depreciation_start_date, -1 * asset_used_for_months), 1
|
||||||
|
)
|
||||||
|
if getdate(computed_available_for_use_date) < getdate(self.asset_doc.available_for_use_date):
|
||||||
|
computed_available_for_use_date = self.asset_doc.available_for_use_date
|
||||||
|
depr_booked_for_months = date_diff(last_depr_date, computed_available_for_use_date) / (365 / 12)
|
||||||
|
return depr_booked_for_months
|
||||||
|
|
||||||
def get_total_pending_days_or_years(self):
|
def get_total_pending_days_or_years(self):
|
||||||
if cint(frappe.db.get_single_value("Accounts Settings", "calculate_depr_using_total_days")):
|
if cint(frappe.db.get_single_value("Accounts Settings", "calculate_depr_using_total_days")):
|
||||||
last_depr_date = self.get_last_booked_depreciation_date()
|
last_depr_date = self.get_last_booked_depreciation_date()
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ class StraightLineMethod(Document):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.fb_row.shift_based:
|
if self.fb_row.shift_based:
|
||||||
self.get_shift_depr_amount(row_idx)
|
return self.get_shift_depr_amount(row_idx)
|
||||||
|
|
||||||
if self.fb_row.daily_prorata_based:
|
if self.fb_row.daily_prorata_based:
|
||||||
return self.get_daily_prorata_based_depr_amount(row_idx)
|
return self.get_daily_prorata_based_depr_amount(row_idx)
|
||||||
@@ -51,31 +51,29 @@ class StraightLineMethod(Document):
|
|||||||
return yearly_depr_amount / total_days_in_current_depr_year
|
return yearly_depr_amount / total_days_in_current_depr_year
|
||||||
|
|
||||||
def get_shift_depr_amount(self, row_idx):
|
def get_shift_depr_amount(self, row_idx):
|
||||||
depreciable_value = (
|
if not self.schedules_before_clearing:
|
||||||
flt(self.asset_doc.gross_purchase_amount)
|
pending_periods = flt(self.pending_months) / flt(self.fb_row.frequency_of_depreciation)
|
||||||
- flt(self.asset_doc.opening_accumulated_depreciation)
|
return self.depreciable_value / pending_periods
|
||||||
- flt(self.fb_row.expected_value_after_useful_life)
|
|
||||||
)
|
|
||||||
if self.get("__islocal") and not self.asset_doc.flags.shift_allocation:
|
|
||||||
pending_depreciations = flt(
|
|
||||||
self.fb_row.total_number_of_depreciations
|
|
||||||
- self.asset_doc.opening_number_of_booked_depreciations
|
|
||||||
)
|
|
||||||
return depreciable_value / pending_depreciations
|
|
||||||
|
|
||||||
asset_shift_factors_map = self.get_asset_shift_factors_map()
|
asset_shift_factors_map = self.get_asset_shift_factors_map()
|
||||||
shift = (
|
|
||||||
self.schedules_before_clearing[row_idx].shift
|
if self.schedules_before_clearing:
|
||||||
if len(self.schedules_before_clearing) > row_idx
|
shift = (
|
||||||
else None
|
self.schedules_before_clearing[row_idx].shift
|
||||||
)
|
if len(self.schedules_before_clearing) > row_idx
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
shift_factor = asset_shift_factors_map.get(shift, 0)
|
shift_factor = asset_shift_factors_map.get(shift, 0)
|
||||||
|
|
||||||
shift_factors_sum = sum(
|
shift_factors_sum = sum(
|
||||||
[flt(asset_shift_factors_map.get(d.shift)) for d in self.schedules_before_clearing]
|
[
|
||||||
|
flt(asset_shift_factors_map.get(d.shift))
|
||||||
|
for d in self.schedules_before_clearing
|
||||||
|
if not d.journal_entry
|
||||||
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
return (depreciable_value / shift_factors_sum) * shift_factor
|
return (self.depreciable_value / shift_factors_sum) * shift_factor
|
||||||
|
|
||||||
def get_asset_shift_factors_map(self):
|
def get_asset_shift_factors_map(self):
|
||||||
return dict(frappe.db.get_all("Asset Shift Factor", ["shift_name", "shift_factor"], as_list=True))
|
return dict(frappe.db.get_all("Asset Shift Factor", ["shift_name", "shift_factor"], as_list=True))
|
||||||
|
|||||||
@@ -2,6 +2,15 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
frappe.ui.form.on("Asset Shift Allocation", {
|
frappe.ui.form.on("Asset Shift Allocation", {
|
||||||
onload: function (frm) {
|
onload: function (frm) {
|
||||||
|
frm.set_query("asset", function () {
|
||||||
|
return {
|
||||||
|
filters: {
|
||||||
|
company: frm.doc.company,
|
||||||
|
docstatus: 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
frm.events.make_schedules_editable(frm);
|
frm.events.make_schedules_editable(frm);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
"finance_book",
|
"finance_book",
|
||||||
"amended_from",
|
"amended_from",
|
||||||
"depreciation_schedule_section",
|
"depreciation_schedule_section",
|
||||||
|
"column_break_jomc",
|
||||||
"depreciation_schedule"
|
"depreciation_schedule"
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
@@ -57,7 +58,9 @@
|
|||||||
"fieldname": "depreciation_schedule",
|
"fieldname": "depreciation_schedule",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
"label": "Depreciation Schedule",
|
"label": "Depreciation Schedule",
|
||||||
"options": "Depreciation Schedule"
|
"no_copy": 1,
|
||||||
|
"options": "Depreciation Schedule",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
@@ -65,12 +68,16 @@
|
|||||||
"label": "Naming Series",
|
"label": "Naming Series",
|
||||||
"options": "ACC-ASA-.YYYY.-",
|
"options": "ACC-ASA-.YYYY.-",
|
||||||
"reqd": 1
|
"reqd": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldname": "column_break_jomc",
|
||||||
|
"fieldtype": "Column Break"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-03-27 13:06:35.732191",
|
"modified": "2025-01-10 16:25:31.397325",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Assets",
|
"module": "Assets",
|
||||||
"name": "Asset Shift Allocation",
|
"name": "Asset Shift Allocation",
|
||||||
|
|||||||
@@ -16,10 +16,8 @@ from frappe.utils import (
|
|||||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||||
get_asset_depr_schedule_doc,
|
get_asset_depr_schedule_doc,
|
||||||
get_temp_asset_depr_schedule_doc,
|
|
||||||
)
|
|
||||||
from erpnext.erpnext.assets.doctype.asset_depreciation_schedule.deppreciation_schedule_controller import (
|
|
||||||
get_asset_shift_factors_map,
|
get_asset_shift_factors_map,
|
||||||
|
get_temp_depr_schedule_doc,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -32,9 +30,7 @@ class AssetShiftAllocation(Document):
|
|||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from frappe.types import DF
|
from frappe.types import DF
|
||||||
|
|
||||||
from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import (
|
from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import DepreciationSchedule
|
||||||
DepreciationSchedule,
|
|
||||||
)
|
|
||||||
|
|
||||||
amended_from: DF.Link | None
|
amended_from: DF.Link | None
|
||||||
asset: DF.Link
|
asset: DF.Link
|
||||||
@@ -43,32 +39,138 @@ class AssetShiftAllocation(Document):
|
|||||||
naming_series: DF.Literal["ACC-ASA-.YYYY.-"]
|
naming_series: DF.Literal["ACC-ASA-.YYYY.-"]
|
||||||
# end: auto-generated types
|
# end: auto-generated types
|
||||||
|
|
||||||
def after_insert(self):
|
|
||||||
self.fetch_and_set_depr_schedule()
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.asset_depr_schedule_doc = get_asset_depr_schedule_doc(self.asset, "Active", self.finance_book)
|
self.asset_depr_schedule_doc = get_asset_depr_schedule_doc(self.asset, "Active", self.finance_book)
|
||||||
|
if self.get("depreciation_schedule") and self.docstatus == 0:
|
||||||
|
self.validate_invalid_shift_change()
|
||||||
|
self.update_depr_schedule()
|
||||||
|
|
||||||
self.validate_invalid_shift_change()
|
def after_insert(self):
|
||||||
self.update_depr_schedule()
|
self.fetch_and_set_depr_schedule()
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
self.create_new_asset_depr_schedule()
|
self.create_new_asset_depr_schedule()
|
||||||
|
|
||||||
|
def validate_invalid_shift_change(self):
|
||||||
|
for i, sch in enumerate(self.depreciation_schedule):
|
||||||
|
if sch.journal_entry and self.asset_depr_schedule_doc.depreciation_schedule[i].shift != sch.shift:
|
||||||
|
frappe.throw(
|
||||||
|
_(
|
||||||
|
"Row {0}: Shift cannot be changed since the depreciation has already been processed"
|
||||||
|
).format(i)
|
||||||
|
)
|
||||||
|
|
||||||
|
def update_depr_schedule(self):
|
||||||
|
self.adjust_depr_shifts()
|
||||||
|
|
||||||
|
asset_doc = frappe.get_doc("Asset", self.asset)
|
||||||
|
fb_row = self.get_finance_book_row(asset_doc)
|
||||||
|
|
||||||
|
temp_depr_schedule_doc = get_temp_depr_schedule_doc(
|
||||||
|
asset_doc, fb_row, updated_depr_schedule=self.depreciation_schedule
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update the depreciation schedule with the new shifts
|
||||||
|
self.depreciation_schedule = []
|
||||||
|
self.modify_depr_schedule(temp_depr_schedule_doc.get("depreciation_schedule"))
|
||||||
|
|
||||||
|
def adjust_depr_shifts(self):
|
||||||
|
"""
|
||||||
|
Adjust the shifts in the depreciation schedule based on the new shifts
|
||||||
|
"""
|
||||||
|
shift_factors_map = get_asset_shift_factors_map()
|
||||||
|
reverse_shift_factors_map = {v: k for k, v in shift_factors_map.items()}
|
||||||
|
factor_diff = self.calculate_shift_factor_diff(shift_factors_map)
|
||||||
|
|
||||||
|
# Case 1: Reduce shifts if there is an excess factor
|
||||||
|
if factor_diff > 0:
|
||||||
|
self.reduce_depr_shifts(factor_diff, shift_factors_map, reverse_shift_factors_map)
|
||||||
|
|
||||||
|
# Case 2: Add shifts if there is a missing factor
|
||||||
|
elif factor_diff < 0:
|
||||||
|
self.add_depr_shifts(factor_diff, shift_factors_map, reverse_shift_factors_map)
|
||||||
|
|
||||||
|
def calculate_shift_factor_diff(self, shift_factors_map):
|
||||||
|
original_shift_sum = sum(
|
||||||
|
shift_factors_map.get(schedule.shift, 0)
|
||||||
|
for schedule in self.asset_depr_schedule_doc.depreciation_schedule
|
||||||
|
)
|
||||||
|
new_shift_sum = sum(
|
||||||
|
shift_factors_map.get(schedule.shift, 0) for schedule in self.depreciation_schedule
|
||||||
|
)
|
||||||
|
return new_shift_sum - original_shift_sum
|
||||||
|
|
||||||
|
def reduce_depr_shifts(self, factor_diff, shift_factors_map, reverse_shift_factors_map):
|
||||||
|
for i, schedule in reversed(list(enumerate(self.depreciation_schedule))):
|
||||||
|
if factor_diff <= 0:
|
||||||
|
break
|
||||||
|
|
||||||
|
current_factor = shift_factors_map.get(schedule.shift, 0)
|
||||||
|
if current_factor <= factor_diff:
|
||||||
|
self.depreciation_schedule.pop(i)
|
||||||
|
factor_diff -= current_factor
|
||||||
|
else:
|
||||||
|
new_factor = current_factor - factor_diff
|
||||||
|
self.depreciation_schedule[i].shift = reverse_shift_factors_map.get(new_factor)
|
||||||
|
factor_diff = 0
|
||||||
|
|
||||||
|
def add_depr_shifts(self, factor_diff, shift_factors_map, reverse_shift_factors_map):
|
||||||
|
factor_diff = abs(factor_diff)
|
||||||
|
shift_factors = sorted(shift_factors_map.values(), reverse=True)
|
||||||
|
|
||||||
|
while factor_diff > 0:
|
||||||
|
for factor in shift_factors:
|
||||||
|
if factor <= factor_diff:
|
||||||
|
self.add_schedule_row(factor, reverse_shift_factors_map)
|
||||||
|
factor_diff -= factor
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
frappe.throw(
|
||||||
|
_("Could not find a suitable shift to match the difference: {0}").format(factor_diff)
|
||||||
|
)
|
||||||
|
|
||||||
|
def add_schedule_row(self, factor, reverse_shift_factors_map):
|
||||||
|
schedule_date = add_months(
|
||||||
|
self.depreciation_schedule[-1].schedule_date,
|
||||||
|
cint(self.asset_depr_schedule_doc.frequency_of_depreciation),
|
||||||
|
)
|
||||||
|
if is_last_day_of_the_month(self.depreciation_schedule[-1].schedule_date):
|
||||||
|
schedule_date = get_last_day(schedule_date)
|
||||||
|
|
||||||
|
self.append(
|
||||||
|
"depreciation_schedule",
|
||||||
|
{
|
||||||
|
"schedule_date": schedule_date,
|
||||||
|
"shift": reverse_shift_factors_map.get(factor),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_finance_book_row(self, asset_doc):
|
||||||
|
idx = 0
|
||||||
|
for d in asset_doc.get("finance_books"):
|
||||||
|
if d.finance_book == self.finance_book:
|
||||||
|
idx = d.idx
|
||||||
|
break
|
||||||
|
|
||||||
|
return asset_doc.get("finance_books")[idx - 1]
|
||||||
|
|
||||||
|
def modify_depr_schedule(self, temp_depr_schedule):
|
||||||
|
for schedule in temp_depr_schedule:
|
||||||
|
self.append(
|
||||||
|
"depreciation_schedule",
|
||||||
|
{
|
||||||
|
"schedule_date": schedule.schedule_date,
|
||||||
|
"depreciation_amount": schedule.depreciation_amount,
|
||||||
|
"accumulated_depreciation_amount": schedule.accumulated_depreciation_amount,
|
||||||
|
"journal_entry": schedule.journal_entry,
|
||||||
|
"shift": schedule.shift,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def fetch_and_set_depr_schedule(self):
|
def fetch_and_set_depr_schedule(self):
|
||||||
if self.asset_depr_schedule_doc:
|
if self.asset_depr_schedule_doc:
|
||||||
if self.asset_depr_schedule_doc.shift_based:
|
if self.asset_depr_schedule_doc.shift_based:
|
||||||
for schedule in self.asset_depr_schedule_doc.get("depreciation_schedule"):
|
self.modify_depr_schedule(self.asset_depr_schedule_doc.depreciation_schedule)
|
||||||
self.append(
|
|
||||||
"depreciation_schedule",
|
|
||||||
{
|
|
||||||
"schedule_date": schedule.schedule_date,
|
|
||||||
"depreciation_amount": schedule.depreciation_amount,
|
|
||||||
"accumulated_depreciation_amount": schedule.accumulated_depreciation_amount,
|
|
||||||
"journal_entry": schedule.journal_entry,
|
|
||||||
"shift": schedule.shift,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
self.flags.ignore_validate = True
|
self.flags.ignore_validate = True
|
||||||
self.save()
|
self.save()
|
||||||
@@ -85,143 +187,6 @@ class AssetShiftAllocation(Document):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate_invalid_shift_change(self):
|
|
||||||
if not self.get("depreciation_schedule") or self.docstatus == 1:
|
|
||||||
return
|
|
||||||
|
|
||||||
for i, sch in enumerate(self.depreciation_schedule):
|
|
||||||
if sch.journal_entry and self.asset_depr_schedule_doc.depreciation_schedule[i].shift != sch.shift:
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"Row {0}: Shift cannot be changed since the depreciation has already been processed"
|
|
||||||
).format(i)
|
|
||||||
)
|
|
||||||
|
|
||||||
def update_depr_schedule(self):
|
|
||||||
if not self.get("depreciation_schedule") or self.docstatus == 1:
|
|
||||||
return
|
|
||||||
|
|
||||||
self.allocate_shift_diff_in_depr_schedule()
|
|
||||||
|
|
||||||
asset_doc = frappe.get_doc("Asset", self.asset)
|
|
||||||
fb_row = asset_doc.finance_books[self.asset_depr_schedule_doc.finance_book_id - 1]
|
|
||||||
|
|
||||||
asset_doc.flags.shift_allocation = True
|
|
||||||
|
|
||||||
temp_depr_schedule = get_temp_asset_depr_schedule_doc(
|
|
||||||
asset_doc, fb_row, new_depr_schedule=self.depreciation_schedule
|
|
||||||
).get("depreciation_schedule")
|
|
||||||
|
|
||||||
self.depreciation_schedule = []
|
|
||||||
|
|
||||||
for schedule in temp_depr_schedule:
|
|
||||||
self.append(
|
|
||||||
"depreciation_schedule",
|
|
||||||
{
|
|
||||||
"schedule_date": schedule.schedule_date,
|
|
||||||
"depreciation_amount": schedule.depreciation_amount,
|
|
||||||
"accumulated_depreciation_amount": schedule.accumulated_depreciation_amount,
|
|
||||||
"journal_entry": schedule.journal_entry,
|
|
||||||
"shift": schedule.shift,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
def allocate_shift_diff_in_depr_schedule(self):
|
|
||||||
asset_shift_factors_map = get_asset_shift_factors_map()
|
|
||||||
reverse_asset_shift_factors_map = {asset_shift_factors_map[k]: k for k in asset_shift_factors_map}
|
|
||||||
|
|
||||||
original_shift_factors_sum = sum(
|
|
||||||
flt(asset_shift_factors_map.get(schedule.shift))
|
|
||||||
for schedule in self.asset_depr_schedule_doc.depreciation_schedule
|
|
||||||
)
|
|
||||||
|
|
||||||
new_shift_factors_sum = sum(
|
|
||||||
flt(asset_shift_factors_map.get(schedule.shift)) for schedule in self.depreciation_schedule
|
|
||||||
)
|
|
||||||
|
|
||||||
diff = new_shift_factors_sum - original_shift_factors_sum
|
|
||||||
|
|
||||||
if diff > 0:
|
|
||||||
for i, schedule in reversed(list(enumerate(self.depreciation_schedule))):
|
|
||||||
if diff <= 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
shift_factor = flt(asset_shift_factors_map.get(schedule.shift))
|
|
||||||
|
|
||||||
if shift_factor <= diff:
|
|
||||||
self.depreciation_schedule.pop()
|
|
||||||
diff -= shift_factor
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get(
|
|
||||||
shift_factor - diff
|
|
||||||
)
|
|
||||||
diff = 0
|
|
||||||
except Exception:
|
|
||||||
frappe.throw(
|
|
||||||
_("Could not auto update shifts. Shift with shift factor {0} needed.")
|
|
||||||
).format(shift_factor - diff)
|
|
||||||
elif diff < 0:
|
|
||||||
shift_factors = list(asset_shift_factors_map.values())
|
|
||||||
desc_shift_factors = sorted(shift_factors, reverse=True)
|
|
||||||
depr_schedule_len_diff = self.asset_depr_schedule_doc.total_number_of_depreciations - len(
|
|
||||||
self.depreciation_schedule
|
|
||||||
)
|
|
||||||
subsets_result = []
|
|
||||||
|
|
||||||
if depr_schedule_len_diff > 0:
|
|
||||||
num_rows_to_add = depr_schedule_len_diff
|
|
||||||
|
|
||||||
while not subsets_result and num_rows_to_add > 0:
|
|
||||||
find_subsets_with_sum(shift_factors, num_rows_to_add, abs(diff), [], subsets_result)
|
|
||||||
if subsets_result:
|
|
||||||
break
|
|
||||||
num_rows_to_add -= 1
|
|
||||||
|
|
||||||
if subsets_result:
|
|
||||||
for i in range(num_rows_to_add):
|
|
||||||
schedule_date = add_months(
|
|
||||||
self.depreciation_schedule[-1].schedule_date,
|
|
||||||
cint(self.asset_depr_schedule_doc.frequency_of_depreciation),
|
|
||||||
)
|
|
||||||
|
|
||||||
if is_last_day_of_the_month(self.depreciation_schedule[-1].schedule_date):
|
|
||||||
schedule_date = get_last_day(schedule_date)
|
|
||||||
|
|
||||||
self.append(
|
|
||||||
"depreciation_schedule",
|
|
||||||
{
|
|
||||||
"schedule_date": schedule_date,
|
|
||||||
"shift": reverse_asset_shift_factors_map.get(subsets_result[0][i]),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
if depr_schedule_len_diff <= 0 or not subsets_result:
|
|
||||||
for i, schedule in reversed(list(enumerate(self.depreciation_schedule))):
|
|
||||||
diff = abs(diff)
|
|
||||||
|
|
||||||
if diff <= 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
shift_factor = flt(asset_shift_factors_map.get(schedule.shift))
|
|
||||||
|
|
||||||
if shift_factor <= diff:
|
|
||||||
for sf in desc_shift_factors:
|
|
||||||
if sf - shift_factor <= diff:
|
|
||||||
self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get(sf)
|
|
||||||
diff -= sf - shift_factor
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
self.depreciation_schedule[i].shift = reverse_asset_shift_factors_map.get(
|
|
||||||
shift_factor + diff
|
|
||||||
)
|
|
||||||
diff = 0
|
|
||||||
except Exception:
|
|
||||||
frappe.throw(
|
|
||||||
_("Could not auto update shifts. Shift with shift factor {0} needed.")
|
|
||||||
).format(shift_factor + diff)
|
|
||||||
|
|
||||||
def create_new_asset_depr_schedule(self):
|
def create_new_asset_depr_schedule(self):
|
||||||
new_asset_depr_schedule_doc = frappe.copy_doc(self.asset_depr_schedule_doc)
|
new_asset_depr_schedule_doc = frappe.copy_doc(self.asset_depr_schedule_doc)
|
||||||
|
|
||||||
@@ -259,17 +224,3 @@ class AssetShiftAllocation(Document):
|
|||||||
get_link_to_form(self.doctype, self.name)
|
get_link_to_form(self.doctype, self.name)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def find_subsets_with_sum(numbers, k, target_sum, current_subset, result):
|
|
||||||
if k == 0 and target_sum == 0:
|
|
||||||
result.append(current_subset.copy())
|
|
||||||
return
|
|
||||||
if k <= 0 or target_sum <= 0 or not numbers:
|
|
||||||
return
|
|
||||||
|
|
||||||
# Include the current number in the subset
|
|
||||||
find_subsets_with_sum(numbers, k - 1, target_sum - numbers[0], [*current_subset, numbers[0]], result)
|
|
||||||
|
|
||||||
# Exclude the current number from the subset
|
|
||||||
find_subsets_with_sum(numbers[1:], k, target_sum, current_subset, result)
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ def execute():
|
|||||||
"Property Setter",
|
"Property Setter",
|
||||||
{"doc_type": "Journal Entry", "field_name": "voucher_type", "property": "options"},
|
{"doc_type": "Journal Entry", "field_name": "voucher_type", "property": "options"},
|
||||||
["name", "value"],
|
["name", "value"],
|
||||||
|
as_dict=True,
|
||||||
)
|
)
|
||||||
if custom_je_type:
|
if custom_je_type:
|
||||||
custom_je_type.value += "\nAsset Disposal"
|
custom_je_type.value += "\nAsset Disposal"
|
||||||
|
|||||||
Reference in New Issue
Block a user