@@ -140,15 +140,20 @@ impl YearAndMonth {
140140 /// use klirr_core::prelude::*;
141141 /// let start = YearAndMonth::january(2025);
142142 /// let end = YearAndMonth::april(2025);
143- /// assert_eq!(end.elapsed_months_since(start), 3);
143+ /// assert_eq!(end.elapsed_months_since(start).unwrap() , 3);
144144 /// ```
145145 ///
146- /// # Panics
147- /// Panics if the `start` month is after the `end` month.
148- pub fn elapsed_months_since ( & self , start : impl Borrow < Self > ) -> u16 {
146+ /// # Throws
147+ /// Throws an error if the `start` month is after the `end` month.
148+ pub fn elapsed_months_since ( & self , start : impl Borrow < Self > ) -> Result < u16 > {
149149 let end = self ;
150150 let start = start. borrow ( ) ;
151- assert ! ( start <= end, "Expected start <= end month" ) ;
151+ if start > end {
152+ return Err ( Error :: StartPeriodAfterEndPeriod {
153+ start : start. to_string ( ) ,
154+ end : end. to_string ( ) ,
155+ } ) ;
156+ }
152157 let start_year = * * start. year ( ) ;
153158 let start_month = * * start. month ( ) as u16 ;
154159 let end_year = * * end. year ( ) ;
@@ -159,7 +164,8 @@ impl YearAndMonth {
159164 let months_per_year = 12 ;
160165 let start_months = start_year * months_per_year + start_month;
161166 let end_months = end_year * months_per_year + end_month;
162- end_months - start_months
167+ let months_elapsed = end_months - start_months;
168+ Ok ( months_elapsed)
163169 }
164170}
165171
@@ -192,7 +198,7 @@ impl IsPeriod for YearAndMonth {
192198 Granularity :: Month
193199 }
194200
195- fn elapsed_periods_since ( & self , start : impl Borrow < Self > ) -> u16 {
201+ fn elapsed_periods_since ( & self , start : impl Borrow < Self > ) -> Result < u16 > {
196202 self . elapsed_months_since ( start)
197203 }
198204
@@ -232,7 +238,7 @@ impl IsPeriod for YearAndMonth {
232238/// &target_month,
233239/// is_expenses,
234240/// &months_off_record,
235- /// );
241+ /// ).unwrap() ;
236242///
237243/// // The expected invoice number is calculated as follows:
238244/// // - Offset is 100
@@ -248,13 +254,13 @@ pub fn calculate_invoice_number<Period: IsPeriod>(
248254 target_period : & Period ,
249255 is_expenses : bool ,
250256 record_of_periods_off : & RecordOfPeriodsOff < Period > ,
251- ) -> InvoiceNumber {
252- assert ! (
253- !record_of_periods_off . contains ( offset . period ( ) ) ,
254- "Record of periods off contains offset.period(): {:?} but it should not." ,
255- offset . period ( )
256- ) ;
257- let periods_elapsed_since_offset = target_period. elapsed_periods_since ( offset. period ( ) ) ;
257+ ) -> Result < InvoiceNumber > {
258+ if record_of_periods_off . contains ( offset . period ( ) ) {
259+ return Err ( Error :: RecordsOffMustNotContainOffsetPeriod {
260+ offset_period : format ! ( " {:?}" , offset . period ( ) ) ,
261+ } ) ;
262+ }
263+ let periods_elapsed_since_offset = target_period. elapsed_periods_since ( offset. period ( ) ) ? ;
258264
259265 let mut periods_off_to_subtract = 0 ;
260266 for period_off in record_of_periods_off. iter ( ) {
@@ -271,7 +277,7 @@ pub fn calculate_invoice_number<Period: IsPeriod>(
271277 // expenses the same month, the expense invoice number is always higher.
272278 invoice_number += 1 ;
273279 }
274- InvoiceNumber :: from ( invoice_number)
280+ Ok ( InvoiceNumber :: from ( invoice_number) )
275281}
276282
277283/// Calculates the number of working days in a given month, excluding weekends.
@@ -589,7 +595,8 @@ mod tests {
589595 & YearAndMonth :: from ( target_period) ,
590596 is_expenses,
591597 information. record_of_periods_off ( ) ,
592- ) ;
598+ )
599+ . unwrap ( ) ;
593600 assert_eq ! ( invoice_number, expected. into( ) ) ;
594601 }
595602
@@ -859,7 +866,7 @@ mod tests {
859866 fn test_elapsed_months_since_when_start_month_is_later_in_the_year_than_end_month ( ) {
860867 let start = YearAndMonth :: december ( 2024 ) ;
861868 let end = YearAndMonth :: april ( 2025 ) ;
862- assert_eq ! ( end. elapsed_months_since( start) , 4 ) ;
869+ assert_eq ! ( end. elapsed_months_since( start) . unwrap ( ) , 4 ) ;
863870 assert ! ( start < end) ;
864871 }
865872
@@ -871,16 +878,14 @@ mod tests {
871878 }
872879
873880 #[ test]
874- #[ should_panic]
875- fn test_elapsed_months_since_panic ( ) {
881+ fn elapsed_months_since_throws_when_start_month_is_later_than_end_month ( ) {
876882 let start = YearAndMonth :: april ( 2025 ) ;
877883 let end = YearAndMonth :: march ( 2025 ) ;
878- end. elapsed_months_since ( start) ;
884+ assert ! ( end. elapsed_months_since( start) . is_err ( ) ) ;
879885 }
880886
881887 #[ test]
882- #[ should_panic]
883- fn test_calculate_invoice_number_panics_for_invalid_input ( ) {
888+ fn test_calculate_invoice_number_throws_for_invalid_input ( ) {
884889 let month = YearAndMonth :: may ( 2025 ) ;
885890 let invoice_info = ProtoInvoiceInfo :: builder ( )
886891 . offset (
@@ -893,12 +898,13 @@ mod tests {
893898 . purchase_order ( PurchaseOrder :: sample ( ) )
894899 . build ( ) ;
895900
896- let _ = calculate_invoice_number (
901+ let result = calculate_invoice_number (
897902 invoice_info. offset ( ) ,
898903 & YearAndMonth :: december ( 2025 ) ,
899904 true ,
900905 invoice_info. record_of_periods_off ( ) ,
901906 ) ;
907+ assert ! ( result. is_err( ) ) ;
902908 }
903909
904910 #[ test]
0 commit comments