491 lines
15 KiB
Plaintext
491 lines
15 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_curr INTEGER
|
|
DEFINE cust, old_cust custrec
|
|
DEFINE cust_state SMALLINT
|
|
|
|
CONSTANT STATE_NAVIGATE = 0
|
|
CONSTANT STATE_MODIFY = 1
|
|
CONSTANT STATE_APPEND = 2
|
|
|
|
CONSTANT otitle = "Customer"
|
|
|
|
MAIN
|
|
DEFINE ordlist_lastrow INTEGER
|
|
|
|
OPTIONS INPUT WRAP
|
|
|
|
OPEN FORM f_cust FROM "CustOrders"
|
|
DISPLAY FORM f_cust
|
|
|
|
DIALOG ATTRIBUTES(FIELD ORDER FORM, UNBUFFERED)
|
|
|
|
INPUT cust.* FROM custrec.* ATTRIBUTES(WITHOUT DEFAULTS)
|
|
ON CHANGE custrec.cust_name
|
|
IF NOT cust_check_name(DIALOG) THEN NEXT FIELD CURRENT END IF
|
|
ON CHANGE custrec.cust_address
|
|
IF NOT cust_check_address(DIALOG) THEN NEXT FIELD CURRENT END IF
|
|
ON CHANGE custrec.cust_state
|
|
INITIALIZE cust.cust_city, cust.cust_zipcode, cust.cust_address TO NULL
|
|
END INPUT
|
|
|
|
DISPLAY ARRAY orders TO ordlist.*
|
|
BEFORE ROW
|
|
MESSAGE SFMT("Order record %1 / %2", DIALOG.getCurrentRow("ordlist"), DIALOG.getArrayLength("ordlist"))
|
|
AFTER ROW
|
|
LET ordlist_lastrow = arr_curr()
|
|
END DISPLAY
|
|
|
|
BEFORE DIALOG
|
|
CALL cust_loadlist(DIALOG,100)
|
|
CALL cust_move_to(DIALOG, 1)
|
|
|
|
ON ACTION zoom_city
|
|
CALL cust_zoom_city(DIALOG)
|
|
|
|
ON ACTION cust_query
|
|
CALL cust_query(DIALOG)
|
|
|
|
ON ACTION cust_first
|
|
CALL cust_move_to(DIALOG, 1)
|
|
ON ACTION cust_previous
|
|
CALL cust_move_to(DIALOG, cust_curr - 1)
|
|
ON ACTION cust_next
|
|
CALL cust_move_to(DIALOG, cust_curr + 1)
|
|
ON ACTION cust_last
|
|
CALL cust_move_to(DIALOG, customers.getLength())
|
|
|
|
ON ACTION dialogtouched
|
|
CALL cust_touched(DIALOG)
|
|
|
|
ON ACTION cust_append
|
|
IF NOT cust_append(DIALOG) THEN CONTINUE DIALOG END IF
|
|
NEXT FIELD cust_name
|
|
|
|
ON ACTION cust_delete -- VALIDATE=NO
|
|
CALL cust_delete(DIALOG)
|
|
DISPLAY BY NAME cust.*
|
|
|
|
ON ACTION cust_undo -- VALIDATE=NO
|
|
CALL cust_undo(DIALOG)
|
|
DISPLAY BY NAME cust.*
|
|
|
|
ON ACTION cust_save
|
|
IF NOT cust_save(DIALOG) THEN CONTINUE DIALOG END IF
|
|
|
|
ON ACTION ord_append
|
|
CALL ord_append(DIALOG)
|
|
|
|
ON ACTION ord_modify
|
|
CALL ord_modify(DIALOG)
|
|
|
|
ON ACTION ord_delete
|
|
CALL ord_delete(DIALOG)
|
|
|
|
ON ACTION close
|
|
IF cust_check_changed(DIALOG) THEN EXIT DIALOG END IF
|
|
|
|
END DIALOG
|
|
END MAIN
|
|
|
|
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)
|
|
CALL cust_touched(d)
|
|
END IF
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_touched(d)
|
|
DEFINE d ui.Dialog
|
|
LET cust_state = STATE_MODIFY
|
|
CALL cust_setup(d)
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_changed(d)
|
|
DEFINE d ui.Dialog
|
|
DEFINE r INTEGER
|
|
IF cust_modifying() THEN
|
|
CALL cust_setup(d)
|
|
LET r = mbox_ync(otitle,"Do you want to save your changes?","question")
|
|
IF r == 1 THEN
|
|
IF NOT cust_save(d) THEN LET r = 3 END IF
|
|
END IF
|
|
IF r == 2 THEN
|
|
CALL cust_clean(d)
|
|
END IF
|
|
RETURN (r == 1 OR r == 2)
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_modifying()
|
|
RETURN cust_state != STATE_NAVIGATE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_undo(d)
|
|
DEFINE d ui.Dialog
|
|
CASE cust_state
|
|
WHEN STATE_MODIFY
|
|
IF NOT mbox_yn(otitle,"Undo customer modification?","question") THEN RETURN END IF
|
|
LET cust.* = old_cust.*
|
|
CALL cust_clean(d)
|
|
WHEN STATE_APPEND
|
|
IF NOT mbox_yn(otitle,"Cancel customer creation?","question") THEN RETURN END IF
|
|
CALL customers.deleteElement(customers.getLength())
|
|
CALL cust_clean(d)
|
|
CALL cust_move_to(d, customers.getLength())
|
|
END CASE
|
|
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_name(d)
|
|
DEFINE d ui.Dialog
|
|
IF LENGTH(cust.cust_name) = 0 THEN
|
|
CALL mbox_ok(otitle,"You must specify a customer name.","stop")
|
|
RETURN FALSE
|
|
END IF
|
|
IF cust.cust_name MATCHES "*[@#$%^&]*" THEN
|
|
CALL mbox_ok(otitle,"The customer name containts invalid characters.","stop")
|
|
RETURN FALSE
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_address(d)
|
|
DEFINE d ui.Dialog
|
|
IF NOT cust_verify_address_format(cust.cust_address) THEN
|
|
CALL mbox_ok(otitle,"Address must hold a number followed by a comma and the street name.","stop")
|
|
RETURN FALSE
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_city(d)
|
|
DEFINE d ui.Dialog
|
|
-- Inter-dependent field validation
|
|
IF cust.cust_city IS NULL AND cust.cust_zipcode IS NOT NULL THEN
|
|
CALL mbox_ok(otitle,"You must specify a city because zipcode is not null.","stop")
|
|
RETURN FALSE
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_data(d)
|
|
DEFINE d ui.Dialog
|
|
IF d.validate("custrec.*") < 0 THEN
|
|
RETURN "*"
|
|
END IF
|
|
IF NOT cust_check_name(d) THEN RETURN "custrec.cust_name" END IF
|
|
IF NOT cust_check_city(d) THEN RETURN "custrec.cust_city" END IF
|
|
IF NOT cust_check_address(d) THEN RETURN "custrec.cust_address" END IF
|
|
RETURN NULL -- data is valid
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_check_fields(d)
|
|
DEFINE d ui.Dialog
|
|
DEFINE fn STRING
|
|
LET fn = cust_check_data(d)
|
|
IF fn IS NULL THEN RETURN TRUE END IF
|
|
IF fn != "*" THEN CALL d.nextField(fn) END IF
|
|
RETURN FALSE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_save(d)
|
|
DEFINE d ui.Dialog
|
|
IF NOT cust_check_fields(d) THEN RETURN FALSE END IF
|
|
IF cust_state == STATE_APPEND THEN
|
|
-- SQL INSERT ...
|
|
END IF
|
|
IF cust_state == STATE_MODIFY THEN
|
|
-- SQL UPDATE ...
|
|
END IF
|
|
LET customers[cust_curr].* = cust.*
|
|
CALL cust_clean(d)
|
|
CALL mbox_ok("Customers", "Changes saved to database", "information")
|
|
CALL d.setFieldTouched("custrec.*",FALSE)
|
|
CALL cust_setup(d)
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_append(d)
|
|
DEFINE d ui.Dialog
|
|
IF NOT cust_autosave(d) THEN RETURN FALSE END IF
|
|
INITIALIZE cust.* TO NULL
|
|
CALL ord_loadlist(d,0,0)
|
|
LET cust.cust_id = cust_curr + 101044
|
|
LET cust_state = STATE_APPEND
|
|
CALL customers.appendElement()
|
|
LET cust_curr = customers.getLength()
|
|
CALL cust_setup(d)
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_delete(d)
|
|
DEFINE d ui.Dialog
|
|
IF cust_curr<= 0 THEN RETURN END IF
|
|
IF cust_modifying() THEN
|
|
CALL cust_setup(d)
|
|
IF NOT mbox_yn(otitle,"Cancel current changes?","question") THEN RETURN END IF
|
|
CALL cust_clean(d)
|
|
ELSE
|
|
IF NOT mbox_yn(otitle,"Delete current customer?","question") THEN RETURN END IF
|
|
END IF
|
|
-- SQL DELETE ...
|
|
CALL customers.deleteElement(cust_curr)
|
|
IF customers.getLength()==0 THEN
|
|
CALL mbox_ok(otitle,"No more customers in list, switching to query mode","stop")
|
|
CALL cust_query(d)
|
|
RETURN
|
|
END IF
|
|
IF cust_curr>customers.getLength() THEN
|
|
LET cust_curr=customers.getLength()
|
|
END IF
|
|
CALL cust_move_to(d,cust_curr)
|
|
CALL cust_setup(d)
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_query(d)
|
|
DEFINE d ui.Dialog
|
|
DEFINE sql STRING
|
|
IF NOT cust_check_changed(d) THEN RETURN END IF
|
|
DISPLAY "Enter customer search criterias" TO cust_info
|
|
WHILE TRUE
|
|
LET int_flag = FALSE
|
|
CONSTRUCT BY NAME sql ON cust_id, cust_name, cust_state,
|
|
cust_city, cust_zipcode, cust_address, cust_checked
|
|
ATTRIBUTES( CANCEL=FALSE, ACCEPT=FALSE )
|
|
ON ACTION close
|
|
IF mbox_yn(otitle,"Quit application?","question") THEN EXIT PROGRAM END IF
|
|
ON ACTION cust_fetch
|
|
ACCEPT CONSTRUCT
|
|
END CONSTRUCT
|
|
IF NOT int_flag THEN
|
|
-- Dummy query, should use database query instead.
|
|
CALL cust_loadlist(d,LENGTH(sql))
|
|
CALL cust_setup(d)
|
|
CALL mbox_ok(otitle,SFMT("Found %1 customer records in database",customers.getLength()),"information")
|
|
EXIT WHILE
|
|
END IF
|
|
END WHILE
|
|
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 customers.getLength()>0)
|
|
LET on_first = (cust_curr == 1)
|
|
LET on_last = (cust_curr == customers.getLength())
|
|
LET cust_ro = (has_rows AND cust_state == STATE_NAVIGATE)
|
|
|
|
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)
|
|
|
|
CALL d.setActionActive("ord_append", cust_ro)
|
|
CALL d.setActionActive("ord_modify", cust_ro)
|
|
CALL d.setActionActive("ord_delete", cust_ro)
|
|
|
|
CASE cust_state
|
|
WHEN STATE_APPEND
|
|
DISPLAY "Creating a new customer record (save with ctrl-s)" TO cust_info
|
|
WHEN STATE_MODIFY
|
|
DISPLAY "Modifying current customer record (save with ctrl-s)" TO cust_info
|
|
OTHERWISE
|
|
DISPLAY SFMT("Customer record %1 / %2",cust_curr,customers.getLength()) TO cust_info
|
|
END CASE
|
|
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_clean(d)
|
|
DEFINE d ui.Dialog
|
|
LET old_cust.* = cust.*
|
|
LET cust_state = STATE_NAVIGATE
|
|
CALL cust_setup(d)
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_autosave(d)
|
|
DEFINE d ui.Dialog
|
|
IF cust_modifying() THEN
|
|
IF NOT cust_save(d) THEN RETURN FALSE END IF
|
|
END IF
|
|
RETURN TRUE
|
|
END FUNCTION
|
|
|
|
FUNCTION cust_move_to(d,index)
|
|
DEFINE d ui.Dialog
|
|
DEFINE index INTEGER
|
|
IF NOT cust_autosave(d) THEN RETURN END IF
|
|
IF index > customers.getLength() THEN
|
|
LET index = customers.getLength()
|
|
END IF
|
|
IF index < 1 THEN
|
|
LET index = 1
|
|
END IF
|
|
LET cust.* = customers[index].*
|
|
LET old_cust.* = cust.*
|
|
LET cust_curr = index
|
|
MESSAGE SFMT("Customer: %1/%2", cust_curr, customers.getLength())
|
|
CALL ord_loadlist(d, customers[index].cust_id, (index mod 5) * 3)
|
|
CALL d.setCurrentRow("ordlist",1)
|
|
CALL cust_setup(d)
|
|
END FUNCTION
|
|
|
|
-- Dummy function to fill the list of customers (normally, SELECT from database)
|
|
FUNCTION cust_loadlist(d,m)
|
|
DEFINE d ui.Dialog
|
|
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
|
|
IF customers.getLength()>0 THEN
|
|
LET cust_curr = 1
|
|
LET cust.* = customers[cust_curr].*
|
|
CALL ord_loadlist(d, customers[cust_curr].cust_id, (cust_curr mod 5) * 3)
|
|
ELSE
|
|
LET cust_curr = 0
|
|
INITIALIZE cust.* TO NULL
|
|
CALL ord_loadlist(d, 0, 0)
|
|
END IF
|
|
CALL cust_clean(d)
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_loadlist(d,mid,m)
|
|
DEFINE d ui.Dialog
|
|
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
|
|
IF NOT cust_check_changed(d) THEN RETURN END IF
|
|
CALL ord_input('A', cust.cust_id, cust.cust_name, 0)
|
|
END FUNCTION
|
|
|
|
FUNCTION ord_modify(d)
|
|
DEFINE d ui.Dialog
|
|
IF NOT cust_check_changed(d) THEN RETURN END IF
|
|
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 cust_check_changed(d) THEN RETURN END IF
|
|
IF NOT mbox_yn(otitle,"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
|
|
|