package Ġcom . housing . movie . features . order . data . service Ċ Ċ import Ġcom . housing . movie . exceptions .* Ċ import Ġcom . housing . movie . features . discount . data . repository . Discount Repository Ċ import Ġcom . housing . movie . features . discount . domain . entity . Discount Ċ import Ġcom . housing . movie . features . movie . data . repository . Movie Repository Ċ import Ġcom . housing . movie . features . movie . domain . entity . Movie Ċ import Ġcom . housing . movie . features . order . data . repository . Order Repository Ċ import Ġcom . housing . movie . features . order . domain . entity . Order Ċ import Ġcom . housing . movie . features . order . domain . service . Order QueryParams Ċ import Ġcom . housing . movie . features . order . domain . service . Order Service Ċ import Ġcom . housing . movie . features . order . domain . use case . create _ order . Create Order Request Ċ import Ġcom . housing . movie . features . plan . data . repository . Plan Repository Ċ import Ġcom . housing . movie . features . plan . domain . entity . Plan Ċ import Ġcom . housing . movie . features . user . data . repository . UserRepository Ċ import Ġcom . housing . movie . features . user . domain . entity . Application User Ċ import Ġcom . housing . movie . utils . DateTime Helper Ċ import Ġcom . housing . movie . utils . Servlet Helper Ċ import Ġorg . springframework . data . repository . findById OrNull Ċ import Ġorg . springframework . stereotype . Service Ċ import Ġjava . time . Month Ċ import Ġjava . util .* Ċ import Ġkotlin . math . round To Long Ċ Ċ @ Service Ċ class ĠOrder ServiceImpl ( ĊĠĠĠ Ġprivate Ġval Ġorder Repository : ĠOrder Repository , ĊĠĠĠ Ġprivate Ġval Ġuser Repository : ĠUser Repository , ĊĠĠĠ Ġprivate Ġval Ġmovie Repository : ĠMovie Repository , ĊĠĠĠ Ġprivate Ġval Ġplan Repository : ĠPlan Repository , ĊĠĠĠ Ġprivate Ġval Ġdiscount Repository : ĠDiscount Repository Ċ ) Ġ: ĠOrder Service Ġ{ ĊĊĠĠĠ Ġcompanion Ġobject Ġ{ ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠUSER _ NOT _ FOUND Ġ= Ġ" User Ġnot Ġfound ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMO VI ES _ AND _ PLAN _ CAN NOT _ BE _ NULL Ġ= Ġ" Movies Ġor Ġplan Ġcannot Ġbe Ġempty ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMO VI ES _ AND _ PLAN _ CAN NOT _ EXISTS _ AT _ THE _ SAME _ TIME Ġ= Ġ" Movies Ġand Ġplan Ġcannot Ġexists Ġat Ġthe Ġsame Ġm om ment ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMOV IE _ NOT _ FOUND Ġ= Ġ" Movie Ġnot Ġfound ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠPL AN _ NOT _ FOUND Ġ= Ġ" Plan Ġnot Ġfound ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDIS COUNT _ NOT _ FOUND Ġ= Ġ" Discount Ġnot Ġfound ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠDIS COUNT _ INVALID ATE Ġ= Ġ" Discount Ġis Ġunable Ġto Ġbe Ġused Ġat Ġthe Ġmoment ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠORDER _ NOT _ FOUND Ġ= Ġ" Order Ġnot Ġfound ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠUSER _ AL READY _ PUR CH ASE D _ PLAN Ġ= Ġ" User Ġhave Ġalready Ġen rolled Ġa Ġplan ." ĊĠĠĠĠĠĠĠ Ġconst Ġval ĠMOV IE _ AL READY _ PUR CH ASE D Ġ= Ġ" Movie Ġalready Ġpurch ased : Ġ% s " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Orders UseCase ( order QueryParams : ĠOrder QueryParams ): ĠList < Order > Ġ{ ĊĊĠĠĠĠĠĠĠ Ġval Ġorders Ġ= Ġmutable ListOf < Order >() ĊĠĠĠĠĠĠĠ Ġval ĠuserId Ġ= Ġorder QueryParams . user _ id ĊĠĠĠĠĠĠĠ Ġval Ġfrom Time Ġ= ĠDateTime Helper . time Stamp To Calendar ( order QueryParams . from _ time ) ĊĠĠĠĠĠĠĠ Ġval Ġto Time Ġ= ĠDateTime Helper . time Stamp To Calendar ( order QueryParams . to _ time ) ĊĊĠĠĠĠĠĠĠ Ġif Ġ( userId Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( from Time Ġ== Ġnull Ġ&& Ġto Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( order Repository . findBy OrderBy Order Time Desc ()) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( from Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠCalendar . getInstance () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠstartTime . set ( 1 9 9 0 , ĠMonth . J AN U ARY . value , Ġ 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( order Repository . findBy Order Time Between OrderBy Order Time Desc ( startTime , Ġto Time !! )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( to Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠendTime Ġ= ĠCalendar . getInstance () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( order Repository . findBy Order Time Between OrderBy Order Time Desc ( from Time , ĠendTime )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( order Repository . findBy Order Time Between OrderBy Order Time Desc ( from Time , Ġto Time )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( from Time Ġ== Ġnull Ġ&& Ġto Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( order Repository . findBy User _ Id OrderBy Order Time Desc ( userId )) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( from Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠstartTime Ġ= ĠCalendar . getInstance () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠstartTime . set ( 1 9 9 0 , ĠMonth . J AN U ARY . value , Ġ 1 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorder Repository . findBy User _ Id And Order Time Between OrderBy Order Time Desc ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠuserId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠstartTime , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Time !! ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( to Time Ġ== Ġnull ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval ĠendTime Ġ= ĠCalendar . getInstance () ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorder Repository . findBy User _ Id And Order Time Between OrderBy Order Time Desc ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠuserId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfrom Time , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠendTime ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorders . addAll ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorder Repository . findBy User _ Id And Order Time Between OrderBy Order Time Desc ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠuserId , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfrom Time , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Time ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġorders ĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġcreate Order ( create Order Request : ĠCreate Order Request ): ĠOrder Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġusername Ġ= ĠServlet Helper . retrieve Username And Roles Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠCustom Authentication Exception () ĊĠĠĠĠĠĠĠ Ġ}. first ĊĊĠĠĠĠĠĠĠ Ġval Ġuser Ġ= Ġvalidate User ( username ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmovie Ids Ġ= Ġcreate Order Request . movie Ids ĊĠĠĠĠĠĠĠ Ġval Ġplan Id Ġ= Ġcreate Order Request . plan Id ĊĠĠĠĠĠĠĠ Ġval Ġdiscount Code Ġ= Ġcreate Order Request . discount Code ĊĊĠĠĠĠĠĠĠ Ġif Ġ( movie Ids Ġ== Ġnull Ġ&& Ġplan Id Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠMissing Property Exception ( MO VI ES _ AND _ PLAN _ CAN NOT _ BE _ NULL ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġif Ġ( movie Ids Ġ!= Ġnull Ġ&& Ġplan Id Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠConversion Exception ( MO VI ES _ AND _ PLAN _ CAN NOT _ EXISTS _ AT _ THE _ SAME _ TIME ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġmovies Ġ= Ġvalidate Movies ( movie Ids , Ġusername ) ĊĠĠĠĠĠĠĠ Ġval Ġplan Ġ= Ġvalidate Plan ( plan Id , Ġusername ) ĊĠĠĠĠĠĠĠ Ġval Ġdiscount Ġ= Ġvalidate Discount ( discount Code ) ĊĠĠĠĠĠĠĠ Ġval Ġtotal Ġ= Ġcalculate Order Total ( discount , Ġplan , Ġmovies Ġ?: Ġempty List ()) ĊĊĠĠĠĠĠĠĠ Ġvar Ġorder Ġ= ĠOrder ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġuser Ġ= Ġuser , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmovies Ġ= Ġmovies ?. to Mutable List () Ġ?: Ġmutable ListOf (), ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdiscount Ġ= Ġdiscount , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġplan Ġ= Ġplan , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtotal Ġ= Ġtotal ĊĠĠĠĠĠĠĠ Ġ) ĊĊĊĠĠĠĠĠĠĠ Ġorder Ġ= Ġorder Repository . save ( order ) ĊĊĠĠĠĠĠĠĠ Ġsave Order To User ( user , Ġorder ) ĊĠĠĠĠĠĠĠ Ġsave Order To Movies ( movies , Ġorder ) ĊĠĠĠĠĠĠĠ Ġsave Order To Plan ( plan , Ġorder ) ĊĠĠĠĠĠĠĠ Ġsave Order To Discount ( discount , Ġorder ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġorder ĊĊĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcalculate Order Total ( discount : ĠDiscount ?, Ġplan : ĠPlan ?, Ġmovies : ĠList < Movie >): ĠDouble Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġdiscount Value Ġ= Ġdiscount ?. value Ġ?: Ġ 0 . 0 ĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( plan Ġ!= Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbase Price Ġ= Ġplan . price ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdiscount ed Price Ġ= Ġbase Price Ġ- Ġ( discount Value Ġ* Ġbase Price ) Ġ/ Ġ 1 0 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfinal Price Ġ= Ġif Ġ( discount ed Price Ġ< Ġ 0 ) Ġ 0 . 0 Ġelse Ġdiscount ed Price ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġround ( final Price ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbase Price Ġ= Ġmovies . size Ġ* Ġ( movies . first OrNull () Ġ?: ĠMovie ()). price ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdiscount ed Price Ġ= Ġbase Price Ġ- Ġ( discount Value Ġ* Ġbase Price ) Ġ/ Ġ 1 0 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfinal Price Ġ= Ġif Ġ( discount ed Price Ġ< Ġ 0 ) Ġ 0 . 0 Ġelse Ġdiscount ed Price ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġround ( final Price ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġround ( value : ĠDouble ): ĠDouble Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġ( value Ġ* Ġ 1 0 0 ) Ġ/ Ġ 1 0 0 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġget Order ById ( orderId : ĠUUID ): ĠOrder Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġorder Repository . findById OrNull ( orderId ) Ġ?: Ġthrow ĠNotFound Exception ( ORDER _ NOT _ FOUND ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Order To User ( user : ĠApplication User , Ġorder : ĠOrder ) Ġ{ ĊĠĠĠĠĠĠĠ Ġuser . orders . add ( order ) ĊĠĠĠĠĠĠĠ Ġuser Repository . save ( user ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Order To Movies ( movies : ĠList < Movie > ?, Ġorder : ĠOrder ) Ġ{ ĊĊĠĠĠĠĠĠĠ Ġmovies Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġmovies . forEach Ġ{ Ġmovie Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġmovie . orders . add ( order ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġmovie Repository . save All ( movies ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Order To Plan ( plan : ĠPlan ?, Ġorder : ĠOrder ) Ġ{ ĊĠĠĠĠĠĠĠ Ġplan Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġplan . orders . add ( order ) ĊĠĠĠĠĠĠĠ Ġplan Repository . save ( plan ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġsave Order To Discount ( discount : ĠDiscount ?, Ġorder : ĠOrder ) Ġ{ ĊĠĠĠĠĠĠĠ Ġdiscount Ġ?: Ġreturn ĊĊĠĠĠĠĠĠĠ Ġdiscount . orders . add ( order ) ĊĠĠĠĠĠĠĠ Ġdiscount . remaining Amount Ġ-= Ġ 1 ĊĠĠĠĠĠĠĠ Ġdiscount Repository . save ( discount ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate User ( username : ĠString ): ĠApplication User Ġ{ ĊĊĠĠĠĠĠĠĠ Ġreturn Ġuser Repository . findBy Username ( username Ġ= Ġusername ) Ġ?: Ġthrow Ġ ĠNotFound Exception ( USER _ NOT _ FOUND ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Movies ( movie Ids : ĠList < UUID > ?, Ġusername : ĠString ): ĠList < Movie >? Ġ{ ĊĠĠĠĠĠĠĠ Ġmovie Ids Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! is Movie Already Purchase d ( movie Ids , Ġusername )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġmovies Ġ= Ġmovie Repository . findById IsIn ( movie Ids ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( movies . isEmpty ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠNotFound Exception ( MOV IE _ NOT _ FOUND ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġmovies ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġempty List () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġis Movie Already Purchase d ( movie Ids : ĠList < UUID >, Ġusername : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġorders With Movies Ġ= Ġorder Repository . findBy User _ Username And Movies Is NotEmpty OrderBy Order Time Desc ( username ) ĊĊĠĠĠĠĠĠĠ Ġval Ġpurch ased Movies Ids Ġ= Ġmutable ListOf < UUID >() ĊĊĠĠĠĠĠĠĠ Ġorders With Movies . forEach Ġ{ Ġorder Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġpurch ased Movies Ids . addAll ( order . movies . map Ġ{ Ġit . id Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġoverlap Movie Ids Ġ= Ġpurch ased Movies Ids . intersect ( movie Ids ) ĊĊĠĠĠĠĠĠĠ Ġ// ĠThe Ġintersection Ġbetween Ġpurch ased Ġmovie Ġids Ġand Ġwilling Ġto Ġpurchase Ġmovie Ids Ġis Ġthe Ġoverlapping Ġmovie ĊĠĠĠĠĠĠĠ Ġif Ġ( overlap Movie Ids . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġthrow ĠObject AlreadyExists Exception ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠMOV IE _ AL READY _ PUR CH ASE D . format ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoverlap Movie Ids . join ToString ( separator Ġ= Ġ", ") Ġ{ Ġit . toString () Ġ}, ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġfalse ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Plan ( plan Id : ĠUUID ?, Ġusername : ĠString ): ĠPlan ? Ġ{ ĊĠĠĠĠĠĠĠ Ġplan Id Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġif Ġ( is User Already En rolled Any In Expired Plan ( username )) Ġthrow ĠObject AlreadyExists Exception ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠUSER _ AL READY _ PUR CH ASE D _ PLAN ĊĠĠĠĠĠĠĠ Ġ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġplan Repository . findById OrNull ( plan Id ) Ġ?: Ġthrow ĠNotFound Exception ( PLAN _ NOT _ FOUND ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠIf Ġuser Ġalready Ġen rolled Ġin Ġa Ġplan Ġthat Ġhas Ġnot Ġexpired Ġyet Ġ-> Ġfalse ĊĠĠĠ Ġprivate Ġfun Ġis User Already En rolled Any In Expired Plan ( username : ĠString ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġorders Ġ= Ġorder Repository . findBy User _ Username And Plan IsNotNull OrderBy Order Time Desc ( username ) ĊĊĠĠĠĠĠĠĠ Ġreturn Ġorders . any Ġ{ Ġorder Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġexpired Date Ġ= Ġorder . order Time ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpired Date . add ( Calendar . DATE , Ġorder . plan ?. expired Ġ?: Ġ 0 ) ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpired Date . after ( Calendar . getInstance ()) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġvalidate Discount ( discount Code : ĠString ?): ĠDiscount ? Ġ{ ĊĠĠĠĠĠĠĠ Ġdiscount Code Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġreturn Ġdiscount Repository . findBy Code And Time End Is After And Remaining Amount Is GreaterThan And Enabled IsTrue ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdiscount Code , ĊĠĠĠĠĠĠĠĠĠĠĠ ĠCalendar . getInstance () ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġthrow ĠNotFound Exception ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠDIS COUNT _ INVALID ATE ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠ Ġ} Ċ }