fix: remove duplicate patch

This commit is contained in:
Khushi Rawat
2025-01-14 01:49:40 +05:30
parent 5f21d7ea1d
commit 813164c25b
9 changed files with 209 additions and 246 deletions

View File

@@ -160,7 +160,7 @@ class Asset(AccountsController):
if self.calculate_depreciation:
self.set_depreciation_rate()
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:
self.finance_books = []

View File

@@ -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 (
get_asset_depr_schedule_doc,
get_asset_depr_schedule_name,
get_temp_asset_depr_schedule_doc,
get_temp_depr_schedule_doc,
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]
temp_asset_depreciation_schedule = get_temp_asset_depr_schedule_doc(
asset_doc, row, getdate(disposal_date)
)
temp_asset_depreciation_schedule = get_temp_depr_schedule_doc(asset_doc, row, getdate(disposal_date))
accumulated_depr_amount = temp_asset_depreciation_schedule.get("depreciation_schedule")[
-1

View File

@@ -107,14 +107,9 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
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
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)
self.create_depreciation_schedule()
def get_finance_book_row(self, fb_row=None):
if fb_row:
@@ -144,6 +139,7 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
self.total_number_of_depreciations = self.fb_row.total_number_of_depreciations
self.frequency_of_depreciation = self.fb_row.frequency_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.daily_prorata_based = self.fb_row.get("daily_prorata_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
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(
asset_doc,
row,
disposal_date=None,
date_of_return=None,
update_asset_finance_book_row=False,
new_depr_schedule=None,
):
if updated_depr_schedule:
modify_depreciation_dchedule(temp_schedule_doc, updated_depr_schedule)
temp_schedule_doc.create_depreciation_schedule(fb_row, disposal_date)
return temp_schedule_doc
def get_current_asset_depr(asset_doc, row):
current_schedule = get_asset_depr_schedule_doc(asset_doc.name, "Active", row.finance_book)
if not current_schedule:
frappe.throw(
_("Asset Depreciation Schedule not found for Asset {0} and Finance Book {1}").format(
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:
temp_asset_depr_schedule_doc.depreciation_schedule = []
def modify_depreciation_dchedule(temp_schedule_doc, updated_depr_schedule):
temp_schedule_doc.depreciation_schedule = []
for schedule in new_depr_schedule:
temp_asset_depr_schedule_doc.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,
},
)
for schedule in updated_depr_schedule:
temp_schedule_doc.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,
},
)
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()

View File

@@ -42,7 +42,6 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
depr_schedule = []
self.schedules_before_clearing = self.get("depreciation_schedule")
for schedule in self.get("depreciation_schedule"):
if schedule.journal_entry:
num_of_depreciations_completed += 1
@@ -68,7 +67,6 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
self.schedule_date = self.get_next_schedule_date(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 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(
self.fb_row.frequency_of_depreciation
) + cint(self.fb_row.increase_in_asset_life)
depr_booked_for_months = 0
last_depr_date = self.get_last_booked_depreciation_date()
if last_depr_date:
depr_booked_for_months = date_diff(last_depr_date, self.asset_doc.available_for_use_date) / (
365 / 12
)
depr_booked_for_months = self.get_booked_depr_for_months_count(last_depr_date)
self.pending_months = total_months - depr_booked_for_months
@@ -245,9 +239,22 @@ class DepreciationScheduleController(StraightLineMethod, WDVMethod):
last_depr_date = add_months(
self.fb_row.depreciation_start_date, -1 * self.fb_row.frequency_of_depreciation
)
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):
if cint(frappe.db.get_single_value("Accounts Settings", "calculate_depr_using_total_days")):
last_depr_date = self.get_last_booked_depreciation_date()

View File

@@ -25,7 +25,7 @@ class StraightLineMethod(Document):
)
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:
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
def get_shift_depr_amount(self, row_idx):
depreciable_value = (
flt(self.asset_doc.gross_purchase_amount)
- flt(self.asset_doc.opening_accumulated_depreciation)
- 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
if not self.schedules_before_clearing:
pending_periods = flt(self.pending_months) / flt(self.fb_row.frequency_of_depreciation)
return self.depreciable_value / pending_periods
asset_shift_factors_map = self.get_asset_shift_factors_map()
shift = (
self.schedules_before_clearing[row_idx].shift
if len(self.schedules_before_clearing) > row_idx
else None
)
if self.schedules_before_clearing:
shift = (
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_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):
return dict(frappe.db.get_all("Asset Shift Factor", ["shift_name", "shift_factor"], as_list=True))

View File

@@ -2,6 +2,15 @@
// For license information, please see license.txt
frappe.ui.form.on("Asset Shift Allocation", {
onload: function (frm) {
frm.set_query("asset", function () {
return {
filters: {
company: frm.doc.company,
docstatus: 1,
},
};
});
frm.events.make_schedules_editable(frm);
},

View File

@@ -12,6 +12,7 @@
"finance_book",
"amended_from",
"depreciation_schedule_section",
"column_break_jomc",
"depreciation_schedule"
],
"fields": [
@@ -57,7 +58,9 @@
"fieldname": "depreciation_schedule",
"fieldtype": "Table",
"label": "Depreciation Schedule",
"options": "Depreciation Schedule"
"no_copy": 1,
"options": "Depreciation Schedule",
"read_only": 1
},
{
"fieldname": "naming_series",
@@ -65,12 +68,16 @@
"label": "Naming Series",
"options": "ACC-ASA-.YYYY.-",
"reqd": 1
},
{
"fieldname": "column_break_jomc",
"fieldtype": "Column Break"
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-03-27 13:06:35.732191",
"modified": "2025-01-10 16:25:31.397325",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Shift Allocation",

View File

@@ -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_depreciation_schedule.asset_depreciation_schedule import (
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_temp_depr_schedule_doc,
)
@@ -32,9 +30,7 @@ class AssetShiftAllocation(Document):
if TYPE_CHECKING:
from frappe.types import DF
from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import (
DepreciationSchedule,
)
from erpnext.assets.doctype.depreciation_schedule.depreciation_schedule import DepreciationSchedule
amended_from: DF.Link | None
asset: DF.Link
@@ -43,32 +39,138 @@ class AssetShiftAllocation(Document):
naming_series: DF.Literal["ACC-ASA-.YYYY.-"]
# end: auto-generated types
def after_insert(self):
self.fetch_and_set_depr_schedule()
def validate(self):
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()
self.update_depr_schedule()
def after_insert(self):
self.fetch_and_set_depr_schedule()
def on_submit(self):
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):
if self.asset_depr_schedule_doc:
if self.asset_depr_schedule_doc.shift_based:
for schedule in self.asset_depr_schedule_doc.get("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.modify_depr_schedule(self.asset_depr_schedule_doc.depreciation_schedule)
self.flags.ignore_validate = True
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):
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)
),
)
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)

View File

@@ -6,6 +6,7 @@ def execute():
"Property Setter",
{"doc_type": "Journal Entry", "field_name": "voucher_type", "property": "options"},
["name", "value"],
as_dict=True,
)
if custom_je_type:
custom_je_type.value += "\nAsset Disposal"