迅速開発GoAdminでマスタ管理

### はじめに
これは 株式会社 RetailAI X Advent Calendar 2022 の 15 日目の記事です。

昨日は @Mikey  さんの記事でした。[NFTはなぜ難しいのだろう？](https://qiita.com/esoul/items/f699b7e40766bba92e76)
本日は、[『迅速開発GoAdminでマスタ管理』](https://qiita.com/risei/private/499e357f8864e1dc71d2)について書いています。


### この記事の目的
go-adminの使い方法をまとめます：

サンプルコード：https://github.com/GoAdminGroup/example

### GoAdminのコマンドラインツールをインストールします。
<pre>
<code>
GO111MODULE=on GOPROXY=https://goproxy.cn go install github.com/GoAdminGroup/go-admin/adm
</code>
</pre>
### インストールした後、versionを確認できます。
```
> adm -V
GoAdmin CLI v1.2.7
```

### GoAdminに必要なsqlファイルをデータベースに導入します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/674188cb-69d5-bdc3-e9f2-5af3c0423872.png)

### データモデルファイルを生成
プロジェックトしたに以下のコメンドを実行する：

```
> adm generate
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/9e1e7fc4-b063-aa7e-0257-b09ae9fc34ee.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/af845b07-9bbe-17ab-08d2-0c3c0dad5922.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/13f4085d-c8bc-5f48-d874-5e22e00cfc75.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/587e2b8d-45c1-c4bb-7453-b3017612bb73.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/9f6d537e-8e29-6baf-3fd7-0fd4e6681d4d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/7c4d7c0d-3a83-112d-abf4-91e136eb0a76.png)
### 以下のファイルを作成しました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/0185f60c-fa86-bf81-fc6e-4eb94c4759e5.png)

#### <font color="Crimson">*注意、自動作成したのコードでGetInfoのHideFilterArea()を使っています。これは削除が必要です。削除しない場合、エラーが発生します。</font>
正しいのは
<pre><code>info := stores.GetInfo()</pre></code>
自動作成したのコード：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/09547bd7-8d4c-d847-c72f-d984501413cc.png)
### main.goを書きます：
```
package main

import (
	"context"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"os/signal"
	"time"

	_ "github.com/GoAdminGroup/go-admin/adapter/gin"                 // web framework adapter
	_ "github.com/GoAdminGroup/go-admin/modules/db/drivers/postgres" // sql driver
	_ "github.com/GoAdminGroup/themes/adminlte"                      // ui theme

	"github.com/GoAdminGroup/example/pages"
	"github.com/GoAdminGroup/example/tables"
	"github.com/GoAdminGroup/go-admin/engine"
	"github.com/GoAdminGroup/go-admin/template"
	"github.com/GoAdminGroup/go-admin/template/chartjs"
	"github.com/gin-gonic/gin"
)

func main() {
	startServer()
}

func startServer() {
	gin.SetMode(gin.ReleaseMode)
	gin.DefaultWriter = ioutil.Discard

	r := gin.Default()

	eng := engine.Default()

	template.AddComp(chartjs.NewChart())

	if err := eng.AddConfigFromJSON("./config.json").
		AddGenerators(tables.Generators).
		AddGenerator("external", tables.GetExternalTable).
		Use(r); err != nil {
		panic(err)
	}

	r.Static("/uploads", "./uploads")

	eng.HTML("GET", "/admin", pages.DashboardPage)
	eng.HTML("GET", "/admin/form", pages.GetFormContent)
	eng.HTML("GET", "/admin/table", pages.GetTableContent)
	eng.HTMLFile("GET", "/admin/hello", "./html/hello.tmpl", map[string]interface{}{
		"msg": "Hello world",
	})

	srv := &http.Server{
		Addr:    ":9033",
		Handler: r,
	}

	go func() {
		if err := srv.ListenAndServe(); err != nil {
			log.Printf("listen: %s\n", err)
		}
	}()

	quit := make(chan os.Signal, 1)
	signal.Notify(quit, os.Interrupt)
	<-quit

	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()
	if err := srv.Shutdown(ctx); err != nil {
		log.Fatal("Server Shutdown:", err)
	}
	log.Println("Server exiting")
	
}
```

### 実行してみます：
```
> go run .
```

http://localhost:9033/admin/login
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/7be4b0ef-b96b-d91a-5539-2030fbfe0574.png)

パスワード：admin

### 最後メニュー設定します：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/6aade1ad-9467-c027-3252-6b0a0878d103.png)
画面を刷新して、メニューをクリックして、画面を入ります。:v:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112105/1c4f1be2-5d7f-1535-fabb-dbc586c63267.png)


### 追記機能：
1.指定列で検索
```
FieldFilterable()
```
例：店舗番号で検索
```
info.AddField("店舗番号", "store_cd", db.Int4).
    FieldFilterable()
```

2.名前で曖昧検索
```
FieldFilterable(types.FilterType{Operator: types.FilterOperatorLike})
```
例：店舗名で曖昧検索
```
info.AddField("商品名", "name", db.Varchar).
		FieldFilterable(types.FilterType{Operator: types.FilterOperatorLike})
```
3.登録日、更新日はDefault現在の日時
```
formList.AddField("登録日時", "created_at", db.Timestamptz, form.Datetime).
    FieldNotAllowAdd().FieldDisableWhenUpdate()

formList.AddField("更新日時", "updated_at", db.Timestamptz, form.Text).
    FieldNow().FieldNotAllowAdd().FieldHideWhenUpdate()
```
4.必須項目
```
FieldMust()
```
例：データを新規追加/更新する時、店舗名は必須項目場合
```
formList.AddField("店舗名", "name", db.Varchar, form.Text).FieldMust()
```
5.更新できない項目
```
FieldNotAllowEdit()
```
例：
店舗情報を更新するとき、店舗番号を更新できないように
```
formList.AddField("店舗番号", "store_cd", db.Int4, form.Text).FieldNotAllowEdit()
```
6.ボタン追加
```
info.AddButton("納品書出力", icon.Save, action.PopUp("/admin/delivery", "", func(ctx *context.Context) (success bool, msg string, data interface{}) {
		XXXXXXロジックXXXXXX
		return true, "", ""
	}), "yellow")
```

### ドキュメント資料：
https://book.go-admin.cn/

### 終わりに

最後まで読んでいただき、ありがとうございました！
次回は@takudooonさんの記事です。
お楽しみください！