Adding special reservation validations |
Top Previous Next |
DISCLAIMER: This article involves Advanced Customizations, which can be technically challenging to get working and is not part of standard support. This is programming and must be done precisely or the results can be unpredictable. This information is provided as a service for those who have the technical skills to work through it -- we cannot help you solve any issues with getting it working. For more information about Advanced Customizations, see the full documentation:
https://campgroundmaster.com/help/overview32.html
This Advanced Customizations example is the most complex we've had so far, but the more adventurous of you may find it useful.
The goal here is to do some special validations when making a reservation, warn the operator if the validations fail, and give them the option to either continue or not. Since we need to do it *before* the reservation is completed, it must be done as a Dialog customization to the New Reservation dialog. We can accomplish what we need by adding elements of type "Action on data saved", and selecting the options in the elements to do the action before the normal processing and allow aborting the action.
Now there are some assumptions made here to simplify things -- we're assuming no linked reservations need to be checked, no complications with splitting reservations, etc... so this example isn't foolproof, but should cover most situations.
The three things we're going to validate are listed below. One is a common request to not allow continuing without "How found" filled in, and the other two are typical restrictions with some membership parks:
1. "How found" must be filled in.
2. At least a 7-day gap between reservations for the same customer.
3. No more than 3 "active" current or future reservations in place at any time.
Since this example involves a lot of data entry, it's not going to be a click-by-click tutorial. If you're with us this far, then hopefully you just need the expression details to fill in the blanks. Remember that when entering expressions, never use the Enter key -- while the text below may show multiple lines for an expression, that's just a limitation of this formatting -- keep entering the expression text as a single line (if using copy/paste, you may need to delete the extra line breaks manually).
Also note that while the first restriction is easy to test with a single expression, the other two involve a lengthy process of checking all other reservations for that customer. This is best done using a separate Script so the expression in the Elements are simplified. We've included the complete scripts below as well.
So, first we need to add a Dialog definition, with the following details:
Dialog name: New Reservation restrictions
Add-on (checked): New Reservation
Enabled (checked)
Note: Only one Add-on definition can be active for a given dialog, so if you already had such a definition for New Reservation then you would just add elements on to the existing one instead of creating a new one here.
Now we'll add the validations as 3 separate elements:
Element 1: (How found filled in)
Element Type: Action on data saved
Action expression:
IIFQ( Empty(DlgGetDropListSelectedText(1084)), 'Eval(MessageBox("How-found must be filled in",0,2), DlgSetFocusCtrl(1084), .F.)', '.T.')
Execute the Action before... (checked)
Abort the operation which triggered... (checked)
Element 2: (Validate for 7-day gaps between reservations)
Element Type: Action on data saved
Action expression:
Eval(SetVar("pCust",ThisCust()), SetVar("dFrom",DlgGetCtrlDate(1052)), SetVar("dTo",DlgGetCtrlDate(1068)), iifq(B(CallScript("ResvGapUnder7")), '.T.', 'MessageBox("This would result in less than 7 days gap between reservations for this customer.\\n\\nAre you sure you want to proceed?", 2, 1) = 2'))
Execute the Action before... (checked)
Abort the operation which triggered... (checked)
Element 3: (Validate for a max of 3 current/future reservations)
Element Type: Action on data saved
Action expression:
Eval(SetVar("pCust",ThisCust()), iifq(DlgGetCtrlDate(1068) < Today() OR B(CallScript("ResvMax3Future")), '.T.', 'MessageBox("This would result in more than 3 current or future reservations for this customer.\\n\\nAre you sure you want to proceed?", 2, 1) = 2'))
Execute the Action before... (checked)
Abort the operation which triggered... (checked)
IMPORTANT: If you're using version 4.1 or earlier, then the last two Action expressions above must be modified -- instead of "\\n", you need to use "\n" (just one backslash instead of two, as explained in a previous article).
OK, that does it for the dialog definition, but before it will work, we need to add the following Scripts.
Script 1:
Script name: ResvGapUnder7
Description: Returns False if there's another reservation for this customer with less than a 7 day gap between them
Expressions: (The line numbers are not to be entered of course)
1. ; Input:
2. ; dFrom and dTo vars should be the dates of the new reservation
3. ; pCust should be the customer this reservation is for
4. SetVar("fOK", .T.)
5. SetVar("nMinGap", 7)
6. SetVar("nList", CustNumResv(pCust))
7. SetVar( "n", 1)
8. WHILE n <= nList
9. SetVar( "pResv", CustResvAt(pCust, n) )
10. IF (dFrom > FieldDate(pResv,"Resv_Last_Date") AND Days(dFrom, FieldDate(pResv,"Resv_Last_Date")) < (nMinGap+1)) OR (dTo < FieldDate(pResv,"Resv_First_Date") AND Days(FieldDate(pResv,"Resv_First_Date"), dTo) < (nMinGap+1)) OR (dTo >= FieldDate(pResv,"Resv_First_Date") AND dTo <= FieldDate(pResv,"Resv_Last_Date")) OR (dFrom >= FieldDate(pResv,"Resv_First_Date") AND dFrom <= FieldDate(pResv,"Resv_Last_Date")) OR (dFrom <= FieldDate(pResv,"Resv_First_Date") AND dTo >= FieldDate(pResv,"Resv_Last_Date"))
11. IF ResvIsActive(pResv, .T. , .F. , .T., .T.) AND (FieldValue(ThisResv(),"Field_Index") != FieldValue(pResv,"Field_Index"))
12. SetVar("fOK", .F.)
13. ENDIF
14. ENDIF
15. SetVar("n", n+1)
16. ENDWHILE
17. ; Returns False if there's another reservation for this customer with less than a 7 day gap between them
18. fOK
Script 2:
Script name: ResvMax3Future
Description: Returns False if this would make more than 3 future reservations
Expressions:
1. ; Input:
2. ; pCust should be the customer this reservation is for
3. SetVar("nFuture", 0)
4. SetVar("nList", CustNumResv(pCust))
5. SetVar( "n", 1)
6. WHILE n <= nList
7. SetVar( "pResv", CustResvAt(pCust, n) )
8. IF FieldDate(pResv,"Resv_Last_Date") >= Today()
9. IF ResvIsActive(pResv, .T. , .F. , .T., .T.) AND (FieldValue(ThisResv(),"Field_Index") != FieldValue(pResv,"Field_Index"))
10. SetVar("nFuture", nFuture+1)
11. ENDIF
12. ENDIF
13. SetVar("n", n+1)
14. ENDWHILE
15. nFuture < 3
That completes the necessary programming. With everything entered properly, it will perform the validations we needed. You'll notice that the two scripts are similar and basically perform a loop through all reservations of the given customer to check the necessary conditions. These examples could be modified to do other types of customer-based validation, such as looking for previous reservation balances, notes in previous reservations, types if sites they stayed in before, etc. You could also just do customer validation (e.g. without the loop), such as proper fields filled in, make sure the rig type is appropriate for the site selected, and so forth.