Show pageOld revisionsBacklinksBack to top This page is read only. You can view the source, but not change it. Ask your administrator if you think this is wrong. [<10>] ====== Loan Object ====== This object will have a lot more rules since it has a distinct life cycle. Let us define this life cycle first before defining the rules. A loan is created in the ''New'' state. In this state the loan is considered to be invalid. The loan validates itself and if validation is OK the loan moves itself to the ''Current'' state. Once the borrowed item has been returned the loan is moved to the “Past” state. It stays in the “Past” state until it is deleted. Before we start defining the rules we should also consider renewal of the loan. According to the [[6000_case_study:0300_library_app#Item_types_table|requirements]] there is a limitation on a number of times a loan can be renewed. The Loan object therefore needs to maintain this number in a separate attribute, which we will call ''RenewalCount''. We will add this attribute of the ''Number'' type to the Loan object (initial value of the attribute is 0). ===== Rules of the "New" state ===== Let us now define the rules applicable to the ''New'' state of the ''Loan'' object. Note that a loan is created in this state (we set the initial value of the Status attribute to ''New''). ==== "Item availability validation" Rule. ==== A loan can be created only for the item that is not on loan already. We obviously check the ''Available'' flag of the Item object but we also need to consider the situation when the loan is for the reserved item (in this case the item is considered to be unavailable, but the loan converting the reservation must be allowed). The action of the rule must be ''[[ref:a_f:a:report_error|REPORT ERROR]]'' which indicates that whatever operation the system is executing currently must be aborted as one of the objects in the system is invalid. We define the following rule with the name “Item availability validation”: <code aim>IF Loan.Status='New' AND Loan.Item.Available='No' AND NOT( Loan.Item.CurrentReservation.Member=Loan.Member AND Loan.Item.CurrentReservation.Status='Offered') THEN REPORT ERROR 'The item is not available for borrowing.' </code> ==== "Member status validation" Rule ==== A loan can be created only for active members: <code aim>IF Loan.Status='New' AND Loan.Member.Status<>'Active' THEN REPORT ERROR 'Non-active members are not allowed to borrow items.' </code> ==== "Same type items validation” Rule" ==== A member cannot borrow more than a maximum allowed number of loans for items of a particular type. This can be checked by the following condition: <code aim>COUNT Loan WHERE ( Loan IN ThisLoan.Member.Loans AND Loan.Status='Current' AND Loan.Item.Type = ThisLoan.Item.Type) >= Loan.Item.Type.MaxBorrowNumber </code> We count the current loans that belong to our member and have the same type as our item and compare with the maximum value defined in the type of our item. Note that we use ''ThisLoan'' in the condition – this is to differentiate our loan from all other loans that are being searched (see also the [[2000_concepts:0800_data_processing:0100_rule_evaluation:0800_context_rule_execution:0200_instance_prefixes|Instance Prefixes]]). The entire rule looks like so: <code aim>IF Loan.Status='New' AND COUNT Loan WHERE ( Loan IN ThisLoan.Member.Loans AND Loan.Status='Current' AND Loan.Item.Type=ThisLoan.Item.Type) >= Loan.Item.Type.MaxBorrowNumber THEN REPORT ERROR 'Member already has <<Loan.Item.Type.MaxBorrowNumber>> <<Loan.Item.Type.Name>>s.' </code> ==== "Total items validation" Rule ==== A member may not have more than the maximum number of loans. The rule looks like so(( At the moment the rule uses fixed number 10 as the maximum number of loans. We will address the requirement that management should be able to change this number from time to time in the [[6000_case_study:0400_configuration:1000_other_requirements:0300_system_initialisation#System_Settings_Object|Systems Settings Object]] )): <code aim>IF Loan.Status='New' AND COUNT Loan WHERE ( Loan IN ThisLoan.Member.Loans AND Loan.Status='Current') >= 10 THEN REPORT ERROR 'Member already has maximum allowed number of items.' </code> ==== "Due date" Rule ==== We must also have a rule that calculates the initial value of the ''DueDate'' attribute. The rule looks like this: <code aim>IF Loan.Status='New' THEN Loan.DueDate=Loan.LoanDate+Loan.Item.Type.MaxLoanPeriod </code> ==== "Current loan" Rule ==== As we said before valid loan should automatically move itself into the ''Current'' state(( The question here is whether the ''Loan'' should move itself into the ''Current'' state or the state should be explicitly set to ''Current'' externally after the loan has been created. There are merits in both approaches – we prefer here to get the loan to set its state automatically and demonstrate rule priorities. )). The rule looks like this: <code aim>IF Loan.Status = 'New' THEN Loan.Status = 'Current' </code> The rule looks a bit strange. The problem here is that the state transition should only be performed when the loan has been validated. Note that the sequence of all previous rules is not important – we can add them to the ''Loan'' object in any order (even the ''DueDate'' rule – it does not matter if the date is calculated for the invalid loan). In most cases all rules associated with a business object are equivalent as far as their order of execution is concerned – the system picks the order itself at random (see also the [[2000_concepts:0800_data_processing:0100_rule_evaluation|Rule Evaluation]]). Our automatic transition into the ''Current'' state is the rare case when the order of execution of a particular rule is important – we want to be sure that the rule that makes a state transition is executed after the validation rules. The mechanism to ensure this is to lower the priority of the ''Current'' state rule. We can do this when we enter the rule – we need to switch to the “Advanced” tab of the rule editor, click on the “I want to assign priority manually” radio button and specify the lower priority than the default priority of 30 (for example, 20) – see also [[2000_concepts:0800_data_processing:0100_rule_evaluation:0700_evaluation_unorder_rule_collections:0500_rule_priorities|Rule Priorities]]. ===== Rules of the "Current" state. ===== In this state we mostly need to concentrate on loan renewal. We will consider the loan as being renewed when its renewal count is incremented and not zero (we assume that the “RenewalCount” attribute is incremented externally to indicate an attempt to renew the loan). ==== "Renewed due date" rule ==== This is the rule that re-calculates the due date when the loan has been renewed: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.RenewalCount > 0 THEN INCREASE Loan.DueDate BY Loan.Item.Type.MaxLoanPeriod </code> Note that we can freely perform arithmetic operations with dates by adding a number of days to the due date. ==== "Renewal limit validation" rule ==== A loan cannot be renewed more times than allowed by the type of the item that has been borrowed. This can be captured by the following rule: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.RenewalCount > 0 AND Loan.RenewalCount > Loan.Item.Type.MaxRenewals THEN REPORT ERROR 'Cannot renew loan, the maximum number of renewals (<<Loan.Item.Type.MaxRenewals>>) is reached.' </code> ==== "Renewal reservation validation" rule ==== A loan cannot be renewed if someone has already reserved the borrowed item while it was on loan. We express this in the following rule: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.Item.CurrentReservation IS DEFINED AND Loan.RenewalCount > 0 THEN REPORT ERROR 'Cannot renew loan, there is a reservation for the item.' </code> ==== "Renewal member validation" rule ==== An attempt for loan renewal must be rejected if the library has made a decision to suspend the member who has borrowed the item. Therefore we check that the member status is still “Active”: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.Member.Status<>'Active' AND Loan.RenewalCount > 0 THEN REPORT ERROR 'Cannot renew loan for non-active member.' </code> ==== "Renewal item validation" rule ==== An attempt for loan renewal must be rejected if the library has made a decision to withdraw the borrowed item. Therefore we check that the item status is still “Released”: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.Item.InternalStatus<>'Released' AND Loan.RenewalCount > 0 THEN REPORT ERROR 'Cannot renew loan, the item is requested back to library.' </code> ===== Rules of the "Past" state ===== Finally we need to add rules applicable to a loan in the “Past” state. ==== "Return date" rule ==== This rule registers the return date of the loan when it has been closed: <code aim>IF Loan.Status WAS CHANGED TO 'Past' THEN Loan.ReturnDate = CURRENT_DATE </code> ==== "Renewal status validation" rule ==== An attempt to renew the loan in the “Past” state must be rejected: <code aim>IF Loan.RenewalCount WAS CHANGED AND Loan.Status<>'Current' AND Loan.RenewalCount > 0 THEN REPORT ERROR 'Cannot renew non-current loan' </code> These are all the rules of the Loan object. We can now enter these rules into //**AwareIM**// using either the Standard or Textual forms of the rule editor as described in the [[6000_case_study:0400_configuration:0600_business_rules:0100_item_object|Item Object Rules]]. Log In