2015年8月18日 星期二

Scriptcase 的 button 如何改變label?

上網找了一下Scriptcase如何程式中,改變顯現的Label。

在程式中,經常會有"鎖定/解鎖"按鈕的需求,當開放時,按鈕顯現的是"鎖定",而當鎖定以後,按鈕顯現的是"解鎖"。也就是兩個不同的狀態,可以隨著狀態不同而交替顯示按鈕名稱。

Scriptcase 裡面並沒有提供 可以直接控制物件屬性的方法,希望以後可以有,這樣可以更有彈性的滿足更多的不同需求。

可是,這會兒還沒有怎麼辦?

找了Scriptcase 的 論壇,找到一個網友提供的方法,就是製做兩個 Button,然後使用 sc_btn_display("button_name",on/off),來控制。

可以設計一個資料表中的欄位,其值只有兩個狀態:1/0。

當 1 時,顯示 button_1, on,而button_2, off
當 0 時,相反。

將這程式寫在 Events -> OnLoad 中,即可。

2015年8月16日 星期日

Scriptcase 的 SQL ERROR!

當訪問數據庫時發生錯誤:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 3

View SQL


昨天發生了這個ERROR,查了好久,查不到!

原先一直以為是 trigger 裡面的SQL Statement 的問題,一行一行的查,每個函數也都花了時間查了!結果,找不到Error!

最後,才一直回憶,我最近一次修改了什麼?

原來,我將一個欄位設為 Disabled Field,我不希望讓使用者可以點擊那個欄位,結果就出現了這個 SQL syntax error 的問題。
將之改回 Enable ,就沒問題了!

後來,我發現有個屬性:SQL Type:Text,這個屬性我過去幾乎沒有去管他,也沒有發生過什麼錯誤。這次,因為這個欄位的型態應該是 Number,而不是 Text,所以,我將之改為 Number,一樣設 Disabled Field,結果就OK了!

原來問題發生在這裡:SQL Type不符合上面!

mysql trigger error handle

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinventoryexceptionreasons_delete $$
CREATE TRIGGER before_tblinventoryexceptionreasons_delete
BEFORE DELETE ON tblinventoryexceptionreasons
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblinventoryexceptionreasons = old.idtblinventoryexceptionreasons) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exception reasons table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_storesalesconfig_delete $$
CREATE TRIGGER before_storesalesconfig_delete
BEFORE DELETE ON tblstoresalesconfig
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblstoresales WHERE tblstoresales.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the sales table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventory WHERE tblinventory.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinventoryexceptions WHERE tblinventoryexceptions.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory exceptions table with this item.';
  END IF;
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblstoresalesconfig=old.idtblstoresalesconfig) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

DELIMITER $$
DROP TRIGGER IF EXISTS before_tblinvoice_delete $$
CREATE TRIGGER before_tblinvoice_delete
BEFORE DELETE ON tblinvoice
FOR EACH ROW BEGIN
  IF (SELECT COUNT(*) FROM tblinvoicedetails WHERE tblinvoicedetails.idtblinvoice = old.idtblinvoice) > 0
  THEN
    SET NEW='Error: Cannot delete this item. There are records in the inventory details table with this item.';
  END IF;
END$$
DELIMITER ;

2015年8月13日 星期四

Scriptcase 開發有感:Business Rule 設計在mysql

應該盡量把  Business Rule 設計在 mysql 裡面,也就是 Stored Procedure / Trigger 等

Scriptcase 只要單純的做 FORM的 IO/AUDI就好。

舉一些例子:

會員編號的產生,auto_increment 是一個自動產生數字序號的方法
如果是要產生文字的編碼,就得自己製作。這應該直接由 trigger 來做即可,不用 AP 來做。


WRITE ONCE:只能寫一次的資料。

2015年8月12日 星期三

Scriptcase:如何設定一個欄位的初始值

當有需要在新增一筆資料時,有些欄位需要給予一個初始值。
在Scriptcase 裡面,Fields -> Initial Value (type) ->Defined Value,底下 Initial Value:可以設入一個初始值。
如果該初始值,是一個常數,如:數字、字母,那簡單,輸入就好。而如果是一個變數,就可以用 [variable] 。
那可以是函數嗎? 一個自訂函數可以嗎?
好像不行ㄟ!

只好試試看其他方法。

後來想了,將函數寫在 Form Event -> OnApplicationInit 中,將結果寫在一個變數中, 例如[v_result],然後,將此變數填在該欄位的 Initial Value裡面。

同時,記得到 Application -> Global Variable 中去找到這個變數,並將之設定為"OUT"


2015年8月8日 星期六

Scriptcase 控制欄位鎖住/開鎖的方法

會有需要鎖單功能,也就是將表單鎖住,不讓使用者修改。
需要經過開鎖,才可以編修。

ScriptCase 有提供對欄位 設為 readonly, disabled 等 macro

sc_block_display (Block_Name, on/off)
sc_field_disabled ("Field_Name = True/False", "Parameter")
sc_field_display ({My_Field}, on/off)
sc_field_readonly ({Field}, on/off)
sc_form_show 'on' or 'off

以上這些 Macro,可以對  form / block / field 做各種顯示不顯示,等設定。

而對於 Master / Detail 裡的 Detail 就不能了。因為 Detail 是另一個 Application 不是一個 field 或 block!

如果設了兩個 Block,分別設為 detail ,一個有IUD功能,另一個沒有,結果還是沒有!

最後,試了一個變通的方法:

製作兩個 Detail  Application,一個可以準備可以允許編輯用的;另一個準備來只准讀取 Read Only 的。幸好,使用 Scriptcase 複製 Application 還蠻方便。一下子就好了,名稱上一個叫做 xxxxxx_detail ;另一個叫做 xxxxx_detail_readonly,其內容,其實都一模一樣。

就在 Master application中,分別建立兩個 Master/Detail,一個在聯結中設定允許INSERT/UPDATE/DELETE、另一個不允許INSERT/UPDATE/DELETE,然後,分別放在兩個不同的Block中,而用 sc_block_display()來控制顯示哪一個block,就可以了!

註:2015/08/17 今天終於找到了,讓上面所講的鎖定/結鎖,能自動儲存起來,存在一個欄位中,然後,往前、往後以後,回到這一筆資料,依然是鎖定/解鎖 的狀態。
那就是:

if ({lock_field}=='1') {
   {lock_field}='0';
   enable_all_fields();
} else {
    {lock_field}='1';
    disable_all_fields();
}
sc_ajax_javascript( 'nm_atualiza', array('alterar'));


註:自己另行設計一個 button,TYPE:JavaScript,可以自訂 LABEL、還有 CONFIRM Message等。
在下面的 JavaScript 裡面輸入:

nm_atualiza('alterar');

這是執行"SAVE"的意思。



另一個應用場景是:如果希望自動執行SAVE,而不要讓使用者再按一次SAVE,就可以在程式中自己加入這段程式碼。

下面這一段程式:
執行SAVE,然後等一秒鐘,然後自動下一筆(nm_move('avanca');)

nm_atualiza('alterar'); setTimeout(function() {nm_move('avanca');},1000); //you need a delay (1000 = 1s) here to wait for the update to finish, otherwise the form would lock up. You might need to adjust the time. Just try what works best for your system.

Parameters for nm_move():
first = ‘inicio’
previous = ‘retorna’
next = ‘avanca’
last = ‘final’








如何判斷現在FORM是在 insert mode? 還是 update mode?

只要用  if (empty({primary_key})) 就可以知道是否為新增模式了。 如果 {promary_key} 是空白的,那麼就是在新增模式;反之,就是更新模式。 以上。