scieee AI-readable full text Open interactive document viewer

EU-Rent as an artifact-centric process model: technical report

Estañol Lamarca, Montserrat,Queralt Calafat, Anna,Sancho Samsó, María Ribera,Teniente López, Ernest

Abstract

Business process modeling using an artifact-centric approach has raised a significant interest over the last few years. This approach is usually stated in terms of the BALSA framework which defi nes the four dimensions of an artifact-centric business process model: Business Artifacts, Lifecycles, Services and Associations. One of the research challenges in this area is looking for diff erent diagrams to represent these dimensions. Bearing this in mind, this technical report shows how various UML diagrams can be used to represent all the elements in the BALSA framework by applying them to the EU-Rent case study.

Full text

EU-Rent as an Artifact-Centric Process Model: Technical Report Montse Estañol, Anna Queralt, Maria Ribera Sancho, Ernest Teniente September 2012 Abstract Business process modeling using an artifact-centric approach has raised a significant interest over the last few years. This approach is usually stated in terms of the BALSA framework which denes the four dimensions of an artifactcentric business process model: Business Artifacts, Lifecycles, Services and Associations. One of the research challenges in this area is looking for dierent diagrams to represent these dimensions. Bearing this in mind, this technical report shows how various UML diagrams can be used to represent all the elements in the BALSA framework by applying them to the EU-Rent case study. Contents 1 Introduction 2 2 Artifact-Centric Business Process Models in UML 4 2.1 Introduction.............................. 4 2.2 BusinessArtifacts .......................... 4 2.3 Business Artifact Lifecycle . . . . . . . . . . . . . . . . . . . . . . 5 2.4 Services ................................ 5 2.5 Associations.............................. 6 2.6 Summary ............................... 6 3 EU-Rent Car Rental Service as an Artifact-Centric Model in UML 7 3.1 Introduction.............................. 7 3.2 Assumptions ............................. 8 3.3 Business Artifacts as a Class Diagram . . . . . . . . . . . . . . . 8 3.4 Lifecycle of RentalAgreement as a State Machine Diagram . . . . 18 3.5 Associations as Activity Diagrams and Services as Action Contracts 20 Appendices 45 A Structural Schema in OCL 46 A.1 ClassDiagram ............................ 46 A.2 Integrity Constraints . . . . . . . . . . . . . . . . . . . . . . . . . 46 1 Chapter 1 Introduction Business process design is a key activity in organisations. Business process models have been traditionally based on an activity-centric perspective and thus specied by means of diagrams which dene how a business process or workow is supposed to operate, but giving little importance (or none at all) to the information produced as a consequence of the process execution. Therefore, this approach under-species the data underlying the service and the way it is manipulated by the process tasks [4]. Nearly a decade ago, a new information-centric approach to business process modeling emerged [7] and it is still used today. It relies on the assumption that any business needs to record details of what it produces in terms of concrete information. Business artifacts, or simply artifacts, are proposed as a means to record this information. They model key business-relevant entities which are updated by a set of services (specied by pre and postconditions) that implement business process tasks. This approach has been successfully applied in practice and it provides a simple and robust structure for workow modeling [2, 1]. The artifact-centric approach to business process specication has been shown to have a great intuitive appeal to business managers. However, further research is needed with regards to the best artifact-centric model since none of the existing models can adequately handle the broad requirements of business process modeling [6]. This technical report shows the results of a applying our particular proposal for an artifact-centric approach using UML diagrams. We consider that one way of validating it is by applying it to a big case study. EU-Rent, as it is explained in [5], is a case study originally developed by Model Systems, Ltd. EU-Rent is the name of a ctional company which rents cars. It has branches in various countries and it oers the typical car rental services and keeps information about its customers. The technical report [5] includes a detailed description of EU-Rent and its specication using standard notation: UML 2.0 and OCL 2.0. We considered that EU-Rent would be an appropriate case study for validating our proposal because it presents a service which most people would be familiar with, but at the same time it is complex enough to oer a good testing environment. In order to avoid unnecessary repetition, we take [5] as a starting point for our own report. We refer to it in order to nd the detailed description of the EU-Rent company and how it works. Unless otherwise stated, we have followed exactly the same criteria described in it. 2 This technical report is structured in the following way: Chapter 1: Introduction presents the purpose of the document and its structure. Chapter 2: Artifact-Centric Business Process Models in UML summarises our proposal for describing business process from an artifact-centric perspective using UML models. Chapter 3: EU-Rent Car Rental Service as an Artifact-Centric Model in UML shows how the EU-Rent car rental service would be specied using the proposal summarised in Section 2. Acknowledgements: The research that resulted in the work presented here has received the nancial support of UPC (Universitat Politècnica de Catalunya - Barcelona Tech). 3 Chapter 2 Artifact-Centric Business Process Models in UML This chapter describes briey our proposal for specifying artifact-centric business process models in UML. A very brief summary is presented at the end. 2.1 Introduction Traditional process-centric business process models are essentially uni-dimensional in the sense that they focus almost entirely on the process model, its constructs and its patterns, and provide little or no support for understanding the structure or the life-cycle of the data that underlies and tracks the history of most workows [6]. In contrast, the artifact-centric approach provides four explicit inter-related but separable dimensions in the specication of the business process [6, 3]. This four-dimensional framework is referred to as BALSA - Business Artifacts, Lifecycles, Service and Associations, rst described in [6, 3]. By showing the UML diagram which is more appropriate to dene each one of these four dimensions we will be able to construct our proposal for the specication of artifact-centric business process models in this language. However, UML is not enough, as usually UML diagrams make use of some textual notation to precisely specify those aspects that cannot be graphically represented. Currently, the OCL (Object Constraint Language) [10] is probably the most popular one of these notations and we will also use it in our proposal. OCL supplements UML by providing expressions that have neither the ambiguities of natural language nor the inherent diculty of logic. The rest of the section gives a brief explanation of the four BALSA dimensions and we explain how we propose representing them using UML diagrams. 2.2 Business Artifacts The conceptual schema of business artifacts is intended to hold all of the information needed in completing business process execution. A business artifact has an identity , which makes it distinguishable from any other artifact, and can 4 be tracked as it progresses through the workow of the business process execution. It will usually have also a set of attributes to store the data needed for the workow execution. The relationship of a business artifact with other artifacts must also be shown when this information is relevant for the business being dened. In business terms, an artifact represents the explicit knowledge concerning progress toward a business operational goal at any instant. Therefore, at any time of the execution, the information contained in the set of artifact records all the information about the business operation. In UML, conceptual schemas are dened by means of class diagrams. We will use a UML class diagram to show the business entities and how they are related to each other, represented as classes and associations respectively. Each class (or business artifact) may have a series of attributes that represent relevant information for the business. Moreover, they can be externally identied by specic attributes or by the relationships they can take part in. A class diagram may also require a list of integrity constraints that, as their name implies, establish a series of restrictions over the class diagram. Constraints can be either specied graphically in the UML class diagram or textually by means of the OCL language. Furthermore, the UML class diagram allows representing class hierarchies graphically. We will benet from this by representing the dierent states in an artifact's lifecycle as subclasses of a superclass, as long as these subclasses hold relevant information or are in relevant relationships. The advantage of having dierent subclasses for a particular artifact is that it allows having exactly those attributes and relationships that are needed according to its state, preserving at the same time the artifact's original ID and the characteristics that are independent of the artifact's state which are represented in the superclass. 2.3 Business Artifact Lifecycle The lifecycle of a business artifact states the key, business-relevant, stages in the possible evolution of the artifact, from inception to nal disposal and archiving. It is natural to represent it by using a variant of state machines, where each state of the machine corresponds to a possible stage in the lifecycle of an artifact from the class [6]. We propose representing the states an artifact may go through in a UML state machine diagram. 2.4 Services A service (or task) in a business process encapsulates a unit of work meaningful to the whole business process. The action of services makes business artifacts evolve, e.g. they may cause modications on the information stored by the artifacts or they may make artifacts to evolve to a new stage, relevant from the business perspective. Our way of representing services is by means of an OCL operation contract. As we have mentioned before, OCL is a formal language that avoids ambiguities. Moreover, it is declarative, which means that it does not indicate how things should be done, but rather what should be done. 5 Operation contracts consist in a set of input parameters and output parameters, a precondition and a postcondition. Both input and output parameters can be classes (i.e. business artifacts) or simple types (e.g. integers, strings, etc.). A precondition states the conditions that must be true before invoking the operation and refers to the values of artifact attributes at the time when the service is called. The postcondition indicates the state of the business artifacts after the execution of the operation. It may refer to the values of artifact attributes at the time when the service is called (appending operator @pre) and to their values after the service has nished execution (no operator or appending operator @post). Those artifacts that do not appear in the postcondition keep their state from before the execution of the operation. 2.5 Associations The problem, however, is that having the services as detailed above is not enough. We need also a way to establish the conditions under which they can be executed since, in a business process, services make changes to artifacts in a manner that is restricted by a set of constraints. Since the goal of the associations is to dene the right sequencing of service execution, we propose using UML activity diagrams for specifying them. In this way, each service is represented as an action (a rounded rectangle) in the activity diagram. Arrows show the order in which actions have to be executed. Swimlanes indicate the main business artifact involved in each action, and the notes stereotypes as Participant indicate who is the responsible for carrying out that action. By modeling associations in this way we achieve our proposal to incorporate also some notions of process awareness, despite its intrinsic artifact-centric nature. Therefore, we may also explicitly capture the control ow of the business process, aspect which is usually lacking in previous artifact-centric proposals. 2.6 Summary In summary, following the BALSA model described in [6], we will use the following UML diagrams to represent each of its elements: • UML class diagram to represent the business artifacts. • State machine diagram to represent the business artifacts' lifecycle. • Services will be represented as OCL operations with preconditions and postconditions. • Associations will be shown graphically in a UML activity diagram. 6 Chapter 3 EU-Rent Car Rental Service as an Artifact-Centric Model in UML This chapter shows how our proposal is applied to a particular example. As we have already mentioned in the Introduction, we will use the EU-Rent specication described in [5] as a starting point. In the rst section of this chapter we give a brief overview of how the EU-Rent company works. Section Assumptions details some considerations and assumptions we have made in order to specify the car rental service provided by EU-Rent. The rest of sections in this chapter show the various diagrams and elements that make up the EU-Rent service specication. 3.1 Introduction This introduction is meant to give a brief overview of EU-Rent. For a detailed description of how the company works, check pages 1-15 of [5]. EU-Rent is a case study originally developed by Model Systems, Ltd. EU- Rent is a ctional car rental company with branches in multiple countries. It is part of a bigger company, EU-Corporation, which also owns hotels and an airline. A prospective client must be registered with the company in order to rent a car: he/she may make a reservation some days in advance, or rent the car on the spot (what is called a walk-in rental). Customers are allowed to have many reservations, but they can only have one rental at a time. They are also allowed to return the car to a branch other than the pick-up branch. The company keeps information about the customers, such as a history of their rentals and records any bad experiences (e.g a late return or a damaged car). Therefore, a particular customer may be blacklisted (i.e. he/she will not be allowed to rent a car) if certain conditions are met. On the other hand, customers may belong to the Loyalty Incentive Scheme. Customers in this program are allowed to pay for their rentals using loyalty points. Moreover, any rental may qualify for a discount, and the customer is always oered the best price for the rental. However, loyalty points can only 7 EU_RentPerson Customer membershipDate : Date / availablePoints : Natural LoyaltyMember blacklistedDate : Date Blacklisted id : String name : String address String birthdate : Date telephone : Natural EU_CoPerson Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.2: Class diagram of EU_CoPerson and its subclasses 3.3.2.2 Derived Attributes and Classes LoyaltyMember ? availablePoints - It holds the result of adding the points obtained in the rentals made by the customer which have not been paid with points, and substracting the points spent in the rentals paid with points. 3.3.3 Reservation and its Subclasses The diagram in Figure 3.3 shows the class Reservation and its subclasses. reservationDate : DateTime Reservation ReservationWithSpecialDiscount cancellationDate : DateTime CanceledReservation PointsPaymentReservation creditCardNumber : Natural GuaranteedReservation motivation : CancellingMotivation CanceledCustomerLiable CanceledCompanyLiable / fine : Money {frozen} / GuaranteedCanceled {d,c} Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.3: Class diagram of Reservation and its subclasses As it can be seen in the diagram, a Reservation may be: 14 • A ReservationWithSpecialDiscount , if it includes a discount on the basic price. • A PointsPaymentReservation , if it can be paid with points and the customer wishes to. • A GuaranteedReservation , if the customer leaves his credit card number. • A CanceledReservation , if the reservation is cancelled. We distinguish two subtypes:  CanceledCompanyLiable , if EU-Rent is responsible for the cancellation.  CanceledCustomerLiable , if the customer is the ultimate responsible for the cancellation. A CanceledCustomerLiable reservation may also be of GuaranteedCanceled subtype if it was also a GuaranteedReservation . It is important to mention that, in the original specication [5], CanceledReservation had CanceledCustomer and CanceledCompany as subclasses, showing whether the reservation had been cancelled at a request from the customer or the company had decided to do so, respectively. In our class diagram, subclasses CanceledCustomerLiable and CanceledCompanyLiable show who is the ultimate responsible for the cancellation of the reservation: the company may decide to cancel a reservation because a customer is not t to drive; although it is the company who makes the decision, the customer is liable for it. 3.3.3.1 Integrity Constraints • reservationDate of a Reservation must be previous to its beginning date. • Requested car model in a Reservation must be in requested car group. • PointsPaymentReservation must be made at least 14 days in advance of its beginning date. • cancellationDate of a CanceledReservation must be after or on the same reservationDate and before, on the beginning date of the RentalAgreement or on the day after at the latest. This has been changed from the original report [5]. 3.3.3.2 Derived Classes and Attributes GuaranteedCanceled ? Derived class - All Reservations that are both GuaranteedReservation and CanceledCustomerLiable . ? ne - A ne of one day rental must be paid if the rental was guaranteed and the cancelling date is the same day (or later if the customer does not pick up the car) as the expected beginning of the rental. Otherwise, no ne must be paid. 15 registrationNumber : String Car currentMileage : Double mileageFromLastService : Double lastMaintenanceDate : Date acquisitionDate : Date / available : Boolean / assigned : Boolean OwnCar beginningDate : Date RepairsScheduled /NeedsMaintenance ToBeSoldCar beginningDate : Date MaintenanceScheduled /NeedToBeSoldCar BeingTransferred Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.4: Class diagram of Car and its subclasses 3.3.4 Car and its Subclasses The class diagram of Car and its subclasses can be seen in Figure 3.4. An OwnCar represents those cars that are owned by EU-Rent (the company, under special circumstances, can use cars that do not belong to it). An OwnCar may be in the process of being transferred from one branch to the other ( Being- Transferred ), may need maintenance ( NeedsMaintenance subtype), may need to be sold ( NeedToBeSold ) or may be of the ToBeSoldCar type, which means that it can no longer be used as it is in the process of being sold. Finally, a Car may be scheduled for repairs ( RepairsScheduled ) even if it does not belong to EU-Rent. 3.3.4.1 Integrity Constraints • Car can only be assigned, at most, to one rental; excluding both closed and canceled rentals. • Car is identied by registration number • A Car that needs maintenance cannot have more than 10% of the mileage required for maintenance and not more than 10% of the required time between services may have elapsed. • A Car that is to be sold ( ToBeSoldCar ) cannot be assigned to a rental, excepting those rentals that are closed or canceled. 3.3.4.2 Derived Classes and Attributes NeedsMaintenance ? Derived class - A car needs maintenance if it was serviced more than 3 months ago or has accumulated more than 10,000 km since the last service. 16 NeedToBeSoldCar ? Derived class - An OwnCar is of subtype NeedToBeSoldCar if it was bought more than a year ago or has accumulated more than 40,000 km. 3.3.5 ClosedRental and its Subclasses The diagram in Figure 3.5 shows the class ClosedRental and its subclasses. paymentType : PayType creditCardNumberDamages : Natural / rentalPriceWithTax : Money ClosedRental / extraInterval : Duration / extraCostWithTax : Money /LateReturn /EarlyReturn /PaidWithPointsRental return_time {d,c} Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.5: Class diagram of ClosedRental and its subclasses A ClosedRental may be PaidWithPointsRental , if it has been paid with points; and may also be a LateReturn if the car has been returned later than expected or an EarlyReturn , if it has been returned more than an hour earlier than expected. 3.3.5.1 Integrity Constraints • In a PaidWithPointsRental , the Reservation for the corresponding rental was made at least 14 days in advance of the rental's beginning date. • In a PaidWithPointsRental , the Customer must be a member of Loyalty Incentive Scheme (i.e. LoyaltyMember ) in order to pay with points. It is an initial constraint, as the customer must be a Loyalty Incentive Member only at the time of paying; later on he/she may not be a member any longer. 3.3.5.2 Derived Classes and Attributes ClosedRental ? rentalPriceWithTax - Price of the rental plus taxes. It is the result of multiplying the carTax in the actual drop-o branch and the bestPrice of the rental. 17 PaidWithPointsRental ? Derived class - All ClosedRentals that have been paid with points (i.e their paymentType is Points ). LateReturn ? Derived class - All ClosedRentals such that the actualReturn is later than the agreedEnding . ? extraInterval - Duration of the period between the agreedEnding and the actualReturn of the car. ? extraCostWithTax - Holds the price of the extraInterval , considering the best price for duration without applying any discounts, and the cost of the taxes according to country where the car has been dropped o. EarlyReturn ? Derived class - All ClosedRentals such that the actualReturn is more than an hour sooner than the agreedEnding . 3.3.6 Types The types that have been dened for EU-Rent can be seen in Figure 3.6. Note that most of them have been dened from scratch or redened from [5]. blacklisting no_show unable_to_drive customer_canceled <<enumeration>> CancellingMotivation EUCorpCustomer EURentCustomer NotRegistered <<enumeration>> CustomerType CarReady CarNotReady NoReservation <<enumeration>> ReservationStatus Points SpecialDiscount BestPrice BasePrice <<enumeration>> PayType veryhigh high medium low verylow <<enumeration>> Level lateReturn carDamage paymentProblem <<enumeration>> BadExpType hour day <<enumeration>> Period mileageForService : Double = 10000 timeForService : Duration = (month, 3) MaintenanceRequirements Unit : Period numberOfUnits : Natural Duration Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.6: Denition of types 3.4 Lifecycle of RentalAgreement as a State Machine Diagram Although many of the business artifacts represented in the class diagram have a lifecycle, in order to keep it simple we will focus only on the lifecycle of what is the main business artifact: RentalAgreement . The state machine diagram for the service can be seen in Figure 3.7. It shows the whole lifecycle of RentalAgreement , from the moment a customer 18 ExtendedRental CanceledReservation ClosedRental OpenRental Reservation Extend Rental Return Car [not guaranteedReservation] (now() - beginning)>90min / Cancel Reservation Customer is Blacklisted/ Cancel Reservation [guaranteedReservation] today()>day(beginning) / Cancel Reservation Pick-Up Car[cancel] Make Walk-In Rental[success] Extend Rental Cancel Reservation by Customer Demand [success] Return Car Pick-Up Car[success] Make Reservation[success] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.7: State machine diagram for RentalAgreement makes a reservation or rents a car to the moment when the car is returned. It is worth noting that this diagram does not follow exactly the standard described in [9]: we have more than one outgoing transition from the start node. This is necessary because the service can be initialized in dierent ways (e.g. by making a walk-in rental or a reservation). In any case, the transitions between states are triggered by either domain events, time events or change events [8]. However, our domain events are not always atomic: they can be subprocesses which are further decomposed into actions (or services). These subprocesses may have a condition in square brackets which the subprocess has to meet when it ends in order for the transition to be red. For example, the transition from Reservation to OpenRental will only be triggered when: 1- subprocess Pick Up Car takes place AND 2- it ends successfully AND 3- RentalAgreement is in state Reservation . If this same subprocess ends fullling the condition cancel when the service is in state Reservation , then the RentalAgreement would be canceled. The postconditions in the state transitions can also be non-atomic. For example, when time event today() > day(beginning) takes place and the Reservation has been guaranteed, then the reservation must be canceled. This is done through subprocess Cancel Reservation . The state machine diagram in Figure 3.7 shows that there are two possible ways of creating a RentalAgreement : either with Make Reservation or Make Walk-In Rental . In the case of Make Reservation , the user has to Pick-Up Car before actually using it. It is also important to notice that in state Reservation , the reservation may be cancelled either because the customer requests it ( Cancel Reservation by Customer Demand ) or because one of the following conditions is met: 1- the car is not picked up 90 minutes after the scheduled pick-up time and the reservation is not guaranteed, 2- the car is not picked-up in the scheduled day and the reservation was guaranteed, 3- the customer is blacklisted, 4- Pick-Up Car is cancelled. In all these cases, the service ends. While the rental is open, the customer can request an extension ( Extend Rental . The RentalAgreement will become a ClosedRental when the customer returns the car ( Return Car ). 19 3.5 Associations as Activity Diagrams and Services as Action Contracts The activity diagrams provide the details for each of the subprocesses in the state machine diagrams. Each subprocess is decomposed into actions, which in turn can be atomic (they are services as dened in BALSA) or further decomposed in another activity diagram (indicated by a rake-like symbol). Therefore, activity diagrams act as associations between services. In each activity diagram, the transitions that lead to an end node may be stereotyped with a tag that indicates the outcome of the subprocess. Examples of tags are succeed and fail , which may be then used in the state machine diagram to determine the following state in the service evolution. Swimlanes indicate the main artifact involved in each of the services or actions, and they are labeled with stereotype material if they are dealing with a real, physical object and not its representation. Those actions that deal with information resources are further specied by action contracts using OCL. They correspond to services in BALSA. Each subsection corresponds to one of the subprocesses in the state machine diagram. However, there are some actions within activity diagrams whose details are dened in another activity diagram: they also have a subsection of their own. 3.5.1 Make Reservation Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Renter <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.8: Activity Diagram for Make Reservation 3.5.1.1 Obtain Customer See section 3.5.2 on page 25. 3.5.1.2 Obtain Data for Rental and Calculate Price Obtains the data for the rental (such as beginning and end date, the countries the user wants to visit, the preferred car model or car group, etc.) and calculates 20 its price, considering the fact that there may be some applicable oers or the customer may be eligible to pay with points. There are four dierent possible prices: • Basic Price - It is calculated according to the rental duration, without considering any discounts. • Best Price - It is calculated considering the existing discounts, excluding those discounts that were must be applied at reservation time. IMPORTANT NOTE: In the original specication [5], apparently Best Price and Price with Special Discount are calculated in the same way, considering in both cases discounts applicable at reservation time. We have considered that this is a mistake, and for Best Price we do not include the reservation-time discounts. • Price with Special Discount - It considers all types of applicable discounts, including those than can only be selected at reservation time. • Points - The payment with points can only be selected if the user is member of the Loyalty Incentive Scheme and has enough points. The cost in points of the rental is calculated from the Basic Price (or Base Price) of the rental. Additional comments: • Although there is an integrity constraint that does not allow users to pay with points if the reservation is not made 14 days in advance, this action checks it anyway, to avoid oering the user the option to pay with points if he is not able to. • points() - changes from Money to Points. • isBetter() - checks whether one alternative is better than the other. • durationT() - obtains the corresponding duration given a period and a natural number. • applicable() - used to determine if a particular discount is applicable to a customer. • apply() - applies a discount to a particular price. It is needed because the Discount class contains this information in a String format, as it may be given as a percentage over the nal price, certain conditions may have to be met, etc. action obtainDataForRentalAndCalculatePrice ( startDate : DateTime , endDate : DateTime , pickUpBranch : String , dropOffBranch: String , countries: Set ( String ) , carG : String , carM : String , person : EU_CoPerson) : Set (TupleType( id : PayType , desc : String ) ) localPre : − localPost : 21 −− Change input EU_CoPerson into EU_RentPerson and again to Customer . At this point EU_CoPerson must already be EU_RentPerson but may not be a Customer −− person . oclAsType (EU_RentPerson) . oclIsTypeOf (Customer ) and let c : Customer=person . oclAsType ( Customer ) in −− Create Rental Agreement −− −− 1. Creates the RentalAgreement as a Reservation subtype with the input data −− −− 2. Links the EU_RentPerson with this RentalAgreement −− Reservation . allInstances () − >exists ( r | r . oclIsNew () and r . driver=c . oclAsType (EU_RentPerson) and r . renter=c and r . beginning=startDate and r . initEnding=endDate and r . reservationDate=now() and r . pickUpBranch=Branch . allInstances () − >sel ect (pub | pub . name=pickUpBranch ) and r . dropOffBranch=Branch . allInstances () − >sel ect (dob | dob . name=dropOffBranch ) and ( if (carG = ' ' ) then r . requestedGroup=CarGroup . allInstances () − >s el ec t ( cg | cg . worse − >isEmpty () ) else r . requestedGroup=CarGroup . allInstances () − >s el ec t ( cg | cg .name=carG) endif ) and ( if (carM <> ' ' ) then r . requestedModel=CarModel . allInstances () − >sel ect (cm | cm.name=carM) else true endif ) and countries − >forAll ( co2 | r.country − >se lect ( co | co .name=co2 ) − >notEmpty () ) and r.country − >includes (Branch . allInstances () − >sel ect (b | b . name=pickUpBranch ) . country ) and r.country − >includes (Branch . allInstances () − >sel ect (b | b . name=dropOffBranch ) . country ) ) −− Calculate Price −− −− 1. basePrice and bestPrice are derived attribu t es in the class / business a rti fac t . Therefore , there is no need to calculate them. −− let basePr : Money=r . basicPrice let bestPr :Money=r . bestPrice −− 2. We have to calculate the price considering the discounts available at reservation time −− −− 2.1. We selec t those discounts applicable to the particular rentGroup and the time of the rental . We also check i f i t s a ppl ica ble to the Customer . −− let applicableDiscounts: Set ( Discount ) = r . rentGroup . discount − >se lect ( dis | dis . beginningDate<=r . initEnding and ( dis . oclIsTypeOf ( ClosedDiscount ) implies dis . oclAsType ( ClosedDiscount ) . endingDate>=today () and applicable ( dis , c ) ) in −− 2.2. We create a function to determine , of a l l applicableDiscounts , the best one for a particular duration −− let bestDiscountPerDuration ( rd : RentalDuration , price : 22 Money) : Discount = applicableDiscounts − >se lect (d | d . rentalDuration=rd ) − > reject ( disAct : Discount | applicableDiscounts − > sel ect (d2 | d2 . rentalDuration=rd ) − > exists ( disOther : Discount | apply ( disOther , price ) . isBetter ( apply ( disAct , price ) ) ) − >any () −− 2.3. We calculate the price of the rental including the discounts −− −− 2.3.1. Each RentalAgreement is associated to various RentalDurations. −− 2.3.2. Each RentalAgreement is linked to various CarGroupDurationPrices (through bestDurationPrices ) . This contains the best price for each rental duration for the CarGroup of the RentalAgreement . That is , for every RentalDuration , there is exactly one CarGroupDurationPrice. −− −− 2. 3.3. This implies that , i f we navigate the relationship bestDurationPrices and sel e ct the CarGroupDurationPrice for a particular RentalDuration , there w il l only be ONE CarGroupDurationPrice. −− 2.3.4. We calculate the price of the rental by iterating through the RentalDurations linked to the RentalAgreement and selecting the corresponding price in bestDurationPrices . We then obtain the best Discount for a particular RentalDuration and CarGroup , apply this Discount to the price in CarGroupDurationPrice and multiply this for the number of a particular RentalDuration there is in a RentalAgreement . Finally , we add this value to the accumulated price and we examine the next RentalDuration. −− let bestSpD : Money = r.applicableRentalDurations − >i te ra t e ( elem ; tup : Tuple{ currentPrice : Money=0, accPrice : Money=0} | currentPrice = r . bestDurationPrices − > select (cGDP | cGDP. rentalDuration=elem . rentalDuration ) . price currentPrice = apply ( bestDiscountPerDuration ( elem . rentalDuration , currentPrice) , currentPrice) accPrice = accPrice + currentPrice ∗ elem . quantity ) . accPrice in answerSOptions= Sequence {} − >append( Tuple{id=PayType : : BasePrice , desc= basePr . toString }) − >append( Tuple{id=PayType : : BestPrice , desc=bestPr . toString }) − > append( Tuple{ id=PayType : : SpecialDiscount , desc=bestSpD . toString }) −− Check i f able to pay with points −− −−− 1. Reservation must be made at le a st 14 days in advance −− −−− 2. Customer must belong to Loyalty Incentive −− −−− 3. Customer must have enough points to pay −− if ( startDate >= (today ()+day (14) ) and p . oclIsTypeOf ( LoyaltyMember ) and ( points ( r . basicPrice ) <= ( c . oclAsType ( LoyaltyMember ) . availablePoints ) ) ) then answerSOptions − >append( Tuple{ id=PayType : : Points , desc=points . toString }) 23 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Renter <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.11: Activity Diagram for Handover 30 action addDriverToRental (p : EU_CoPerson , ra : RentalAgreement ) localPre : −− We need to check these conditions here as we do not want the whole a ct iv it y diagram to abort execution i f they are not met −− ra . beginning<=now() and ra . assignedCar . oclIsTypeOf ( Prepared ) localPost : ra . driver − >includes (p . oclAsType (EU_RentPerson) ) 3.5.4.6 Sign Rental Agreement The customer signs the rental agreement in order to accept the rental conditions and be able to rent the car. Deals with material resources 3.5.4.7 Conrm Pick-Up Conrms that the car has been picked up and the rental is open. action confirmPickUp ( ra : RentalAgreement ) localPre : − localPost : ra . oclIsTypeOf (OpenRental ) and ra . oclAsType ( OpenRental ) . actualPickUpTime=now () 3.5.4.8 Hand Car Over The car is given to the customer. Deals with material resources 3.5.5 Check Requirements Fullment 3.5.5.1 Check Existing Person Has the same OCL code as action Check Existing Customer in section 3.5.2.1, page 25. 3.5.5.2 Insert New EU-Corporation Driver Inserts a new EU-Corporation customer using his/her personal data. Additional comments: • The postcondition checks whether the person is over 25 years of age, a condition which is guaranteed by the integrity constraints. However, in this particular case, we do not want to cancel the whole process if the person does not fulll the requirements, as it is simply an additional driver and not the customer. 31 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Customer <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Blacklisted Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> <<participant>> <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] [false] <<succeed>> [true] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.12: Activity Diagram for Check Requirements Fullment action insertNewEU − CorporationDriver ( cid : String , cname : String , cbirthday : Date , cAddress : String , cTelephone: Integer ) : EU_CoPerson localPre : − localPost : if ( ( today () − cbirthday )<year (25) ) then result=null else EU_CoPerson . allInstances () − >exists (p | p . oclIsNew () and p . id=cid and p . name=cname and p . birthday=cbirthday and p . address=cAddress and p . telephone=cTelephone ) and result=p endif 3.5.5.3 Get Driving License Obtains the driver's license information and creates a EU_RentPerson . Additional comments: • The postcondition checks whether the driving license is valid, a condition which is guaranteed by the integrity constraints. However, in this particular case, we do not want to cancel the whole process if the license is not valid, as it is simply the driving license of an additional driver and not the customer. 32 action getDrivingLicense (p : EU_CoPerson , dExpiry : Date , dIssue : Date , lnumber : Integer ) localPre : − localPost : if (( dExpiry < dIssue ) or ( dExpiry < today () ) or (( today () − dIssue ) > year (1) ) ) then result=null else p . oclIsTypeOf (EU_RentPerson) and DrivingLicence . allInstances () − >exists ( l | l . oclIsNew () and l . number=lnumber and l . issue=dIssue and l . expiry=dExpiry and r.drivingLicense=l) and result=r 3.5.5.4 Check Driver Blacklisted Checks whether the EU_RentPerson has been blacklisted. Additional comments: • We need to check whether the additional driver has been blacklisted. If he has, the operation fails but it does not imply the failure of the whole subprocess, just the insertion of the new driver (as it is shown in the activity diagram). action checkDriverBlacklisted (EU_CoP: EU_CoPerson) : Boolean localPre : − localPost : result=EU_CoP. oclAsType (EU_RentPerson) . oclIsTypeOf ( Blacklisted ) 3.5.6 Make Walk-In Rental 3.5.6.1 Obtain Customer See section 3.5.2 on page 25. 3.5.6.2 Obtain Rental Data The action obtains the data for the rental (such as the beginning and end dates, the countries the customer wants to travel to with the car, the preferred car group or car model, etc.) and creates the RentalAgreement. Additional comments: • The operation creates the RentalAgreement . There is no need to create a Reservation because the Customer will take the car with him immediately. • As we have previously called the action Obtain Customer , we can guarantee that the EU_CoPerson is already a EU_RentPerson . • We need a way to identify the branch from which the system is being run. So far, we have a function, currentBranch() , that returns the Branch from which the Reservation is being made. 33 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Any <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Customer <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Blacklisted Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> <<participant>> <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] [false] <<succeed>> [true] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.13: Activity Diagram for Make Walk-In Rental • We assign the car directly to the RentalAgreement . To do so, we rst make sure that only currently available CarModels and CarGroups are selected. If the user chooses a CarModel , then we assign the car with least mileage belonging to that CarModel . If the user selects a CarGroup (or if he has not selected any), then we assign the car with the least mileage from that group (or with the least mileage if he has not specied a group). • The description of the case study states that, when assigning cars, the absolute mileage should be considered instead of the car's mileage since its last service. However, in the original operation's specication, the mileage since the last service is used. We have considered that this is a mistake, and therefore we have used the car's absolute mileage. • The specication in the original technical report does not calculate nor show the cost of the rental to the customer, as he/she will not be able to select any special oers. Apparently, then, there is no need to calculate the cost of the rental. action obtainRentalData ( endDate : Date , pickUpBranch : String , dropOffBranch: String , countries: Set ( String ) , carG : String , carM: String , p : EU_CoPerson) : RentalAgreement localPre availableCarModel: carM<>' ' implies currentBranch () . carsAvailableNow . carModel .name − >includes (carM) localPre availableCarGroup : carG<>' ' implies currentBranch () . groupsAvailableNow .name − >includes (carG) localPre availableCars : (carM = ' ' and carG = ' ' ) implies currentBranch () . carsAvailableNow − >notEmpty () 34 localPost : let c : EU_RentPerson=p . oclAsType (EU_RentPerson) in −− Create Rental Agreement −− RentalAgreement . allInstances () − > exists ( ra . oclIsNew () and ra . driver=c and c . isTypeOf (Customer ) and ra . renter=c . oclAsType ( Customer ) and ra . beginning=now() and ra . initEnding=endDate and ra . pickUpBranch=currentBranch () and ra . dropOffBranch=Branch . allInstances () − >sel ect (dob | dob . name=dropOffBranch ) and −− We assign the car model with the least mileage −− ( if (carM <> ' ' ) then ra. car = currentBranch() .carsAvailableNow − > s e le c t ( c | c . carModel . name=carM) − >sortedBy ( currentMileage ) − > f i r s t () else ( if (carG = ' ' ) then ra. car = currentBranch() .carsAvailableNow − > sortedBy ( currentMileage ) − > f i r s t () else ra. car = currentBranch() .carsAvailableNow − > sel ec t (c | c . carGroup .name=carG) − > sortedBy ( currentMileage ) − > f i r s t () endif ) endif ) and −− We add the countries to the li st , including the branches ' countries −− countries − >forAll ( co2 | ra . country − >se lect ( count | count .name=co2 ) − >notEmpty () ) and ra . country − >includes ( currentBranch () . country ) and ra . country − >includes (Branch . allInstances () − >sel ect (b | b . name=dropOffBranch ) . country ) and −− We return the Rental Agreement −− result = ra ) 3.5.6.3 Handover Check section 3.5.4 on page 29. 3.5.7 Extend Rental Agreement 3.5.7.1 Call Branch The customer calls an EU-Rent branch to ask for a rental extension. Deals with material resources . 3.5.7.2 Obtain ID, Data for Extension and Verify This action extends a Rental Agreement as long as the customer has an open rental that has not been closed, the new end date is later that the previous end date and the car is not in need of maintenance. Additional comments: • It does not check for overlapping rentals as this is guaranteed by the integrity constraints. 35 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Customer <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> <<participant>> <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.14: Activity Diagram for Extend Rental Agreement • Extension must be applied to the currently OpenRental . • It is necessary to check that Rental is not ClosedRental because ClosedRental is a subclass of OpenRental . • New end date must be later than agreedEnding . action obtainIDDataExtensionVerify (cid: String , newEndDate : DateTime) : Boolean localPre customerHasOpenRental : Customer . allInstances () − > sel ec t (c | c . id=cid ) . rentalAgreement − > sel ec t ( ra | ra . oclIsTypeOf (OpenRental ) and not ra . oclIsTypeOf ( ClosedRental ) ) − >notEmpty () localPre laterReturnDate: let rental : OpenRental = (Customer . allInstances () − > sel ec t (c | c . id=cid ) . rentalAgreement − > sel ec t ( ra | ra . oclIsTypeOf (OpenRental ) and not ra . oclIsTypeOf ( ClosedRental ) ) ) . oclAsType ( OpenRental ) in rental . agreedEnding < newEndDate localPost : let currentRental : OpenRental= Customer . allInstances () − > sel ect ( c | c . id=cid ) . rentalAgreement − > sel ec t ( ra | ra . oclIsTypeOf ( OpenRental) and not ra . oclIsTypeOf ( ClosedRental ) ) . oclAsType (OpenRental) in if ( currentRental . car . oclIsTypeOf ( NeedsMaintenance ) ) then result=f al se else currentRental . oclIsTypeOf ( ExtendedRental ) and currentRental . oclAsType ( ExtendedRental ) . lastNewEnding = newEndDate and currentRental . oclAsType ( ExtendedRental ) . extension . extensionDone = now() and result=true endif 36 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Renter <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.15: Activity Diagram for Cancel Reservation by Customer Demand 3.5.8 Cancel Reservation by Customer Demand 3.5.8.1 Obtain Data and Cancel This action obtains the startDate of a rental and a user's id and cancels the corresponding reservation. It returns the money that the customer has to be charged for the cancellation (may be 0). Additional comments: • The description of the use case states that a car should be freed if it had been previously assigned to a no-show reservation. However, in the original operation's specication this is not taken care of. It is not taken care of here either. • A ne should be charged if reservation is cancelled on pick-up day. This action returns money that has to be charged. action obtainDataAndCancel ( cid : String , startDate : DateTime) : Money localPre : − localPost : let ra : RentalAgreement = Customer . allInstances () − > sel ec t (c | c . id=cid and c . beginning=startDate ) . rentalAgreement − >se lect ( r | r . oclIsTypeOf ( Reservation ) and not r.oclIsKindOf(CanceledReservation) and not r . oclIsKindOf ( OpenRental ) ) in ra.oclIsTypeOf(CanceledReservation) and ra . oclIsTypeOf ( CanceledCustomerLiable ) and ra . oclAsType ( CanceledCustomerLiable ) . motivation=CancelingMotivation : : customer_canceled and ra . oclAsType ( CanceledCustomerLiable ) . cancellationDate=now() and if ( ra . oclIsTypeOf ( GuaranteedCancel ) ) then resul t=ra . oclAsType ( GuaranteedCancel ) . fine 37 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Renter <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.16: Activity Diagram for Cancel Reservation else result=0 endif 3.5.8.2 Charge Fine The customer is charged a ne for the cancellation of the reservation. Deals with material resources . 3.5.9 Cancel Reservation 3.5.9.1 Cancel Reservation Company This action cancels a user's reservation at the request of EU-Rent. However, the customer may also have to pay a ne if the company is forced to cancel it due to a customer's fault (e.g. becoming blackslisted). Additional comments: • The original specication for this operation did not charge the user for cancelling the reservation. However, we consider that if the company is forced to cancel a reservation because of the user's fault, the user should be charged as if it had been a no-show reservation. The original description, in fact, states that this is so. • We have included the charge operation in this action, instead of having a separate action for it, because this is done automatically and there is no interaction with the user. • charge() - charges the cancellation cost to the user. action CancelReservationCompany ( res : Reservation , reason : CancellingMotivation) localPre : − localPost : 38 Cancel Reservation by Customer Demand Make Reservation Pick-Up Car Return Car Handover Extend Rental Agreement Check Requirements Fulfillment Make Walk-In Rental Contact Customer Call Police Obtain Customer Cancel Reservation Obtain Data and Cancel Reservation RentalAgreement Check RentalAgreement Status Reservation Any Reservation <<material>> Money <<material>> Branch RentalAgreement <<material>> Car RentalAgreement RentalAgreement Undefined <<material>> User <<material>> Contract <<material>> Car RentalAgreement EU_RentPerson Car <<material>> Money EU_RentPerson EU_CoPerson EU_CoPerson EU_CoPerson <<material>> Renter <<material>> Police <<material>> Insurance Company EU_RentPerson EU_CoPerson Reservation <<material>> Money Check Driver Status Get Driving License Choose Price Obtain Data for Rental and Calculate Price <<participant>> Choose Cancel at No Cost Cancel Reservation Unable to Drive Handover <<participant>> <<participant>> Charge Fine <<participant>> <<external>> Call Branch Obtain ID, Data for Extension and Verify Check Car Close Rental Handover Obtain Rental Data Verify State of Driver Verify State of Customer Sign Rental Agreement Sign Additional Driver's Authorization Hand Car Over Add Driver to Rental Check Requirements Fulfillment Confirm Pick-Up Record Damages, Mileage and Maintenance Record Mileage and Maintenance <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> <<participant>> Pay <<participant>> <<participant>> <<participant>> Check Existing Person Insert New EU-Corporation Driver <<participant>> <<participant>> Obtain Customer <<participant>> Obtain Customer <<participant>> <<participant>> Call Customer Call Police Notify Insurance Company Check Existing Customer Add Customer's Driving License Insert New EU-Corporation Customer <<participant>> <<participant>> <<participant>> Cancel Reservation Company <<participant>> Calculate Reimbursement Reimburse Money <<participant>> Pay Fine <<participant>> [else] <<cancel>> [result > 0] [EUCorpCustomer] [EURentCustomer] [NotRegistered] [else] <<succeed>> [else] [damages] <<cancel>> [success] <<succeed>> [failure] <<fail>> <<succeed>> [result>0] [else] [fail] [success] <<succeed>> [blacklisted] <<fail>> [EURentCustomer] [null] <<fail>> [null] <<fail>> [NotRegistered] [else] [EUCorpCustomer] [CarReady] [NoReservation] <<fail>> <<succeed>> [failure] [success] <<succeed>> [else] [unable to drive] <<fail>> [else] [unable to drive] [new driver] [else] [false] [true] <<cancel>> [CarNotReady] Visual Paradigm for UML Community Edition [not for commercial use] Figure 3.17: Activity Diagram for Return Car res . oclIsTypeOf ( CanceledCustomerLiable ) and res . oclAsType ( CanceledCustomerLiable ) . motivation=reason and res . oclAsType ( CanceledCustomerLiable ) . cancellationDate=now() if ( res . oclIsTypeOf ( GuaranteedCanceled ) ) then charge ( res . oclAsType ( GuaranteedCanceled ) . fi ne ) else true endif 3.5.10 Return Car 3.5.10.1 Close Rental This action closes the corresponding rental after a customer returns the car. It calculates the nal price of the rental and, if the customer has returned the car later than expected, a bad experience is recorded. Additional comments: • Checks if the user fulls any blacklisting criterion. If ClosedRental (closedR) is a LateReturn , then we add a BadExperience of this type to the ClosedRental , we calculate the degree of the BadExperience and the Customer loses his membership to the Loyal Incentive Scheme. • As the car has been returned, we must indicate the new type of the rental, ClosedRental . • If the car is returned to a branch other than the pickUpBranch , then car ownership is transfered to the dropOBranch . 39 Appendix A Structural Schema in OCL The following appendix includes the denition of the integrity constraints and the derivation rules in OCL corresponding to class diagrams in Chapter 3. A.1 Class Diagram Following the method described in [8], in this section we present the class diagram with the corresponding operations that dene the derivation rules for attributes and their relationships, together with the integrity constraints, also represented as operations. A.2 Integrity Constraints The following section denes, for each class in Chapter 3, its integrity constraints and derivation rules. A.2.1 Branch Id id key: context Branch : : nameIsKey () : Boolean body : result=Branch . allInstances () − > isUnique (name) Derived relationship carsAvailableNow context Branch : : carsAvailableNow () : Set (OwnCar) body : r esult = s e l f . car − >se lect ( c | c . oclIsKindOf (OwnCar) and c . oclAsType (OwnCar) . a va ila bl e ) . oclAsType (OwnCar) Derived relationship groupsAvailableNow context Branch : : carsAvailableNow () : Set (CarGroup) body : r esult = s e l f . carsAvailableNow . carModel . carGroup − >asSet () 46 name : String <<IC>> nameIsKey() carsAvailableNow() groupsAvailableNow() Branch registrationNumber : String <<IC>> registrationNumberIsKey() <<IC>> onlyOneAssignment() carGroup() Car faults() EU_RentPerson <<IC>> rentalsDoNotOverlap() Customer number : Natural issue : Date expiration : Date <<IC>> validLicense() <<IC>> numberIsKey() DrivingLicense / basePrice : Money / bestPrice : Money / lastModification : Date <<IC>> correctInterval() <<IC>> visistsBranchCountries() basicPrice() bestPrice() bestDurationPrices() agreedEnding() applicableDiscountPerDuration() rentGroup() lastModification() RentalAgreement name : String mechanicalConditionsReqs : Set(String) emissionsReqs : Set(String) carTax : Double <<IC>> nameIsKey() Country expectedPreparedTime : Time <<iniIC>> pickUpBranchIsResponsible() AssignedCar actualTime : Time Prepared name : String <<IC>> nameIsKey() <<IC>> totalOrder() CarGroup name : String characteristics : Sequence(String) <<IC>> nameIsKey() CarModel DateTime reservationDate : DateTime <<IC>> onTimeReservation() <<IC>> modelsInGroup() Reservation name : String <<IC>> nameIsKey() <<IC>> totalOrder() CarGroup actualPickUpTime : Time OpenRental paymentType : PayType creditCardNumberDamages : Natural / rentalPriceWithTax : Money rentalPriceWithTax() ClosedRental <<IC>> trueExtensions() agreedEnding() ExtendedRental name : String effect : String description : String beginningDate : Date reservationTime : Boolean <<IC>> nameIsKey() Discount name : String minimumDuration : Natural maximumDuration : Natural timeUnit : Period <<IC>> nameIsKey() <<IC>> coherentPrices() <<IC>> totalOrder() RentalDuration DateTime price : Money CarGroupDurationPrice endingDate : Date <<IC>> correctEnding() EndDurationPrice endingDate : Date <<IC>> correctEnding() ClosedDiscount type : BadExpType <<IC>> typeIsKey() BadExperience /CarDamage degree : Level FaultSeriousness price : Money DamageCost registrationNumber : String <<IC>> registrationNumberIsKey() <<IC>> onlyOneAssignment() carGroup() Car extensionDone : DateTime Extension price : Money CarGroupDurationPrice degree : Level FaultSeriousness currentMileage : Double mileageFromLastService : Double lastMaintenanceDate : Date acquisitionDate : Date / available : Boolean / assigned : Boolean available() assigned() OwnCar / quantity : Natural quantity() /ApplicableRentalDurations 1..* 0..* 1 1..* 1 * agreedEnding 0..1 0..1 worse better 1 0..* 1 * pickUpBranch * 1 actualReturn 0..* 0..* * 1..* 0..1 0..1 shorter longer 1 * * * groupsAvailableNow 0..1 0..* lastNewEnding 0..1 * * 1 dropOffBranch * * driver rentalsAsDriver * * 1..* 1 * initEnding * 0..1 * 0..1 requestedModel 1 1 1 * rentGroup bestDurationPrices * 1 requestedGroup 1..* * 1 1..* actualReturnBranch 1 * 1..* * beginning renter * beginning 1..* 1 carGroup 0..* 1..* faults 0..* 0..1 carsAvailableNow * /ApplicableRentalDurations ApplicableGroups /isAvailable /GroupAvailability /HasFaults /BestDurations ^isResponsibleFor {subsets} DamageCost FaultSeriousness ApplicableDurations Extension ReturnedTo ReturnedAt RentalAgreement initialEnding / agreedEnding < isIn isOfA / isGroup categoryOrder / visits ^ isLocatedAt pickUp AssignedCar < drives dropOff has Visual Paradigm for UML Community Edition [not for commercial use] Figure A.1: Main class diagram for EU-Rent Car Rental Service. 47 faults() EU_RentPerson <<IC>> rentalsDoNotOverlap() Customer membershipDate : Date / availablePoints : Natural availablePoints() <<IC>> meetsLoyalPermanence() LoyaltyMember blacklistedDate : Date <<IC>> noRentals() Blacklisted id : String name : String address String birthdate : Date telephone : Natural <<IC>> is25orOlder() <<IC>> idIsKey() EU_CoPerson Visual Paradigm for UML Community Edition [not for commercial use] Figure A.2: Class diagram of EU_CoPerson and its subclasses A.2.2 EU_CoPerson Id is key: context EU_CoPerson : : idIsKey () : Boolean body : result = EU_CoPerson. allInstances () − >isUnique(id) Must be 25 or older: context EU_CoPerson : : is25OrOlder () : Boolean body : result = today () − s e l f . birthdate () >= year (25) ) A.2.3 EU_RentPerson Derived relationship faults : context EU_RentPerson : : faults () : Boolean body : let faultsAsDriver : FaultSeriousness = s e l f . rentalsAsDriver − > sel ec t (rA | rA. oclIsTypeOf ( ClosedRental ) ) . oclAsType ( ClosedRental ) . faultSeriousness let faultsAsRenter : FaultSeriousness = Customer . allInstances () − > se le ct ( c | c . id = s e l f . id ) . rentalAgreement − > sel ect (rA | rA. oclIsTypeOf ( ClosedRental ) ) . oclAsType ( ClosedRental ) . faultSeriousness in result = faultsAsDriver − >asSet () − > union ( faultsAsRenter ) − >asSet () 48 reservationDate : DateTime <<IC>> onTimeReservation() <<IC>> modelsInGroup() Reservation bestPrice() ReservationWithSpecialDiscount cancellationDate : DateTime <<IC>> correctCancellation() CanceledReservation <<IC>> _14DaysInAdvance() PointsPaymentReservation creditCardNumber : Natural GuaranteedReservation motivation : CancellingMotivation CanceledCustomerLiable CanceledCompanyLiable / fine : Money {frozen} fine() allInstances() / GuaranteedCanceled {d,c} Visual Paradigm for UML Community Edition [not for commercial use] Figure A.3: Class diagram of Reservation and its subclasses A.2.4 RentalAgreement The pick-up and drop-o branches' countries must be included in the list of countries of the RentalAgreement : context RentalAgreement : : visitsBranchCountries () : Boolean body : r esult = s e l f . Countries − >includes ( s e l f . PickUpBranch . Country ) and s e l f . Countries − >includes ( s e l f . DropOffBranch . Country ) Correct interval for rental agreement: context RentalAgreement : : correctInterval () : Boolean body : r esult=s e l f . beginning< s e l f . initEnding and s e l f . actualReturn> s e l f . beginning Derived attribute basicPrice 1 : context RentalAgreement : : basicPrice () : Money body : −− We have to calculate the price considering the best applicable prices , but without any discounts . −− −− 1. Each RentalAgreement is associated to various RentalDurations. −− 2. Each RentalAgreement is linked to various CarGroupDurationPrices ( through bestDurationPrices ) . This contains the best price for each rental duration for the CarGroup of the RentalAgreement . That is , for every RentalDuration , there is exactly one CarGroupDurationPrice . −− −− 3. This implies that , i f we navigate the relationship bestDurationPrices and sel ec t the CarGroupDurationPrice for a particular RentalDuration , there w il l only be ONE CarGroupDurationPrice. −− 2.3.4. We calculate the price of the rental by i t eratin g through the RentalDurations linked to the RentalAgreement and selecting the corresponding price in bestDurationPrices . We 1 This code has been changed from the original specication in [5]. 49 registrationNumber : String <<IC>> registrationNumberIsKey() <<IC>> onlyOneAssignment() carGroup() Car currentMileage : Double mileageFromLastService : Double lastMaintenanceDate : Date acquisitionDate : Date / available : Boolean / assigned : Boolean available() assigned() OwnCar beginningDate : Date RepairsScheduled <<IC>> notOver10Percent() allInstances() /NeedsMaintenance <<IC>> notAssignedReservation() ToBeSoldCar beginningDate : Date MaintenanceScheduled allInstances() /NeedToBeSoldCar BeingTransferred Visual Paradigm for UML Community Edition [not for commercial use] Figure A.4: Class diagram of Car and its subclasses then multiply this for the number of a particular RentalDuration there is in a RentalAgreement . Finally , we add this value to the accumulated price and we examine the next RentalDuration. −− result = self .applicableRentalDuration − >i te ra t e ( elem ; tup : Tuple{ currentPrice : Money=0, accPrice : Money=0} | currentPrice = s e l f . bestDurationPrices − > sel ec t (cGDP | cGDP. rentalDuration=elem . rentalDuration ) . price accPrice = accPrice + currentPrice ∗ elem . quantity ) . accPrice Derived attribute bestPrice 2 : context RentalAgreement : : bestPrice () : Money body : −− We have to calculate the price considering the discounts available . However , we must exclude those discounts that are only applicable at reservation time , as the function is in RentalAgreement and may not be of the Reservation subtype . −− −− 1. We s el ec t those discounts applicable to the particular rentGroup and the la st modification of the rental , excluding those that must be selected at reservation time . We also check i f i t s a pp lica bl e to the Customer . −− let applicableDiscounts: Set ( Discount )=s e l f . rentGroup . discount − >se lect ( dis | dis . beginningDate<=s e l f . initEnding and ( dis . oclIsTypeOf ( ClosedDiscount ) implies dis . oclAsType ( ClosedDiscount ) . endingDate>=s e l f . lastModification ) and dis . reservationTime=f als e and applicable ( dis , c ) ) in 2 This code has been modied from the original specication in [5]. 50 paymentType : PayType creditCardNumberDamages : Natural / rentalPriceWithTax : Money rentalPriceWithTax() ClosedRental / extraInterval : Duration / extraCostWithTax : Money allInstances() extraCostWithTax() /LateReturn allInstances() /EarlyReturn <<IC>> enoughInAdvance() <<iniIC>> customerIsLoyaltyMember() allInstances() bestPrice() /PaidWithPointsRental return_time {d,c} Visual Paradigm for UML Community Edition [not for commercial use] Figure A.5: Class diagram of ClosedRental and its subclasses blacklisting no_show unable_to_drive customer_canceled <<enumeration>> CancellingMotivation EUCorpCustomer EURentCustomer NotRegistered <<enumeration>> CustomerType CarReady CarNotReady NoReservation <<enumeration>> ReservationStatus Points SpecialDiscount BestPrice BasePrice <<enumeration>> PayType veryhigh high medium low verylow <<enumeration>> Level lateReturn carDamage paymentProblem <<enumeration>> BadExpType hour day <<enumeration>> Period mileageForService : Double = 10000 timeForService : Duration = (month, 3) MaintenanceRequirements Unit : Period numberOfUnits : Natural Duration Visual Paradigm for UML Community Edition [not for commercial use] Figure A.6: Denition of types −− 2. We create a function to determine , of a l l applicableDiscounts , the best one for a particular duration −− let bestDiscountPerDuration ( rd : RentalDuration , price : Money) : Discount = applicableDiscounts − >se lect (d | d . rentalDuration=rd ) − > reject ( disAct : Discount | applicableDiscounts − > sel ect (d2 | d2 . rentalDuration=rd ) − > exists ( disOther : Discount | apply ( disOther , price ) . isBetter ( apply ( disAct , price ) ) ) − >any () −− 3. We calculate the price of the rental including the discounts −− −− 3.1. Each RentalAgreement is associated to various RentalDurations. −− −− 3.2. Each RentalAgreement is linked to various CarGroupDurationPrices ( through bestDurationPrices ) . This contains the best price for each rental duration for the CarGroup of the RentalAgreement . That is , for every RentalDuration , there is exactly one CarGroupDurationPrice. −− 51 −− 3.3. This implies that , i f we navigate the rel at ion sh ip bestDurationPrices and sel ec t the CarGroupDurationPrice for a particular RentalDuration , there w il l only be ONE CarGroupDurationPrice . −− −− 3.4. We calculate the price of the rental by iter a ting through the RentalDurations linked to the RentalAgreement and selecting the corresponding price in bestDurationPrices . We then obtain the best Discount for a particular RentalDuration and CarGroup , apply this Discount to the price in CarGroupDurationPrice and multiply this for the number of a particular RentalDuration there is in a RentalAgreement . Finally , we add this value to the accumulated price and we examine the next RentalDuration. −− result = self .applicableRentalDuration − >i te ra t e ( elem ; tup : Tuple{ currentPrice : Money=0, accPrice : Money=0} | currentPrice = s e l f . bestDurationPrices − > sel ec t (cGDP | cGDP. rentalDuration=elem . rentalDuration ) . price currentPrice = apply ( bestDiscountPerDuration ( elem . rentalDuration , currentPrice) , currentPrice) accPrice = accPrice + currentPrice ∗ elem . quantity ) . accPrice Derived attribute lastModication : context RentalAgreement : : lastModification () : DateTime body : if s e l f . oclIsTypeOf ( Reservation ) then resul t = s e l f . reservationDate else resul t = s e l f . beginning endif Derived relationship bestDurationPrices context RentalAgreement : : bestDurationPrices () : Set (CarGroupDurationPrice) body : let applicableDuration: Set (CarGroupDurationPrice)= s e l f . rentGroup . carGroupDurationPrice − > s el e ct ( cg : CarGroupDurationPrice | cg . beginning<= s e l f . ending and ( cg . oclIsTypeOf ( EndDurationPrice ) implies cg . oclAsType ( EndDurationPrice ) . endingDate >= s e l f . lastModification ) let bestCurrentDuration: Set (CarGroupDurationPrice)= applicableDuration − >reje ct (cgCur : CarGroupDurationPrice | applicableDuration − > ex is ts ( cgOther : CarGroupDurationPrice | cgOther . rentalDuration=cgCur . rentalDuration and cgOther . carGroup= cgCur . carGroup and cgOther . price<cgCur . price ) ) in result = bestCurrentDuration − > sortedBy ( rentalDuration . shorter ) Derived relationship rentalDuration 3 3 This relationship and its correspoding associative class do not appear in the original specication in [5]. We suppose that duration of a rental is measured either in days or hours. 52 context RentalAgreement : : rentalDuration () : Set (RentalDuration) body : let rentalDur : Duration = durationT ( s e l f . agreedEnding − s e l f . initEnding ) let rentalDays : Natural = rentalDur . numberOfUnits in let possibleRentalDur: Set (RentalDuration) = if ( rentalDur . unit = Period : : day) then RentalDuration . allInstances () − >s el e ct ( rd | rd . timeUnit=Period : : day) − >sortedBy(maximumDuration) − >reverse () else −− The rental wi ll only be for a few hours −− RentalDuration . allInstances () − >s el e ct ( rd | rd . timeUnit=Period : : hour ) − >sortedBy(maximumDuration) − >reverse () endif in possibleRentalDur − >i te ra t e ( elem ; selRentalDur : OrderedSet ( RentalDuration ) − >isEmpty() | if ( rentalDays >= elem . maximumDuration) then selRentalDur=selRentalDur − >including ( elem ) rentalDays=rentalDays%maximumDuration else true endif if ( rentalDays >= elem . minimumDuration) then selRentalDur=selRentalDur − >including ( elem ) rentalDays=rentalDays%minimumDuration else true endif ) result = selRentalDur Derived relationship agreedEnding . context RentalAgreement : : agreedEnding () : DateTime body : result= initEnding Derived relationship rentGroup : context RentalAgreement : : rentGroup () : CarGroup body : if s e l f . oclIsKindOf ( Reservation ) then if s e l f . car − >isEmpty () or s e l f . car . carGroup<>s e l f . carGroup . worse then resul t=s e l f . carGroup else resul t=s e l f . carGroup . worse endif else resul t=s e l f . car . carGroup endif A.2.5 Reservation Reservation date of a rental must be previous to its beginning date. context Reservation : : onTimeReservation () : Boolean body : r esult=s e l f . reservationDate < s e l f . beginning 53 Requested car model must be in requested car group. context Reservation : : modelIsInGroup () : Boolean body : r esult=s e l f . requestedModel − >notEmpty () implies s e l f . requestedModel . carGroup=s e l f . requestedGroup A.2.6 ReservationWithSpecialDiscount Derived attribute bestPrice : • This code has been modied from the original specication in [5]. context ReservationWithSpecialDiscount : : bestPrice () : Money body : −− We have to calculate the price considering the discounts available at reservation time −− −− 1. We s el ec t those discounts applicable to the particular rentGroup and la st modification of the rental . We also check i f i t s a pp lica bl e to the Customer . −− let applicableDiscounts: Set ( Discount )=s e l f . rentGroup . discount − >se lect ( dis | dis . beginningDate<=s e l f . initEnding and ( dis . oclIsTypeOf ( ClosedDiscount ) implies dis . oclAsType ( ClosedDiscount ) . endingDate>=s e l f . lastModification and applicable ( dis , c ) ) in −− 2. We create a function to determine , of a l l applicableDiscounts , the best one for a particular duration −− let bestDiscountPerDuration ( rd : RentalDuration , price : Money) : Discount = applicableDiscounts − >se lect (d | d . rentalDuration=rd ) − > reject ( disAct : Discount | applicableDiscounts − > sel ect (d2 | d2 . rentalDuration=rd ) − > exists ( disOther : Discount | apply ( disOther , price ) . isBetter ( apply ( disAct , price ) ) ) − >any () −− 3. We calculate the price of the rental including the discounts −− −− 3.1. Each RentalAgreement is associated to various RentalDurations. −− −− 3.2. Each RentalAgreement is linked to various CarGroupDurationPrices ( through bestDurationPrices ) . This contains the best price for each rental duration for the CarGroup of the RentalAgreement . That is , for every RentalDuration , there is exactly one CarGroupDurationPrice. −− −− 3.3. This implies that , i f we navigate the rel at ion sh ip bestDurationPrices and sel ec t the CarGroupDurationPrice for a particular RentalDuration , there w il l only be ONE CarGroupDurationPrice . −− −− 3.4. We calculate the price of the rental by iter a ting through the RentalDurations linked to the RentalAgreement and selecting the corresponding price in bestDurationPrices . We then obtain the best Discount for a particular RentalDuration and CarGroup , apply this Discount to the price in CarGroupDurationPrice and multiply this for the number of a particular RentalDuration there is in a RentalAgreement . Finally , we add this value to the accumulated price and we examine the next RentalDuration. −− 54 result = self .applicableRentalDuration − >i te ra t e ( elem ; tup : Tuple{ currentPrice : Money=0, accPrice : Money=0} | currentPrice = s e l f . bestDurationPrices − > sel ec t (cGDP | cGDP. rentalDuration=elem . rentalDuration ) . price currentPrice = apply ( bestDiscountPerDuration ( elem . rentalDuration , currentPrice) , currentPrice) accPrice = accPrice + currentPrice ∗ elem . quantity ) . accPrice A.2.7 PointsPaymentReservation PointsPaymentReservation must be made at least 14 days in advance of its beginning date. context PointsPaymentReservation : : _14DaysInAdvance () : Boolean body : r esult =( s e l f . beginning − s e l f . reservationDate )>=day (14) A.2.8 CanceledReservation Cancellation date of a reservation must be after or on the same reservation date and before the beginning date, on the same date or the day after. This has been changed from the original report. context CanceledReservation : : correctCancellation () : Boolean body : r esult =( s e l f . cancellationDate>=s e l f . reservationDate and s e l f . cancellationDate <=(s e l f . beginning+day (1) ) ) A.2.9 GuaranteedCanceled Derived class: context GuaranteedCanceled : : allInstances () : Set (GuaranteedCanceled) body : result=CanceledCustomerLiable . allInstances () − > intersection ( GuaranteedReservation . allInstances () ) Derived attribute ne : context GuaranteedCanceled : : fine () : Money body : if s e l f . beginning=s e l f . cancellationDate then resul t = s e l f . bestDurationPrices − >se lect (cGDP | not (cGDP. oclIsTypeOf ( EndDurationPrice ) ) and cGDP. rentalDuration . timeUnit= Period : : day and cGDP. rentalDuration . minimumDuration=1) − >f i r s t () . price else result = 0 endif 55 A.2.29 Discount Discounts are identied by name. context Discount : : nameIsKey () : Boolean body : result = Discount . allInstances () − >isUnique (name) A.2.30 EndDurationPrice Ending date of EndDurationPrice must be on the same day or later than its beginning date. context EndDurationPrice : : correctEnding () : Boolean body : r esult = s e l f . endingDate >= s e l f . beginning A.2.31 ClosedDiscount Ending date of ClosedDiscount must be on the same day or later than beginning date. context ClosedDiscount : : correctEnding () : Boolean body : r esult = s e l f . beginningDate <= s e l f . endingDate A.2.32 BadExperience BadExperience is identied by type. context BadExperience : : typeIsKey () : Boolean body : result = BadExperience . allInstances () − >isUnique ( type ) A.2.33 CarDamage Derived class: context CarDamage : : allInstances () : Set (CarDamage) result = BadExperience . allInstances () − > s el ec t (b | b . type=BadExpType : : carDamage ) A.2.34 Country Countries are identied by name. context Country : : nameIsKey () : Boolean body : result = Country . allInstances () − >isUnique (name) 62