guides:o4w:oi10:reference_guide:o4w_sample_stored_procedures

O4W Sample Stored Procedures

O4W_EXAMPLE0

O4W_EXAMPLE0
Subroutine O4W_EXAMPLE0(CtlEntId, Event, Request)

* Example #0: A simple entry/collection form

*

* Always include our equates

$Insert O4WEquates

*

* Determine how we were called, and what to do

*

Begin Case

            Case event _eqc "CREATE"

                        * Creation event - called the first time through for each application

                        * Specify that this will generate a full web page                   

                        O4WForm()

                        * Put up the 'header' describing the page

                        O4WHeader("Revelation Software POS (Pizza Ordering System)", 4)

                        * "Space down" a few blank lines

                        O4WBreak()

                        O4WBreak()

                        * Use a table to align everything neatly

                        O4WTableStart("mainTable")

                        * Display a prompt in the first 'cell' of the table

                        O4WSetCell(1,1)

                        O4WText("Delivery Address: ")

                        * And put up a 'textbox' for the response in the next 'cell'

                        O4WSetCell(1,2)

                        O4WTextbox('','' ,'' , 'ADD1')

                        * Repeat for the other desired information

                        * Notice the shortcut: only specifying the 'row number' to O4WSetCell automatically puts you in the first column of that row

                        O4WSetCell(2)

                        O4WText("Address 2:")

                        * Notice the shortcut: if neither the row nor column is specified in O4WSetCell, it automatically puts you in the next column of the current row

                        O4WSetCell()

                        O4WTextbox('','','','ADD2')

                        O4WSetCell(3)

                        O4WText("City:")

                        O4WSetCell()

                        O4WTextBox('','','','CITY')

                        O4WSetCell(4)

                        O4WText("State:")

                        O4WSetCell()

                        O4WTextBox('','','','STATE')

                        O4WSetCell(5)

                        O4WText("Zip:")

                        O4WSetCell()

                        O4WTextBox('','','','ZIP')

                        O4WSetCell(6)

                        O4WText("Pizza Size:")

                        O4WSetCell()

                        * Display a list of choices as radio buttons (allowing only a single choice)

                        O4WRadioButton("Small", "S", "SIZE")

                        O4WRadioButton("Medium", "M", "SIZE")

                        O4WRadioButton("Large", "L", "SIZE")

                        O4WSetCell(7)

                        O4WText("Toppings:")

                        O4WSetCell()

                        * Display a list of toppings as checkboxes (allowing multiple choices)

                        O4WCheckBox("Pepperoni", "P", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Sausage", "S", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Extra Cheese", "C", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Mushrooms", "M", "TOPPINGS")

                        * End the table

                        O4WTableEnd("mainTable")

                        O4WBreak()

                        * Display a button for them to submit the order

                        O4WButton("Order!", "BTNORDER")

                        * Tell O4W you wish to be notified when the user clicks on this button

                        O4WQualifyEvent("BTNORDER", "CLICK")

            Case event _eqc "CLICK"

                        * Click event - called when the button is pressed

                        * Read in all the values

                        ADD1 = O4WGetValue("ADD1")

                        ADD2 = O4WGetValue("ADD2")

                        CITY = O4WGetValue("CITY")

                        STATE = O4WGetValue("STATE")

                        ZIP = O4WGetValue("ZIP")

                        * 'SIZE' will return the S/M/L code from the SIZE radio buttons

                        SIZE = O4WGetValue("SIZE")

                        * 'TOPPINGS' will return an @VM-delimited list of the selected toppings

                        TOPPING = O4WGetValue("TOPPINGS")

                        * Calculate the price from the toppings and size selected

                        cost = 0

                        Begin Case

                                    Case SIZE = "S"

                                                cost = 700

                                    Case SIZE = "M"

                                                cost = 1000

                                    Case SIZE = "L"

                                                cost = 1300

                                    Case 1

                                                * Not a valid size - return an error

                                                O4WError("We're sorry, but the size '":size:"' doesn't appear to be valid!")

                                                Return

                        End Case

                        * Now find each of the toppings

                        num.toppings = dcount(topping, @VM)

                        For each.topping = 1 To num.toppings

                                    this.topping = topping<1,each.topping>

                                    Begin Case

                                                Case THIS.TOPPING = "P"

                                                            cost += 100

                                                Case THIS.TOPPING = "S"

                                                            cost += 100

                                                Case THIS.TOPPING = "C"

                                                            cost += 50

                                                Case THIS.TOPPING = "M"

                                                            cost += 100

                                                Case 1

                                                            * Not a valid topping?  Report an error

                                                            O4WError("We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!")

                                                            Return

                                    End Case

                        Next each.topping

                        * In a 'real' application, you'd now write all the information we collected into a database somewhere

                        orderNum = DATE():"*":TIME()

                        * <WRITE INFORMATION HERE>

                        * Notify the customer that his order has been received, and give him/her the total

      O4WError('Thank you for your order!  Your order number is ':orderNum:'.  Your total is ':OCONV(cost,'MD2,$'):'.', 'Thank You')

End Case

*

Return 0

image688.jpg

image690.jpg

O4W_EXAMPLE1

O4W_EXAMPLE1
Subroutine O4W_EXAMPLE1(CtlEntId, Event, Request)

* Example #1: A simple entry/collection form

*

* example 1: establish some constants we'll use in the example

Equ SizeList$ To "Small,Medium,Large"

Equ SizeCode$ To "S,M,L"

Equ SizeCost$ To "700,1000,1300"

*

Equ ToppingList$ To "Pepperoni,Sausage,Extra Cheese,Mushrooms"

Equ ToppingCode$ To "P,S,C,M"

Equ ToppingCost$ To "100,100,50,100"

*

* Always include our equates

$Insert O4WEquates

*

* Determine how we were called, and what to do

*

Begin Case

            Case event _eqc "CREATE"

                        * Creation event - called the first time through for each application

                        * Specify that this will generate a full web page                   

                        O4WForm()

      * example 1: Define the section that the form will go in

      O4WSectionStart('mainSection')

                        * Put up the 'header' describing the page

                        O4WHeader("Revelation Software POS (Pizza Ordering System)", 4)

                        * "Space down" a few blank lines

                        O4WBreak()

                        O4WBreak()

                        * Use a table to align everything neatly

                        O4WTableStart("mainTable")

                        * Display a prompt in the first 'cell' of the table

                        O4WSetCell(1,1)

                        O4WText("Delivery Address: ")

                        * And put up a 'textbox' for the response in the next 'cell'

                        O4WSetCell(1,2)

                        O4WTextbox('','' ,'' , 'ADD1')

                        * Repeat for the other desired information

                        * Notice the shortcut: only specifying the 'row number' to O4WSetCell automatically puts you in the first column of that row

                        O4WSetCell(2)

                        O4WText("Address 2:")

                        * Notice the shortcut: if neither the row nor column is specified in O4WSetCell, it automatically puts you in the next column of the current row

                        O4WSetCell()

                        O4WTextbox('','','','ADD2')

                        O4WSetCell(3)

                        O4WText("City:")

                        O4WSetCell()

                        O4WTextBox('','','','CITY')

                        O4WSetCell(4)

                        O4WText("State:")

                        O4WSetCell()

                        O4WTextBox('','','','STATE')

                        O4WSetCell(5)

                        O4WText("Zip:")

                        O4WSetCell()

                        O4WTextBox('','','','ZIP')

                        O4WSetCell(6)

                        O4WText("Pizza Size:")

                        O4WSetCell()

                        * Display a list of choices as radio buttons (allowing only a single choice)

                        * example 1: Instead of hard-coding the choices...

                        /*

                        O4WRadioButton("Small", "S", "SIZE")

                        O4WRadioButton("Medium", "M", "SIZE")

                        O4WRadioButton("Large", "L", "SIZE")

                        */

                        *...it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.SIZES = DCount(SizeList$, ",")

                        For each.size = 1 To num.sizes

                                    this.size = Field(SizeList$, ",", each.size)

                                    this.code = Field(SizeCode$, ",", each.size)

                                    O4WRadioButton(this.size, this.code, "SIZE")

                        Next each.size

                        O4WSetCell(7)

                        O4WText("Toppings:")

                        O4WSetCell()

                        * Display a list of toppings as checkboxes (allowing multiple choices)

                        * example 1: instead of hard-coding the choices...

                        /*

                        O4WCheckBox("Pepperoni", "P", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Sausage", "S", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Extra Cheese", "C", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Mushrooms", "M", "TOPPINGS")

                        */

                        *...it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.TOPPINGS = DCount(ToppingList$, ",")

                        For each.topping = 1 To num.toppings

                                    this.topping = Field(ToppingList$, ",", each.topping)

                                    this.code = Field(ToppingCode$, ",", each.topping)

                                    O4WCheckBox(this.topping, this.code, "TOPPINGS")

                                    O4WBreak()

                        Next each.topping

                        * End the table

                        O4WTableEnd("mainTable")

                        O4WBreak()

                        * Display a button for them to submit the order

                        O4WButton("Order!", "BTNORDER")

                        * Tell O4W you wish to be notified when the user clicks on this button

                        O4WQualifyEvent("BTNORDER", "CLICK")

      * example 1: finish up the main section we defined

      O4WSectionEnd('mainSection')

      * example 1: create a special area for us to use when displaying some response to the user

      * nothing goes in it now, but we may fill it in later

      O4WSectionStart('responseArea')

      O4WSectionEnd('responseArea')

            Case event _eqc "CLICK"

                        * Click event - called when the button is pressed

      * example 1: Tell O4W we'll be generating a response updating the current form (as opposed to making a whole new form)

      O4WResponse()

                        * Read in all the values

                        ADD1 = O4WGetValue("ADD1")

                        ADD2 = O4WGetValue("ADD2")

                        CITY = O4WGetValue("CITY")

                        STATE = O4WGetValue("STATE")

                        ZIP = O4WGetValue("ZIP")

                        * 'SIZE' will return the S/M/L code from the SIZE radio buttons

                        SIZE = O4WGetValue("SIZE")

                        * 'TOPPINGS' will return an @VM-delimited list of the selected toppings

                        TOPPING = O4WGetValue("TOPPINGS")

                        * example 1: calculate the price from the toppings and size selected, using the equated list

                        locate size In SizeCode$ Using "," Setting pos Then

                                    cost = Field(SizeCost$,",",pos)

                        End Else

                                    * Couldn't find the size in the list?  Report an error to the customer

                                    O4WError("We're sorry, but the size '":size:"' doesn't appear to be valid!")

                                    Return

                        End

                        * example 1: Now find each of the toppings in the equated list

                        num.toppings = dcount(topping, @VM)

                        For each.topping = 1 To num.toppings

                                    this.topping = topping<1,each.topping>

                                    Locate this.topping In ToppingCode$ Using "," Setting pos Then

                                                cost += Field(ToppingCost$, ",", pos)

                                    End Else

                                                * Couldn't find the topping in the list?  Report an error

                                                O4WError("We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!")

                                    End

                        Next each.topping

                        * In a 'real' application, you'd now write all the information we collected into a database somewhere

                        orderNum = DATE():"*":TIME()

                        * <WRITE INFORMATION HERE>

                        * Notify the customer that his order has been received, and give him/her the total

      * example 1: We'll put this information into our 'responseArea'

      * Note that we use a special style so that O4W knows we're updating the previously-defined area (and not asking to create a new one)

      O4WSectionStart('responseArea', O4WResponseStyle())

      O4WHeader('Your order number is ':orderNum, 4)

      O4WBreak()

      O4WText('Thank you for your order!  Your order total is ':OCONV(cost,'MD2,$'):'.')

      O4WBreak()

      O4WText('Please press ')

      * Build a 'link' to return to the home page

      O4WLink('here', O4W_LINKTYPE_NORMAL$, 'www.revelation.com')

      O4WText(' to return to the home page')

      O4WSectionEnd('responseArea')

      * Display this area as a 'dialog box' to the user

      O4WDialog('responseArea', 'Thank You')

End Case

*

Return 0

image692.jpg

image694.jpg

O4W_EXAMPLE2

O4W_EXAMPLE2
Subroutine O4W_EXAMPLE2(CtlEntId, Event, Request)

* Example #2: A simple entry/collection form with some dynamic updates

*

* Establish some constants we'll use in the example

Equ SizeList$ To "Small,Medium,Large"

Equ SizeCode$ To "S,M,L"

Equ SizeCost$ To "700,1000,1300"

*

Equ ToppingList$ To "Pepperoni,Sausage,Extra Cheese,Mushrooms"

Equ ToppingCode$ To "P,S,C,M"

Equ ToppingCost$ To "100,100,50,100"

*

* Always include our equates

$Insert O4WEquates

*

* Determine how we were called, and what to do

*

Begin Case

            Case event _eqc "CREATE"

                        * Creation event - called the first time through for each application

                        * Specify that this will generate a full web page                   

                        O4WForm()

      * Define the section that the form will go in

      O4WSectionStart('mainSection')

                        * Put up the 'header' describing the page

                        O4WHeader("Revelation Software POS (Pizza Ordering System)", 4)

                        * "Space down" a few blank lines

                        O4WBreak()

                        O4WBreak()

                        * Use a table to align everything neatly

                        O4WTableStart("mainTable")

                        * Display a prompt in the first 'cell' of the table

                        O4WSetCell(1,1)

                        O4WText("Delivery Address: ")

                        * And put up a 'textbox' for the response in the next 'cell'

                        O4WSetCell(1,2)

                        O4WTextbox('','' ,'' , 'ADD1')

                        * Repeat for the other desired information

                        * Notice the shortcut: only specifying the 'row number' to O4WSetCell automatically puts you in the first column of that row

                        O4WSetCell(2)

                        O4WText("Address 2:")

                        * Notice the shortcut: if neither the row nor column is specified in O4WSetCell, it automatically puts you in the next column of the current row

                        O4WSetCell()

                        O4WTextbox('','','','ADD2')

                        O4WSetCell(3)

                        O4WText("City:")

                        O4WSetCell()

                        O4WTextBox('','','','CITY')

                        O4WSetCell(4)

                        O4WText("State:")

                        O4WSetCell()

                        * O4WTextBox('','','','STATE')

                        * example 2: Use a combo box for the state

                        * O4W provides a standard 'states' code record in the standard "configuration" file

                        stateInfo = Xlate("O4WCODES", "CODES_STATES", "", "X")

                        num.states = dcount(stateInfo<1>, @VM)

                        * Define a 'default' value to prompt the user

                        O4WListBox("Select...", "", "STATE")

                        For each.state = 1 To num.states

                                    state.name = stateInfo<1,each.state>

                                    state.code = stateInfo<2,each.state>

                                    O4WListBox(state.name, state.code, "STATE")

                        Next each.state

                        O4WSetCell(5)

                        O4WText("Zip:")

                        O4WSetCell()

                        O4WTextBox('','','','ZIP')

                        O4WSetCell(6)

                        O4WText("Pizza Size:")

                        O4WSetCell()

                        * Display a list of choices as radio buttons (allowing only a single choice)

                        * If we wanted to 'hard code' the choices, we could do this:

                        /*

                        O4WRadioButton("Small", "S", "SIZE")

                        O4WRadioButton("Medium", "M", "SIZE")

                        O4WRadioButton("Large", "L", "SIZE")

                        */

                        * But it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.SIZES = DCount(SizeList$, ",")

                        For each.size = 1 To num.sizes

                                    this.size = Field(SizeList$, ",", each.size)

                                    this.code = Field(SizeCode$, ",", each.size)

                                    *O4WRadioButton(this.size, this.code, "SIZE")

                                    * example 2: identify each radio button with a unique name

                                    O4WRadioButton(this.size, this.code, "SIZE", "SIZE_":this.code)

                        Next each.size

                        O4WSetCell(7)

                        O4WText("Toppings:")

                        O4WSetCell()

                        * Display a list of toppings as checkboxes (allowing multiple choices)

                        * If we wanted to 'hard code' the choices, we could do this:

                        /*

                        O4WCheckBox("Pepperoni", "Pepperoni", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Sausage", "Sausage", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Extra Cheese", "ExtraCheese", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Mushrooms", "Mushrooms", "TOPPINGS")

                        */

                        * But it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.TOPPINGS = DCount(ToppingList$, ",")

                        For each.topping = 1 To num.toppings

                                    this.topping = Field(ToppingList$, ",", each.topping)

                                    this.code = Field(ToppingCode$, ",", each.topping)

                                    *O4WCheckBox(this.topping, this.code, "TOPPINGS")

                                    * example 2: identify each checkbox with a unique name

                                    O4WCheckBox(this.topping, this.code, "TOPPINGS", "TOPPINGS_":this.code)

                                    O4WBreak()

                        Next each.topping

                        * End the table

                        O4WTableEnd("mainTable")

                        O4WBreak()

                        * example 2: define an area where the 'running total' can go

                        O4WSectionStart('runningTotal')

                        O4WSectionEnd('runningTotal')

                        * Display a button for them to submit the order

                        O4WButton("Order!", "BTNORDER")

                        * Tell O4W you wish to be notified when the user clicks on this button

                        O4WQualifyEvent("BTNORDER", "CLICK")

                        * example 2: Tell O4W we want to be notified when the size or toppings change

                        O4WQualifyEvent("TOPPINGS", "CHANGE", "CHECKBOX")

                        O4WQualifyEvent("SIZE", "CHANGE", "RADIOBUTTON")

      * finish up the main section we defined

      O4WSectionEnd('mainSection')

      * create a special area for us to use when displaying some response to the user

      * nothing goes in it now, but we may fill it in later

      O4WSectionStart('responseArea')

      O4WSectionEnd('responseArea')

            Case event _eqc "CLICK"

                        * Click event - called when the button is pressed

      * Tell O4W we'll be generating a response updating the current form (as opposed to making a whole new form)

      O4WResponse()

                        * Read in all the values

                        ADD1 = O4WGetValue("ADD1")

                        ADD2 = O4WGetValue("ADD2")

                        CITY = O4WGetValue("CITY")

                        STATE = O4WGetValue("STATE")

                        ZIP = O4WGetValue("ZIP")

                        * example 2: Make sure these values have something in them

                        If TRIM(ADD1) = "" Or TRIM(CITY) = "" Or TRIM(STATE) = "" Or TRIM(ZIP)="" Then

                                    O4WError("Please be sure to enter complete address information before proceeding")

                                    Return

                        End

                        * example 2: move the extraction of the size and topping values, and the calculation of the cost, to a subroutine so we can call it from the 'change' event too

                        /*

                        * 'SIZE' will return the S/M/L code from the SIZE radio buttons

                        SIZE = O4WGetValue("SIZE")

                        * 'TOPPINGS' will return an @VM-delimited list of the selected toppings

                        TOPPING = O4WGetValue("TOPPINGS")

                        * Calculate the price from the toppings and size selected

                        locate size In SizeCode$ Using "," Setting pos Then

                                    cost = Field(SizeCost$,",",pos)

                        End Else

                                    * Couldn't find the size in the list?  Report an error to the customer

                                    O4WError("We're sorry, but the size '":size:"' doesn't appear to be valid!")

                                    Return

                        End

                        * Now find each of the toppings

                        num.toppings = dcount(topping, @VM)

                        For each.topping = 1 To num.toppings

                                    this.topping = topping<1,each.topping>

                                    Locate this.topping In ToppingCode$ Using "," Setting pos Then

                                                cost += Field(ToppingCost$, ",", pos)

                                    End Else

                                                * Couldn't find the topping in the list?  Report an error

                                                O4WError("We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!")

                                    End

                        Next each.topping

                        */

                        Gosub calcTotal

                        If error <> "" Then

                                    O4WError(error)

                                    Return

                        end

                        * In a 'real' application, you'd now write all the information we collected into a database somewhere

                        orderNum = DATE():"*":TIME()

                        * <WRITE INFORMATION HERE>

                        * Notify the customer that his order has been received, and give him/her the total

      * We'll put this information into our 'responseArea'

      * Note that we use a special style so that O4W knows we're updating the previously-defined area (and not asking to create a new one)

      O4WSectionStart('responseArea', O4WResponseStyle())

      O4WHeader('Your order number is ':orderNum, 4)

      O4WBreak()

      O4WText('Thank you for your order!  Your order total is ':OCONV(cost,'MD2,$'):'.')

      O4WBreak()

      O4WText('Please press ')

      * Build a 'link' to return to the home page

      O4WLink('here', 0, 'www.revelation.com')

      O4WText(' to return to the home page')

      O4WSectionEnd('responseArea')

      * Display this area as a 'dialog box' to the user

      O4WDialog('responseArea', 'Thank You')

            Case event _eqc "CHANGE"

                        * example 2: the 'CHANGE' event is triggered when our toppings or size is changed

                        * Update our total cost

                        cost = 0

                        * Because of how we organized our form, all the values are passed to us when we get the CHANGE event

                        Gosub calcTotal

                        If error <> "" Then

                                    * display any error message instead of our total

                                    O4WError(error)

                                    Return

                        end

                        * No error - display the total cost

                        * Tell O4W we're generating an update to the current form and not an entire new form

                        O4WResponse()

      * We'll put this information into our 'runningTotal'

      * Note that we use a special style so that O4W knows we're updating the previously-defined area (and not asking to create a new one)

      O4WSectionStart('runningTotal', O4WResponseStyle())

                        O4WText("Current Order Total: ":Oconv(cost, "MD2,$"))

                        O4WSectionEnd('runningTotal')

End Case

*

Return 0

*

*

* example 2: calcTotal subroutine will pull in the size and toppings info and calculate the cost

* if any errors occur, the variable "error" will be returned with the error text

calcTotal:

error = ""

* 'SIZE' will return the S/M/L code from the SIZE radio buttons

SIZE = O4WGetValue("SIZE")

* 'TOPPINGS' will return an @VM-delimited list of the selected toppings

TOPPING = O4WGetValue("TOPPINGS")

* Calculate the price from the toppings and size selected

locate size In SizeCode$ Using "," Setting pos Then

            cost = Field(SizeCost$,",",pos)

End Else

            * Couldn't find the size in the list?  Report an error to the customer

            error = "We're sorry, but the size '":size:"' doesn't appear to be valid!"

            Return

End

* Now find each of the toppings

num.toppings = dcount(topping, @VM)

For each.topping = 1 To num.toppings

            this.topping = topping<1,each.topping>

            Locate this.topping In ToppingCode$ Using "," Setting pos Then

                        cost += Field(ToppingCost$, ",", pos)

            End Else

                        * Couldn't find the topping in the list?  Report an error

                        error = "We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!"

                        return

            End

Next each.topping

Return

image696.jpg

image698.jpg

O4W_EXAMPLE3

O4W_EXAMPLE3
Subroutine O4W_EXAMPLE3(CtlEntId, Event, Request)

* Example #3: A simple entry/collection form with some dynamic updates, validation, and images

*

* Establish some constants we'll use in the example

Equ SizeList$ To "Small,Medium,Large"

Equ SizeCode$ To "S,M,L"

Equ SizeCost$ To "700,1000,1300"

*

Equ ToppingList$ To "Pepperoni,Sausage,Extra Cheese,Mushrooms"

Equ ToppingCode$ To "P,S,C,M"

Equ ToppingCost$ To "100,100,50,100"

*

* example 3: include some images

Equ imagePath To "../examples/images/pizza"

 

* Always include our equates

$Insert O4WEquates

 

* example 3: define a 'validation' style that we can use

requiredStyle = O4WValidateStyle('','required')

 

*

* Determine how we were called, and what to do

*

Begin Case

            Case event _eqc "CREATE"

                        * Creation event - called the first time through for each application

                        * Specify that this will generate a full web page                   

                        O4WForm()

      * Define the section that the form will go in

      O4WSectionStart('mainSection')

                        * Put up the 'header' describing the page

                        O4WHeader("Revelation Software POS (Pizza Ordering System)", 4)

                        * "Space down" a few blank lines

                        O4WBreak()

                        O4WBreak()

                        * Use a table to align everything neatly

                        O4WTableStart("mainTable")

                        * Display a prompt in the first 'cell' of the table

                        O4WSetCell(1,1)

                        O4WText("Delivery Address: ")

                        * And put up a 'textbox' for the response in the next 'cell'

                        O4WSetCell(1,2)

                        * example 3: add in some validation (note that we now provide an "ID" for the textbox, in addition to the "Name")

                        O4WTextbox('','' ,'' , 'ADD1', "ADD1", requiredStyle)

                        * Repeat for the other desired information

                        * Notice the shortcut: only specifying the 'row number' to O4WSetCell automatically puts you in the first column of that row

                        O4WSetCell(2)

                        O4WText("Address 2:")

                        * Notice the shortcut: if neither the row nor column is specified in O4WSetCell, it automatically puts you in the next column of the current row

                        O4WSetCell()

                        O4WTextbox('','','','ADD2')

                        O4WSetCell(3)

                        O4WText("City:")

                        O4WSetCell()

                        * example 3: add in some validation

                        O4WTextBox('','','','CITY', 'CITY', requiredStyle)

                        O4WSetCell(4)

                        O4WText("State:")

                        O4WSetCell()

                        * O4WTextBox('','','','STATE')

                        * Use a combo box for the state

                        * O4W provides a standard 'states' code record in the standard "configuration" file

                        stateInfo = Xlate("O4WCODES", "CODES_STATES", "", "X")

                        num.states = dcount(stateInfo<1>, @VM)

                        * Define a 'default' value to prompt the user

                        O4WListBox("Select...", "", "STATE")

                        For each.state = 1 To num.states

                                    state.name = stateInfo<1,each.state>

                                    state.code = stateInfo<2,each.state>

                                    O4WListBox(state.name, state.code, "STATE")

                        Next each.state

                        O4WSetCell(5)

                        O4WText("Zip:")

                        O4WSetCell()

                        * example 3: add in another specific validation for zip codes

                        O4WTextBox('','','','ZIP', 'ZIP', O4WValidateStyle('','zip','1'))

                        O4WSetCell(6)

                        O4WText("Pizza Size:")

                        O4WSetCell()

                        * Display a list of choices as radio buttons (allowing only a single choice)

                        * If we wanted to 'hard code' the choices, we could do this:

                        /*

                        O4WRadioButton("Small", "S", "SIZE")

                        O4WRadioButton("Medium", "M", "SIZE")

                        O4WRadioButton("Large", "L", "SIZE")

                        */

                        * But it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.SIZES = DCount(SizeList$, ",")

                        For each.size = 1 To num.sizes

                                    this.size = Field(SizeList$, ",", each.size)

                                    this.code = Field(SizeCode$, ",", each.size)

                                    *O4WRadioButton(this.size, this.code, "SIZE")

                                    * identify each radio button with a unique name

                                    O4WRadioButton(this.size, this.code, "SIZE", "SIZE_":this.code)

                        Next each.size

                        * example 3: add another cell to contain the image of the pizza

                        O4WSetCell()

                        * example 3: for now, put up the generic cheese image

                        O4WImage("Mmmm...pizza!", imagePath:"L_.jpg",'','','','imagePizza')

                        O4WSetCell(7)

                        O4WText("Toppings:")

                        O4WSetCell()

                        * Display a list of toppings as checkboxes (allowing multiple choices)

                        * If we wanted to 'hard code' the choices, we could do this:

                        /*

                        O4WCheckBox("Pepperoni", "Pepperoni", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Sausage", "Sausage", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Extra Cheese", "ExtraCheese", "TOPPINGS")

                        O4WBreak()

                        O4WCheckBox("Mushrooms", "Mushrooms", "TOPPINGS")

                        */

                        * But it's better to drive this from the constants we declared at the top (so we can change them without changing the program logic)

                        NUM.TOPPINGS = DCount(ToppingList$, ",")

                        For each.topping = 1 To num.toppings

                                    this.topping = Field(ToppingList$, ",", each.topping)

                                    this.code = Field(ToppingCode$, ",", each.topping)

                                    *O4WCheckBox(this.topping, this.code, "TOPPINGS")

                                    * identify each checkbox with a unique name

                                    O4WCheckBox(this.topping, this.code, "TOPPINGS", "TOPPINGS_":this.code)

                                    O4WBreak()

                        Next each.topping

                        * End the table

                        O4WTableEnd("mainTable")

                        O4WBreak()

                        * define an area where the 'running total' can go

                        O4WSectionStart('runningTotal')

                        O4WSectionEnd('runningTotal')

                        * Display a button for them to submit the order

                        O4WButton("Order!", "BTNORDER")

                        * Tell O4W you wish to be notified when the user clicks on this button

                        * example 3: we don't just want to click the button - we want to validate our validations too

                        *O4WQualifyEvent("BTNORDER", "CLICK")

                        O4WQualifyEvent("BTNORDER", "VALIDATE")

                        * Tell O4W we want to be notified when the size or toppings change

                        O4WQualifyEvent("TOPPINGS", "CHANGE", "CHECKBOX")

                        O4WQualifyEvent("SIZE", "CHANGE", "RADIOBUTTON")

      * finish up the main section we defined

      O4WSectionEnd('mainSection')

      * create a special area for us to use when displaying some response to the user

      * nothing goes in it now, but we may fill it in later

      O4WSectionStart('responseArea')

      O4WSectionEnd('responseArea')

            Case event _eqc "CLICK"

                        * Click event - called when the button is pressed

      * Tell O4W we'll be generating a response updating the current form (as opposed to making a whole new form)

      O4WResponse()

                        * Read in all the values

                        ADD1 = O4WGetValue("ADD1")

                        ADD2 = O4WGetValue("ADD2")

                        CITY = O4WGetValue("CITY")

                        STATE = O4WGetValue("STATE")

                        ZIP = O4WGetValue("ZIP")

                        * Make sure these values have something in them

                        If TRIM(ADD1) = "" Or TRIM(CITY) = "" Or TRIM(STATE) = "" Or TRIM(ZIP)="" Then

                                    O4WError("Please be sure to enter complete address information before proceeding")

                                    Return

                        End

                        * move the extraction of the size and topping values, and the calculation of the cost, to a subroutine so we can call it from the 'change' event too

                        /*

                        * 'SIZE' will return the S/M/L code from the SIZE radio buttons

                        SIZE = O4WGetValue("SIZE")

                        * 'TOPPINGS' will return an @VM-delimited list of the selected toppings

                        TOPPING = O4WGetValue("TOPPINGS")

                        * Calculate the price from the toppings and size selected

                        locate size In SizeCode$ Using "," Setting pos Then

                                    cost = Field(SizeCost$,",",pos)

                        End Else

                                    * Couldn't find the size in the list?  Report an error to the customer

                                    O4WError("We're sorry, but the size '":size:"' doesn't appear to be valid!")

                                    Return

                        End

                        * Now find each of the toppings

                        num.toppings = dcount(topping, @VM)

                        For each.topping = 1 To num.toppings

                                    this.topping = topping<1,each.topping>

                                    Locate this.topping In ToppingCode$ Using "," Setting pos Then

                                                cost += Field(ToppingCost$, ",", pos)

                                    End Else

                                                * Couldn't find the topping in the list?  Report an error

                                                O4WError("We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!")

                                    End

                        Next each.topping

                        */

                        Gosub calcTotal

                        If error <> "" Then

                                    O4WError(error)

                                    Return

                        end

                        * In a 'real' application, you'd now write all the information we collected into a database somewhere

                        orderNum = DATE():"*":TIME()

                        * <WRITE INFORMATION HERE>

                        * Notify the customer that his order has been received, and give him/her the total

      * We'll put this information into our 'responseArea'

      * Note that we use a special style so that O4W knows we're updating the previously-defined area (and not asking to create a new one)

      O4WSectionStart('responseArea', O4WResponseStyle())

      O4WHeader('Your order number is ':orderNum, 4)

      O4WBreak()

      O4WText('Thank you for your order!  Your order total is ':OCONV(cost,'MD2,$'):'.')

      O4WBreak()

      O4WText('Please press ')

      * Build a 'link' to return to the home page

      O4WLink('here', 0, 'www.revelation.com')

      O4WText(' to return to the home page')

      O4WSectionEnd('responseArea')

      * Display this area as a 'dialog box' to the user

      O4WDialog('responseArea', 'Thank You')

            Case event _eqc "CHANGE"

                        * the 'CHANGE' event is triggered when our toppings or size is changed

                        * Update our total cost

                        cost = 0

                        * Because of how we organized our form, all the values are passed to us when we get the CHANGE event

                        Gosub calcTotal

                        If error <> "" Then

                                    * display any error message instead of our total

                                    O4WError(error)

                                    Return

                        end

                        * No error - display the total cost

                        * Tell O4W we're generating an update to the current form and not an entire new form

                        O4WResponse()

                        * example 3: update the image with our current selections

                        O4WImage("Mmmm...pizza!", imagePath:imageType:".jpg",'','','','imagePizza', O4WResponseStyle('','','1'))              

      * We'll put this information into our 'runningTotal'

      * Note that we use a special style so that O4W knows we're updating the previously-defined area (and not asking to create a new one)

      O4WSectionStart('runningTotal', O4WResponseStyle())

                        O4WText("Current Order Total: ":Oconv(cost, "MD2,$"))

                        O4WSectionEnd('runningTotal')

End Case

*

Return 0

*

*

* calcTotal subroutine will pull in the size and toppings info and calculate the cost

* if any errors occur, the variable "error" will be returned with the error text

* example 3: also create imageType (with details about which picture to display)

calcTotal:

error = ""

* 'SIZE' will return the S/M/L code from the SIZE radio buttons

SIZE = O4WGetValue("SIZE")

* example 3: make sure a size is selected

If size = "" Then

   error = "We're sorry, but you must select a size to continue"

            Return

End

 

* 'TOPPINGS' will return an @VM-delimited list of the selected toppings

TOPPING = O4WGetValue("TOPPINGS")

* Calculate the price from the toppings and size selected

locate size In SizeCode$ Using "," Setting pos Then

            cost = Field(SizeCost$,",",pos)

End Else

            * Couldn't find the size in the list?  Report an error to the customer

            error = "We're sorry, but the size '":size:"' doesn't appear to be valid!"

            Return

End

* Now find each of the toppings

num.toppings = dcount(topping, @VM)

For each.topping = 1 To num.toppings

            this.topping = topping<1,each.topping>

            Locate this.topping In ToppingCode$ Using "," Setting pos Then

                        cost += Field(ToppingCost$, ",", pos)

            End Else

                        * Couldn't find the topping in the list?  Report an error

                        error = "We're sorry, but the topping '":this.topping:"' doesn't appear to be valid!"

                        return

            End

Next each.topping

* example 3

* always show 'large' pizza

* imageType = size:"_"

imageType = "L_"

* don't show anything special for 'extra cheese'

* If Index(topping, "C", 1) Then imageType := "C"

If Index(topping, "M", 1) Then imageType := "M"

If Index(topping, "P", 1) Then imageType := "P"

If Index(topping, "S", 1) Then imageType := "S"

Return

image700.jpg

image702.jpg

O4W_REVSHOW

O4W_REVSHOW
Subroutine O4W_REVSHOW(CTLENTID, EVENT, REQUEST)

*

* Build an O4W Stored Procedure to make Penn & Teller reservations

*

* Demonstrated at Revelation Software User Conference 04/2010

* NOTE: for this to work you will need (in addition to the standard O4W files):

* 1. The "template" named tickets.html, and

* 2. The "youtubin" plugin

*

*

* Insert our required equates

*

$Insert O4WCOMMON

$Insert O4WEQUATES

*

* Respond to the various events that our O4W form generates

*

Begin Case

*          Every form is called with the "create" event when it starts up

            Case EVENT _EQC "CREATE"

*                      Specify the location of the "template" we want to use for this form                  

                        O4WForm("C:\TEMP\tickets.html")

*                      Add in the "js" (javascript) and "css" (style sheets) for any of our plugins

                        O4WScript("../plugins/Zebra_DatePicker/zebra_datepicker.js")

                        O4WStyleSheet("../plugins/Zebra_DatePicker/metallic.css")

                        O4WScript("../plugins/youtube/jquery.youtubin-1.js")

*                      What do we want to show at the top of our browser page?                

                        O4WTitle("Penn & Teller Reservations")

*                      Convert our sections into tabs                   

                        O4WTabs("orderTabs", "showing":@VM:"reserve", "Select A Show":@VM:"Reservation Details")

                        O4WSectionStart("showing", O4WMarkedStyle('','0'))

*                      Put up a button to hide or show our on-line help

                        O4WButton("Show/Hide Instructions...", "BTN_HELP")

*                      Build the on-line help into a special section

                        O4WSectionStart("helpSection")

                        O4WText("You should put some help text here.  It would make everyone's life much easier!")

                        O4WSectionEnd("helpSection")

*                      When the form starts up, make sure the help section is hidden            

                        O4WQualifyEvent("", "hide", "helpSection")

*                      Enable the pure client-side "toggling" of the help section when the help button is clicked              

                        O4WQualifyEvent("BTN_HELP", "toggle", "helpSection", "1")

*                      Output a newline so things look nice

                        O4WBreak()

*                      Lay out our show information as a table so it looks nice as well           

                        O4WTableStart("showInfo")

                        O4WSetCell(1,1)

                        O4WText("Show date:")

                        O4WSetCell(1,2)

*                      Build a textbox with the current date as the default value

*                      The textbox will be 10 characters wide, it will be named "DATE", and

*                      it will have a unique ID of "txtDATE"

                        O4WTextbox(Oconv(DATE(), "D4/"), 10, "", "DATE", "txtDATE")

                        O4WSetCell(2,1)

                        O4WText("Number of tickets:")

                        O4WSetCell(2,2)

*                      Build a textbox with "0" as the default value

*                      The textbox will be 5 characters wide, and will accept no more than 5 characters

*                      It will be named "NUMTICKETS" and have the unique ID of "txtNUMBER"

*                      When the form is submitted, or validated, the textbox will be checked to make sure only numeric data

*                      is present - and that something is, indeed, present               

                        O4WTextbox("0", "5", "5", "NUMTICKETS", "txtNUMBER", O4WValidateStyle('', O4W_VALIDATE_NUM$, "1"))

                        O4WSetCell(3,1)

                        O4WText("Total Cost":@VM:"($49.99/seat):")

                        O4WSetCell(3,2)

                        O4WText("$0.00", "lblCost")

                        O4WSetCell(3,3)

*                      We'll put up a button labeled "Update"...

                        O4WButton("Update", "BTN_UPDATE")

*                      ...that will generate a "click" event when pressed

                        O4WQualifyEvent("BTN_UPDATE", "CLICK")

                        O4WTableEnd("showInfo")

                        O4WSectionEnd("showing")

*                      In the next section let's collect the "demographic" data for the buyer                

                        O4WSectionStart("reserve", O4WMarkedStyle('','0'))

                        O4WTableStart("demoInfo")

                        O4WSetCell(1,1)

                        O4WText("Name:")

                        O4WSetCell(1,2)

                        O4wTextbox("", "", "", "NAME")

                        O4WSetCell(2,1)

                        O4WText("Address 1:")

                        O4WSetCell(2,2)

                        O4WTextbox("", "", "", "ADD1")

                        O4WSetCell(3,1)

                        O4WText("Address 2:")

                        O4WSetCell(3,2)

                        O4WTextbox("", "", "", "ADD2")

                        O4WSetCell(4,1)

                        O4WText("City:")

                        O4WSetCell(4,2)

                        O4WTextbox("", "", "", "CITY")

                        O4WSetCell(4,3)

                        O4WText("State:")

                        O4WSetCell(4,4)

*                      Build a listbox with the state information: first, read the state names and codes...           

                        states = Xlate("O4WCODES", "CODES_STATES", "", "X")

*                      ...and then pass them into a listbox named "ST"                   

                        O4WListbox(states<1>, states<2>, "ST")

                        O4WSetCell(5,3)

                        O4WText("ZIP:")

                        O4WSetCell(5,4)

                        O4WTextbox("", "", "", "ZIP")

                        O4WTableEnd("demoInfo")

                        O4WSectionEnd("reserve")

                        O4WSectionEnd("orderTabs")

                        O4WBreak()

*                      Outside of the tabs, display a "Make Your Reservation" button and a link to YouTube

                        o4wTableStart("displayTable", O4WMarkedStyle('','0'))

                        O4WButton("Make Your Reservation!", "BTN_RESERVE")

                        O4WSetCell(1,2)

                        url = "http://www.youtube.com/watch?v=_qQX-jayixQ&NR=1"

                        O4WLink("Watch a clip!", O4W_LINKTYPE_NORMAL$, url, "", "lnkPT")

                        O4WTableEnd("displayTable")

*                      When the "BTN_RESERVE" is clicked, it will generate a "SUBMIT" event

*                      (which is like a CLICK event, but it also performs any validation)

                        O4WQualifyEvent("BTN_RESERVE", "SUBMIT")

*                      Turn our textbox (with the ID "txtDATE") into a "date picker" field by using

*                      the "Zebra DatePicker" plugin

                        O4WPlugin("testDATE","Zebra_DatePicker", "{format: 'M d, Y'}")

*                      Turn our Penn & Teller link (with the ID "lnkPT") into an embedded video by

*                      using the "youtubin" plugin

                        O4WPlugin("lnkPT", "youtubin")

*          The CLICK event was generated by the BTN_UPDATE            

            Case EVENT _EQC "CLICK"

*                      Let O4W know we're building a response (and not a full page)

                        O4WResponse()

*                      Pull in the value of the NUMTICKETS field               

                        numTickets = O4WGetValue("NUMTICKETS")

                        If Num(numTickets) And numTickets <> "" then

*                                  Had a valid number; calculate the cost and update the lblCost control

*                                  Note the use of the O4WResponseStyle to tell the control we're only

*                                  updating its text portion

                                    O4WUpdate("lblCost", Oconv(numTickets * 4999, "MD2,$"), O4WResponseStyle('','1'))

                        End Else

*                                  Didn't have a valid number - show an error message             

                                    O4WError("You must enter a valid number to continue")

                        End

*          The SUBMIT event was generated by the BTN_RESERVE                    

            Case EVENT _EQC "SUBMIT"

*                      After a SUBMIT, we do have to build a new page - so we'll call O4WForm with

*                      our template again         

                        O4WForm("C:\TEMP\tickets.html")

*                      Load in the data from the form

                        numTickets = O4WGetValue("NUMTICKETS")

                        NAME = O4WGetValue("NAME")

                        amt = Oconv(numTickets * 4999, "MD2,$")

                        * Imagine that we get all the rest of the info from the form too...

                        * ...and write it out somewhere in the database

* Now generate a thank you message

                        O4WText("Thanks, ":NAME:"! Please be sure to complete your purchase using PayPal and your tickets will be waiting for you at the 'All Call' box")

* And call the PayPal site (with the O4WPayPal api) to do a "buy it now" transaction

                        O4WPaypal("BUY", "", "xxx@revelation.com", "Penn and Teller tickets", "pttickets", NUMTICKETS, "$49.99", "$0.00", "$0.00")

End Case

*

Return 0

image704.jpg

image706.jpg

image708.jpg

Login Screen

Below is code for a sample login screen for use with an O4W application. This code will prompt for username and password, validate the user and launch an O4W menu.

O4W_CUSTLOGIN
Subroutine O4W_CUSTLOGIN(CtlEntId, Event, Request)

*

* O4W Example code: login screen

*

$Insert O4WCommon

$Insert O4WEquates

*

*

Begin Case

            Case EVENT _EQC "CREATE"

                        O4WForm()

                        * Have we already logged in?

                        loginCookie = O4WCookie("tempCookie")

                        If loginCookie <> "" Then

                                    * we've already had our cookie set; we must have logged in already

                                    * get the information stored in our temp file (referenced by the cookie)

                                    Read userInfo From O4WTempFile%, loginCookie Then

                                                * found the information from the successful login; go ahead and display the menu

                                                userName = userInfo<1>

                                                userPrivileges = userInfo<2>

                                                * display the menu

                                                O4WMenu("SAMPLE_MENU")

                                                * and some welcome text

                                                O4WHeader("Welcome, ":userName, 4)

                                                O4WBreak()

                                                O4WBreak()

                                                O4WText("Please select an option from the menu to continue")

                                                Return 0

                                    End

                                    * Couldn't read our user information record from the temp file?

                                    * Must have been a false alarm; fall through to the login page

                        end

                        O4WHeader("O4W Customer Login":@VM:"Login Please", 4)

                        O4WTableStart("loginTable", O4WTableStyle("", "", "", "1"))

                        O4WText("User name: ")

                        O4WSetCell(1,2)

                        O4WTextBox("",'' ,'' ,'' , "uname")

                        O4WSetCell(2,1)

                        O4WText("Password: ")

                        O4WSetCell(2,2)

                        O4WPwdBox("",'' ,'' ,'' , "pwd")

                        O4WSetCell(3,2)

                        O4WButton("Login", "BTNLOGIN", O4WInputStyle('','','','',1))

                        O4WTableEnd("loginTable")

                        O4WQualifyEvent("BTNLOGIN", "CLICK")

                        * Define an empty section for any messages we might have to issue

                        O4WSectionStart("msgArea", O4WMarkedStyle('','0'))

                        O4WSectionEnd("msgArea")

            Case EVENT _EQC "CLICK"

                        Begin Case

                                    Case CtlEntId _eqc "BTNLOGIN"

                                                O4WResponse()

                                                * evaluate what the user entered

                                                userName = O4WGetValue("uname")

                                                passwd = O4WGetValue("pwd")

                                                bIsBad = 1

                                                userPrivileges = ""

                                                * given the username and password, validate this user

                                                * normally done by looking in a table and verifying that the passwords match

                                                onfileInfo = Xlate("MYUSERTABLE", userName, "", "X")

                                                If onFileInfo <> "" Then

                                                            If passwd = onFileInfo<1> And passwd <> "" Then

                                                                        * this user is ok to proceed

                                                                        bIsBad = 0

                                                                        * record what "permissions level" they have as well (in case we need to allow different "levels" of users)

                                                                        userPrivileges = onFileInfo<2>

                                                            End

                                                end

                                                If bIsBad then

                                                            * Bad - display error in the "msgArea"

                                                            O4WSectionStart("msgArea", O4WResponseStyle():O4WMarkedStyle('','0'))

                                                            O4WText("Invalid logon - please retry",'' , O4WColors("","","red"))

                                                            O4WSectionEnd("msgArea")

                                                            RETURN

                                                End

                                                * Success! Record login status in our temp file so we can find this information later

                                                * first, build a unique ID that we can use as our key to the temp table

                                                tempKey = O4WGenerateID("LOGIN")

                                                * and save it into our cookie

                                                O4WCookie("tempCookie", tempKey)

                                                * now save the user information into the temp table with this key

                                                cfgInfo = ""

                                                CFGINFO<1> = username

                                                CFGINFO<2> = userPrivileges

                                                Write CFGINFO On O4WTempFile%, tempKey

                                                * force redisplay of this page to properly display the menu

                                                O4WRedirect("O4W_CUSTLOGIN")

                        End case

End CASE

*

Return 0

This sample login routine must be registered and its required permissions must be set to “none”.

The routine also assumes that you have created an O4W menu (in the sample code above it is called SAMPLE_MENU). The permissions for this O4W menu must be set to “none”.

This routine also assumes you have a table that contains user names, passwords and “permission levels” which can be customized as needed.

For anything that needs to determine what user you are logged in as, and what permissions you have, you can use the following code snippet:

tempKey = O4WCookie(“tempCookie”)

userName = “”

userPerms = “”

if tempKey <> “” then

   Read userInfo from O4WTempFile%, tempkey then

      userName – userInfo<1>

      userPerms = userInfo<2>

   End

End

For this login screen to be truly “integrated”, you must also change your O4W configuration so that you have a custom “O4W Permissions Authorization procedure”; this custom procedure will check the required permissions for any O4W Form, Report, Dashboard, or Procedure against the “permissions level” assigned to the logged-in user, and determine whether the user should be allowed to execute the Form, Report, Dashboard, or Procedure. A sample Permissions Authorization procedure might look like the following:

O4WCUSTOMPERMISSIONS
Function O4WCUSTOMPERMISSIONS(ReqdPerms, SessionInfo)

$Insert O4WCommon

$Insert O4WEquates

tempKey = O4WCookie(“tempCookie”)

userName = “”

userPerms = “”

if tempKey <> “” then

   Read userInfo from O4WTempFile%, tempkey then

      userName = userInfo<1>

      userPerms = userInfo<2>

   End

End

** For this simple example, assume being logged in is all that is required to proceed (so we do not compare “userPerms” with “ReqdPerms”)

If userName <> “” then

   Rslt = 1

End Else

   Rslt = -1; * not logged in – do not let them run this

End

Return Rslt

Invoice Form

O4W_INVOICE_REPORT
Subroutine O4W_INVOICE_REPORT(CTLENTID, EVENT, REQUEST)

*

* Demonstration routine

*

 

$Insert O4WCOMMON

$Insert O4WEQUATES

 

Declare Function ucase

 

* Open our tables (otherwise we can't generate any report)

Open 'INVOICES' To INV.FL Else

            O4WError("Unable to open INVOICES table - cannot proceed!")

            Return 0

End

Open 'DICT','INVOICES' To @DICT Else

            O4WError("Unable to open DICT.INVOICES table - cannot proceed!")

            Return 0

End

 

* Define some style variables that we'll use repeatedly

* This creates some "temporary" unnamed styles that we can reuse

rightAlignStyle = O4WTextOptions("", "","1"):O4WAlignStyle("", O4W_ALIGN_RIGHT$)

greenbarStyle = o4wcolorstyle("", "lightgreen")

* Alternatively, this creates a named style ("overallSection") that we can reuse

O4WTableStyle("overallSection", "", "", O4W_ALIGN_CENTER$)

O4WSizeStyle("overallSection", "90%")

* This creates some named styles ("invoiceSection", "headingOverride") with some explicit CSS commands

* These could also go directly into our stylesheet

O4WRawStyle("invoiceSection", "margin-left":@fm:"margin-right":@fm:"text-align", "0px":@FM:"0px":@FM:"left")

O4WRawStyle("headingOverride", "padding", "8px 0px")

 

Begin Case

            Case EVENT _EQC "CREATE"

                        * Create event should always use O4WForm call (optionally specifying the template to use)

                        O4WFORM()

                        * Load in the stylesheet that will "dress up" our output

                        * CSS derived from editable invoice example at http://www.css-tricks.com (lots of good information there!)

                        O4WStyleSheet("../stylesheet/invoicereport.css")

                        O4WHeader("Invoice Report", 3)

                        O4WBreak()

                        O4WBreak()

                        *

                        * In the CREATE event, we will define a section for our prompt

                        * In the later pages, this section will be replaced with the invoice report output

                        *

                        * Only take up 90% of the page, and center this section

                        O4WSectionStart("invOutput", O4WMarkedOptions('1'):"overallSection")

                        * Allow for override in URL for the number of invoices per page

                        nppg = O4WGetValue("PPG")

                        If nppg = "" Or Not(Num(nppg)) Then nppg = 10

                        * Store this away so our later pages know how many should be shown

                        O4WStore(nppg, "inv_per_page", "inv_per_page")

                        O4WStore("1", "pageno", "pageno")

                        * Build a table to display the prompts

                        O4WTableStart("paramTable")

                        O4WText("Enter starting date: ")

                        O4WSetCell()

                        * As a further enhancement, this could be a 'datepicker' control

                        O4WTextbox(Oconv(DATE(), "D4/"), "", "", "STDATE")

                        O4WSetCell(2)

                        O4WText("Enter ending date: ")

                        O4WSetCell()

                        O4WTEXTBOX(Oconv(DATE(), "D4/"), "", "", "EDDATE")

                        O4WSetCell(3, 2)

                        * Display the button...

                        O4WButton("Go...", "BTN_GO")

                        * ... and associate it with the "CLICK" action

                        O4WQualifyEvent("BTN_GO", "CLICK")

                        O4WTableend("paramTable")

                        O4WSectionEnd("invOutput")

            *

            * CLICK event handler

            * This may be invoked either when navigating back and forth, or when first submitting the report parameters

            *

            Case event _eqc "CLICK"

                        Begin Case

                                    Case ctlentid _eqc "BTN_GO"

                                                * Called after submitting the report parameters

                                                * When responding to an event, we will almost always need the O4WResponse() call (comparable to the O4WForm() call on the CREATE event)

                                                o4wresponse()

                                                * determine which invoices fall in our date (if any)

                                                STDATE = O4WGETVALUE("STDATE")

                                                EDDATE = O4WGETVALUE("EDDATE")

                                                * As an enhancement, we chould check that these are valid, and if not, return an error...

                                                * "normal" OpenInsight programming is used here

                                                stmt = 'SELECT INVOICES BY INVOICE_DATE BY CUST_NAME'

                                                DELIM = ""

                                                If stdate <> "" Then

                                                            stmt := ' WITH INVOICE_DATE >= "':STDATE:'"'

                                                            DELIM = ' AND'

                                                End

                                                If eddate <> "" Then

                                                            stmt := DELIM:' WITH INVOICE_DATE <= "':EDDATE:'"'

                                                End

                                                * Get the unique ID that O4W has already generated for this page

                                                * Use this as the key to store the selected IDs

                                                UniqueID = ucase(o4wgetvalue("O4WUniqueID"))

                                                LISTID = UniqueID:"*LIST"

                                                Call Rlist(STMT, 4, LISTID,'' ,'' )

                                                * did we select anything?

                                                * note: this only works if we don't span multiple records; in newer versions of OpenInsight, use RTI_LIST instead to read in the entire list

                                                listinfo = Xlate("SYSLISTS", LISTID, "", "X")

                                                If listinfo = "" Then

                                                            * Return an error

                                                            o4wError("No invoices selected; please retry")

                                                End Else

                                                            * Preserve the list of IDs in the O4WTEMP table

                                                            listinfo = Delete(listinfo, 1, 0, 0) ;* First, remove the "list header" from field 1

                                                            Write listinfo On O4WTempFile%, LISTID

                                                            * Some browsers may have available the parameters from the URL even on our AJAX events

                                                            * O4W will make multiple occurences of the same parameter available as @VM delimited values

                                                            * Make sure, then, that if we have more than one hanging around, we operate on only one

                                                            invperpage = o4wgetvalue("inv_per_page")<1,1>

                                                            If invperpage = "" Or Not(Num(invperpage)) Then

                                                                        invperpage = 10

                                                            End

                                                            pageno = o4wgetvalue("pageno")<1,1>

                                                            If pageno = "" Or Not(Num(pageno)) Then

                                                                        pageno = 1

                                                            End

                                                            * The "buildInvoices" subroutine will generate the invoices for the current page

                                                            Gosub buildInvoices

                                                End

                                    Case ctlentid _eqc "BTN_NEXT"

                                                * Called by the NEXT button

                                                o4wresponse()

                                                invperpage = o4wgetvalue("inv_per_page")<1,1> ;* make sure, if we have more than one hanging around, we only get one

                                                If invperpage = "" Or Not(Num(invperpage)) Then

                                                            invperpage = 10

                                                End

                                                pageno = o4wgetvalue("pageno")<1,1>

                                                If pageno = "" Or Not(Num(pageno)) Then

                                                            pageno = 1

                                                End

                                                * Increment the page number that we were on

                                                pageno += 1

                                                * Build the invoices for this page

                                                Gosub buildInvoices

                                    Case ctlentid _eqc "BTN_PREV"

                                                * Called by the PREV button

                                                o4wresponse()

                                                invperpage = o4wgetvalue("inv_per_page")<1,1> ;* make sure, if we have more than one hanging around, we only get one

                                                If invperpage = "" Or Not(Num(invperpage)) Then

                                                            invperpage = 10

                                                End

                                                pageno = o4wgetvalue("pageno")<1,1>

                                                If pageno = "" Or Not(Num(pageno)) Then

                                                            pageno = 1

                                                End

                                                * Decrement the page number that we were on

                                                pageno -= 1

                                                * Sanity check of the results

                                                If pageno < 1 Then pageno = 1

                                                * Build the invoices for this page

                                                Gosub buildInvoices

                        End case

End Case

 

Return 0

 

buildInvoices:

* Tell O4W that we want to replace the "invOutput" section of the displayed browser page

O4WSectionStart("invOutput", O4WResponseOptions():O4WMarkedOptions('1'):"overallSection")

* Preserve the values we want to pass in on the "Next" or "Prev" button presses

O4WStore(invperpage, "inv_per_page", "inv_per_page")

O4WStore(pageno, "pageno", "pageno")

* Retrieve the unique ID that O4W has generated for this form

UniqueID = ucase(o4wgetvalue("O4WUniqueID"))

LISTID = UniqueID:"*LIST"

* Try to retrieve the list of selected invoices we generated previously

Read listInfo From O4WTempFile%, ListID Else listInfo = ""

* Is that list missing or empty?  => Error

If listInfo = "" Then

            O4WError("Error: No items selected, or list item lost")

            Return

End

* Calculate how many invoices are in the list, and which ones in the list we should process for this page

num.items = dcount(listInfo, @FM)

stno = (pageno-1)*invperpage + 1

edno = stno + invperpage - 1

* Sanity check - are we beyond the end of the list?

If stno > num.items Then

            O4WError("Error: Invalid page number")

            Return

End

* If the last page has fewer than our maximum to display, adjust ourselves accordingly

If edno > num.items Then edno = num.items

cntr = 0

*

* For each ID in our list, we will read the invoice record, pull out its information (and associated information from the CUSTOMERS table), and display it in appropriate sections

*

For each.invoice = stno To edno

            @ID = listInfo<each.invoice>

            Read @record From INV.FL, @ID Else

                        @RECORD = "Record ":@ID:" not found"

            End

            cntr += 1

            * get all the details

            INV_DATE = {INVOICE_DATE}

            CUST_NO = {CUST_NO}

            CUST_NAME = {CUST_NAME}

            ORD_DATE = {ORDER_DATE}

            ORD_NUM = {ORDER_NUMBER}

            DUE_DATE = {DUE_DATE}

            PAID_DATE = {PAID_DATE}

            QTYS = {QTYS}

            DESCS = {DESCS}

            ITEMS = {ITEMS}

            PRICES = {PRICES}

            EXTENDED = {EXT_COSTS}

            AMOUNT = {AMOUNT}

            * get address information

            CUSTINFO = Xlate("CUSTOMERS", CUST_NO, "", "X")

            ADD1 = CUSTINFO<3>

            ADD2 = CUSTINFO<4>

            CITY = CUSTINFO<5>

            ST = CUSTINFO<6>

            ZIP = CUSTINFO<7>

            COUNTRY = CUSTINFO<8>

            * Display this invoice in its own section

            * "Green bar" the output for easier identification

            invcolor = ""

            If cntr/2 = int(cntr/2) Then

                        * change the background color of this section

                        invcolor = greenbarStyle

            End

            * Insert a few blank lines

            O4WBreak()

            O4WBreak()

            O4WBreak()

            *

            * Each invoice will go into its own section

            * Note the use of the CNTR variable - this makes sure that each element has a unique ID (as required)

            *

            o4wsectionstart("invoice_":cntr, "invoiceSection":@SVM:invcolor)

            * Display the word "INVOICE", and assign it to the "hdr" style

            * We also assign it to the "headerOverride" style (dynamically created at the top of this report) to override the padding setting in our template's css

            o4wtext("INVOICE", "", "headingOverride":@SVM:O4WTextOptions("","","1"):"hdr")

            O4WBreak()

            O4WBreak()

            * Create a section to hold who we are, assigning it to the "identity" class

            O4WSectionStart("identity_":cntr, "identity")

            * Create a section for the address itself, assigning it to the "address" class

            O4WsectionStart("address_":cntr, "address")

            * ...and output our address information

            O4WText("Revelation Software")

            o4wbreak()

            O4WText("99 Kinderkamack Rd.")

            O4WBreak()

            O4WText("First Floor")

            O4WBreak()

            O4WText("Westwood, NJ 07675")

            O4WSectionEnd("address_":cntr)

            * Display a logo with the "logo" class

            O4WSectionStart("logo_":cntr, "logo")

            o4wimage("logo", "../images/logo.gif")

            O4WSectionEnd("logo_":cntr)

            O4WSectionEnd("identity_":cntr)

            * Some css to make things align properly

            o4wsectionstart("clearing_":cntr, O4WPositionStyle("","","","","","both"));o4wsectionend("clearing_":cntr)

            * Create the customer section using the "customer" class

            O4WSectionStart("customer_":cntr, "customer")

            * Output the customer information, assigned to the "customer-title" class

            * O4W will automatically make each value its own line in the display

            * Let's put this all together

            custOutput = ""

            custOutput<1,-1> = CUST_NAME

            custOutput<1,-1> = TRIM(ADD1)

            If trim(ADD2) <> "" Then custOutput<1,-1> = TRIM(ADD2)

            custOutput<1,-1> = CITY:", ":ST:"  ":ZIP

            If COUNTRY _eqc "US" or COUNTRY _eqc "USA" Then

                        country = ""

            End

            If trim(COUNTRY) <> "" Then custOutput<1,-1> = COUNTRY

            O4WText(custOutput, "", "customer-title")

            * Display a table of overall information about this invoice

            O4WTableStart("meta_":cntr, "meta")

            * Move to cell (1,1), and assign that cell to the "meta-head" class

            O4WSetCell(1,1,"","meta-head")

            O4WText("Invoice #")

            * Shorthand to move to the next cell - (1,2) in this case

            O4WSetCell()

            O4WText(@ID)

            O4WSetCell(2, 1, "", "meta-head")

            O4WText("Date")

            O4WSetCell()

            O4WText(Oconv(INV_DATE, "D"))

            O4WSetCell(3, 1, "", "meta-head")

            O4WText("Amount Due")

            O4WSetCell()

            O4WText(Oconv(AMOUNT, "MD2,$"))

            O4WTableEnd("meta_":cntr)

            O4WSectionEnd("customer_":cntr)

            * Create a table to display the line items, and the subtotals/totals

            O4WTableStart("items_":cntr, "items")

            * Display the column headings

            O4WTableHeader("Item")

            O4WTableHeader("Description")

            O4WTableHeader("Unit Price")

            O4WTableHeader("Quantity")

            O4WTableHeader("Ext")

            num.lines = dcount(items, @VM)

            total = 0

            For each.item = 1 To num.lines

                        O4WSetCell(each.item, 1, "", "item-name")

                        o4wtext(items<1,each.item>)

                        O4WSetCell(each.item, 2, "", "description")

                        O4WText(descs<1,each.item>)

                        O4WSetCell(each.item, 3, "", "cost")

                        O4WText(Oconv(PRICEs<1,EACH.ITEM>, "MD2,$"), "", rightAlignStyle)

                        O4WSetCell(each.item, 4, "", "qty")

                        O4WText(qtys<1,each.item>, "", rightAlignStyle)

                        O4WSetCell(each.item, 5, "", "price")

                        O4WText(Oconv(extended<1,each.item>, "MD2,$"), "", rightAlignStyle)

                        total += extended<1,each.item>

            Next each.item

            * Move to the next row, first column, and use "column spanning" to consume 2 columns; also, mark this as the "blank" style

            O4WSetCell(num.items+1, 1, "", O4WTableCellOptions(2):"blank")

            * Move to the 3rd column, and use column spanning to consume 2 more columnes; mark this as the "total-line" style

            O4WSetCell("", 3, "", O4WTableCellOptions(2):"total-line")

            O4WText("Subtotal")

            O4WSetCell("", 5, "", "total-value")

            O4WText(Oconv(total, "MD2,$"), "", rightAlignStyle)

            O4WSetCell(num.items+2, 1, "", O4WTableCellOptions(2):"blank")

            O4WSetCell("", 3, "", O4WTableCellOptions(2):"total-line")

            O4WText("Total")

            O4WSetCell("", 5, "", "total-value")

            O4WText(Oconv(total, "MD2,$"), "", rightAlignStyle)

            O4WTableEnd("items_":cntr)

            * Done with the line items and subtotals/totals

            * Start the terms section, assigning it to the "terms" style

            O4WSectionStart("terms_":cntr, "terms")

            O4WHeader("Terms", 5)

                O4WText("NET 30 days. Finance charges of 1.5% will be made on unpaid balances after 30 days")

            O4WSectionEnd("terms_":cntr)

            o4wsectionend("invoice_":cntr)

            O4WBreak()

            O4WBreak()

            * Finally, display a line using the "dashes" style

            O4WDivider("", "dashes")

Next each.invoice

*

* Display our forward/back buttons

* Only enable them, though, if appropriate

If stno > 1 Then

            * Create the button, and make sure it's enabled

            O4WButton("< Back", "BTN_PREV", O4WInputStyle("","1", "0"))

            O4WQualifyEvent("BTN_PREV", "CLICK")

End Else

            * Create the button, but make it disabled and read-only

            O4WButton("< Back", "BTN_PREV", O4WInputStyle("", "0","1"))

End

o4wspace(5)

If edno < num.items Then

            O4WButton("Next >", "BTN_NEXT", O4WInputStyle("","1","0"))

            O4WQualifyEvent("BTN_NEXT", "CLICK")

End Else

            O4WButton("Next >", "BTN_NEXT", O4WInputStyle("", "0","1"))

End

*

O4WSectionEnd("invOutput")

Return

image710.jpg

image712.jpg

Order Entry

O4W_ORDER_ENTRY
Subroutine O4W_ORDER_ENTRY(ctlentid, event, request)

*

* O4W coding example

*

* Create, edit, or delete records in the ORDERS table

* URL: http://.../oecgi4.exe/O4W_ORDER_ENTRY

*

* Prompt the user for the order number: allow for lookup, manual entry, or left blank => new order

*

* Main Program flow: CREATE event (to draw form initially)

*

*                    RETURNVALUE event/ONUM if order search button pressed or

*                    LOSTFOCUS event/ONUM if order number entered explicitly

*                       handleOrderNumber {may optionally display dialog if existing record has been changed, and then CLICK\BTN_READ or CLICK\BTN_READ_CANCEL} => loadRecord => retrieveRecord => displayHeader => displayDetails

*

*                    RETURNVALUE event/OCUST if customer search button pressed

*                                                          CHANGE event/OCUST to update the customer name

*                                                                     markAsChanged

*

*                                                          CLICK event/BTN_SEARCH_PROD_<line#> if product search button pressed to ask which type of search

*                                                          RETURNVALUE event/ITEM after product search completed

*                                                   CHANGE event/ITEM, QTY, or PRICE to update the order details

*                                                                      displayDetails => markAsChanged

*

*                                                          CLICK event/BTN_SAVE to save the record

*                                                                      lockrecord => saverecord => resetpages

*                                                          CLICK event/BTN_DELETE to confirm deletion of record => CLICK event/BTN_DELETE2 to delete the record

*                                                                      lockrecord => deleterecord => resetpages

*                                                          CLICK event/BTN_CANCEL to reload the original order record

*                                                                      retrieveRecord => displayHeader => displayDetails => markAsFresh

 

 

* Insert required equates and commons

$Insert O4WCOMMON

$Insert O4WEQUATES

* Since we're going to check the configuration record, include this equate as well

$Insert O4WConfigEquates

 

Declare Function Repository

 

* Open our data and dictionary tables, otherwise we have an error

Open "ORDERS" To ORDER.TBL Else

            O4WError("Unable to access ORDERS table")

            Return 0

End

Open "DICT","ORDERS" To @DICT Else

            O4WError("Unable to access DICT.ORDERS table")

            Return 0

End

 

* define some O4W "styles"

selectedStyle = O4WMarkedOptions("1")

deselectedStyle = O4WMarkedOptions("0")

textReplace = O4WResponseOptions("1")

textReplaceTrigger = O4WResponseOptions("1", "", "1")

borderStyle = O4WTableStyle("", "1", "1")

roStyle = O4WInputOptions("0","1"):O4WColorStyle("", "lightblue")

size10pct = O4WSizeStyle("", "10%")

size50pct = O4WSizeStyle("", "50%")

rtJustn = O4WAlignStyle("", "2")

 

* retrieve (if set) our unique id

uniqueID = O4WGetValue("O4WUniqueID")

 

* read the configuration record (using the appropriate repository method)

configRec = Repository("ACCESS", @APPID<1>:"*CONFIG*O4W*CFG_O4W")

Call Set_Status(0)

* determine the "lock procedure" that has been specified in the configuration record

LOCK_PROC = configRec<O4WCONFIG_LOCK_PROC$>

If LOCK_PROC = "" Then LOCK_PROC = "O4WI_LOCKHANDLER"

 

 

Begin Case

            Case EVENT _EQC "CREATE"

                        * Generate the base form

                        * Since no template has been explicitly specified, use the default template

                        O4WForm()

                        * Save this variable in the web page

                        O4WStore("", "activeRecord", "activeRecord")

                        * After the O4WForm call, the unique ID has been created - load it in

                        uniqueID = O4WGetValue("O4WUniqueID")

                       

                        * Display a header

                        O4WHeader("Order Entry/Inquiry", 3)

                        * Establish the tabs

                        O4WTabs("orderForm", "orderHeader":@VM:"orderDetails", "Header":@VM:"Details")

                       

                        * Create the header section

                        O4WSectionStart("orderHeader", deselectedStyle)

                        * and a table to contain the order header information

                        O4WTableStart("tableHeader")

                        O4WSetCell(1,1)

                        O4WText("Order Number: ")

                        O4WSetCell()

                        O4WButton("?", "BTN_SEARCH_ORDERS")

                        * Associate a popup with this button

                        O4WPopup("Order Search", O4W_LINKTYPE_POPUP$, "ORDER_POPUPS", "", "orderpopup", "BTN_SEARCH_ORDERS")

                        O4WTextbox("", "", "", "ONUM","ONUM")

                        * Tell O4W we want to be notified when the ONUM textbox has lost focus

                        o4wqualifyevent("ONUM", "LOSTFOCUS")               

                        O4WSetCell(4, 1)

                        O4WText("Customer Number: ")

                        O4WSetCell()

                        O4WButton("?", "BTN_SEARCH_CUST")

                        * Associate a popup with this button too

                        O4WPopup("Customer Search", O4W_LINKTYPE_POPUP$, "CUSTOMER_ID_POPUP", "", "custpopup", "BTN_SEARCH_CUST")

                        O4WTextbox("", "", "", "OCUST", "OCUST")

                        * Tell O4W we want to be notified when the OCUST textbox has changed

                        o4wqualifyevent("OCUST", "CHANGE", "textbox")                 

                        O4WSetCell()

                        O4WSetCell(5, 2, "", O4WTableCellOptions(2))

                        * Display a textbox, but mark it as "read only" and style it so that it looks different

                        O4WTextbox("", "40", "", "OCUSTNAME", "OCUSTNAME", roStyle)

                        O4WSetCell(6,1)

                        O4WText("Order Date: ")

                        O4WSetCell()

                        O4WDatePicker("","12","1","","ODATE", "ODATE")

                        O4WTableEnd("tableHeader")

                        O4WSectionEnd("orderHeader")

                       

                        O4WSectionStart("orderDetails", deselectedStyle)

                        * Can't fill in the order details yet (without an order being selected), but set up this section as a placeholder

                        O4WText("Please select an existing or new order...")

                        O4WSectionEnd("orderDetails")

 

                        O4WSectionEnd("orderForm")

                       

                        * Define this section for our special dialogs

                        O4WSectionStart("specialDialog", deselectedStyle)

                        O4WSectionEnd("specialDialog")

                       

                        * Define the buttoms

                        O4WButton("Save", "BTN_SAVE")

                        O4WButton("Delete", "BTN_DELETE")

                        O4WButton("Cancel", "BTN_CANCEL")

                        * And set them so they generate the 'click' event

                        O4WQualifyEvent("BTN_SAVE", "CLICK")

                        O4WQualifyEvent("BTN_DELETE", "CLICK")

                        O4WQualifyEvent("BTN_CANCEL", "CLICK")

           

            Case event _eqc "LOSTFOCUS"

                        * Generated when a control loses focus (if the appropriate O4WQualifyEvent on that control has been set)

                        Begin Case

                                    Case ctlentid _eqc "ONUM"

                                                O4WResponse()

                                                @ID = O4WGetValue("ONUM")

                                                * Load in the value of the ONUM textbox, and call handleOrderNumber to retrieve that record (if appropriate)

                                                Gosub handleOrderNumber

                                    End case

                       

            Case event _eqc "CHANGE"

                        * Generated when a control's value changes (if the appropriate O4WQualifyEvnet on that control has been set)

                        * Note that O4W provides 2 additional values: O4WChangeID (the ID of the control that made the change), and O4WChangeValue (the value it's been changed to)

                        Begin Case

                                    Case ctlentid _eqc "OCUST"

                                                * Customer # has changed - update our customer name display

                                                O4WResponse()

                                                @RECORD = ""

                                                @ID = O4WGetValue("ONUM")

                                                {CUST_NO} = O4WGetValue("O4WChangeValue")

                                                O4WUpdate("OCUSTNAME", {CUSTOMER_NAME}, textReplace)

                                                * make sure we know that something's changed, so we can't just navigate away from this without being prompted to save our changes

                                                Gosub markAsChanged

                                               

                                    Case ctlentid _eqc "ITEM" Or ctlentid _eqc "QTY" Or ctlentid _eqc "PRICE"

                                                * One of our detail lines has been added or changed

                                                O4WResponse()

                                                * who changed?  which line, which control?  This way, we can determine who to set the focus to...

                                                whichOne = O4WGetValue("O4WChangeID")

                                                * Our controls are defined as "ITEM_1", "ITEM_2", etc.  However, if a new line has been added, it will have a more complex (auto-generated) ID, such as ITEM_3_o4wid_2

                                                If Count(whichOne, "_") > 1 Then

                                                            * More than one "_" in the ID? This must be a newly-added line

                                                            changeLine = -1

                                                End Else

                                                            changeLine = Field(whichOne, "_", 2)

                                                End

                                                * Load in the current contents of all our fields

                                                Gosub retrieveCurrentRecord

                                                * fill in any defaults, and determine where to set the focus to

                                                items = {ITEM}

                                                qtys = {QTY}

                                                cost = {PRICE}

                                                num.items = dcount(items, @VM)

                                                For each.item = num.items To 1 step -1

                                                            * default the quantity and price if they're not set

                                                            If qtys<1,each.item> = "" Then

                                                                        qtys<1,each.item> = 1

                                                            End

                                                            If cost<1,each.item> = "" then

                                                                        cost<1,each.item> = Xlate('PRODUCTS',  items<1,each.item>, "PRICE",  "")

                                                            end

                                                Next each.item

                                                {ITEM} = items

                                                {QTY} = qtys

                                                {PRICE} = cost

                                                * Update the "order details" section

                                                Gosub displayDetails

                                                * now set the focus as appropriate

                                                If changeLine = -1 Then

                                                            * this was a newly-added line, so it's the last value

                                                            changeLine = dcount(items,@VM)

                                                end

                                                Begin Case

                                                            Case ctlentid _eqc "ITEM"

                                                                        O4WFocus("PRICE_":changeLine)

                                                            Case ctlentid _eqc "PRICE"

                                                                        O4WFocus("QTY_":changeLine)

                                                            Case ctlentid _eqc "QTY"

                                                                        O4WFocus("ITEM_":(changeLine+1))

                                                End Case

                                                * Remember to mark us as having been changed, so we can't navigate away and lose our changes without a verification prompt

                                                Gosub markAsChanged

                        End Case

                       

            Case event _eqc "CLICK"

                        * Generated when a button is pressed

                        Begin Case

                                    Case ctlentid _eqc "BTN_CANCEL"

                                                * Throw away any changes, and reload the original contents of the record?

                                                O4WResponse()

                                                * Get the ID

                                                @ID = O4WGetValue("ONUM")

                                                * see if there are any changes, and if there are prompt before reloading

                                                Gosub handleOrderNumber

                                               

                                    Case CTLENTID _EQC "BTN_SAVE"

                                                * called when the 'save' button is pressed

                                                * make sure we can lock the record, and it hasn't been changed by anyone else since we originally read it in

                                                Gosub lockRecord

                                                If error = "" Then

                                                            * No problems - write it out

                                                            Gosub saveRecord

                                                            * Display our "update successful" response

                                                            O4WError("Order '":@ID:"' updated", "Save Order")

                                                            * blank the fields, mark us as unchanged, and return to first tab

                                                            Gosub resetPages

                                                End

                                    Case ctlentid _eqc "BTN_DELETE"

                                                * called to delete the record

                                                * put up a dialog box to verify the deletion first

                                                O4WResponse()

                                                * retrieve the item id

                                                @ID = O4WGetValue("ONUM")

                                                * build our dialog to verify the deletion

                                                O4WSectionStart('specialDialog', selectedStyle:O4WResponseStyle())

                                                * save the order ID in the dialog

                                                O4WStore(@ID, "ONUM", "ONUM")

                                                O4WText("Please verify deletion of order '":@ID:"'")

                                                O4WBreak()

                                                O4WButton("Delete", "BTN_DELETE2", selectedStyle)

                                                O4WButton("Cancel", "BTN_DIALOG_CANCEL")

                                                * Notify us when these buttons are pressed

                                                O4WQualifyEvent("BTN_DELETE2", "CLICK")

                                                O4WQualifyEvent("BTN_DIALOG_CANCEL", "CLICK")

                                                O4WSectionEnd('specialDialog')

                                                * and then show the dialog

                                                O4WDialog('specialDialog', 'Confirm Deletion','' ,'' , 'width:350')

                                    Case ctlentid _eqc "BTN_DELETE2"

                                                * called after confirming the delete request

                                                * first, make sure we can lock the record and no one else has changed it since we read it

                                                Gosub lockRecord

                                                If error = "" Then

                                                            * no problems - proceed with the deletion

                                                            Gosub deleteRecord

                                                            * display our 'deletion successful' message

                                                            O4WError("Order '":@ID:"' deleted", "Delete Order")

                                                            * blank the fields, mark us as unchanged, and return to first tab

                                                            Gosub resetPages

                                                End

 

                                    * the following 2 controls are displayed on the "record has changed - do you want to discard these changes" dialog box

                                    Case ctlentid _eqc "BTN_READ"

                                                * yes, the user wants to discard any changes and load in the new record

                                                O4WResponse()

                                                * dismiss the dialog box

                                                O4WDialog("specialDialog")

                                                * retrieve their new ID

                                                @ID = O4WGetValue("ONUM")

                                                * load in the record

                                                Gosub loadRecord

                                    Case ctlentid _eqc "BTN_CANCEL_READ"

                                                * no, the user does _not_ want to throw away their changes to the current record

                                                O4WResponse()

                                                * retrieve the original ID

                                                origID = O4WGetValue("ID")

                                                * dismiss the dialog box

                                                O4WDialog("specialDialog")

                                                * and just reset the value in the order number textbox

                                                O4WUpdate("ONUM", origID, textReplace)

 

                                    * this is generated when the 'search' button is pressed in one of the order detail lines

                                    * the user is given a choice of search methods

                                    Case ctlentid[1,16] _eqc "BTN_SEARCH_PROD_"

                                                O4WResponse()

                                                * determine which line the user was on (each button is identified with its line number)

                                                whichOne = ctlentid[17, Len(ctlentid)]

                                                * build a dialog box to ask what type of search to perform

                                                O4WSectionStart("specialDialog", O4WResponseOptions())

                                                * Note the button contains the line number (so we'll know what to update after the user makes their choice)

                                                O4WButton("Search for product by text", "BTN_SEARCH3_PROD_":whichOne)

                                                * associate an index lookup popup with this button

                                                O4WPopup("Product Search", O4W_LINKTYPE_INDEXLOOKUP$, "", "PRODUCTS":@FM:"DESCRIPTION_XREF":@fm:"ID":@VM:"DESCRIPTION", "prodpopup2", "BTN_SEARCH3_PROD_":whichOne)

                                                O4WText(" or ")

                                                O4WButton("List all products", "BTN_SEARCH2_PROD_":whichOne)

                                                * associate a regular popup with this button

                                                O4WPopup("Product Search", O4W_LINKTYPE_POPUP$, "PRODUCT_POPUP", "", "prodpopup1", "BTN_SEARCH2_PROD_":whichOne)

                                                * Provide a 'cancel' button to dismiss the dialog

                                                O4WBreak()

                                                O4WBreak()

                                                O4WButton("Cancel", "BTN_DIALOG_CANCEL")

                                                * Generate the 'click' event when it's pressed

                                                O4WQualifyEvent("BTN_DIALOG_CANCEL", "CLICK")

                                                O4WSectionEnd("specialDialog")

                                                O4WDialog("specialDialog", "Product Search",'' ,'' , 'width:550')

                                               

                                    Case ctlentid _eqc "BTN_DIALOG_CANCEL"

                                                O4WResponse()

                                                * dismiss the dialog box

                                                O4WDialog("specialDialog")

                                               

                        End Case

                       

            Case event _eqc "RETURNVALUE"

                        * The user has selected a value from a popup

                        O4WResponse()

                        * determine which control had the popup, and what the user selected

                        callingCtl = O4WGetValue('o4wPopupCtl')

                        popupValue = O4WGetValue('o4wValue')                

                        Begin Case

                                    Case callingCtl _eqc "BTN_SEARCH_ORDERS"

                                                * this was the order search popup

                                                                * update the order number with the selected value

                                                O4WUpdate("ONUM", popupValue, textReplace)

                                                @ID = popupValue

                                                * Fill in the rest of the form based on this record ID

                                                * If "automatic lose focus" is not desired, disable the following line:

                                                Gosub handleOrderNumber

                                    Case callingCtl _eqc "BTN_SEARCH_CUST"

                                                * this was the customer search popup

                                                * update the customer number textbox with the selected value

                                                * note the use of the "textReplaceTrigger" style - this not only replaces the text, but also triggers the "change" event

                                                * the change event (previously defined) will derive the customer name from this value

                                                O4WUpdate("OCUST", popupValue, textReplaceTrigger)

                                    Case callingCtl[1,17] _eqc "BTN_SEARCH2_PROD_" Or callingCtl[1,17] _eqc "BTN_SEARCH3_PROD_"

                                                * this was either of the 2 different product search popups (regular or index lookup)

                                                * first, dismiss the dialog box that asked which type of search to use

                                                O4WDialog("specialDialog")

                                                * determine which line item in the order details called the popup

                                                whichLine = callingCtl[18, Len(callingCtl)]

                                                * update the product on that line of the order details, and trigger the "change" event for that item

                                                O4WUpdate("ITEM_":whichLine, popupValue, textReplaceTrigger)

                        End case

                       

End Case

Return 0

 

retrieveRecord:

* call the lockhandler routine to read the original record

Call @LOCK_PROC(O4W_LOCKHANDLER_ACTION_READ$, order.tbl, @ID, @RECORD,  UniqueID:"*ORDERS*":@id:"*ORIG")

Return

 

lockRecord:

* call the lockhandler routine to lock (if possible) the original record

* this will verify that the underlying record is unchanged, And we can lock it

error = "" ;* assume success

* load in the current ID and record contents from the browser form

Gosub retrieveCurrentRecord

* call the lockhandler to see if the record is able to be locked, and is unchanged from its original state

stat = Function(@lock_proc(O4W_LOCKHANDLER_ACTION_CHECK$, order.tbl, @id, curr.record, UniqueID:"*ORDERS*":@ID:"*ORIG", O4W_LOCKHANDLER_OPTION_LOCK$))

* check for results from the 'check' call

If stat = O4W_LOCKHANDLER_NO_LOCK$ Then

            * couldn't get the lock on this item - let the user choose another ID

            error = "Unable to lock order '":@ID:"'"

            O4WError(error)

            Return

End

If stat = O4W_LOCKHANDLER_ITEM_CHANGED$ Then

            * someone else changed the record while we worked on it - let the user choose another ID

            error = "Order '":@ID:"' has been changed by another user"

            * remember to unlock our current record, though

            Call @LOCK_PROC(O4W_LOCKHANDLER_ACTION_UNLOCK$, order.tbl, @ID)

            O4WError(ERROR)

            Return

End

Return

 

saveRecord:

* call the lockhandler routine to save the modified record

Call @LOCK_PROC(O4W_LOCKHANDLER_ACTION_WRITE$, ORDER.TBL, @ID, @RECORD, UniqueID:"*ORDERS*":@ID:"*ORIG")

Return

 

deleteRecord:

* delete the record from the orders table, and release any lock

Delete order.tbl, @ID

* release the record lock

Call @LOCK_PROC(O4W_LOCKHANDLER_ACTION_UNLOCK$, ORDER.TBL, @ID)

Delete O4WTempFile%, UniqueID:"*ORDERS*":@ID:"*ORIG"

return

 

retrieveCurrentRecord:

@ID = O4WGetValue("ONUM")

@RECORD = ""

{CUST_NO} = O4WGetValue("OCUST")

odate = O4WGetValue("ODATE")

* if no date filled in, use todays date

If odate = "" Then

            odate = date()

End Else

            odate = Iconv(odate,"D")

end

{ORDER_DATE} = odate

items = O4WGetValue("ITEM")

qtys = O4WGetValue("QTY")

prices = O4WGetValue("PRICE")

* trim off any blank lines

num.items = dcount(items, @VM)

For each.item = num.items To 1 step -1

            If items<1,each.item> = "" Then

                        items = Delete(items, 1, each.item, 0)

                        qtys = Delete(qtys, 1, each.item, 0)

                        prices = Delete(prices, 1, each.item, 0)

            End

Next each.item

{ITEM} = items

{QTY} = qtys

{PRICE} = Iconv(prices, "MD2")

Return

 

resetPages:

* blank out the order number

O4WUpdate("ONUM", "", textReplace)

@RECORD = ""

Gosub displayHeader

* mark as unchanged (as of now)

Gosub markAsFresh

* go to the first tab

O4WGoToTab("orderForm", 1)

return

 

handleOrderNumber:

* do we currently have an 'active' (changed) record in process?

isActive = O4WGetValue("activeRecord")

If isActive <> "" Then

            * yes; build our dialog to verify the change of record

            O4WSectionStart('specialDialog', selectedStyle:O4WResponseStyle())

            * save the newly-entered order ID in the dialog

            O4WStore(@ID, "ONUM", "ONUM")

            * save the original item ID in the dialog, too

            O4WStore(isActive, "ID", "ID")

            O4WText("Discard any changes to existing record?")

            O4WBreak()

            O4WButton("Yes, Discard and Load New Record", "BTN_READ", selectedStyle)

            O4WButton("No, Cancel and Keep Current Record", "BTN_CANCEL_READ")

            * Notify us when these buttons are pressed with the 'click' event

            O4WQualifyEvent("BTN_READ", "CLICK")

            O4WQualifyEvent("BTN_CANCEL_READ", "CLICK")

            O4WSectionEnd('specialDialog')

            * and then show the dialog

            O4WDialog('specialDialog', 'Confirm Discard of Any Changes','' ,'' , 'width:650')

            return

End

* no, no currently active record - just load in the record for this @ID

Gosub loadRecord

Return

 

loadRecord:

If @ID = "" Then

            * new order - get next sequential number

            Lock @DICT, "%SK%" Else

                        O4WError("Unable to lock sequential counter record")

                        Return

            END

            Read NEXT.NUM From @DICT, "%SK%" Else NEXT.NUM = 1000

                @ID = NEXT.NUM

            Write NEXT.NUM +1 On @DICT, "%SK%"

            Unlock @DICT, "%SK%"

            * Update the text box with this order number

            O4WUpdate("ONUM", @ID, textReplace)

End

* read in the record for this @ID

Gosub RetrieveRecord     

* display the header and details

Gosub displayHeader

* Mark this record as unchanged (for now)

Gosub markAsFresh

* make sure we're on the first tab

O4WGoToTab("orderForm", 1)

Return

 

markAsFresh:

* turn off the browser page warning

O4WPlugin("$", "o4wsetConfirmUnload", "false")

* and clear out our own flag that indicates the record has changed

o4wUpdate("activeRecord", "", textReplace)

Return

 

markAsChanged:

* tell the browser that we need the "don't navigate away!" warning message

O4WPlugin("$", "o4wsetConfirmUnload", "true")

* remember what our current record ID is in case someone tries to change it

o4wUpdate("activeRecord", @ID, textReplace)

Return

 

displayHeader:

* load up the header fields

O4WUpdate("OCUST", {CUST_NO}, textReplace)

O4WUpdate("OCUSTNAME", {CUSTOMER_NAME}, textReplace)

O4WUpdate("ODATE", Oconv({ORDER_DATE}, "D"), textReplace)

* and fall through to update the details...

 

displayDetails:

* rebuild the section containing our order details

o4wSectionStart("orderDetails", O4WResponseStyle():deselectedStyle)

* build a table for our order lines

O4WTableStart("tableDetails", borderStyle:O4WSizeStyle("","100%"))

O4WTableHeader("Item", "2", "", size10pct)

O4WTableHeader("Description", "", "", size50pct)

O4WTableHeader("Cost", "", "", size10pct)

O4WTableHeader("Qty", "", "", size10pct)

O4WTableHeader("Ext Cost")

num.items = dcount({ITEM}, @vm) +1 ;* always have one blank row at the end

For each.item = 1 To num.items

            O4WSetCell(each.item, 1,'' , borderStyle)

            O4WButton("?", "BTN_SEARCH_PROD_":each.item)

            * display some choices as to what type of popup should be run when this button is pressed

            O4WQualifyEvent("BTN_SEARCH_PROD_":each.item, "CLICK")

            O4WSetCell('','' ,'' , borderStyle)

            * mark these with the 'o4wClearDuplicateVal' and 'o4wClearDuplicateText' styles so that the "Add" button clears out these fields when a new row is added

            O4WTextBox({ITEM}<1,EACH.ITEM>, "", "", "ITEM", "ITEM_":each.item, "o4wClearDuplicateVal")

            O4WSetCell('','','',borderStyle)

            O4WText({DESCRIPTION}<1,EACH.ITEM>, "DESC_":each.item, "o4wClearDuplicateText")

            O4WSetCell('','','',borderStyle)

            O4WTextBox(Oconv({PRICE}<1,EACH.ITEM>, "MD2,$"), "", "", "PRICE", "PRICE_":each.item, rtJustn:"o4wClearDuplicateVal")

            O4WSetCell('','','',borderStyle)

            O4WTextBox({QTY}<1,EACH.ITEM>, "", "", "QTY", "QTY_":each.item, rtJustn:"o4wClearDuplicateVal")

            O4WSetCell("", "", "", rtJustn:borderStyle)

            O4WText(Oconv({EXT_COST}<1,EACH.ITEM>, "MD2,$"), "EXT_":each.item, "o4wClearDuplicateText")

Next each.item

O4WTableEnd("tableDetails")

* build another table to display the sub total

O4WTableStart("tableSummary", O4WSizeStyle("","100%"))

O4WSetCell(1,1,'', O4WSizeStyle("","90%"))

O4WSpace(5)

O4WSetCell(1,2,'' , rtJustn:borderStyle)

O4WText(Oconv({SUB_TOTAL}, "MD2,$"))

O4WTableEnd("tableSummary")

O4WButton("Add Row", "BTN_ADD")

O4WButton("Delete Row", "BTN_DEL")

* Automatically add or remove the last row when these buttons are pressed

O4WQualifyEvent("BTN_ADD", "ADDTOTABLE", "tableDetails", "-1")

O4WQualifyEvent("BTN_DEL", "DELETEFROMTABLE", "tableDetails", "-1")

* Notify us when any of the ITEM, QTY, or PRICE field values are changed

O4WQualifyEvent("ITEM", "CHANGE", "textbox")

O4WQualifyEvent("PRICE","CHANGE", "textbox")

O4WQualifyEvent("QTY",  "CHANGE", "textbox")

o4wSectionEnd("orderDetails")

Return

image714.jpg

image716.jpg

image718.jpg

image720.jpg

image722.jpg

image724.jpg

Generic Edit Record Routine

O4W_EDIT_RECORD
Subroutine O4W_EDIT_RECORD(CtlEntId, Event, Request)

*

* O4W coding example

*

* Create, edit, or delete records in any table

* URL: http://.../oecgi4.exe/O4W_EDIT_RECORD

* or : http://.../oecgi4.exe/O4W_EDIT_RECORD?TABLE=<tablename>

* or : http://.../oecgi4.exe/O4W_EDIT_RECORD?TABLE=<tablename>&ITEM=<itemid>

*

* Prompt the user for the table name, and (after it's selected) the item ID, or allow for entry of a new item ID, or

* Prompt the user for the item ID, or allow for entry of a new item ID, when a table name is passed in

* After the table and item name have been specified, determine which fields in the dictionary we can use, and build

*       editable fields for each allowed dictionary item

*

* Main Program flow: CREATE event (which may call getID)

*                    CHANGE event (if table not specified in URL), which then calls getID

*                    CLICK event/BTNEDIT which then calls DisplaySection

*

*                    CLICK event/BTNCANCEL which then calls DisplaySection, or

*                    CLICK event/BTNSAVE which calls LockIT (may then call ChooseAnother), or

*                    CLICK event/BTNDELETE which calls LockIT (may then call ChooseAnother)

*               

 

*

* Insert required equates and commons

$Insert O4WCommon

$Insert O4WEquates

* Since we're going to check the configuration record, include this equate as well

$Insert O4WConfigEquates

 

Declare Function Repository

 

* define some O4W "styles"

textReplace = O4WResponseStyle('','1','')

styleReplace = O4WResponseStyle('','','1')

selectMe = O4WMarkedStyle('','1')

deSelectMe = O4WMarkedStyle('','0')

enableMe = O4WInputStyle('','1')

disableMe = O4WInputStyle('','0')

promptColor = O4WColorStyle("", "lightblue")

* retrieve (if set) our unique id

uniqueID = O4WGetValue("O4WUniqueID")

 

* read the configuration record (using the appropriate repository method)

configRec = Repository("ACCESS", @APPID<1>:"*CONFIG*O4W*CFG_O4W")

Call Set_Status(0)

* determine the "filter procedure" that has been specified in the configuration record

FILTER_PROC = configRec<O4WCONFIG_FILTER_PROC$>

If FILTER_PROC = "" Then FILTER_PROC = "O4WI_FILTER"

 

Begin Case

            Case Event _eqc "CREATE"

                        * Initial form creation

                        O4WForm()

                        * get our unique ID (set by o4wform)

                        uniqueID = O4WGetValue("O4WUniqueID")

                        O4WHeader("OpenInsight for Web: Create/Edit Records", 3)

                        O4WBreak()

                        O4WBreak()

                        * define the area for our 'breadcrumbs'

                        O4WSectionStart("breadcrumb", deSelectMe)

                        O4WSectionEnd("breadcrumb")

                        *...and define the breadcrumbs themselves

                        O4WBreadCrumbs("breadcrumb", "SELECTION":@VM:"EDITSECTION", O4WI_FORMATMSG(O4W_MESSAGE_BREADCRUMB_SELECT$):@VM:"Edit")

                        O4WBreak()

                        O4WBreak()

                       

                        * this is the 'selection' page - allow the user to specify the table and item to edit

                        O4WSectionStart("SELECTION", selectMe)

                        * Might we be called with a table and item already specified?             

                        TABLE = O4WGetValue("TABLE")

                        ID = O4WGetValue("ITEM")

                        bHaveBoth = 1

                        O4WTableStart("promptTable")

                        If table = "" Then

                                    bHaveBoth = 0

                                    * build the prompt for the table name

                                    O4WSetCell(1,1)

                                    O4WText("Please select the table: ")

                                    * use the shorthand to move to the next cell in the current row

                                    O4WSetCell()

                                    * call the filter procedure to retrieve what table(s) we are allowed to work on

                                    TLIST = Function(@FILTER_PROC("O4W_EDIT_RECORD", O4WSessionInfo%))

                                    * build the list of tables into a listbox - and select 'none' to start

                                    O4WListBox("Please select...", "<none>", "TABLE", "", "tblNONE", selectMe)

                                    O4WListbox(tlist, tlist, "TABLE",'' , tlist)

                                    * mark the table name input so we know when one has been selected

                                    O4WQualifyEvent("TABLE", "CHANGE", "LISTBOX")

                                    * define a section for getting the ID once the table is selected

                                    * of course, we can't actually fill this in yet - these are "placeholders" until the table has been chosen

                                    O4WSetCell(2,1)

                                    O4WText("Please select the record ID: ")

                                    O4WSetCell(2,2)

                                    O4WSectionStart("idSection")

                                    O4WText("<Please select a table...>")

                                    O4WSectionEnd("idSection")

                                    O4WSetCell(3,1)

                                    O4WText("Or enter the name of a record to create: ")

                                    O4WSetCell(3,2)

                                    O4WSectionStart("newidSection")

                                    O4WText("<Please select a table...>")

                                    O4WSectionEnd("newidSection")

                        End Else

                                    * have table specified; what about item?

                                    If ID = "" Then

                                                * No, the item ID has not been passed in - build the list of available item ids

                                                bHaveBoth = 0

                                                O4WSetCell(1,1)

                                                O4WText("Please select the ":TABLE:" record ID: ")

                                                O4WSetCell()

                                                Gosub getID

                                                O4WSetCell(2,1)

                                                O4WText("Or enter the name of a record to create: ")

                                                O4WSetCell(2,2)

                                                O4WTextbox("", "", "", "NEWITEM")

                                    End

                        End

                        If bHaveBoth = 0 Then

                                    * since we don't have both, put up the button to proceed when they _do_ have both specified

                                    * use "+1" to increment the row (whatever it currently is)

                                    O4WSetCell("+1", 2)

                                    O4WButton("Edit", "BTNEDIT", selectMe)

                                    * Qualify our "click" event

                                    O4WQualifyEvent("BTNEDIT", "CLICK")

                        End

                        * finish up our table for the prompts

                        O4WTableEnd("promptTable")

                        * finish up the section (page) for the prompts

                        O4WSectionEnd("SELECTION")

                       

                        * define the section (page) for the actual editing

                        O4WSectionStart("EDITSECTION", selectMe)

                        If id = "" Or table = "" Then

                                    * don't have all the required pieces - just leave us on the selection page

                                    O4WSetBreadcrumb("SELECTION")

                        End Else

                                    * have both table and item id - move directly to the editing

                                    O4WSetBreadcrumb("EDITSECTION")

                                    Open TABLE To CODE.FL Else

                                                O4WError("Unable to open table '":TABLE:"'")

                                                Return

                                    End

                                    * call the lockhandler routine to read the original record

                                    Call o4wi_lockhandler(O4W_LOCKHANDLER_ACTION_READ$, code.fl, id, info, UniqueID:"*":table:"*":id:"*ORIG")

                                    Gosub displaySection ;* re-entry point to redisplay

                        end

                        o4wsectionEnd("EDITSECTION")

                       

                        * preserve a section for our special messages

                        O4WSectionStart("specialDialog", selectMe)

                        O4WSectionEnd("specialDialog")

 

            Case event _eqc "CHANGE"

                        * table to operate on has changed

                        O4WResponse()

                        * what table have they selected?

                        TABLE = O4WGetValue("O4WChangeID")

                        * rebuild the "placeholders" with the prompts for the id

                        O4WSectionStart("idSection", o4wresponsestyle())

                        Gosub getID

                        O4WSectionEnd("idSection")

                        *...and the prompt for a "new item"

                        O4WSectionStart("newidSection", o4wresponsestyle())

                        O4WTextbox("", "", "", "NEWITEM")

                        O4WSectionEnd("newidSection")

                       

            Case event _eqc "CLICK"

                        Begin Case

                                    Case CTLENTID _EQC "BTNCANCEL"

                                                * Throw away any changes, and refresh the page with a current copy of the record

                                                O4WResponse()

                                                TABLE = O4WGetValue("TABLE")<1,1>

                                                ID = O4WGetValue("ID")<1,1>

                                                If ID = "" Or TABLE = "" Then

                                                            * don't know what we were working on? That's a problem

                                                            O4WError("Unable to retrieve record")

                                                            Return

                                                End

                                                Open TABLE To CODE.FL Else

                                                            * Can't open the table we think we're working on? That's a problem

                                                            O4WError("Unable to open table '":table:"'")

                                                            Return

                                                End

                                                * re-read the record

                                                Call o4wi_lockhandler(O4W_LOCKHANDLER_ACTION_READ$, code.fl, ID, info, UniqueID:"*":TABLE:"*":ID:"*ORIG")

                                                * recreate the section containing the editable fields

                                                O4WSectionStart("EDITSECTION", O4WResponseOptions():selectMe)

                                                Gosub displaySection ;* redisplay this record

                                                O4WSectionEnd("EDITSECTION")

                                    Case CTLENTID _EQC "BTNSAVE" Or ctlentid _eqc "BTNSAVE2"

                                                * called either on the original 'save' button press, or after selecting a new item ID

                                                * make sure we can lock the record, and it hasn't been changed by anyone else since we originally read it in

                                                Action = "Save"

                                                Actionbtn = "BTNSAVE"

                                                Gosub lockIT

                                                If error = "" Then

                                                            * No problems - write it out

                                                            Call O4WI_Lockhandler(O4W_LOCKHANDLER_ACTION_WRITE$, code.fl, ID, INFO, UniqueID:"*":TABLE:"*":ID:"*ORIG")

                                                            * Display our "update successful" response

                                                            O4WError("Record '":ID:"' updated", "Save Record")

                                                End

                                    Case ctlentid _eqc "BTNCANCEL2"

                                                * Called when cancelling the save/delete dialog

                                                * Just dismiss the dialog

                                                O4WDialog("specialDialog")

                                    Case ctlentid _eqc "BTNDELETE"

                                                * called to delete the record

                                                * verify the deletion first

                                                O4WResponse()

                                                * retrieve the table and item id

                                                ID = O4WGetValue("ID")<1,1>

                                                TABLE = O4WGetValue("TABLE")<1,1>

                                                * build our dialog to verify the deletion

                                                O4WSectionStart('specialDialog', SelectMe:O4WResponseStyle())

                                                * save the table and Item ID in the dialog

                                                O4WStore(ID, "ID", "ID")

                                                O4WStore(TABLE, "TABLE", "TABLE")

                                                O4WText("Please verify deletion of record '":ID:"' in table '":table:"'")

                                                O4WBreak()

                                                O4WButton("Delete", "BTNDELETE2", selectMe)

                                                O4WButton("Cancel", "BTNCANCEL2")

                                                O4WQualifyEvent("BTNDELETE2", "CLICK")

                                                O4WQualifyEvent("BTNCANCEL2", "CLICK")

                                                O4WSectionEnd('specialDialog')

                                                * and then show the dialog

                                                O4WDialog('specialDialog', 'Confirm Deletion')

                                    Case ctlentid _eqc "BTNDELETE2"

                                                * called after confirmation of deletion action

                                                * first, make sure we can lock the record and no one else has changed it since we read it

                                                Action = "Delete"

                                                Actionbtn = "BTNDELETE"

                                                Gosub lockIT

                                                If error = "" Then

                                                            * no problems - proceed with the deletion

                                                            * Check to see if this record already existed (ie, it wasn't a new record request)

                                                            Open table To code.fl Else

                                                                        O4WError("Unable to open table '":TABLE:"'")

                                                                        Return

                                                            End

                                                            Readv tstExist From code.fl, ID, 1 Else tstExist = ""

                                                            * do the actual deletion

                                                            Delete code.fl, ID

                                                            * release the record lock

                                                            Call O4WI_Lockhandler(O4W_LOCKHANDLER_ACTION_UNLOCK$, code.fl, ID)

                                                            Delete O4WTempFile%, UniqueID:"*":TABLE:"*":ID:"*ORIG"

                                                            * display our 'deletion successful' message

                                                            O4WError("Record '":ID:"' deleted", "Delete Record")

                                                            * If the record existed, remove it from our list of records on the selection page

                                                            If tstExist <> "" And bIsNew = 0 then

                                                                        * refresh our list of available records

                                                                        O4WScript('','o4wMoveValue("ITEM","","1");')

                                                            End

                                                            *...and move back to that selection page

                                                            O4WSetBreadcrumb("SELECTION")

                                                End

                                    Case CTLENTID _EQC "BTNEDIT"

                                                * Called when the "Edit" button is pressed

                                                O4WResponse()

                                                * determine which table the user entered

                                                table = O4WGetValue("TABLE")<1,1>

                                                If table = "<none>" Then table = ""

                                                * determine whether the user selected a record name from the list, or entered a new one

                                                existingItem = O4WGetValue("ITEM")

                                                If existingItem = "<none>" Then existingItem = ""

                                                newItem = O4WGetValue("NEWITEM")

                                                * make sure we have all the information we need, and it's valid

                                                If existingItem = "" And newItem = "" Then

                                                            O4WError("You must specify a record to edit or create.")

                                                            Return

                                                End

                                                If table = "" Then

                                                            O4WError("You must specify which table to use")

                                                            Return

                                                End

                                                Open table To code.fl Else

                                                            o4werror("Unable to open table '":table:"'")

                                                            Return

                                                end

                                                If existingItem <> "" Then

                                                            * try to read the record

                                                            Call o4wi_lockhandler(O4W_LOCKHANDLER_ACTION_READ$, code.fl, existingItem, info, UniqueID:"*":table:"*":existingItem:"*ORIG")

                                                            * didn't read anything? That's not right...

                                                            If info = "" then

                                                                        O4WError("Record '":existingItem:"' not on file in table '":TABLE:"'")

                                                                        Return

                                                            End

                                                            ID = existingItem

                                                End Else

                                                            * even if they keyed in the item id explicitly, still try to read it (maybe it _does_ exist)

                                                            Call o4wi_lockhandler(O4W_LOCKHANDLER_ACTION_READ$, code.fl, newItem, info, UniqueID:"*":table:"*":newItem:"*ORIG")

                                                            ID = newItem

                                                End

                                                * rebuild the section where the editable fields are displayed

                                                O4WSectionStart("EDITSECTION", selectMe:O4WResponseStyle())

                                                Gosub displaySection

                                                O4WSectionEnd("EDITSECTION")

                                                * set our breadcrumb so we display the editable section

                                                O4WSetBreadcrumb("EDITSECTION")

                        End case

End Case

*

*

Return 0

*

*

*

lockIT: * verify underlying record is unchanged, And we can Lock it

error = "" ;* assume success

O4WDialog('specialDialog') ;* Dismiss dialog (if it's up)

TABLE = O4WGetValue("TABLE")<1,1>

Open TABLE To code.fl Else

            error = "Table '":TABLE:"' could not be opened"

            O4WError(error)

            Return

End

* This may be a new record (potentially), or an existing record

bIsNew = 0

ID = O4WGetValue("NEWID")

If ID <> "" Then

            bIsNew = 1

End else

            ID = O4WGetValue("ID")<1,1>

End

If ID = "" Then

            * couldn't retrieve the item ID

            error = "Unable to access record ID"

            O4WError(error)

            Return

End

* call the lockhandler to see if the record is able to be locked, and is unchanged from its original state

stat = O4WI_LOCKHANDLER(O4W_LOCKHANDLER_ACTION_CHECK$, code.fl, id, curr.info, UniqueID:"*":table:"*":ID:"*ORIG", O4W_LOCKHANDLER_OPTION_LOCK$)

* the "check" method of the lockhandler will also retrieve the current contents of the record

* load in any changes made by the user into this current record

info = curr.info ;* we start with the original record, because in this routine we may not modify all fields

MAXFIELDS = O4WGetValue("MAXFIELDS")

For each.field = 1 To MAXFIELDS

            * get the value (if any) for this field

            * note that, since we may not have an entry for each field, we have to see if there was a field present for this field number

            this.value = o4wgetvalue("FIELD_":EACH.FIELD, bStatus)

            If bStatus Then

                        * yes, this field was present - continue processing

                        * if this value contained @VM or @SVM originally, and it wasn't marked as a multivalued field, we recorded that information

                        maybeConvert = o4wgetvalue("FIELD_":EACH.FIELD:"_TYPE")

                        If maybeConvert <> "" Then

                                    * we had VM or SVM in the original - but not "M" in the dict

                                    * we converted (for display) to a text area - that means each line is @TM delimited

                                    * convert back to VM or SVM as appropriate

                                    If maybeConvert = "0" Then

                                                * we had @SVM in the original

                                                Convert @TM To @SVM In this.value

                                    End Else

                                                * we had @VM in the original

                                                Convert @TM To @VM In this.value

                                    End

                        End

                        * record this information in the record

                        info<each.field> = this.value

            end

Next each.field

* finally, check for results from the 'check' call

If stat = O4W_LOCKHANDLER_NO_LOCK$ Then

            * couldn't get the lock on this item - let the user choose another ID

            error = "Unable to lock record '":ID:"' in table '":table:"'"

            Gosub chooseAnother

            Return

End

If stat = O4W_LOCKHANDLER_ITEM_CHANGED$ Then

            * someone else changed the record while we worked on it - let the user choose another ID

            error = "Record '":ID:"' in table '":TABLE:"' has been changed by another user"

            * remember to unlock our current record, though

            Call o4wi_lockhandler(O4W_LOCKHANDLER_ACTION_UNLOCK$, table, ID)

            Gosub chooseAnother

            Return

End

If bIsNew Then

            * this is supposed to be a new record - is it?

            Read tst From code.fl, id Else tst = ""

            If tst <> "" Then

                        * some contents for this record already exists - we can't overwrite it - let the user choose another ID

                        error = "Record '":ID:"' already on file"

                        Gosub chooseAnother

                        return

            end

            O4WUpdate("ID", ID, textReplace)

end

Return

*

*

*

chooseAnother: * Give users option To rename record

* Use our special dialog for the entry prompts

O4WSectionStart('specialDialog', selectMe:O4WResponseStyle())

* save the loaded-in contents from the browser

O4WStore(INFO, "INFO", "INFO")

O4WText(Error)

O4WBreak()

O4WText("Enter a new name for this record (if desired): ")

O4WTextBox("", "", "",'' ,"NEWID")

O4WBreak()

O4WBreak()

O4WButton(ACTION, ACTIONBTN:"2", selectMe)

O4WQualifyEvent(ACTIONBTN:"2", "CLICK")

O4WSectionEnd('specialDialog')

* show the dialog

O4WDialog('specialDialog', 'Error During ':ACTION)

Return

*

*

displaySection: * show the editable record

O4WHeader("Table: ":TABLE:"; Record: ":ID, 3)

* Determine which fields to display, and how to display them...

* call the filter procedure to retrieve the list of valid dictionary items for us

DICT.IDS = Function(@FILTER_PROC("O4W_EDIT_RECORD", O4WSessionInfo%, TABLE))

* for each of the dictionaries, determine which one is the 'master' for each field

num.ids = dcount(DICT.IDS, @VM)

attinfo = ""

For each.id = 1 To num.ids

            thisID = dict.ids<1,each.id>

            dictInfo = Xlate("DICT.":table, thisID, "", "X")

            If dictInfo <> "" Then

                        If dictInfo<1> = "F" And dictInfo<28> = "1" Then

                                    fno = dictInfo<2>

                                    If fno <> "0" Then

                                                * determine the various pieces of information about this dictionary that we care about

                                                isMV = dictInfo<4>

                                                justn = dictInfo<9>

                                                Locate justn In "L,R,C,T" Using "," Setting justPosn Then

                                                            * convert into O4W alignment code

                                                            justn = Field("0,2,1,-1", ",", justPosn)

                                                end

                                                colwidth = dictInfo<10>

                                                Locate fno In attInfo<1> by "AR" Using @VM Setting posn Else

                                                            * store this relevant information away in the attInfo array for each field we'll work on

                                                            attInfo = Insert(attInfo, 1, posn, 0, fno)

                                                            attInfo = Insert(attInfo, 2, posn, 0, thisID)

                                                            attInfo = Insert(attInfo, 3, posn, 0, isMV)

                                                            attInfo = Insert(attInfo, 4, posn, 0, justn)

                                                            attInfo = Insert(attInfo, 5, posn, 0, colwidth)

                                                End

                                    end

                        end

            end

Next each.id

* Start the table that will contain all the fields to display/edit

O4WTableStart('bigEdit')

num.atts = dcount(attInfo<1>, @VM)

For each.att = 1 To num.atts

            * retrieve the relevant formatting,etc. information from the attInfo array we built

            fno = attInfo<1,each.att>

            fname = attInfo<2,each.att>

            isMV = attInfo<3,each.att>

            justn = attInfo<4, each.att>

            colwidth = attInfo<5,each.att>

            * set our cell to column one on each row, and set our color for this cell

            O4WSetCell(each.att, 1,'' , promptColor)

            * display the field number and the field name

            O4WText(fmt(fno, "R#3"):". ":fname)

            * move to column 2

            O4WSetCell()

            * get the current value

            thisField = info<fno>

            If isMV = "M" Then

                        * display the multivalues in a 'growing/shrinking' table with a fixed maximum size

                        O4WSectionStart("mvfield_":fno, O4WSizeStyle("", "", "300"))

                        num.val = dcount(thisField, @VM)

                        If num.val = 0 Then num.val = 1 ;* always allow at least one value so we draw at least one textbox

                        O4WTableStart("subtable_":fno)

                        * display some table headers to look nice

                        o4wtableheader("Action")

                        O4WTableHeader("Value")

                        For each.val = 1 To num.val

                                    * get the current value

                                    thisVal = thisField<1,each.val>

                                    * move to the next row, column 1

                                    O4WSetCell("+1", 1)

                                    * add in our insert and delete buttons

                                    * note the use of a "named style" for each button - either "insbutton" or "delbutton"

                                    O4WButton("Ins", "BTN_INS_":fno:"_":EACH.VAL, "insbutton")

                                    O4WButton("Del", "BTN_DEL_":fno:"_":EACH.VAL, "delbutton")

                                    * move to column 2

                                    O4WSetCell()

                                    * display the contents, using the width and alignment from the dictionary

                                    * we mark this with the "o4wClearDuplicateVal" named style, so that O4W knows to clear this out when it's duplicated with the "insert" button

                                    O4WTextbox(thisVal, colwidth,'' , "FIELD_":fno, "", O4WTextStyle("", "", "", "", justn):"o4wClearDuplicateVal")

                        Next each.val

                        O4WTableEnd("subtable_":fno)

                        * add an additional "add" and "delete" set of buttons to add and delete the last row

                        O4WButton("Add Value", "BTN_ADD_":fno)

                        O4WButton("Delete Value", "BTN_DEL_":fno)

                        * qualify the add and delete buttons

                        O4WQualifyEvent("BTN_ADD_":fno, "ADDTOTABLE", "subtable_":fno, "-1")

                        O4WQualifyEvent("BTN_DEL_":fno, "DELETEFROMTABLE", "subtable_":fno, "-1")

                        O4WSectionEnd("mvfield_":fno)

                        * use a plugin so that, if the number of multivalues exceeds our fixed size, we'll have a scroll bar

                        O4WPlugin("$", "o4wScrollTable", "'subtable_":fno:"','mvfield_":fno:"','0'")

            End Else

                        * _should_ be single valued display here

                        HAVE.VM = Count(thisField, @VM)

                        HAVE.SVM = Count(thisField, @SVM)

                        If HAVE.VM+HAVE.SVM Then

                                    * what do we do about multivalue data here? Treat this as a text area...

                                    Convert @VM:@SVM To @tm:@tm In thisField

                                    O4WTextArea(thisField, colwidth, 5, "0", "FIELD_":fno)

                                    * remember whether we had any @VM - if we did, that's what we'll use when we read the data back in

                                    O4WStore(HAVE.VM, "", "FIELD_":fno:"_TYPE")

                        End Else

                                    * actual single valued data, as expected

                                    * display in a text box, justified and sized as specified in the dictionary

                                    O4WTextbox(thisField, colwidth,'' , "FIELD_":fno, "", O4WTextStyle("", "", "", "", justn))

                        end

            end

Next each.att

O4WTableEnd('bigEdit')

* use our "named style" for the insert and delete buttons to send a single qualify event for _all_ those buttons

* note the use of "." before the style name - this tells the qualify event that this applies to an entire named style, and not a specific O4W control

O4WQualifyEvent(".delbutton", "deleterow")

O4WQualifyEvent(".insbutton", "insertrow")

* save the ID and table name

O4WStore(ID, "", "ID")

O4WStore(TABLE, "", "TABLE")

* save the number of fields we operated on (so we know how many to retrieve)

O4WStore(NUM.ATTS, "", "MAXFIELDS")

O4WBreak()

* display our buttons

O4WButton("Save", "BTNSAVE")

O4WSpace(5)

O4WButton("Cancel", "BTNCANCEL")

O4WSpace(5)

O4WButton("Delete", "BTNDELETE")

* and qualify our buttons

O4WQualifyEvent("BTNSAVE", "CLICK")

O4WQualifyEvent("BTNCANCEL", "CLICK")

O4WQualifyEvent("BTNDELETE", "CLICK")

Return

*

*

getID: * build section For entry of ID

Call Set_Status(0)

Call Rlist("SELECT ":TABLE:" BY @ID", '5')

DONE = 0

ids = ""

Loop

            Readnext thisid Else DONE = 1

Until DONE Do

            ids<1,-1> = thisid

Repeat

If ids <> "" Then

            O4WListBox('Select...', '<none>', 'ITEM','' , 'itmNONE')

            O4WListBox(ids,  ids, 'ITEM')

End Else

            O4WText("<No records found>")

end

return

image726.jpg

image728.jpg

image730.jpg

Creating a subroutine to populate an O4W Listbox

image732.jpg

Creating a subroutine to populate an O4W Type ahead Listbox

image733.jpg

  • guides/o4w/oi10/reference_guide/o4w_sample_stored_procedures.txt
  • Last modified: 2024/06/19 20:20
  • by 127.0.0.1