Magpie Project¶
警語¶
本專案乃由 Ho600 與智剛科技合作開發,參加經濟部工業局主辦之開放資料(Open Data)應用推動計畫 Open Data 創新應用競賽 ( http://opendata-contest.tca.org.tw/announcement.aspx ),該計畫的執行單位為台北市電腦公會。
若有十方大德願意提供意見、文件、程式碼或技術指導…等,請務必 同意其智慧財產權無償提供本專案、主辦單位及執行單位使用 ,相關說明可詳見 http://opendata-contest.tca.org.tw/doc/附件二%20參賽同意書.pdf 的第二項智慧財產權部份條文。
不同意者,請作壁上觀即可 ,請勿在本專案內開立「問題( issue )」,分枝「公開專案( public repository )」及使用任何管道通知本團隊成員。
但在競賽結束後,無論是否有得獎。本專案可 視 應用服務的未來發展性,就競賽結束後,對十方大德所貢獻之 新 意見、 新 文件、 新 程式碼、 新 技術指導…等,提出有償的授權使用條款。
若大德對「償」十分偏好,敬請競賽結束後再與本團隊接洽。
競賽結果: 本系統榮獲優等獎( http://opendata-contest.tca.org.tw/announcement4.aspx )。
簡報 pdf¶
專案應用服務名稱¶
眼見為憑請求票系統。
本服務乃結合「眼見為憑 APP 」及「請求票系統」,而 magpie 專案中之文件、程式碼並不包括「眼見為憑 APP 」的程式碼。簡言之,「眼見為憑 APP 」程式碼及技術文件會以何種授權方式釋出,將另案處理。
本服務的目標對象¶
陽光的你 、 陽光的我 以及 陽光的他 ( 關心地方事務的 民眾、村里長、鄉鎮市民代及立法委員、公共事務或國營事業業務承辦人以及機關委託之施工廠商 )。
攤在陽光下的事,用陽光的方法解決它,它的使用者不是很陽光嗎?
使用方式¶
民眾使用智慧型手機(具 GPS 、拍照、上網功能)拍下”任何”想反應的事務:
- 馬路不平
- 電線勾纏
- 堤防破損
- 土石滑落阻擋道路
- 自來水管破損
- 河水變色
- 其他…
在上傳系統後由系統自動依 GPS 座標位置分配事務至那一里、那一村,由該村里長或民意代表代為轉至相關承辦機關(單位),若該事務已有特定分類如馬路不平,則可直接轉所屬縣市建設局之陳情信箱。
民眾所反應事務,其中包含相片及絕對座標位置,可方便承辦人快速委託承包施工單位處理,施工單位亦可利用本 APP 將施工中、施工後相片上傳至本系統回報承辦人。
最後在事務處理完畢後,民眾可在系統上了解整件事務的相關處理流程及成果。
計畫執行者¶
姓名 | 手機 | 個人網站 | 主要負責項目 | |
---|---|---|---|---|
何岳峰 | 0975081291 | hoamon@ho600.com | http://www.hoamon.info/ | 專案管理 |
呂oo | 0921XXXXXX | a5XXXXXX@gmail.com | XXXXXXXXXXXXXXXXXXXXXXXX | 網站系統開發 |
黃oo | 0921XXXXXX | johnXXXXXXXXX@gmail.com | XXXXXXXXXXXXXXXXXXXXXXXX | 網站系統開發 |
林oo | 0912XXXXXX | niXXXXXXXX@gmail.com | XXXXXXXXXXXXXXXXXXXXXXXX | 行動APP撰寫 |
藍浚捷 | 0932XXXXXX | blue0jet@gmail.com | http://www.blue0jet.com/ | 文書資料整理 |
程式碼授權方式¶
New BSD( http://opensource.org/licenses/BSD-3-Clause )
Copyright (c) 2014, ho600
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must
reproduce the above copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other materials provided
with the distribution.
Neither the name of the ho600 nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
所有文件目錄¶
服務構想書¶
緣起與創作原因¶
我們團隊內部份成員有幸於中興大學土木工程學系營建管理組就讀時,參與謝教授孟勳所主持的幾個政府機關研究案,其中一項重點成果即『 遠端工程管理系統 』,該系統整合政府承辦人員、監造人員及施工人員三方角色,共同管理新建及維護工程案以確保施工品質、進度。該系統並獲得資策會所頒發『 傑出資訊應用暨產品獎之電子化政府首獎 』。
在參與『遠端工程管理系統』的需求訪查、功能設計、程式開發、系統維護、客戶服務工作中,培養了我們團隊成員傑出的系統實作能力。
所以當我們看到花蓮市公所推出的『市民報馬仔APP』( 新聞: https://www.youtube.com/watch?v=l0uHZIsD9eE ; APP 網址: http://dp.hualien.gov.tw/Repair/ )後,我們萌生了更宏大的目標: 全國性的地方事務管理系統 ,並讓民眾達到『 所見即所問 』的目標。
解決現階段何種問題¶
目前解決地方型事務的方法主要有三:
- 撥打各縣市政府的 1999 專線,跟客服人員報告那裡出了什麼事情。
- 對政治事務及網路工具較為熟捻的公民,他們可以找到該事務相對應的陳情信箱,將意見透過網站或是電子信箱告知承辦單位。
- 依賴地方事務的實際參與者:村里長及民意代表,由他們主動發現或轉述選民問題,並監督承辦單位的處理過程。
這三種方法會面臨幾個問題:
只有言語,位置很難傳遞:
諸如馬路坑洞、河道有浮木阻塞、土石崩落影響交通、堤防破損…等,一般人實在難以報告它的確實位置。我們可透過一段從電話錄音稿來了解這個問題:
- 客服人員:『您好,很高興為您服務。』
- 提報人:『小姐你好,我這邊是埔里鎮水頭路○○-○號,我發現在這條路上的一根電線桿,被路倒枯木壓到電線,我害怕電線壓久了會斷,請協助解決這個問題。』
- 客服人員:『先生,怎麼稱呼?』
- 提報人:『我姓何。』
- 客服人員:『何先生,您好,請告訴我詳細位置。』
- 提報人:『請從水頭路○○-○○號向○○-○○號方向行走,注意右手邊會看到一個檳樃園,再往前經過一段約 25 公尺的空地後的第二個檳樃園,數過去的第三根電線桿,就能看到被壓到的電線了。』
- 客服人員:『了解。謝謝您的來電,我們將儘快派員處理。』
以上是我節錄的對話內容,已略過了很多重複確認的語句,這一個通報問題,通常不花個十來分鐘完成是很難的。因為要 說清楚位置 在很多時候是件困難的事,但有了 GPS 座標,這就很簡單了。
沒有畫面,事實很難傳遞:
用電話、 Email 傳遞問題,除了有被惡作劇的機會,還不容易確認問題的大小。以土石崩落影響交通為案例,承辦人員如果是以口頭、信件、紙本被通知,那他除了親見走訪一趟外,他如何知道施工廠商要派出多少機具來清除? 又或者承辦單位已與施工廠商簽定開口合約,此時預估施工機具數量的責任也是要落到施工廠商身上,若有相片輔助,即可減少一趟『確認問題大小』的路程。
解決公所人力不足、預算不足的問題:
從『市民報馬仔 APP 網站』的一句警語『 本系統僅供花蓮市轄區使用,其他鄉鎮請勿報修 』來看,這麼好的 APP 只有花蓮市有,難道其他鄉鎮市區都不需要處理 路燈不亮、馬路不平、路牌錯置、反射鏡汙損、水溝蓋被偷 的問題嗎? 不可能 。他們之所以強調的原因,除了地方權責劃分的考量外,他們的資訊人員也沒資源可以把系統開放給全國其他鄉鎮市區使用。若由敝系統承擔資訊系統的建置、開發來加速資訊的傳遞,可以讓公所及其他承辦單位專職事務處理, 解決公所人力不足、預算不足的問題 。
解決管道散落各處的問題:
不同地方發生的事務雖可藉助各縣市的 1999 專線處理,但如果使用的是方法二及方法三的話,不同的地方得找不同的網站、村里長、民代處理,這會減損提報的效率,況且方法一也有部份縣市( 新竹縣、彰化縣、嘉義縣、屏東縣、澎湖縣 )未提供。試想一個場景: 我在雨天過後,從臺中市走中橫到花蓮太魯閣,成為第一個看到土石崩落的用路人,但我是個臺中人,這個提報我該是向臺中市、南投縣、花蓮縣那個縣市的 1999 專線提報呢? 如果我使用『眼見為憑 APP 』提報的話,那麼依位置及問題類型,請求票系統可直接將本問題提報給『 公路總局第四區養護工程處 』,加快事務被處理的時間。
目標市場¶
所有關心、經辦地方公共事務的人。
民眾: 關心公共事務,但不需要知道該事務的負責對象是誰,簡單會裝『眼見為憑 APP 』以及會拍照即可。其利益乃滿足社會參與的成就感,及解決自身周遭所面對的問題。
村、里長、民代: 協助將民眾問題分配到適當的承辦單位,有效地紀錄下為民服務的事蹟,並可在下任選舉時,在本系統下載免費或付費的競選文宣。
事務承辦人員: 方便承辦人員確認事務處理位置、範圍及程度,並提供一個與施工廠商間的協同作業系統。讓承辦人員省時、省力處理地方事務。
施工廠商: 從請求票系統上,廠商可快速、正確看到問題大小,在解決問題之後,也能用『眼見為憑 APP』將施工中、施工後的相片上傳,供承辦人員檢核,未來也可供民眾了解廠商的施作能力。本系統可提供施工廠商宣傳廣告的機會,除了單純說明廠商的營業項目外,也可佐以施工實績證明。
Open Data 來源¶
- 村里邊界線(請參考 docs/open-data/taiwan_village_border*/ 內資料 )
- 鄉鎮市區公所公告之村里長、里幹事及各級民意代表名單(請參考 docs/open-data/(village-chief|village-secretary|villages-and-towns-councilor|counties-and-cities-councilor|governed cities-councilor)/ 內資料 )
- 地方縣市政府陳情信箱、市長信箱、單位信箱( #2 )
- 中央及地方縣市政府各級機關組織架構
產品功能¶
分兩大項: 眼見為憑 APP 及請求票系統。
智慧型手機的使用者在下載『眼見為憑 APP 』後,看到有任何公共事務問題時,直接把 APP 打開,並拍下問題現況, APP 同時會紀錄 相片資訊、 GPS 位置及拍攝時間戳記 ,在網路有連線的情況下上傳至請求票系統。
請求票系統將依位置資訊及問題類型分配給縣市政府或國營事業的承辦單位,如果不能自動分配的話,就傳送給該位置負責的村里長及民代,由他們代轉承辦單位。
確認承辦單位後,請求票系統即寄送問題內容、相片及 GPS 位置到該單位提供的電子信箱、陳情網站或市長信箱。
承辦單位接獲請求票系統的來信時,可在信件內文中,找到「設定處理中」的連結位置,使用該連結位置,承辦人可決定案件的公開程度,並分享給施工單位管理,施工單位即可再使用『眼見為憑 APP 』把拍下處理過程的相片、填寫說明回報給承辦單位。
案件解決後,承辦單位即可回信告知處理過程,並自動將處理過程及成果整理至請求票系統供提報人了解整個問題的相關資訊。
目前進度(截至初選時間為止)¶
眼見為憑 APP 的開發進度,已作到可拍照並紀錄 GPS 座標後上傳系統。惟與請求票系統的 API 介面仍待整合。
請求票系統則是以我們內部已開發完成的任務管理系統,將其修改成符合地方性事務的請求票系統,尚需修改的部份包含欄位的擴建、操作流程改良與『眼見為憑 APP 的整合工作』。
資料收集進度已完成全國村里長資料的收集並匯入系統資料庫。提供通訊住址者,未來將寄送信函宣傳本系統並鼓勵村里長使用,若有提供手機號碼者,則可寄送簡訊告知,邀請他來註冊本系統。
預期成果¶
希望能建立一個正向回饋的地方事務處理流程 ( 從 1 到 6 ,再由 6 回到 1 ):
- 民眾利用 APP 提報問題
- 村里長(及民意代表)分配問題
- 承辦單位確認問題並發派施工廠商
- 施工廠商解決問題回傳成果
- 承辦人員回報處理結果
- 民眾確認成果並鼓勵再度使用本系統
所以我們團隊除了開發 APP 及網站外,第二重要的工作,即充當這個正回饋環節中的使用者,如果分配問題的人不足,我們就介入了解問題,協助分類,從中也學得事務歸類的模型,把模型匯入資料庫以便未來自動分配問題。
當承辦單位無人回應的時候,我們成員會再次將問題整理再加註意見提供承辦人員參考。
當施工廠商面對問題時,我們提供範本供他參考,以期他可以把解決過程中的最佳姿態紀錄下來,以備未來宣傳之用。
未來規劃¶
系統的營運經費來源有三:
- 村里長及民意代表付費下載競選文宣。
- 向施工廠商販賣橫幅廣告。
- 向承辦單位及施工廠商提供客製化的任務管理系統。
有經費後即繼續推廣民眾使用本系統提報地方事務,從而建立起一個『 快速、正確解決地方型事務的生態系 』。
需求規格書¶
前言¶
從一個笑話講起。
劇本¶
出場角色¶
- 小明,路人
- 阿土伯,里長
- 番仔火文聰,代表
- 精實強,承辦人
- 歡喜婆婆,清潔員
故事¶
路人小明走在路上驚奇地在眼前的地上發現了一張垃圾,那居然是“有用過”的衛生紙,基於強烈的愛國心及公德心,不願讓這張“不可愛”的紙屑汙辱臺灣美麗的土地。說是遲,那是快,他拿出了內載「眼見為憑 APP」的手機 [copyright] ,把垃圾拍了下來,所謂的有圖有真相,既然有了真相,他也就心滿意足地繼續往便利商店前進,因為老媽說,家裡的銅葉綠素不夠了,要買罐回家,而他心想的是買大罐的,可以用比較久。
[copyright] | (1, 2) 安裝「眼見為憑 APP」前,或是註冊請求票網站前,都需要有「無償分享著作權」的條款,因為不管是相片或是任何意見都屬於個人著作權的範圍, 非常有必要 在使用者上傳相片、意見前即要求他們「同意分享」,不然就不給上傳。 |
那張垃圾的真相,被「眼見為憑 APP」上傳到請求票網站後 [1] [copyright] ,建立了案號為垃圾我清清(#24577 編號)的任務,從相片的 GPS 座標來看,它直接被丟給了阿土里的阿土伯來管理。
[1] | 「眼見為憑 APP」應支持離線儲存,上線自動上傳的功能 |
還好他的平板電腦的音量有切到最大,來信的“叮咚”有提醒到阿土伯,戴上老花眼睛後,看了看請求票網站的來信,他知道在公園路那邊,有那麼一張垃圾,所以他就把它歸給了市公所清潔隊。這樣請求票網站就可以利用一個叫蟲洞 [2] [3] 的技術,把這張請求票(也就是 #24577 的任務),傳送到市公所清潔隊的公文桌上。
[2] | 請求票系統乃利用 SMTP 協定與各級公務、國營事業單位的意見信箱作對接。所以當一任務被歸類到某一市政、市長、公害…信箱後,請求票系統即整理整個任務的內容、 GPS 座標及相片會以 task24577_45637@magpie.ho600.com 的名義寄出。爾後,該意見信箱把處理過程中的所有通知信回覆到 task24577_45637@magpie.ho600.com 時,請求票網站可將 email 內容轉至網頁內容,供使用者方便瀏覽。 task24577_45637@magpie.ho600.com 中的 _45637 乃 #24577 的檢查碼,以防止有垃圾軟體亂寄信件,無謂增加我們系統負荷。 |
[3] | 蟲洞的實作技術使用 Postfix ,可參考下面範例: http://www.postfix.org/OVERVIEW.html http://serverfault.com/questions/132576/run-script-on-incoming-email-message-to-postfix |
然而在公所未作處理前,就被番仔火文聰給攔胡了,文聰留言說:『阿土伯呀!你要帶老花眼睛了,這張相片明明就在公園路旁的阿土公園入口,那個地方要算市政府公園管理處管的啦~』,所以他就手動地把承辦單位換成了「市政府公園管理處」 [4] 。
[4] | 那份在「市公所清潔隊的公文桌」上的請求票怎麼辦?因為蟲洞不是時光機,所以也不能怎麼辦!就只能讓市公所清潔隊的承辦人點擊上面的超連結,回到請求票網站上看看,當他看到這份任務不關他的事時,就當是中樂透囉~ |
看到蟲洞送來的任務,精實強心下一樂,想起過去沒有請求票系統的時光,接到民眾陳情,他也只能眉頭一皺,雖說案情很單純,不過就是張垃圾,但精實強就是很精實呀,所以轄區 200 處公園,全由他一人承辦,這那有那麼多美國時間可以親自去到現場探勘、調研。現在光是靠這張有真相相片,他就能淡定地撥個電話給歡喜婆婆,請她扮好清潔包商的角色。精實強也只在滑鼠上一滑,這任務就滑進蟲洞,來到歡喜婆婆的信箱(或手機 [5] )。
[5] | 眼見為憑 APP 的進階功能之一,就是擁有 push mail 。 |
歡喜婆婆看到有事作,當然歡喜囉~從相片上,她清楚地知道,這個任務只要她本人到即可,不用掃具、不用垃圾車,空手拾起,放進口袋,就能打到回府。不過,在回府前,要作一件事: 「用眼見為憑 APP 搞自拍」。把自己跟乾淨的地板拍下來,傳回請求票系統,這樣精實強,才能打分數,發工程款呀!
精實強在辦公室內透過請求票系統比對了「嗶否」及「A福特」的相片後,確認了歡喜婆婆的確完成掃地的任務,給她記了 1 點,等月底時就依開口合約規定給予歡喜婆婆請款。當然,這個請款工作不會包含在請求票系統上,這是機關的內部作業。
原則上,請求票系統的目標就是無縫、快速地讓外部(公共設施)使用者、泛公部門承辦人及外包施工廠商三者進行資訊傳遞。任何太陽光照得到的東西,都適合放進請求票系統內。若不是太陽光看得到,但承辦人認為可填入此類資訊方有助其他人的了解,則由承辦人權衡。在任務的處理上,以承辦人為最大權限者。
當承辦人完成此項任務後,即可開放給公眾瀏覽,請求票系統同時也會通知協調人(里長、代表或議員,乃有參與該任務分配的成員)、發票人(也就是路人),此任務已解決歡迎回系統為任務處理的相關人員喝個采、拍個手、留留感性的、呼天搶地的讚頌之言。
票的轉換流程¶
票的狀態 [6] :
狀態 | 操作者 | 任務負責人 |
---|---|---|
上傳附件中 | APP | 無 |
創建 | 路人 | 里長、里幹事、代表、議員或請求票系統管理員 |
搗蛋任務 | 里長、里幹事、代表、議員 | 無(需填寫理由,在隱藏不適當內容後公開,路人會被計大點) |
無法執行任務 | 里長、里幹事、代表、議員 | 無(需填寫理由,路人會被計點) |
重覆任務 | 里長、里幹事、代表、議員 | 無(需指定與那一個任務重覆) |
已分配 | 里長、里幹事、代表、議員 | 泛公部門 |
已受理 | 泛公部門的信箱管理者 | 泛公部門的信箱管理者 |
承辦中 | 泛公部門的信箱管理者 | 泛公部門承辦人 |
發包中 | 泛公部門承辦人 | 外包廠商 |
施工中 | 外包廠商 | 外包廠商 |
已施工 | 外包廠商 | 泛公部門承辦人 |
已驗收 | 泛公部門承辦人 | 泛公部門承辦人 |
重新處理 | 除泛公部門承辦人外 | 泛公部門承辦人 |
狀態值依序定義如下:
[6] | 要好好地跟隊友討論 ( #3 ) 。 |
註解
<技術說明> 搗蛋任務、無法執行任務、重覆任務、已驗收等狀態時, in_working 要等於 False
畫面¶
案件明細頁¶
案件基本欄位¶
參考 bitbucket 的 issue 頁面,案件基本欄位有:
- 創建者
- 創建時間
- 最後更新時間
- 任務負責人
- 操作者
- 狀態
- 類型
- GPS
- 所屬村里
- 所屬單位
- 標題(由網站管理員下)
- 主要相片附檔(限.jpg, 1 張)
- 相片附檔(限.jpg,數量至少 1 張)
- 內容(無內容則必須有錄音檔)
- 錄音檔(限.ogg,限 1 分鐘, 1 個檔) [7]
- 錄音逐字稿(若路人使用錄音檔,則可由網站管理人員手動鍵入)
- 是否公開
- 是否允許評論
[7] | 強迫用戶長話短說。 |
意見基本欄位¶
每一個案件可擁有多個回覆意見,意見乃由參與者自由回覆,參與者依不同案件狀態可有不同人選,如案件剛創立時,參與者為路人、該寄件所在村里之里長、里幹事、代表、議員。在確定承辦單位後,參與者即多了承辦單位的承辦人,案件發包給施工廠商後,參與者即包含施工廠商。
意見呈現的方式則 不採用 bitbucket 模式,而改用 FB 模式,即新意見是在上方,並在使用者將網頁向下捲動時,才會依序秀出舊意見。
意見的基本欄位有:
- 發表者
- 內容(純文字)
- 是否公開
- 附檔(任何格式,數量不限,也獨立設定是否公開)
- 任務負責人變動資料
- 狀態變動資料
- 類型變動資料
- 所屬單位變動資料
案件列表頁¶
案件可依下列欄位查詢:
- 狀態
- 類型(路面、堤防、水溝、路燈、電線桿、人孔蓋...)
- 所屬村里(依縣市、鄉鎮市區階段搜尋)
- 所屬單位(依機關層級搜尋)
- 創建時間
- 結案時間
- 案件是否公開(未公開者,僅秀 GPS 座標、村里)
- 內文關鍵詞
個人資料頁¶
登入頁¶
技術規格書¶
系統主要分五大部份: 請求票網站、 API 、E-Mail Proxy 、 GeoDjango 、時間戳記伺服器。
請求票網站¶
使用者必須啟用 JS ,方能正常使用本網站。
創建帳號/登入¶
路人僅提供使用 Google/Facebook/Yahoo 登入及創建帳號。而使用 APP 創建帳號時一律使用 Google Play 帳號,詳見 ho600_tmp.resources.UserResource.obj_create 。
里長、里幹事、代表、議員帳號資料 [1] 由「開放資料集」匯入,但啟用需經服務處電話人工(網站管理員)驗證。
[1] | 角色明細如下 in_casting_role : |
承辦人帳號則透過 E-Mail Proxy 在傳遞意見時,透過特定連結讓承辦人自建帳號 [2] , 承辦人自建帳號除可使用 GFY 登入,亦可以單位信箱建立帳號。
外包廠商則可利用承辦人所提供的兩組數字 [3] 認領 Ticket 。但認領前,一樣要使用 GFY 登入及創建帳號。且需登錄公司統編或自己的身份證號。
[2] | Ticket 被分配給某個單位後, Ticket 送出問題的內文中,會包含一個特定連結,供承辦人點選後免驗證即可檢視 Ticket 內容。若使用者是使用此特定連結進入,則出現「請他創建帳號」的選項。如果他已創建過,那可以點選登入鈕,該連結一經登入或創建帳號後則立刻失效,未來再點選該連結者,都會提示他們要去跟某某承辦人要權限。若是 Ticket 被更換所屬單位,則特定連結會重新製作,並再開放由第一位點選的承辦人認領 Ticket 。 |
[3] | 第一組是 Ticket 編號加 1 碼檢查碼,第二組是 6 碼驗證數字。 |
Ticket 建立¶
地方事務 Ticket 只能透過「眼見為憑 APP」建立。若是對本系統有意見,則可在本網站創建,其所屬單位必為「敝網站」。
地方事務 Ticket 建立時,直接比對 GPS 位置以對應村里。
地方事務 Ticket 放置在 A 專案; 本系統意見 Ticket 放置在 B 專案。但對使用者前端操作而言,他們應只會注意到地方事務的 ticket 。
Ticket 分配¶
由所屬的里長、里幹事、代表、議員或請求票系統管理員分配 Ticket ,經分配後,也可由承辦單位回本網站改分配或退回分配人。
Ticket 處理¶
承辦人、外包廠商在處理 Ticket 時,可使用 Ticket 所屬的惟一電子信箱回覆意見及附件,回本網站登入後,直接在頁面上填寫意見及上傳附檔。
附檔上傳至 S3 ,其權限為不公開,每次使用者要下載時,由系統給予 1 天 [4] 內有效的下載網址。
[4] | 應可另定。 |
Ticket 結案¶
承辦人審核外包廠商或自辦處理後,可對 Ticket 上的所有意見逐一設定公不公開,但預設值是全部不公開。
關於 Ticket Models¶
需有下列 Models ,才足以紀錄所有資料。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | class Bundle(Ho600LibBaseModel):
pass
class Area(Tree):
name = M.CharField(max_length=16)
class Unit(Tree):
name = M.CharField(max_length=128)
class File(Ho600LibBaseModel):
pass
class Ticket(Ho600LibBaseModel):
bundle = M.ForeignKey(Bundle)
principal = M.ForeignKey(User, related_name='ticket_set_in_principal')
operator = M.ForeignKey(User, related_name='ticket_set_in_operator')
status = M.ForeignKey(Option, related_name='ticket_set_in_status')
kind = M.ForeignKey(Option, related_name='ticket_set_in_kind')
longitude = models.FloatField()
latitude = models.FloatField()
village = M.ForeignKey(Area, null=True)
unit = M.ForeignKey(Unit, null=True)
title = M.CharField(max_length=128, default='')
pictures = M.ManyToManyField(File)
content = M.TextField(default='')
tape = M.ForeignKey(File, null=True)
tape_content = M.TextField(default='')
is_public = M.BooleanField(default=False)
class Reply(Ho600LibBaseModel):
ticket = M.ForeignKey(Ticket)
content = M.TextField(default='')
is_public = M.BooleanField(default=False)
files = M.ManyToManyField(File)
old_principal = M.ForeignKey(User, related_name='reply_set_in_old_principal', null=True)
now_principal = M.ForeignKey(User, related_name='reply_set_in_now_principal', null=True)
old_status = M.ForeignKey(Option, related_name='reply_set_in_old_status', null=True)
now_status = M.ForeignKey(Option, related_name='reply_set_in_now_status', null=True)
old_kind = M.ForeignKey(Option, related_name='reply_set_in_old_kind', null=True)
now_kind = M.ForeignKey(Option, related_name='reply_set_in_now_kind', null=True)
old_unit = M.ForeignKey(Option, related_name='reply_set_in_old_unit', null=True)
now_unit = M.ForeignKey(Option, related_name='reply_set_in_now_unit', null=True)
class Comment(Ho600LibBaseModel):
ticket = M.ForeignKey(Ticket)
reply = M.ForeignKey(Reply, null=True)
content = M.TextField()
scope = M.IntegerField()
|
API¶
帳號建立及驗證¶
路人可直接用 Google Play 帳號在安裝 APP 後,立刻以 Gmail +手機惟一碼創建帳號。
APP 創建帳號所送出的欄位:
- Gmail
- 手機惟一碼
- App verify key,此創建帳號 API 僅供「眼見為憑 APP」使用,所以需以此 key 驗證是否由我們 APP 送來的資料
- auth_key
之後的所有透過 API 傳輸的內容都需要以 auth_key 作驗證。驗證方法為 auth_value = sha1([auth_key]+連線網址+auth_key_id=ZZZ+random_id=XXX+deadline=YYY) ,auth_value 再以 GET 參數附在 request_url 中。
創建 Ticket¶
送出必備欄位:
- auth_key_id
- auth_value
- GPS
- 驗證過的 timestamp (待建立時間戳記伺服器,才能有此資料),或先給予手機上自定的創建時間
- 至少一張相片
- 最多一個錄音檔
- 問題說明
送出選填欄位:
- 類型(路面、堤防、水溝、路燈、電線桿、人孔蓋...),此選項需自動從本網站定期更新。
回傳欄位:
- ticket_id
- ticket_check_code
- 負責人
- 操作者
- 狀態
- 類型
- 對應縣市、鄉鎮市區、村里
- 所屬單位
- 標題
- 相片縮圖網址
- 相片原圖網址
- 內容
- 錄音檔網址
- 錄音檔逐字稿
讀取 Ticket 列表¶
送出必備欄位:
- auth_key_id
- auth_value
結果會回傳已公開、個人所創建的 Ticket ,其回傳欄位同創建成功回傳的欄位。但會多了回覆、評論的相關連結( :todo: hoamon 待整理)。
讀取 Reply 列表¶
- auth_key_id
- auth_value
- ticket_id
- ticket_check_code
讀取 Comment 列表¶
- auth_key_id
- auth_value
- ticket_id
- ticket_check_code
E-Mail Proxy¶
本來是打算以 Postfix 作為收信轉 HTTP POST 的 Proxy ,但考量實作不易且 Mail Server 管理的學問太博大精深了,先放棄了。以 Google App Engine 的 Mail Service 取代。收信地址格式如下:
- LM-[0-9]+-[0-9A-Z]+@www-ho600.appspotmail.com
- DLM-[0-9]+-[0-9A-Z]+@www-ho600.appspotmail.com
- TM-[0-9]+-[0-9A-Z]+@www-ho600.appspotmail.com
- DTM-[0-9]+-[0-9A-Z]+@www-ho600.appspotmail.com
[0-9A-Z]+ 為驗證碼,以排除垃圾信件。
當 GAE 收到如上信件,可依收信地址資料分成三部份資訊:
- 系統代號-Ticket ID-驗證碼@www-ho600.appspotmail.com
系統代號會對應 API 的接收網址、 Ticket ID 對應那一個任務、驗證碼作為檢查用。
信件內容可分下列欄位:
- subject
- sender
- to
- cc
- date
- attachments
- original(除上述內容的原始信件全文)
GAE 首先將 Ticket ID 、標題、寄信地址、 to 、 cc 、寄信時間、附件檔名及內文 POST 到接收網址,然後會拿到附件檔上傳的 S3 位置,再來上傳檔案至 S3 ,完成後再 PATCH 回應 save_done = True 。
GeoDjango¶
PostgreSQL 需要 GEOS, PROJ.4, PostGIS
在 Ubuntu 安裝相關函式庫:
$ sudo apt-get install binutils libproj-dev libgeoip1 gdal-bin python-gdal
$ wget http://download.osgeo.org/geos/geos-3.3.8.tar.bz2
$ tar jxf geos-3.3.8.tar.bz2
$ cd geos-3.3.8
$ ./configure
$ make
$ sudo make install
$ cd ..
$ wget http://download.osgeo.org/proj/proj-4.8.0.tar.gz
$ wget http://download.osgeo.org/proj/proj-datumgrid-1.5.tar.gz
$ tar xzf proj-4.8.0.tar.gz
$ cd proj-4.8.0/nad
$ tar xzf ../../proj-datumgrid-1.5.tar.gz
$ cd ..
$ ./configure
$ make
$ sudo make install
$ cd ..
$ wget http://download.osgeo.org/gdal/gdal-1.9.2.tar.gz
$ tar xzf gdal-1.9.2.tar.gz
$ cd gdal-1.9.2
$ ./configure
$ make # Go get some coffee, this takes a while.
$ sudo make install
$ cd ..
$ wget http://download.osgeo.org/postgis/source/postgis-2.1.3.tar.gz # Ubuntu 14.04 works, but 12.04 not
$ tar -zxf postgis-2.0.3.tar.gz
$ cd postgis-2.0.3/
$ ./configure
$ make
$ sudo make install
$ #此法安裝 postgis-2.0 後,會在 Ubuntu 12.04 上出現 undefined symbol: pj_get_spheroid_defn ,
$ sudo apt-get install postgresql-9.3-postgis-2.1 # but Ubuntu 14.04 does not work
創建樣版資料庫 template_postgis 。以後要開有使用 PostGis 的資料庫可直接複製該樣版。
$ createdb -E UTF8 --lc-collate=zh_TW.UTF-8 --lc-ctype=zh_TW.UTF-8 -T template0 template_postgis
$ createlang -d template_postgis plpgsql
$
$ psql -d postgres -c "UPDATE pg_database SET datistemplate='true' WHERE datname='template_postgis';"
$ POSTGIS_SQL_PATH=`pg_config --sharedir`/contrib/postgis-2.1
$ psql -d template_postgis -f $POSTGIS_SQL_PATH/postgis.sql
$ psql -d template_postgis -f $POSTGIS_SQL_PATH/spatial_ref_sys.sql
$ #如使用的是 AWS PG RDS 的話,上面四行請改以下方文件說明處理
$ #http://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.html#Appendix.PostgreSQL.CommonDBATasks.PostGIS
$
$ psql -d template_postgis -c "GRANT ALL ON geometry_columns TO PUBLIC;"
$ psql -d template_postgis -c "GRANT ALL ON geography_columns TO PUBLIC;"
$ psql -d template_postgis -c "GRANT ALL ON spatial_ref_sys TO PUBLIC;"
$ createdb -T template_postgis test_magpie
再來是以 all_taiwan_village_border/102_05_21_TWD97_121.shp 資料自動產生 Django Model:
$ ./manage.py ogrinspect ../docs/open-data/all_taiwan_village_border/102_05_21_TWD97_121.shp \
VillageBorder --mapping --multi > village_border.py
village_border.py 的內容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | from django.contrib.gis.db import models as M
# This is an auto-generated Django model module created by ogrinspect.
class VillageBorder(M.Model):
obj_id = M.CharField(max_length=10)
objectid_1 = M.IntegerField()
village = M.CharField(max_length=50)
town = M.CharField(max_length=50)
county = M.CharField(max_length=50)
village_id = M.CharField(max_length=48)
town_id = M.CharField(max_length=48)
county_id = M.CharField(max_length=48)
tv_all = M.CharField(max_length=150)
villcode = M.CharField(max_length=16)
ori_villag = M.CharField(max_length=50)
area = M.FloatField()
max_x = M.FloatField()
max_y = M.FloatField()
min_x = M.FloatField()
min_y = M.FloatField()
x = M.FloatField()
y = M.FloatField()
v_id = M.CharField(max_length=20)
sort = M.FloatField()
countyname = M.CharField(max_length=8)
townname = M.CharField(max_length=8)
objectid = M.IntegerField()
orig_fid = M.IntegerField()
shape_leng = M.FloatField()
shape_le_1 = M.FloatField()
shape_area = M.FloatField()
et_id = M.IntegerField()
geom = M.MultiPolygonField(srid=-1)
objects = M.GeoManager()
# Auto-generated `LayerMapping` dictionary for VillageBorder model
VILLAGEBORDER_MAPPING = {
'obj_id' : 'ID',
'objectid_1' : 'OBJECTID_1',
'village' : 'VILLAGE',
'town' : 'TOWN',
'county' : 'COUNTY',
'village_id' : 'VILLAGE_ID',
'town_id' : 'TOWN_ID',
'county_id' : 'COUNTY_ID',
'tv_all' : 'TV_ALL',
'villcode' : 'VILLCODE',
'ori_villag' : 'ORI_VILLAG',
'area' : 'AREA',
'max_x' : 'MAX_X',
'max_y' : 'MAX_Y',
'min_x' : 'MIN_X',
'min_y' : 'MIN_Y',
'x' : 'X',
'y' : 'Y',
'v_id' : 'V_ID',
'sort' : 'SORT',
'countyname' : 'COUNTYNAME',
'townname' : 'TOWNNAME',
'objectid' : 'OBJECTID',
'orig_fid' : 'ORIG_FID',
'shape_leng' : 'Shape_Leng',
'shape_le_1' : 'Shape_Le_1',
'shape_area' : 'Shape_Area',
'et_id' : 'ET_ID',
'geom' : 'MULTIPOLYGON',
}
|
再來利用 import_2014_village_border.py ,即可匯入 all_taiwan_village_border 資料:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | # -*- coding: utf-8 -*-
import os
from django.core.management.base import BaseCommand, CommandError
from django.contrib.gis.utils import LayerMapping
from django.conf import settings
from django.utils.timezone import now, utc
from magpie.models import M, Option, Unit, Area, Casting, VillageBorder, VILLAGEBORDER_MAPPING
class Command(BaseCommand):
help = ''
def handle(self, *args, **kw):
""" Command Example:
./manage.py import_2014_village_border
"""
village_shp = os.path.join(os.path.dirname(os.path.abspath(__file__)),
'..', '..', '..', 'docs', 'open-data',
'taiwan_village_border_TPKM-lat-and-long',
'102_05_21_lat_and_long.shp')
lm = LayerMapping(VillageBorder, village_shp, VILLAGEBORDER_MAPPING, transform=False, encoding='utf-8')
lm.save(strict=True, verbose=True)
vb = VillageBorder.objects.get(objectid_1=488)
vb.village = u'崎峰村'
vb.tv_all = u'林邊鄉崎峰村'
vb.save()
for area in Area.objects.all().order_by('id'):
try:
village_name = area.name
town_name = area.parent.name
city_name = area.parent.parent.name
except AttributeError:
name = area.name
parent = area.parent
while parent:
name = parent.name + name
parent = parent.parent
print 'AttributeError: %s' % (name)
else:
if city_name in ['2010', '2014']: continue
try:
vb = VillageBorder.objects.get(county__in=[city_name, city_name.replace(u'台', u'臺')],
town=town_name,
village=village_name)
except VillageBorder.DoesNotExist:
print 'No VillageBorder: %s%s%s' % (city_name, town_name, village_name)
except VillageBorder.MultipleObjectsReturned:
print 'MultipleObjectsReturned: %s%s%s' % (city_name, town_name, village_name)
else:
area.border = vb
area.save()
|
我們資料庫內的 GPS 座標格式( all_taiwan_village_border, taiwan_village_border_TPKM )為「二度分帶: TWD97 TM2 台灣」格式,一般在 Google Maps 上所查到的 GPS 格式則為「經緯度: TWD97/WGS84」格式。以我的舊家為例,其 Google Maps 上報的是 23.965404, 120.971702 ,經轉換格式後為 247120.147, 2651192.014 。而查詢所在村里的方法如下:
>>> from django.contrib.gis.geos import Point
>>> p = Point(247120.147, 2651192.014)
>>> vb = VillageBorder.objects.get(geom__intersects=p) #匯入資料須為 taiwan_village_border_TPKM.shp
>>> print vb.village
東門里
>>> area = vb.in_area_model.get()
>>> print area.parent.parent.name, area.parent.name, area.name
南投縣 埔里鎮 東門里
另外在 taiwan_village_border_TPKM-lat-and-long 資料集中的格式是 WGS84 ,可直接以 Google Maps 所得座標查詢:
>>> from django.contrib.gis.geos import Point
>>> p = Point(120.971702, 23.965404)
>>> vb = VillageBorder.objects.get(geom__intersects=p) #匯入資料須為 taiwan_village_border_TPKM-lat-and-long.shp
>>> print vb.village
東門里
>>> area = vb.in_area_model.get()
>>> print area.parent.parent.name, area.parent.name, area.name
南投縣 埔里鎮 東門里
本系統內所使用的座標資料為 taiwan_village_border_TPKM-lat-and-long 資料集。
以下是 2010 村里無法對應至 TWD97 的村里邊界資料:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | No VillageBorder: 台北市萬華區糖廍里
No VillageBorder: 高雄市左營區廍北里
No VillageBorder: 高雄市左營區廍南里
No VillageBorder: 高雄市鳥松區坔埔里
No VillageBorder: 高雄市阿蓮區峯山里
No VillageBorder: 高雄市湖內區公舘里
No VillageBorder: 高雄市那瑪夏區達卡努瓦里
No VillageBorder: 新北市板橋區公館里
No VillageBorder: 新北市中和區瓦磘里
No VillageBorder: 新北市中和區灰磘里
No VillageBorder: 新北市永和區新廍里
No VillageBorder: 新北市新店區五峰里
No VillageBorder: 新北市樹林區獇寮里
No VillageBorder: 新北市三峽區永舘里
No VillageBorder: 新北市瑞芳區爪峯里
No VillageBorder: 新北市瑞芳區濂新里
No VillageBorder: 新北市瑞芳區濂洞里
No VillageBorder: 新北市土城區峯廷里
No VillageBorder: 新北市坪林區石[石曹]里
No VillageBorder: 新北市萬里區崁脚里
No VillageBorder: 台中市西區公舘里
No VillageBorder: 台中市西區双龍里
No VillageBorder: 台中市北屯區廍子里
No VillageBorder: 台中市清水區槺榔里
No VillageBorder: 台中市外埔區廍子里
No VillageBorder: 台中市大安區龜里
No VillageBorder: 台中市大肚區蔗廍里
No VillageBorder: 台南市新營區舊廍里
No VillageBorder: 台南市後壁區後廍里
No VillageBorder: 台南市麻豆區晋江里
No VillageBorder: 台南市麻豆區寮廍里
No VillageBorder: 台南市官田區南廍里
No VillageBorder: 台南市佳里區頂廍里
No VillageBorder: 台南市西港區檨林里
No VillageBorder: 台南市七股區塩埕里
No VillageBorder: 台南市七股區槺榔里
No VillageBorder: 台南市新化區山脚里
No VillageBorder: 台南市新化區[上廿下那]拔里
No VillageBorder: 台南市山上區玉峯里
No VillageBorder: 台南市龍崎區石[石曹]里
No VillageBorder: 台南市永康區塩行里
No VillageBorder: 台南市永康區塩洲里
No VillageBorder: 台南市安南區[土昷]南里
No VillageBorder: 台南市安南區塩田里
No VillageBorder: 台南市安南區公[土昷]里
No VillageBorder: 宜蘭縣蘇澳鎮岳明里
No VillageBorder: 桃園縣大園鄉菓林村
No VillageBorder: 桃園縣新屋鄉槺榔村
No VillageBorder: 新竹縣竹東鎮上館里
No VillageBorder: 新竹縣竹東鎮雞林里
No VillageBorder: 新竹縣北埔鄉水磜村
No VillageBorder: 苗栗縣苑裡鎮山腳里
No VillageBorder: 苗栗縣苑裡鎮上館里
No VillageBorder: 苗栗縣竹南鎮公館里
No VillageBorder: 苗栗縣三義鄉双湖村
No VillageBorder: 苗栗縣三義鄉双潭村
No VillageBorder: 彰化縣彰化市下廍里
No VillageBorder: 彰化縣彰化市磚磘里
No VillageBorder: 彰化縣彰化市南瑤里
No VillageBorder: 彰化縣彰化市寶廍里
MultipleObjectsReturned: 彰化縣花壇鄉灣雅村
MultipleObjectsReturned: 彰化縣芬園鄉嘉興村
No VillageBorder: 彰化縣員林鎮大峯里
No VillageBorder: 彰化縣埔鹽鄉廍子村
No VillageBorder: 彰化縣埔鹽鄉瓦磘村
No VillageBorder: 彰化縣埔心鄉舊舘村
No VillageBorder: 彰化縣埔心鄉南舘村
No VillageBorder: 彰化縣埔心鄉新舘村
No VillageBorder: 彰化縣埔心鄉埤腳村
No VillageBorder: 彰化縣二水鄉上豊村
No VillageBorder: 彰化縣芳苑鄉頂廍村
No VillageBorder: 南投縣竹山鎮硘磘里
No VillageBorder: 南投縣名間鄉廍下村
No VillageBorder: 雲林縣斗六市崙峯里
No VillageBorder: 雲林縣西螺鎮公舘里
No VillageBorder: 雲林縣北港鎮公舘里
No VillageBorder: 雲林縣麥寮鄉瓦磘村
No VillageBorder: 雲林縣台西鄉台西村
No VillageBorder: 雲林縣台西鄉海北村
No VillageBorder: 雲林縣台西鄉海南村
No VillageBorder: 雲林縣台西鄉海口村
No VillageBorder: 雲林縣台西鄉溪頂村
No VillageBorder: 雲林縣台西鄉牛厝村
No VillageBorder: 雲林縣台西鄉泉州村
No VillageBorder: 雲林縣台西鄉光華村
No VillageBorder: 雲林縣台西鄉五榔村
No VillageBorder: 雲林縣台西鄉山寮村
No VillageBorder: 雲林縣台西鄉富琦村
No VillageBorder: 雲林縣台西鄉永豐村
No VillageBorder: 雲林縣台西鄉和豐村
No VillageBorder: 雲林縣台西鄉蚊港村
No VillageBorder: 雲林縣台西鄉五港村
No VillageBorder: 雲林縣元長鄉瓦磘村
No VillageBorder: 雲林縣四湖鄉萡子村
No VillageBorder: 雲林縣四湖鄉萡東村
No VillageBorder: 雲林縣水林鄉欍埔村
No VillageBorder: 嘉義縣朴子市双溪里
No VillageBorder: 嘉義縣民雄鄉双福村
No VillageBorder: 嘉義縣中埔鄉塩舘村
No VillageBorder: 嘉義縣中埔鄉石硦村
No VillageBorder: 嘉義縣竹崎鄉文峯村
No VillageBorder: 嘉義縣梅山鄉双溪村
No VillageBorder: 嘉義縣梅山鄉瑞峯村
No VillageBorder: 屏東縣東港鎮下廍里
No VillageBorder: 屏東縣萬丹鄉厦北村
No VillageBorder: 屏東縣萬丹鄉厦南村
No VillageBorder: 屏東縣里港鄉三廍村
No VillageBorder: 屏東縣新園鄉瓦磘村
No VillageBorder: 屏東縣林邊鄉崎峯村
No VillageBorder: 屏東縣滿州鄉响林村
No VillageBorder: 屏東縣瑪家鄉凉山村
No VillageBorder: 台東縣台東市富岡里
No VillageBorder: 台東縣台東市富豐里
No VillageBorder: 台東縣台東市岩灣里
No VillageBorder: 台東縣台東市南王里
No VillageBorder: 台東縣台東市卑南里
No VillageBorder: 台東縣台東市南榮里
No VillageBorder: 台東縣台東市新生里
No VillageBorder: 台東縣台東市民生里
No VillageBorder: 台東縣台東市寶桑里
No VillageBorder: 台東縣台東市馬蘭里
No VillageBorder: 台東縣台東市中心里
No VillageBorder: 台東縣台東市自強里
No VillageBorder: 台東縣台東市民族里
No VillageBorder: 台東縣台東市四維里
No VillageBorder: 台東縣台東市中華里
No VillageBorder: 台東縣台東市強國里
No VillageBorder: 台東縣台東市建國里
No VillageBorder: 台東縣台東市民權里
No VillageBorder: 台東縣台東市仁愛里
No VillageBorder: 台東縣台東市中正里
No VillageBorder: 台東縣台東市大同里
No VillageBorder: 台東縣台東市成功里
No VillageBorder: 台東縣台東市文化里
No VillageBorder: 台東縣台東市中山里
No VillageBorder: 台東縣台東市復國里
No VillageBorder: 台東縣台東市興國里
No VillageBorder: 台東縣台東市復興里
No VillageBorder: 台東縣台東市鐵花里
No VillageBorder: 台東縣台東市新園里
No VillageBorder: 台東縣台東市豐田里
No VillageBorder: 台東縣台東市豐年里
No VillageBorder: 台東縣台東市光明里
No VillageBorder: 台東縣台東市豐樂里
No VillageBorder: 台東縣台東市永樂里
No VillageBorder: 台東縣台東市康樂里
No VillageBorder: 台東縣台東市東海里
No VillageBorder: 台東縣台東市新興里
No VillageBorder: 台東縣台東市豐榮里
No VillageBorder: 台東縣台東市豐谷里
No VillageBorder: 台東縣台東市豐里里
No VillageBorder: 台東縣台東市豐原里
No VillageBorder: 台東縣台東市建和里
No VillageBorder: 台東縣台東市建興里
No VillageBorder: 台東縣台東市建業里
No VillageBorder: 台東縣台東市知本里
No VillageBorder: 台東縣台東市建農里
No VillageBorder: 台東縣關山鎮里壠里
No VillageBorder: 台東縣綠島鄉公舘村
No VillageBorder: 台東縣達仁鄉台坂村
No VillageBorder: 台東縣達仁鄉土坂村
No VillageBorder: 澎湖縣馬公市嵵裡里
No VillageBorder: 澎湖縣湖西鄉菓葉村
MultipleObjectsReturned: 新竹市北區古賢里
No VillageBorder: 嘉義市西區磚磘里
No VillageBorder: 連江縣北竿鄉(土反)里村
No VillageBorder: 金門縣金城鎮東門里
No VillageBorder: 金門縣金城鎮西門里
No VillageBorder: 金門縣金城鎮南門里
No VillageBorder: 金門縣金城鎮北門里
No VillageBorder: 金門縣烏坵鄉大坵村
No VillageBorder: 金門縣烏坵鄉小坵村
|
時間戳記伺服器¶
API 實作階段規格書¶
分四階段為 APP 實作 API 。此四階段也是網站上 js 實作順序,惟 js 實作階段應 領先 APP 。
API
- 帳號相關
- (DONE) APP Sha1 Digest Login
- (DONE) APP/js 以 email 創建用戶
- js 啟用用戶角色(Casting: 村里長、村里幹事、代表、議員)
- APP/js 修改用戶資料
- 任務相關
- (DONE) APP/js 創建任務
- (DONE) APP 更新附件上傳狀態(save_done)
- (DONE) APP/js 更新任務
- APP/js 創建意見
- js 上傳附件(S3 那邊需要開放 CROS)
- (DONE) APP/js 查詢任務
第一階段¶
APP’s Sha1 Digest Login Authentication¶
tastypie 在認證架構上,可使用 MultiAuthentication 方式,串連多種認證方式,在本系統中,只有 UserResource 可使用 Sha1DigestLoginAuthentication + SessionAuthentication + ApiKeyAuthentication ,其他 Resources 皆只能使用 SessionAuthentication 及 ApiKeyAuthentication 。
APP Login: GET UserResource¶
APP 傳入 api_key_id, salt_id, api_key_verify 至 UserResource 時,中間會經過 Sha1DigestLoginAuthentication ,通過 api_key_verify 比對後,該 session 就會被 auth.login(request) ,詳見:
整個 UserResource 在處理完 GET 程序後回傳時,將在 HTTP headers 帶入 csrftoken 及 sessionid 資訊,其 HTTP body 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | {
"meta": {
"limit": 10,
"next": null,
"offset": 0,
"previous": null,
"total_count": 1
},
"objects": [
{
"date_joined": "2014-06-06T13:31:30.065000",
"email": "hoamon+magpieapp@ho600.com",
"first_name": "webmaster",
"id": 605,
"last_login": "2014-06-18T15:14:44.502785",
"last_name": "",
"resource_uri": "/api/lastest/auth/user/605/",
"username": "WEBMASTER.app"
}
]
}
|
APP 以 Google Play 帳號創建用戶: POST UserResource¶
APP 傳入 salt_id, email_of_google_play 至 UserResource 時,中間會經過 Sha1DigestLoginAuthentication ,通過 app_key_verify 比對後,即創建用戶,若已創建,則直接回傳用戶資料,詳見:
其回傳的 HTTP body 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | {
"api_key": {
"id": 1601,
"key": "0acb8cd02e35f6ee3944285cac23192c330bc6fc"
},
"date_joined": "2014-06-18T15:19:19.669140",
"email": "magpie_user_1403105258@gmail.com",
"first_name": "",
"id": 1601,
"last_login": "2014-06-18T15:19:19.669110",
"last_name": "",
"resource_uri": "/api/lastest/auth/user/1601/",
"username": "magpie_user_1403105258@gmail.c"
}
|
APP/js 創建 Ticket: POST TicketResource¶
主要操作 File, Ticket Model 的資料,使用函式為 TicketResource.obj_create 。
創建成功後, TicketResource 回傳的 HTTP body :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | {
"can_comment": false,
"cluster": {
"create_time": "2014-06-06T13:19:03.224000",
"id": 1601,
"is_suspend": false,
"name": "Local Affair",
"resource_uri": "/api/lastest/cluster/1601/",
"slag": ".",
"update_time": "2014-06-06T13:19:03.224000"
},
"content": "Whatever test at 2014-06-29 03:30:48.881906",
"create_time": "2014-06-29T03:30:50.336727",
"creator": {
"date_joined": "2014-06-06T13:31:30.065000",
"email": "hoamon+magpieapp@ho600.com",
"first_name": "webmaster",
"id": 605,
"last_login": "2014-06-29T03:30:48.739071",
"last_name": "",
"resource_uri": "/api/lastest/auth/user/605/",
"username": "WEBMASTER.app"
},
"id": 6,
"in_working": true,
"inspected_time": null,
"is_public": false,
"is_suspend": false,
"kind": null,
"latitude": 24.12058206,
"longitude": 120.67864537,
"mail_key": "VYKW",
"main_picture": "/api/lastest/file/17/",
"operator": {
"date_joined": "2014-06-06T13:31:30.065000",
"email": "hoamon+magpieapp@ho600.com",
"first_name": "webmaster",
"id": 605,
"last_login": "2014-06-29T03:30:48.739071",
"last_name": "",
"resource_uri": "/api/lastest/auth/user/605/",
"username": "WEBMASTER.app"
},
"pictures": [
{
"authentication_absolute_url": "https://s3-us-west-2.amazonaws.com:443/test-magpie006ewq/test/ticket/0/0/6/6/pictures/16/20140629033048-9591928058.jpg?AWSAccessKeyId=AKIAIUMQZW7ZYK7ZWZ5A&Expires=1404617450&Signature=lVyIy9A8%2FECxh2E2aRXHE0pc%2By8%3D",
"create_time": "2014-06-29T03:30:50.291846",
"domain": {
"id": 1598,
"location": "s3-us-west-2.amazonaws.com",
"name": "test-magpie",
"port": "443",
"prefix": "/test-magpie006ewq/test",
"protocol": "https",
"resource_uri": "/api/lastest/domain/1598/"
},
"ext": "jpg",
"extra_attrs": "",
"has_thumb": false,
"id": 16,
"is_suspend": false,
"name": "20140629033048-9591928058",
"note": "",
"resource_uri": "/api/lastest/file/16/",
"save_done": false,
"size": 0,
"update_time": "2014-06-29T03:30:50.361831",
"url_dir": "ticket/0/0/6/6/pictures/16"
},
{
"authentication_absolute_url": "https://s3-us-west-2.amazonaws.com:443/test-magpie006ewq/test/ticket/0/0/6/6/pictures/17/20140629033048-8303573028.jpg?AWSAccessKeyId=AKIAIUMQZW7ZYK7ZWZ5A&Expires=1404617450&Signature=gS6Yu0fdqOPKcEXtm5UV5%2Bwca5E%3D",
"create_time": "2014-06-29T03:30:50.297961",
"domain": {
"id": 1598,
"location": "s3-us-west-2.amazonaws.com",
"name": "test-magpie",
"port": "443",
"prefix": "/test-magpie006ewq/test",
"protocol": "https",
"resource_uri": "/api/lastest/domain/1598/"
},
"ext": "jpg",
"extra_attrs": "",
"has_thumb": false,
"id": 17,
"is_suspend": false,
"name": "20140629033048-8303573028",
"note": "",
"resource_uri": "/api/lastest/file/17/",
"save_done": false,
"size": 0,
"update_time": "2014-06-29T03:30:50.364624",
"url_dir": "ticket/0/0/6/6/pictures/17"
},
{
"authentication_absolute_url": "https://s3-us-west-2.amazonaws.com:443/test-magpie006ewq/test/ticket/0/0/6/6/pictures/18/20140629033048-7126798509.jpg?AWSAccessKeyId=AKIAIUMQZW7ZYK7ZWZ5A&Expires=1404617450&Signature=pVHNoZtSNrJ%2B1LbjWbeCi5BQUoU%3D",
"create_time": "2014-06-29T03:30:50.302083",
"domain": {
"id": 1598,
"location": "s3-us-west-2.amazonaws.com",
"name": "test-magpie",
"port": "443",
"prefix": "/test-magpie006ewq/test",
"protocol": "https",
"resource_uri": "/api/lastest/domain/1598/"
},
"ext": "jpg",
"extra_attrs": "",
"has_thumb": false,
"id": 18,
"is_suspend": false,
"name": "20140629033048-7126798509",
"note": "",
"resource_uri": "/api/lastest/file/18/",
"save_done": false,
"size": 0,
"update_time": "2014-06-29T03:30:50.367220",
"url_dir": "ticket/0/0/6/6/pictures/18"
}
],
"principal": null,
"resource_uri": "/api/lastest/ticket/6/",
"status": {
"id": 1,
"resource_uri": "/api/lastest/ho600_lib/option/1/",
"swarm": "ticket-status",
"value": "initial"
},
"tape_content": "",
"title": "",
"update_time": "2014-06-29T03:30:50.336754",
"village": {
"id": 4098,
"name": "\u7a4d\u5584\u91cc",
"resource_uri": "/api/lastest/area/4098/"
}
}
|
APP 更新附件上傳狀態(save_done): PATCH FileResource¶
當 APP 自行將相片、錄音檔上傳至 S3 後,就需再以 PATCH 連線更新本系統的 File.save_done 欄位。這樣本系統才知道有圖檔給使用者。方法請見:
APP/js 更新任務: PATCH TicketResource¶
APP/js 查詢任務: GET TicketResource¶
基本上,以個人角色先過濾可搜尋到的 Ticket ,之後再依 APP/js 傳來的 query_string 作更細的篩選。
query_string 可下的參數:
js 啟用村里長、村里幹事、議員帳戶: PATCH RoleResource¶
#TODO
第二階段¶
第三階段¶
第四階段¶
創業計劃書¶
營運計劃書¶
系統上線檢查清單¶
編號 | 待檢查內容 | 是否通過 | 檢查者 |
---|---|---|---|
全網站內容以 CC BY-SA 授權發佈, 網站程式碼以 New BSD 發佈。 | |||
系統上線前,會員註冊所同意的條款, 須包含「同意以 CC BY-SA 分享相片及意見的著作權」。 | |||
所創建的地方事務任務必須無緊迫性 (如: 自殺求救、火災救援、溺水救人...)、 無違反社會善良風俗(如: 暴露性器官相片、公然侮辱言論... )。違反者,本系統管理員將於最快時間內撤下違反內容, 並視情況停用該員帳號,禁止使用本系統。 |
開放資料集使用說明¶
村里長¶
來源: http://data.gov.tw/node/7061
資料集描述: 現任村里長
主要欄位說明: 選舉年,市縣別,鄉鎮市別,村里別,姓名,職稱,性別,黨籍,村里辦公處(服務處)地址,村里辦公處(服務處)電話,學歷,簡歷,照片,最後更新日期
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/village-chief/cand2_json.json
村里長選舉結果概況¶
來源: http://data.gov.tw/node/6204
資料集描述: 村里長選舉結果概況
主要欄位說明: 選舉人數、有效票數、無效票數、投票數、投票率、候選人數、當選人數等, 相關欄位對照可參考資料集之格式說明
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/village-chief-election/*
村里幹事¶
來源: http://data.gov.tw/node/7062
資料集描述: 村里幹事
主要欄位說明: 市縣別,鄉鎮市別,村里別,idname:姓名,職稱,性別,鄉鎮市區公所地址,村里辦公處(服務處)地址,鄉鎮市區公所電話,村里辦公處(服務處)電話,學歷,簡歷,照片,最後更新日期
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/village-secretary/cand4_json.json
鄉鎮市民代表¶
來源: http://data.gov.tw/node/7056
資料集描述: 鄉鎮市民代表
主要欄位說明: electname:選舉年,cityname:市縣別,townname:鄉鎮市別,orgname:機關別,idname:姓名,posiname:職稱,sex:性別,partymship:黨籍,officeadress:辦公地址,officetelphone:辦公電話,educatio:學歷,profession:簡歷,id2name:身分別,photograph:照片,upddate:最後更新日期
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/villages-and-towns-councilor/cand_json.json
縣市議員¶
來源: http://data.gov.tw/node/7054
資料集描述: 現任縣市議員
主要欄位說明: electname:選舉年,cityname:市縣別,orgname:機關別,idname:姓名,posiname:職稱,sex:性別,partymship:黨籍,officeadress:辦公地址,officetelphone:辦公電話,educatio:學歷,profession:簡歷,id2name:身分別,photograph:照片,upddate:最後更新日期
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/counties-and-cities-councilor/cand_json.json
直轄市議員¶
來源: http://data.gov.tw/node/7055
資料集描述: 現任直轄市議員
主要欄位說明: electname:選舉年,cityname:市縣別,orgname:機關別,idname:姓名,posiname:職稱,sex:性別,partymship:黨籍,officeadress:辦公地址,officetelphone:辦公電話,educatio:學歷,profession:簡歷,id2name:身分別,photograph:照片,upddate:最後更新日期
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/governed cities-councilor/cand_json.json
全國村里界圖¶
來源: http://data.gov.tw/node/5968
資料集描述: 各縣市村里界,座標系統採TWD97/121分帶
主要欄位說明: 村里別
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/all_taiwan_village_border/*
全國村里界圖(台澎金馬)¶
來源: http://data.gov.tw/node/7440
資料集描述: 各縣市村里界資訊,提供瞭解村里範圍
主要欄位說明: ERSI SHP檔,坐標系統:EPSG:3826(TWD97/121分帶)
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/taiwan_village_border_TPKM/*
全國村里界圖(台澎金馬)-經緯度¶
來源: http://data.gov.tw/node/7439
資料集描述: 全國各村里界資訊,經緯度坐標圖資
主要欄位說明: ESRI SHP檔,坐標系統經緯度
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/taiwan_village_border_TPKM-lat-and-long/*
村里界圖(外島地區)¶
來源: http://data.gov.tw/node/7438
資料集描述: 我國外島地區村里界圖
主要欄位說明: ESRI SHP,坐標系統:EPSG:3825(TWD97/119分帶)
資料集提供機關: 內政部
本專案儲存位置: docs/open-data/taiwan_village_border_only_out_island/*
政府機關唯一識別代碼(OID)¶
來源: http://data.gov.tw/node/7081
資料集描述: 蒐錄中央及地方機關清單及唯一識別編碼
主要欄位說明: 機關OID、機關名稱、機關地址、機關電話
資料集提供機關: 國家發展委員會
本專案儲存位置: docs/open-data/government_OID/GDS.csv
決選簡報逐字稿¶
1¶
大家好,我是XXX。原定的報告人YYY現在在ZZZ參加他的UUU,不克前來。只好我來代打。
2¶
先停頓三秒… 然後講(要微笑喔),這不是投影機壞了,也不是國防布。這真是我們的簡報, 它代表著各位委員等一下腦中的認知模型。
為什麼? 我接下來要講一個YYY真實體驗的故事。
某次颱風過後,我在住家附近閒逛,居然看到有顆檳榔樹倒了,而且還壓到了一根電線桿, 混凝土製的電線桿肯定是不會被壓壞的, 但該死的是這顆樹的大部份重量是作用在接電線的絕緣礙子上面。 我不知道它是否承受得住這顆檳榔樹,所以我趕緊回家上網查台電的客服電話。 對,當這是好幾年前的事了,當時還不流行3G網路及智慧型手機,那個時候, 我拿的是 Palm Treo 650 ,它也還沒有辦法用 wifi 上網呢。
有了電話號碼,及 palm 拍下的電線桿桿號相片。接下來,我就撥給台電,是位小姐接的, 於是我把剛剛看到的路樹壓電線的情況再描述一遍,然後再把電線桿桿號報給她。 結果客服小姐居然說她不懂什麼是電線桿桿號,這真的比扯鈴還扯,這桿號就像電線桿的身份證, 在台電的資料庫中,它還能對應到電線桿的 GPS 座標、尺寸及什麼廠商立的…bal a.bala.
於是,我只好跟她報地址了,這根電線桿的所在地是在一個沒有農舍、沒有門牌的檳榔園旁, 要描述它,只能利用其他的參考座標。所以我請她紀錄,要先找到埔里鎮水頭路17號, 然後向山而行,過了約 50 公尺後,會先看到一個檳榔園,然後是爻白荀田,再過去的檳榔園, 就是目的地了。到那裡就會看到有樹壓到電線桿了。
我也不曉得那位小姐到底有沒有聽懂我的說明,接下來,她要我留下姓名及聯絡方式, 謝謝我的來電後便掛了。
除了這位小姐有沒有聽懂並忠實紀錄我作的描述,如果台電真當這是個事的話,那也會有個派工單, 可能是台電自己的員工,也可能是外包廠商, 那麼這些人看到派工單上的說明,腦袋裡是不是就像這張簡報一樣。
我不知道。但問問各位委員,一樣是跟客服小姐聽了我大致相同的描述, 那您們心中是不是也像這張簡報呢?
所以要解決這個地方型事務的問題,我們首先會面臨幾個難題:
- 說明它發生在那裡
- 解釋問題的程度
- 知道要找的對象是台灣電力公司
3¶
還好現在是 3G 吃到飽,即將進入 4G 的時代,大部份的人手機都有 GPS 及相機功能。 問題在那發生的,用 GPS 測定。問題的程度大小用圖來說明。
有圖就有真相。對施工單位而言,他們可以預先評估要用什麼設備,吊車、卡車、山貓,甚至是要派幾台、多少人力,可以有簡單的估算。
現在剩下的問題,就只有「要找什麼單位?」敝人是土木系出身的, 也常參與一些工務機關的研究案及工程資訊系統的建置,對於公共工程的權責單位劃分有比一般民眾多點認識, 像是以堤防來說,下游多屬河川局管理、中游由水保局管理、上游由林務局,但這也是該河川是屬於中央管河川才是如此劃分。 有些河川是屬於跨省市河川或是縣市管河川,那就分別歸屬於水利署或各縣市水利局管理。 分那麼細,有那些民眾是出了問題後,能立刻想到找誰負責。
所以現在各縣市多半都有 1999 專線,有問題不管大小、知不知道誰負責,反正就打免費電話過去,有專人為您處理。 只是這樣就又回幾年前的那個風雨過後的對話,講的人覺得清清楚楚,聽的人覺得模模糊糊,腦袋裡沒什麼畫面。
4¶
當時,我遇到了這個問題,是覺得問題不大,畢竟我人長那麼大了,也才遇到一次要通報台電。搞不好,這輩子,也就那麼一次。 所以並沒有太放在心上。
直到看到「花蓮市公所的市民報馬仔 APP 」新聞。才想到,我搞錯對象了,重點不是那些公共設施的使用者,是維護者, 他們本身就有這種需求。
這個市民報馬仔 APP 只是提供民眾利用瀏覽器選擇預定的問題類型,再利用 Google Maps 去標註地點。優點是不用打字,用點的, 而且是單純使用 WEB 平台作出來的,可以在 PC/MAC/Android/iOS 上面使用。
但缺點也是有的。它只有花蓮市公所轄區內的馬路相關問題可以用,外縣市或是河川、水電管路就不行了,這很合理。 這個 APP 是花蓮市公所的替代役作的,沒道理,他們花公所的錢去幫全台灣所有鄉鎮市公所服務,就算程式碼開放免費使用, 那也得有人架站,維護管理。
所以我們才提出這個計畫『解決資訊傳遞問題』、『方便跨單位的協作』。
5¶
(攤在陽光下的事,用陽光的方法解決)
我們要解決的問題一定是攤在陽光下的事,因為這樣才抓得到 GPS 。 陽光的方法指的是,各個相關人員在處理問題時,大家看到的資訊都是一樣的。 而且等待任務解決完畢後,承辦人可以選擇對社會大眾公開。
(把地方上有頭有臉的人拉進來)
原本一般民眾不懂得問題該找誰去解決時,現在多是利用 1999 專線。但其實最適當的人選應該是村里長, 及議員們,這本來就是他們的工作,我們希望這個系統是可以把現實中的關係線拉進平台裡,把我們平台變成政治版臉書。
(幫公務員省事,而不是不作事)
公務員分擔的公務,就跟我們國內受薪階級的貧富差距是一樣的,事情多的人,是非常多的。而沒事情的人也是有的。 希望我們平台可以讓這些事情多的公務員,在作事上,可以省點力氣。
(讓施工廠商有機會也露露臉)
很多公共設施的圍牆都會掛著一塊工程告示牌,上面說明了監造單位、營造廠商是誰,且最重要的是留下全民督工專線,歡迎民眾看到不法、不妥、不合理的事情可以通報。 這是給廠商抽鞭子的作法,那我們平台可以給胡蘿蔔的機會,廠商把他們的解決過程、施工相片拍下來,上傳到相關的任務, 這就是一個展示的機會,不然很多鋪馬路、修人行道、路燈之類的工作,作完了,作得好時,不曉得該去給誰拍拍手。
(不只解決問題,更注重協作的品質及效率)
我們平台不是只幫忙解決問題的,還希望各個利用人在處理問題時,可以用最少的力氣。 所以我們主要是把這個平台功能定位為跨單位的工程事務協作系統。
6¶
我們平台包含兩種程式,一個是 WEB ,架在 Amazon 上,跑在 Linux + Nginx + Django + PostgreSQL , AP Server 是用 uWSGI 伺服器。
另一個則是 APP 程式,只出 Android 版的,因為我們沒有 ios 的人才。
7¶
不同角色會依權限看到不同的任務。
一般人可以看到的任務有兩種,一種是自己創建的,另一種是承辦人處理完畢後選擇公開的。
而其他村里長、村里幹事、議員除了這兩種外,還可以看到發生在自己轄區的任務。
而承辦人及施工廠商則是可以看到自己負責處理的任務。
那麼在搜尋之後,如果有包含到未公開的任務,則在列表時,在標題部份會以 未公開 顯示, 且無法觀看詳細資訊。
8¶
WEB 平台是用來協作及展示之用的。要創建任務,只能靠手機 APP , 因為我們需要提報人貢獻兩種資訊一個是 GPS ,另一個是相片。 具備這兩者,我們才允許他能創建地方型的任務。
那麼在未來的系統發展目標中,我們是希望可以加入時間戳記伺服器,這樣一項任務在創建時, 有了 GPS 、絕對時間及它當時拍下的相片, 那麼問題被假造的機率就非常低了。這可以避免無聊人士耗費公共資源。
9¶
這是我們 APP 的螢幕截圖。要創建任務時,就按下「建立事件回報」。
10¶
接下來,就使用手機內建相機軟體來拍照,拍完後,可以選擇放棄,點左邊的X。點右邊則代表使用這張圖。 確定後,會再問您,要繼續拍照,提供佐證,或是直接儲存相片。
12¶
這張是在 APP 上看 WEB 平台的任務資訊,我們 WEB 使用 bootstrap 函式庫, 所以在不同解析度的螢幕上,會作適當的排版調整。
13¶
這是 WEB 版的介面。可以看到用幾張相片、 Google Maps 地點及簡短一句說明, 就能表達問題。
14¶
這是處理任務時,相關人員所看到的表單。
所在村里是我們系統管理員針對 GPS 計算錯誤時,可以修改用的。
承辦單位、類型是給村里長、村里幹事、議員用的。
任務負責人是給承辦單位的總管,像是文書組或是發言人、主任秘書等等,主要就是負責管理單位的陳情信箱的人。
而狀態部份,系統可依當下是什麼角色發派給其他角色時,自動選擇的,但也允許使用者自己調整。
最下方則是對這個任務的回覆意見。
15¶
1)
一開始任務創建完成後,系統會自動分配它是屬於那個村里,確定後,就會寄通知信給這個村里所相關的村里長、村里幹事及議員。
第一個處理的人是里幹事,他選擇承辦單位是中興大學土木系。我們系統會儘量輸入全國各地機關、單位、國營事業的資料, 如果遇到是還沒輸入的,也允許使用者自己打字填寫,事後再由我們管理員作正規化及聯絡信箱的補充。
所以選好承辦單位後,系統就能把任務寄送至該單位的聯絡信箱,收信的人可直接回覆意見或是點選信中連結來到我們網站回覆意見。 因為我們系統在不同任務上,是使用不同的發信地址去寄到各單位的聯絡信箱,所以他們直接回信的話, 我們是可以從收信地址來判斷他回覆的是屬於那一個任務。
這部份的技術,我們是搭配 Google App Engine 的收信服務,它在收到信,可以把收信地址、內文、附件用 HTTP 協定傳到我們網站。
仙人打鼓有時錯。所以有可能遇到里幹事給錯了承辦單位,這也沒有關係,在現實環境中,是用打電話或是去承辦單位直接反應的, 如果反應錯了單位,那也只是踢個足球而已呀!就換個單位提報就行了。
所以土木系的管理員就回了封信,說這不是他們業務,請另找林管處。
里幹事看到回信,就知道事主要換成林管處,一樣是複製貼上相同的意見,再改了承辦單位即可。系統就會再寄信給林管處。
林管處的管理員收到信後,確認這屬於他們工作,那他就會把信轉給單位內的承辦人,如果他們單位內有自己的一套工務管理系統, 也可以把這封信就貼入工務系統裡面去作管理。
所以有可能到了承辦人手上時,這個任務的在現實中處理的各項資訊就會與我們系統暫時剝離了, 因為承辦人不見得會把處理過程一五一十地鍵入我們系統。但是沒關係,只要他最後有把問題解決了, 他總必須回報當初的陳情者,回報內容不管是精采還是簡略,他就是得回報。只要承辦人一回報, 那就是寄信回我們任務專屬的收信信箱。這樣一來,任務資訊就又接回我們系統了。
如果承辦單位還不夠資訊化,沒有專用的工務管理系統,那他可以利用我們系統來當作他們的工務管理系統。
管理員接到工作後,可以在我們系統上,把任務轉給承辦人。
承辦人也可以把自己的處理過程、什麼時候外包、外包廠商的聯絡資訊,放到我們系統上。
17¶
這張是施工後的相片,對比開立任務時的相片,就可以知道到底施工廠商處理地好不好。
當然這種相片驗收方式,也只是一種簡單的。如果是複雜的工程,那還是需要廠商自行提供壓密試驗、平整度的報告, 這就非我們系統能作的。但我們系統可以協助儲存這些實驗報告,作承辦單位、廠商的雲端硬碟。
我們系統的附件儲存位置用的是 Amazon S3 服務。
18¶
不同的角色,在我們系統上的註冊方式有些許的不一樣。以村里長、村里幹事、議員來說, 只要選對服務區域另外再填上姓名、 email 及密碼,就能開立帳號。
當然這可能會發生有人冒用他人身份,遇到此類糾紛時,我們就會要求該帳號需作實名驗證, 目前來說,就是以銀行帳戶為基準,誰拿得出來,那這帳號就歸誰。
承辦人部份則是要求他提供所屬單位的信箱,我們以信箱為憑據。
施工人員則是以公司統編為準,因為一項任務在分派到施工廠商時,是以統編為準的。
19¶
我們系統會使用到的特殊技術有三
EmailProxy 是方便任務的參與者不需要登入我們網站,可以在信箱中收到信,回覆即可。 事實上,這種工作方式,也正是目前大多數人工作的方式,不停地 CC 來 CC 去。 所以我們讓每一個任務具備自己獨一無二的收信地址後,用那個收信地址去寄信給地方人士、承辦單位、施工廠商, 在他們回信後,我們系統都可以清楚判斷他們處理的究竟是那一個任務。
EmailProxy 技術是利用 GAE 的服務來實作,它除了能把 SMTP 協定轉 HTTP 外,也有很高的負載平衡能力,收信的量再大,也不會倒站。
GPS Mapping 則是利用 PostgreSQL 的 PostGIS 函式庫來計算一個點會落在那些區域之中。 這樣我們才能把任務的 GPS 點位拿來對應至所在村里。這部份的 Open Data 則是匯入了全國村里界圖(台澎金馬)-經緯度資料。
而時間戳記伺服器,則還在研發中,大致上的運作原理,就是 APP 內建一把私錀,在創建任務時,用私錀先簽章,簽完的驗證碼, 先丟到我們的時間戳記伺服器中,由時間戳記伺服器拿自己的私錀對這個驗證碼及自己系統上的時間,再作一次簽章,傳回 APP 後, APP 把時間戳記伺服器的簽章附在創建任務的相片之中,這樣我們就能確定相片產生的時間是與時間戳記伺服器的時間是同步的。
20¶
村里長及各級地方民意代表)
提供現任民意代表及未來參選人在平台上建置個人專頁,內容主要整理自實際任務管理的歷程。
也提供不同等級的付費服務,供消費者與潛在選民互動,例: 某些任務在承辦人員經手處理後, 選擇「不公開」給一般大眾查詢閱覽,而這些「不公開」的任務在系統的權限架構下, 還是可以給任務發生轄區的村里長、各級民意代表閱覽,所以消費者可以決定分享給自己選區的特定民眾閱讀。
這模式就像現實世界中,參選人快到選舉日前,大量印製個人過去的喉舌表現文宣,並發送給選區民眾, 本服務僅是將此行為數位化、社群化。
施工廠商)
每個參與任務施工的廠商,都可能有額外的營業項目,非僅單單面對泛公部門。路面修補、堤防修築、 電線整修…這些業務多是由土木包工業、水電工程行處理,現行的施工模式也是多以開口合約議定, 廠商也是跨業經營,在特定時點,處理泛公部門的業務,在平常時段接私部門訂單。
本系統提供廠商的施工實績頁面宣傳他們的施工技術,也可以在其他已公開且類型相似的任務中, 放置廠商的橫幅廣告增大曝光率。
在其他「不公開」的任務中,施工廠商也可單獨分享給特定用戶閱讀任務,藉此證明自己的施工績效。
所有人(泛公部門、施工廠商、其他…)
本團隊過去的軟體開發工作也多是圍繞在工程事務的資訊管理系統上, 未來一樣會遵行此一客製化開發的營運項目。 本平台在營運地方型事務的協作功能下,可證明本公司對此類技術的實作及維護能力。
21¶
時間戳記服務 在電子簽章可能盛行的未來,時間戳記極其重要,但放眼臺灣,似乎沒什麼便利、 便宜的服務可以使用。本系統有意利用此一機會,趁勢培養自身的時間戳記服務能力。 時間戳記服務可運用的軟性市場(非正式的電子簽章):
- 繳交作業的完成時間證明
- 網路文章發佈時間證明
- 網路拍賣喊價證明
- 網路抽獎證明
這些服務的特性都是嚴格講起來不太重要,真正有糾紛也不會上法院打官司, 先要花真金白銀去建置電子簽章實有大動牛刀之笑。 本平台希望未來能有機會踏入這方面的業務。
22¶
最後這是我們使用的 Open Data 資料集。謝謝各位委員的聆聽,我的簡報到此結束,謝謝。