433 lines
14 KiB
Plaintext
433 lines
14 KiB
Plaintext
# Property of Four Js*
|
|
# (c) Copyright Four Js 1995, 2019. All Rights Reserved.
|
|
# * Trademark of Four Js Development Tools Europe Ltd
|
|
# in the United States and elsewhere
|
|
#
|
|
# Four Js and its suppliers do not warrant or guarantee that these
|
|
# samples are accurate and suitable for your purposes. Their inclusion is
|
|
# purely for information purposes only.
|
|
|
|
IMPORT FGL CityList
|
|
IMPORT FGL OrderInput
|
|
IMPORT FGL MsgBox
|
|
|
|
GLOBALS "Globals.4gl"
|
|
|
|
DEFINE cust, old_cust custrec
|
|
|
|
DEFINE cust_curr INT -- current position in the array (scroll cursor)
|
|
DEFINE cust_touched INT -- set if something in the customer record was changed
|
|
DEFINE cust_new INT -- > 0 if new customer is currently edited
|
|
|
|
CONSTANT mytitle = "Customer"
|
|
|
|
CONSTANT S_MOVE = "move"
|
|
CONSTANT S_NEW = "new"
|
|
CONSTANT S_CLOSE = "close"
|
|
CONSTANT S_QUERY = "query"
|
|
CONSTANT S_SAVE = "save"
|
|
|
|
MAIN
|
|
DEFINE state STRING -- requested state in the dialog
|
|
DEFINE req_pos INT -- required position in the dialog
|
|
DEFINE del INT -- delete flag
|
|
|
|
OPTIONS INPUT WRAP
|
|
|
|
OPEN FORM f_cust FROM "CustOrders2"
|
|
DISPLAY FORM f_cust
|
|
|
|
CALL cust_loadlist(9)
|
|
LET state=S_MOVE
|
|
LET cust_curr=1
|
|
WHILE state<>S_CLOSE
|
|
DISPLAY "WHILE,state=",state,",cust_curr():",cust_curr,",req_pos:",req_pos
|
|
IF cust_len() == 0 OR state == S_NEW THEN
|
|
LET cust_curr=cust_len()+1
|
|
LET cust_new=cust_curr
|
|
ELSE
|
|
LET cust_new=0
|
|
CALL cust_fetch(req_pos)
|
|
END IF
|
|
LET state=S_MOVE
|
|
LET req_pos=cust_curr
|
|
LET cust_touched=0
|
|
DIALOG ATTRIBUTES(FIELD ORDER FORM, UNBUFFERED)
|
|
|
|
INPUT cust.* FROM custrec.* ATTRIBUTES(WITHOUT DEFAULTS=NOT cust_new)
|
|
|
|
AFTER FIELD cust_name
|
|
IF cust.cust_name MATCHES "*[@#$%^&]*" THEN
|
|
ERROR "The customer name contains invalid characters."
|
|
NEXT FIELD cust_name
|
|
END IF
|
|
|
|
AFTER FIELD cust_address
|
|
IF NOT cust_check_address(cust.cust_address) THEN
|
|
NEXT FIELD cust_address
|
|
END IF
|
|
|
|
AFTER INPUT
|
|
IF cust.cust_city IS NULL AND cust.cust_zipcode IS NOT NULL THEN
|
|
CALL mbox_ok(mytitle,"You must specify a city because zipcode is not null.","stop")
|
|
NEXT FIELD cust_city
|
|
END IF
|
|
|
|
END INPUT
|
|
|
|
DISPLAY ARRAY orders TO ordlist.*
|
|
BEFORE DISPLAY
|
|
IF cust_new THEN
|
|
CALL mbox_ok(mytitle,"Please save the new customer before adding orders!","stop")
|
|
NEXT FIELD cust_name
|
|
END IF
|
|
|
|
BEFORE ROW
|
|
MESSAGE SFMT("Order record %1 / %2", DIALOG.getCurrentRow("ordlist"), DIALOG.getArrayLength("ordlist"))
|
|
|
|
ON ACTION ord_append
|
|
CALL ord_append(DIALOG)
|
|
|
|
ON ACTION ord_modify
|
|
CALL ord_modify(DIALOG)
|
|
|
|
ON ACTION ord_delete
|
|
CALL ord_delete(DIALOG)
|
|
END DISPLAY
|
|
|
|
BEFORE DIALOG
|
|
CALL cust_setup(DIALOG)
|
|
CALL order_of_cust(cust_curr)
|
|
IF cust_new THEN
|
|
LET old_cust.* = cust.*
|
|
END IF
|
|
|
|
ON ACTION zoom_city
|
|
CALL cust_zoom_city(DIALOG)
|
|
|
|
ON ACTION cust_first
|
|
LET req_pos=1
|
|
LET state=S_MOVE ; ACCEPT DIALOG
|
|
|
|
ON ACTION cust_previous
|
|
LET req_pos=cust_curr-1
|
|
LET state=S_MOVE ; ACCEPT DIALOG
|
|
|
|
ON ACTION cust_next
|
|
LET req_pos=cust_curr+1
|
|
LET state=S_MOVE ; ACCEPT DIALOG
|
|
|
|
ON ACTION cust_last
|
|
LET req_pos=cust_len()
|
|
LET state=S_MOVE ; ACCEPT DIALOG
|
|
|
|
ON ACTION cust_append
|
|
LET state=S_NEW ; ACCEPT DIALOG
|
|
|
|
ON ACTION cust_query --we can perform a safe query also only after
|
|
LET state=S_QUERY ; ACCEPT DIALOG --the validations have been done
|
|
|
|
ON ACTION cust_delete
|
|
IF cust_len() > 0 THEN
|
|
LET del=0
|
|
IF cust_new AND NOT cust_touched THEN
|
|
LET del=1
|
|
ELSE
|
|
IF mbox_yn(mytitle,"Delete current customer?","question") THEN
|
|
LET del=1
|
|
END IF
|
|
END IF
|
|
IF del THEN
|
|
CALL customers.deleteElement(cust_curr)
|
|
-- normally a
|
|
-- IF cust_id>0 THEN
|
|
-- DELETE from customers WHERE cust_id=cust.cust_id
|
|
-- END IF
|
|
LET state=S_MOVE
|
|
EXIT DIALOG
|
|
END IF
|
|
END IF
|
|
|
|
ON ACTION dialogtouched
|
|
LET cust_touched=1
|
|
CALL cust_setup(DIALOG)
|
|
|
|
ON ACTION cust_undo
|
|
LET cust.* = old_cust.*
|
|
DISPLAY BY NAME cust.*
|
|
CALL DIALOG.setFieldTouched("custrec.*",FALSE)
|
|
LET cust_touched=0
|
|
CALL cust_setup(DIALOG)
|
|
|
|
ON ACTION cust_save
|
|
LET state=S_SAVE ; ACCEPT DIALOG
|
|
|
|
ON ACTION cancel
|
|
LET state=S_CLOSE
|
|
--close is a bit difficult: if we did not touch something,
|
|
--we can go out safely, otherwise we need to duplicate things
|
|
--we do normally in AFTER DIALOG
|
|
IF cust_touched THEN
|
|
--we touched something
|
|
CASE mbox_ync(mytitle,"Save your changes?","question")
|
|
WHEN 1 --yes
|
|
ACCEPT DIALOG --go thru the validation and fall finally out
|
|
--in AFTER DIALOG
|
|
WHEN 2 --no
|
|
EXIT DIALOG
|
|
WHEN 3 --cancel
|
|
CONTINUE DIALOG
|
|
END CASE
|
|
ELSE
|
|
--nothing changed, just go out
|
|
EXIT DIALOG
|
|
END IF
|
|
|
|
AFTER DIALOG
|
|
IF state=S_CLOSE OR state=S_SAVE THEN
|
|
--we already confirmed the save, jump to the save code
|
|
GOTO savedb
|
|
ELSE
|
|
IF old_cust.* <> cust.* THEN
|
|
CASE mbox_ync(mytitle,"Save your changes?","question")
|
|
WHEN 1 --yes
|
|
GOTO savedb
|
|
WHEN 3 --cancel and stay in the dialog
|
|
LET state=S_MOVE ; CONTINUE DIALOG
|
|
END CASE
|
|
END IF
|
|
END IF
|
|
EXIT DIALOG
|
|
LABEL savedb: --use the label here to save a local var and some IF's
|
|
IF cust_new THEN
|
|
DISPLAY "INSERT new customer into db"
|
|
LET customers[cust_new].* = cust.*
|
|
ELSE
|
|
DISPLAY "UPDATE customer in db"
|
|
LET customers[cust_curr].* = cust.*
|
|
END IF
|
|
END DIALOG
|
|
--we can perform the query action only if everything was validated before
|
|
IF state == S_QUERY THEN
|
|
CALL cust_query()
|
|
END IF
|
|
END WHILE
|
|
END MAIN
|
|
|
|
FUNCTION cust_len()
|
|
--we use the 'customers' array as a db replacement here
|
|
--normally you could return the real COUNT of the DB statement cursor
|
|
RETURN customers.getLength()
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_fetch(index)
|
|
DEFINE index INTEGER
|
|
IF index > cust_len() THEN
|
|
LET index = cust_len()
|
|
END IF
|
|
IF index < 1 THEN
|
|
LET index = 1
|
|
END IF
|
|
--fetch customer from the DB, index could be used to FETCH ABSOLUTE
|
|
LET cust.* = customers[index].*
|
|
LET old_cust.* = cust.*
|
|
LET cust_curr = index
|
|
MESSAGE SFMT("Fetched Customer: %1/%2", cust_curr, cust_len())
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_setup(d)
|
|
DEFINE d ui.Dialog
|
|
DEFINE has_rows, on_first, on_last, cust_ro INTEGER
|
|
|
|
LET has_rows = (cust_curr > 0 AND cust_len() > 0 )
|
|
LET on_first = (cust_curr == 1)
|
|
LET on_last = (cust_curr == cust_len())
|
|
LET cust_ro = (has_rows AND NOT cust_touched)
|
|
|
|
CALL d.setActionActive("dialogtouched", cust_ro)
|
|
CALL d.setActionActive("cust_undo", NOT cust_ro)
|
|
CALL d.setActionActive("cust_save", NOT cust_ro)
|
|
CALL d.setActionActive("cust_append", TRUE) -- always active
|
|
CALL d.setActionActive("cust_delete", has_rows) -- can delete creation
|
|
CALL d.setActionActive("cust_query", TRUE) -- always active
|
|
CALL d.setActionActive("cust_first", NOT on_first)
|
|
CALL d.setActionActive("cust_previous", NOT on_first)
|
|
CALL d.setActionActive("cust_next", NOT on_last)
|
|
CALL d.setActionActive("cust_last", NOT on_last)
|
|
|
|
IF cust_new THEN
|
|
DISPLAY "New customer (save with ctrl-s)" TO cust_info
|
|
ELSE
|
|
IF cust_touched THEN
|
|
DISPLAY "Modifying customer (save with ctrl-s)" TO cust_info
|
|
ELSE
|
|
DISPLAY SFMT("Customer record %1 / %2",cust_curr,cust_len()) TO cust_info
|
|
END IF
|
|
END IF
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_query()
|
|
DEFINE sql STRING
|
|
DISPLAY "Enter customer search criterias" TO cust_info
|
|
LET int_flag = FALSE
|
|
CONSTRUCT BY NAME sql ON cust_id, cust_name, cust_state,
|
|
cust_city, cust_zipcode, cust_address, cust_checked
|
|
IF NOT int_flag THEN
|
|
-- Dummy query, should use database query instead.
|
|
CALL cust_loadlist(LENGTH(sql))
|
|
CALL mbox_ok(mytitle,SFMT("Found %1 customer records in database",cust_len()),"information")
|
|
END IF
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_zoom_city(d)
|
|
DEFINE d ui.Dialog
|
|
DEFINE s INTEGER
|
|
DEFINE name, state STRING
|
|
CALL select_city(d.getFieldBuffer("cust_city")) RETURNING s, name, state
|
|
IF s==0 THEN
|
|
LET cust.cust_city = name
|
|
LET cust.cust_state = state
|
|
CALL d.setFieldTouched("cust_city",TRUE)
|
|
CALL d.setFieldTouched("cust_state",TRUE)
|
|
LET cust_touched = TRUE
|
|
CALL cust_setup(d)
|
|
END IF
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_verify_address_format(value)
|
|
DEFINE value STRING
|
|
DEFINE num STRING, p,x INTEGER
|
|
IF value IS NULL THEN RETURN TRUE END IF
|
|
LET p = value.getIndexOf(",", 1)
|
|
IF p == 0 THEN RETURN FALSE END IF
|
|
LET num = value.subString(1, p)
|
|
LET x = num
|
|
IF x <= 0 THEN RETURN FALSE END IF
|
|
IF value.getLength() <= p THEN RETURN FALSE END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_address(value)
|
|
DEFINE value STRING
|
|
IF NOT cust_verify_address_format(value) THEN
|
|
CALL mbox_ok(mytitle,"Address must hold a number followed by a comma and the street name.","stop")
|
|
RETURN FALSE
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION order_of_cust(index)
|
|
DEFINE index INTEGER --index should be normally the cust_id
|
|
--MESSAGE SFMT("Customer: %1/%2", cust_curr, cust_len())
|
|
IF index >= 1 AND index <= cust_len() THEN
|
|
CALL ord_loadlist(customers[index].cust_id, (index mod 5) * 3)
|
|
ELSE
|
|
CALL orders.clear()
|
|
END IF
|
|
END FUNCTION
|
|
|
|
-- Dummy function to fill the list of customers (normally, SELECT from database)
|
|
FUNCTION cust_loadlist(m)
|
|
DEFINE m,i INTEGER
|
|
CALL customers.clear()
|
|
FOR i=1 TO m
|
|
LET customers[i].cust_id = i
|
|
LET customers[i].cust_name = "Name " || i
|
|
LET customers[i].cust_state = "CA"
|
|
LET customers[i].cust_city = "San Fransisco"
|
|
LET customers[i].cust_zipcode = 94102
|
|
LET customers[i].cust_address = "52, Marlon Street"
|
|
LET customers[i].cust_checked = i mod 2
|
|
END FOR
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_loadlist(mid,m)
|
|
DEFINE mid,m,i INTEGER
|
|
CALL orders.clear()
|
|
FOR i=1 TO m
|
|
CALL orders.appendElement()
|
|
LET orders[i].ord_id = mid * 100 + i
|
|
LET orders[i].ord_crea = CURRENT YEAR TO SECOND
|
|
LET orders[i].ord_amount = ( i mod 5 ) * 133.56
|
|
END FOR
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_append(d)
|
|
DEFINE d ui.Dialog
|
|
CALL ord_input('A', cust.cust_id, cust.cust_name, 0)
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_modify(d)
|
|
DEFINE d ui.Dialog
|
|
IF d.getCurrentRow("ordlist")==0 THEN RETURN END IF
|
|
CALL ord_input('M', cust.cust_id, cust.cust_name, orders[d.getCurrentRow("ordlist")].ord_id)
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_delete(d)
|
|
DEFINE d ui.Dialog
|
|
IF NOT mbox_yn(mytitle,"Delete select order from database?","question") THEN
|
|
RETURN
|
|
END IF
|
|
CALL d.deleteRow("ordlist",d.getCurrentRow("ordlist"))
|
|
END FUNCTION
|
|
|
|
FUNCTION combo_fill_states(cb)
|
|
DEFINE cb ui.ComboBox
|
|
|
|
CALL cb.addItem("AK","Alaska")
|
|
CALL cb.addItem("AL","Alabama")
|
|
CALL cb.addItem("AR","Arkansas")
|
|
CALL cb.addItem("AZ","Arizona")
|
|
CALL cb.addItem("CA","California")
|
|
CALL cb.addItem("CO","Colorado")
|
|
CALL cb.addItem("CT","Connecticut")
|
|
CALL cb.addItem("DC","D.C.")
|
|
CALL cb.addItem("DE","Delaware")
|
|
CALL cb.addItem("FL","Florida")
|
|
CALL cb.addItem("GA","Georgia")
|
|
CALL cb.addItem("HI","Hawaii")
|
|
CALL cb.addItem("IA","Iowa")
|
|
CALL cb.addItem("ID","Idaho")
|
|
CALL cb.addItem("IL","Illinois")
|
|
CALL cb.addItem("IN","Indiana")
|
|
CALL cb.addItem("KS","Kansas")
|
|
CALL cb.addItem("KY","Kentucky")
|
|
CALL cb.addItem("LA","Louisiana")
|
|
CALL cb.addItem("MA","Massachusetts")
|
|
CALL cb.addItem("MD","Maryland")
|
|
CALL cb.addItem("ME","Maine")
|
|
CALL cb.addItem("MI","Michigan")
|
|
CALL cb.addItem("MN","Minnesota")
|
|
CALL cb.addItem("MO","Missouri")
|
|
CALL cb.addItem("MS","Mississippi")
|
|
CALL cb.addItem("MT","Montana")
|
|
CALL cb.addItem("NC","North Carolina")
|
|
CALL cb.addItem("ND","North Dakota")
|
|
CALL cb.addItem("NE","Nebraska")
|
|
CALL cb.addItem("NH","New Hampshire")
|
|
CALL cb.addItem("NJ","New Jersey")
|
|
CALL cb.addItem("NM","New Mexico")
|
|
CALL cb.addItem("NV","Nevada")
|
|
CALL cb.addItem("NY","New York")
|
|
CALL cb.addItem("OH","Ohio")
|
|
CALL cb.addItem("OK","Oklahoma")
|
|
CALL cb.addItem("OR","Oregon")
|
|
CALL cb.addItem("PA","Pennsylvania")
|
|
CALL cb.addItem("PR","Puerto Rico")
|
|
CALL cb.addItem("RI","Rhode Island")
|
|
CALL cb.addItem("SC","South Carolina")
|
|
CALL cb.addItem("SD","South Dakota")
|
|
CALL cb.addItem("TN","Tennessee")
|
|
CALL cb.addItem("TX","Texas")
|
|
CALL cb.addItem("UT","Utah")
|
|
CALL cb.addItem("VA","Virginia")
|
|
CALL cb.addItem("VT","Vermont")
|
|
CALL cb.addItem("WA","Washington")
|
|
CALL cb.addItem("WI","Wisconsin")
|
|
CALL cb.addItem("WV","West Virginia")
|
|
CALL cb.addItem("WY","Wyoming")
|
|
|
|
END FUNCTION
|
|
|
|
|