33
33
get_asset_depr_schedule_doc ,
34
34
get_depr_schedule ,
35
35
make_draft_asset_depr_schedules ,
36
- make_draft_asset_depr_schedules_if_not_present ,
37
36
update_draft_asset_depr_schedules ,
38
37
)
39
38
from erpnext .controllers .accounts_controller import AccountsController
@@ -127,30 +126,55 @@ def validate(self):
127
126
self .set_missing_values ()
128
127
self .validate_gross_and_purchase_amount ()
129
128
self .validate_finance_books ()
130
-
131
- if not self .split_from :
132
- self .prepare_depreciation_data ()
133
-
134
- if self .calculate_depreciation :
135
- update_draft_asset_depr_schedules (self )
136
-
137
- if frappe .db .exists ("Asset" , self .name ):
138
- asset_depr_schedules_names = make_draft_asset_depr_schedules_if_not_present (self )
139
-
140
- if asset_depr_schedules_names :
141
- asset_depr_schedules_links = get_comma_separated_links (
142
- asset_depr_schedules_names , "Asset Depreciation Schedule"
143
- )
144
- frappe .msgprint (
145
- _ (
146
- "Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
147
- ).format (asset_depr_schedules_links )
148
- )
149
129
self .validate_expected_value_after_useful_life ()
150
130
self .set_total_booked_depreciations ()
151
131
self .total_asset_cost = self .gross_purchase_amount
152
132
self .status = self .get_status ()
153
133
134
+ def create_asset_depreciation_schedule (self ):
135
+ if self .split_from or not self .calculate_depreciation :
136
+ return
137
+
138
+ self .set_depr_rate_and_value_after_depreciation ()
139
+
140
+ schedules = []
141
+ for row in self .get ("finance_books" ):
142
+ self .validate_asset_finance_books (row )
143
+ if not row .rate_of_depreciation :
144
+ row .rate_of_depreciation = self .get_depreciation_rate (row , on_validate = True )
145
+
146
+ schedule_doc = get_asset_depr_schedule_doc (self .name , "Draft" , row .finance_book )
147
+ if not schedule_doc :
148
+ schedule_doc = frappe .new_doc ("Asset Depreciation Schedule" )
149
+
150
+ schedule_doc .prepare_draft_asset_depr_schedule_data (self , row )
151
+ schedule_doc .save ()
152
+ schedules .append (schedule_doc .name )
153
+
154
+ self .show_schedule_creation_message (schedules )
155
+
156
+ def set_depr_rate_and_value_after_depreciation (self ):
157
+ if self .calculate_depreciation :
158
+ self .value_after_depreciation = 0
159
+ self .set_depreciation_rate ()
160
+ else :
161
+ self .finance_books = []
162
+ self .value_after_depreciation = flt (self .gross_purchase_amount ) - flt (
163
+ self .opening_accumulated_depreciation
164
+ )
165
+
166
+ def show_schedule_creation_message (self , schedules ):
167
+ if schedules :
168
+ asset_depr_schedules_links = get_comma_separated_links (schedules , "Asset Depreciation Schedule" )
169
+ frappe .msgprint (
170
+ _ (
171
+ "Asset Depreciation Schedules created/updated:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
172
+ ).format (asset_depr_schedules_links )
173
+ )
174
+
175
+ def on_update (self ):
176
+ self .create_asset_depreciation_schedule ()
177
+
154
178
def on_submit (self ):
155
179
self .validate_in_use_date ()
156
180
self .make_asset_movement ()
@@ -174,17 +198,17 @@ def on_cancel(self):
174
198
self .db_set ("booked_fixed_asset" , 0 )
175
199
add_asset_activity (self .name , _ ("Asset cancelled" ))
176
200
177
- def after_insert (self ):
178
- if self .calculate_depreciation and not self .split_from :
179
- asset_depr_schedules_names = make_draft_asset_depr_schedules (self )
180
- asset_depr_schedules_links = get_comma_separated_links (
181
- asset_depr_schedules_names , "Asset Depreciation Schedule"
182
- )
183
- frappe .msgprint (
184
- _ (
185
- "Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
186
- ).format (asset_depr_schedules_links )
187
- )
201
+ # def after_insert(self):
202
+ # if self.calculate_depreciation and not self.split_from:
203
+ # asset_depr_schedules_names = make_draft_asset_depr_schedules(self)
204
+ # asset_depr_schedules_links = get_comma_separated_links(
205
+ # asset_depr_schedules_names, "Asset Depreciation Schedule"
206
+ # )
207
+ # frappe.msgprint(
208
+ # _(
209
+ # "Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
210
+ # ).format(asset_depr_schedules_links)
211
+ # )
188
212
if (
189
213
not frappe .db .exists (
190
214
{
@@ -214,16 +238,6 @@ def validate_asset_and_reference(self):
214
238
if self .is_existing_asset and self .purchase_invoice :
215
239
frappe .throw (_ ("Purchase Invoice cannot be made against an existing asset {0}" ).format (self .name ))
216
240
217
- def prepare_depreciation_data (self ):
218
- if self .calculate_depreciation :
219
- self .value_after_depreciation = 0
220
- self .set_depreciation_rate ()
221
- else :
222
- self .finance_books = []
223
- self .value_after_depreciation = flt (self .gross_purchase_amount ) - flt (
224
- self .opening_accumulated_depreciation
225
- )
226
-
227
241
def validate_item (self ):
228
242
item = frappe .get_cached_value (
229
243
"Item" , self .item_code , ["is_fixed_asset" , "is_stock_item" , "disabled" ], as_dict = 1
@@ -308,6 +322,22 @@ def validate_finance_books(self):
308
322
title = _ ("Missing Finance Book" ),
309
323
)
310
324
325
+ # def set_depreciation_start_date(self):
326
+ # if not self.calculate_depreciation:
327
+ # return
328
+
329
+ # for d in self.get("finance_books"):
330
+ # if not d.depreciation_start_date:
331
+ # if self.is_existing_asset and self.opening_number_of_booked_depreciations:
332
+
333
+ # months = d.frequency_of_depreciation * self.opening_number_of_booked_depreciations
334
+ # else:
335
+ # months = d.frequency_of_depreciation
336
+
337
+ # d.depreciation_start_date = get_last_day(
338
+ # add_months(self.available_for_use_date, months)
339
+ # )
340
+
311
341
def validate_precision (self ):
312
342
float_precision = cint (frappe .db .get_default ("float_precision" )) or 2
313
343
if self .gross_purchase_amount :
@@ -418,61 +448,65 @@ def validate_asset_finance_books(self, row):
418
448
frappe .throw (
419
449
_ ("Row {0}: Expected Value After Useful Life must be less than Gross Purchase Amount" ).format (
420
450
row .idx
421
- ),
422
- title = _ ("Invalid Schedule" ),
451
+ )
423
452
)
424
453
425
454
if not row .depreciation_start_date :
426
- if not self .available_for_use_date :
427
- frappe .throw (
428
- _ ("Row {0}: Depreciation Start Date is required" ).format (row .idx ),
429
- title = _ ("Invalid Schedule" ),
430
- )
431
455
row .depreciation_start_date = get_last_day (self .available_for_use_date )
456
+ self .validate_depreciation_start_date (row )
432
457
433
458
if not self .is_existing_asset :
434
459
self .opening_accumulated_depreciation = 0
435
460
self .opening_number_of_booked_depreciations = 0
436
461
else :
437
- depreciable_amount = flt (
438
- flt (self .gross_purchase_amount ) - flt (row .expected_value_after_useful_life ),
439
- self .precision ("gross_purchase_amount" ),
440
- )
441
- if flt (self .opening_accumulated_depreciation ) > depreciable_amount :
442
- frappe .throw (
443
- _ ("Opening Accumulated Depreciation must be less than or equal to {0}" ).format (
444
- depreciable_amount
445
- )
462
+ self .validate_opening_depreciation_values (row )
463
+
464
+ def validate_opening_depreciation_values (self , row ):
465
+ row .expected_value_after_useful_life = flt (
466
+ row .expected_value_after_useful_life , self .precision ("gross_purchase_amount" )
467
+ )
468
+ depreciable_amount = flt (
469
+ flt (self .gross_purchase_amount ) - flt (row .expected_value_after_useful_life ),
470
+ self .precision ("gross_purchase_amount" ),
471
+ )
472
+ if flt (self .opening_accumulated_depreciation ) > depreciable_amount :
473
+ frappe .throw (
474
+ _ ("Row #{0}: Opening Accumulated Depreciation must be less than or equal to {1}" ).format (
475
+ row .idx , depreciable_amount
446
476
)
477
+ )
447
478
448
- if self .opening_accumulated_depreciation :
449
- if not self .opening_number_of_booked_depreciations :
450
- frappe .throw (_ ("Please set Opening Number of Booked Depreciations" ))
451
- else :
452
- self .opening_number_of_booked_depreciations = 0
479
+ if self .opening_accumulated_depreciation :
480
+ if not self .opening_number_of_booked_depreciations :
481
+ frappe .throw (_ ("Please set opening number of booked depreciations" ))
482
+ else :
483
+ self .opening_number_of_booked_depreciations = 0
484
+
485
+ if flt (row .total_number_of_depreciations ) <= cint (self .opening_number_of_booked_depreciations ):
486
+ frappe .throw (
487
+ _ (
488
+ "Row #{0}: Total Number of Depreciations cannot be less than or equal to Opening Number of Booked Depreciations"
489
+ ).format (row .idx ),
490
+ title = _ ("Invalid Schedule" ),
491
+ )
453
492
454
- if flt (row .total_number_of_depreciations ) <= cint (self .opening_number_of_booked_depreciations ):
493
+ def validate_depreciation_start_date (self , row ):
494
+ if row .depreciation_start_date :
495
+ if getdate (row .depreciation_start_date ) < getdate (self .purchase_date ):
455
496
frappe .throw (
456
- _ (
457
- "Row {0}: Total Number of Depreciations cannot be less than or equal to Opening Number of Booked Depreciations"
458
- ).format (row .idx ),
459
- title = _ ("Invalid Schedule" ),
497
+ _ ("Row #{0}: Next Depreciation Date cannot be before Purchase Date" ).format (row .idx )
460
498
)
461
499
462
- if row .depreciation_start_date and getdate (row .depreciation_start_date ) < getdate (self .purchase_date ):
463
- frappe .throw (
464
- _ ("Depreciation Row {0}: Next Depreciation Date cannot be before Purchase Date" ).format (
465
- row .idx
500
+ if getdate (row .depreciation_start_date ) < getdate (self .available_for_use_date ):
501
+ frappe .throw (
502
+ _ ("Row #{0}: Next Depreciation Date cannot be before Available-for-use Date" ).format (
503
+ row .idx
504
+ )
466
505
)
467
- )
468
-
469
- if row .depreciation_start_date and getdate (row .depreciation_start_date ) < getdate (
470
- self .available_for_use_date
471
- ):
506
+ else :
472
507
frappe .throw (
473
- _ (
474
- "Depreciation Row {0}: Next Depreciation Date cannot be before Available-for-use Date"
475
- ).format (row .idx )
508
+ _ ("Row #{0}: Depreciation Start Date is required" ).format (row .idx ),
509
+ title = _ ("Invalid Schedule" ),
476
510
)
477
511
478
512
def set_total_booked_depreciations (self ):
@@ -496,15 +530,11 @@ def validate_expected_value_after_useful_life(self):
496
530
if not depr_schedule :
497
531
continue
498
532
499
- accumulated_depreciation_after_full_schedule = [
500
- d .accumulated_depreciation_amount for d in depr_schedule
501
- ]
533
+ accumulated_depreciation_after_full_schedule = max (
534
+ [ d .accumulated_depreciation_amount for d in depr_schedule ]
535
+ )
502
536
503
537
if accumulated_depreciation_after_full_schedule :
504
- accumulated_depreciation_after_full_schedule = max (
505
- accumulated_depreciation_after_full_schedule
506
- )
507
-
508
538
asset_value_after_full_schedule = flt (
509
539
flt (self .gross_purchase_amount ) - flt (accumulated_depreciation_after_full_schedule ),
510
540
self .precision ("gross_purchase_amount" ),
@@ -786,50 +816,59 @@ def get_depreciation_rate(self, args, on_validate=False):
786
816
if isinstance (args , str ):
787
817
args = json .loads (args )
788
818
789
- float_precision = cint ( frappe .db . get_default ( "float_precision" ) ) or 2
819
+ rate_field_precision = frappe .get_precision ( args . doctype , "rate_of_depreciation" ) or 2
790
820
791
821
if args .get ("depreciation_method" ) == "Double Declining Balance" :
792
- return 200.0 / (
822
+ return self .get_double_declining_balance_rate (args , rate_field_precision )
823
+ elif args .get ("depreciation_method" ) == "Written Down Value" :
824
+ return self .get_written_down_value_rate (args , rate_field_precision , on_validate )
825
+
826
+ def get_double_declining_balance_rate (self , args , rate_field_precision ):
827
+ return flt (
828
+ 200.0
829
+ / (
793
830
(
794
831
flt (args .get ("total_number_of_depreciations" ), 2 )
795
832
* flt (args .get ("frequency_of_depreciation" ))
796
833
)
797
834
/ 12
798
- )
835
+ ),
836
+ rate_field_precision ,
837
+ )
799
838
800
- if args . get ( "depreciation_method" ) == "Written Down Value" :
801
- if (
802
- args .get ("rate_of_depreciation" )
803
- and on_validate
804
- and not self .flags .increase_in_asset_value_due_to_repair
805
- ):
806
- return args .get ("rate_of_depreciation" )
839
+ def get_written_down_value_rate ( self , args , rate_field_precision , on_validate ) :
840
+ if (
841
+ args .get ("rate_of_depreciation" )
842
+ and on_validate
843
+ and not self .flags .increase_in_asset_value_due_to_repair
844
+ ):
845
+ return args .get ("rate_of_depreciation" )
807
846
808
- if self .flags .increase_in_asset_value_due_to_repair :
809
- value = flt (args .get ("expected_value_after_useful_life" )) / flt (
810
- args .get ("value_after_depreciation" )
811
- )
812
- else :
813
- value = flt (args .get ("expected_value_after_useful_life" )) / (
814
- flt (self .gross_purchase_amount ) - flt (self .opening_accumulated_depreciation )
815
- )
847
+ if self .flags .increase_in_asset_value_due_to_repair :
848
+ value = flt (args .get ("expected_value_after_useful_life" )) / flt (
849
+ args .get ("value_after_depreciation" )
850
+ )
851
+ else :
852
+ value = flt (args .get ("expected_value_after_useful_life" )) / (
853
+ flt (self .gross_purchase_amount ) - flt (self .opening_accumulated_depreciation )
854
+ )
816
855
817
- depreciation_rate = math .pow (
818
- value ,
819
- 1.0
820
- / (
856
+ depreciation_rate = math .pow (
857
+ value ,
858
+ 1.0
859
+ / (
860
+ (
821
861
(
822
- (
823
- flt (args .get ("total_number_of_depreciations" ), 2 )
824
- - flt (self .opening_number_of_booked_depreciations )
825
- )
826
- * flt (args .get ("frequency_of_depreciation" ))
862
+ flt (args .get ("total_number_of_depreciations" ), 2 )
863
+ - flt (self .opening_number_of_booked_depreciations )
827
864
)
828
- / 12
829
- ),
830
- )
865
+ * flt (args .get ("frequency_of_depreciation" ))
866
+ )
867
+ / 12
868
+ ),
869
+ )
831
870
832
- return flt ((100 * (1 - depreciation_rate )), float_precision )
871
+ return flt ((100 * (1 - depreciation_rate )), rate_field_precision )
833
872
834
873
835
874
def has_gl_entries (doctype , docname , target_account ):
0 commit comments