diff --git a/.github/workflows/commit-msg-check.yml b/.github/workflows/commit-msg-check.yml
index fd6835dec7e5ba1c403e36972fb8895436e95adf..58f298bb63855fe810e4644b4e72bc27fe10dd3e 100644
--- a/.github/workflows/commit-msg-check.yml
+++ b/.github/workflows/commit-msg-check.yml
@@ -1,8 +1,6 @@
 name: 'Commit Message Check'
 
 on:
-  push:
-    branches: [ main ]
   pull_request:
     branches: [ main ]
 
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..521b465ef18c49e353bc280404c8a0758638c2e5
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,28 @@
+GO_BIN_PATH = bin
+
+WEBCONSOLE = webconsole
+
+WEBCONSOLE_GO_FILES = $(shell find -name "*.go" ! -name "*_test.go")
+WEBCONSOLE_JS_FILES = $(shell find ./frontend -name '*.tsx' ! -path "*/node_modules/*")
+WEBCONSOLE_FRONTEND = ./public
+
+debug: GCFLAGS += -N -l
+
+$(WEBCONSOLE): $(GO_BIN_PATH)/$(WEBCONSOLE) $(WEBCONSOLE_FRONTEND)
+
+$(GO_BIN_PATH)/$(WEBCONSOLE): server.go $(WEBCONSOLE_GO_FILES)
+	@echo "Start building $(@F)...."
+	CGO_ENABLED=0 go build -ldflags "$(WEBCONSOLE_LDFLAGS)" -o $@ ./server.go
+
+$(WEBCONSOLE_FRONTEND): $(WEBCONSOLE_JS_FILES)
+	@echo "Start building $(@F) frontend...."
+	cd frontend && \
+	sudo corepack enable && \
+	yarn install && \
+	yarn build && \
+	rm -rf ../public && \
+	cp -R build ../public
+
+clean:
+	rm -rf $(GO_BIN_PATH)/$(WEBCONSOLE)
+	rm -rf public
\ No newline at end of file
diff --git a/backend/WebUI/api_charging.go b/backend/WebUI/api_charging.go
index 3f92b0703f65d6d03980aecc97d860561a786c6c..22db196ee14d16390a8636550c9ca02e6471a7c2 100644
--- a/backend/WebUI/api_charging.go
+++ b/backend/WebUI/api_charging.go
@@ -172,7 +172,10 @@ func GetChargingRecord(c *gin.Context) {
 		}
 
 		for rg, du := range ratingGroupDataUsages {
-			filter := bson.M{"ratingGroup": rg}
+			filter := bson.M{
+				"ueId":        supi,
+				"ratingGroup": rg,
+			}
 			chargingDataInterface, err := mongoapi.RestfulAPIGetOne(chargingDataColl, filter)
 			if err != nil {
 				logger.ProcLog.Errorf("PostSubscriberByID err: %+v", err)
diff --git a/backend/billing/server.go b/backend/billing/server.go
index f2ef04602a665748a70dff33a6ec5e94e053035a..d31cb1d79cb3f0936fa29b7d849f147b87b6e80f 100644
--- a/backend/billing/server.go
+++ b/backend/billing/server.go
@@ -6,7 +6,6 @@ import (
 	"os"
 	"strconv"
 	"sync"
-	"time"
 
 	"github.com/fclairamb/ftpserver/config"
 	"github.com/fclairamb/ftpserver/server"
@@ -19,6 +18,7 @@ import (
 type BillingDomain struct {
 	ftpServer *ftpserver.FtpServer
 	driver    *server.Server
+	wg        *sync.WaitGroup
 }
 
 type Access struct {
@@ -28,10 +28,17 @@ type Access struct {
 	Params map[string]string `json:"params"`
 }
 
+type PortRange struct {
+	Start int `json:"start"`
+	End   int `json:"end"`
+}
+
 type FtpConfig struct {
 	Version        int      `json:"version"`
 	Accesses       []Access `json:"accesses"`
 	Listen_address string   `json:"listen_address"`
+
+	Passive_transfer_port_range PortRange `json:"passive_transfer_port_range"`
 }
 
 // The ftp server is for CDR Push method, that is the CHF will send the CDR file to the FTP server
@@ -39,7 +46,9 @@ func OpenServer(wg *sync.WaitGroup) *BillingDomain {
 	// Arguments vars
 	confFile := "/tmp/webconsole/ftpserver.json"
 
-	b := &BillingDomain{}
+	b := &BillingDomain{
+		wg: wg,
+	}
 	if _, err := os.Stat("/tmp/webconsole"); err != nil {
 		if err := os.Mkdir("/tmp/webconsole", os.ModePerm); err != nil {
 			logger.BillingLog.Error(err)
@@ -68,7 +77,10 @@ func OpenServer(wg *sync.WaitGroup) *BillingDomain {
 				Params: params,
 			},
 		},
-
+		Passive_transfer_port_range: PortRange{
+			Start: 2123,
+			End:   2130,
+		},
 		Listen_address: addr,
 	}
 
@@ -105,33 +117,26 @@ func OpenServer(wg *sync.WaitGroup) *BillingDomain {
 	// Setting up the ftpserver logger
 	b.ftpServer.Logger = logger.FtpServerLog
 
-	go b.Serve(wg)
+	go b.Serve()
 	logger.BillingLog.Info("Billing server Start")
 
 	return b
 }
 
-func (b *BillingDomain) Serve(wg *sync.WaitGroup) {
-	defer func() {
-		logger.BillingLog.Error("Billing server stopped")
-		b.Stop()
-		wg.Done()
-	}()
-
+func (b *BillingDomain) Serve() {
 	if err := b.ftpServer.ListenAndServe(); err != nil {
 		logger.BillingLog.Error("Problem listening ", "err", err)
 	}
-
-	// We wait at most 1 minutes for all clients to disconnect
-	if err := b.driver.WaitGracefully(time.Minute); err != nil {
-		logger.BillingLog.Warn("Problem stopping server", "Err", err)
-	}
 }
 
 func (b *BillingDomain) Stop() {
-	b.driver.Stop()
+	logger.BillingLog.Infoln("Stop BillingDomain server")
 
+	b.driver.Stop()
 	if err := b.ftpServer.Stop(); err != nil {
 		logger.BillingLog.Error("Problem stopping server", "Err", err)
 	}
+
+	logger.BillingLog.Infoln("BillingDomain server stopped")
+	b.wg.Done()
 }
diff --git a/backend/webui_context/context.go b/backend/webui_context/context.go
index 3414c338697b4618fb47aed2a2ac52cbaada4355..6f938b3a0e598dee8971143833b1bb3c38ca3f9f 100644
--- a/backend/webui_context/context.go
+++ b/backend/webui_context/context.go
@@ -10,7 +10,6 @@ import (
 	"github.com/free5gc/openapi/Nnrf_NFManagement"
 	"github.com/free5gc/openapi/models"
 	"github.com/free5gc/openapi/oauth"
-	"github.com/free5gc/webconsole/backend/billing"
 	"github.com/free5gc/webconsole/backend/factory"
 	"github.com/free5gc/webconsole/backend/logger"
 )
@@ -21,7 +20,9 @@ type WEBUIContext struct {
 	NfInstanceID   string
 	NFProfiles     []models.NfProfile
 	NFOamInstances []NfOamInstance
-	BillingServer  *billing.BillingDomain
+
+	// is registered to NRF as AF
+	IsRegistered bool
 
 	NrfUri         string
 	OAuth2Required bool
@@ -40,6 +41,8 @@ func Init() {
 	webuiContext.NfInstanceID = uuid.New().String()
 	webuiContext.NrfUri = factory.WebuiConfig.Configuration.NrfUri
 
+	webuiContext.IsRegistered = false
+
 	ManagementConfig := Nnrf_NFManagement.NewConfiguration()
 	ManagementConfig.SetBasePath(GetSelf().NrfUri)
 	webuiContext.NFManagementClient = Nnrf_NFManagement.NewAPIClient(ManagementConfig)
diff --git a/backend/webui_context/nrf_management.go b/backend/webui_context/nrf_management.go
index c404d97e49fcd934bda9a96e4c8d675b3fc938de..1e6224f7d02f4acf7e44b455fcc248ca1ba73af7 100644
--- a/backend/webui_context/nrf_management.go
+++ b/backend/webui_context/nrf_management.go
@@ -33,7 +33,7 @@ func SendNFRegistration() error {
 			NFInstanceIDDocumentApi.
 			RegisterNFInstance(context.TODO(), GetSelf().NfInstanceID, profile)
 		if err != nil || res == nil {
-			logger.ConsumerLog.Infof("Webconsole-AF register to NRF Error[%s]", err.Error())
+			logger.ConsumerLog.Warnf("Webconsole-AF register to NRF Error[%s]", err.Error())
 			time.Sleep(2 * time.Second)
 			retryTime += 1
 			if retryTime == 10 {
diff --git a/backend/webui_service/webui_init.go b/backend/webui_service/webui_init.go
index 2b9c9014a90ce118b45c9bea7af8ab44ee27551b..e318378888aa6e6ade97cbaa751bb2a2d29e60e6 100644
--- a/backend/webui_service/webui_init.go
+++ b/backend/webui_service/webui_init.go
@@ -1,12 +1,15 @@
 package webui_service
 
 import (
+	"context"
 	"io"
+	"net/http"
 	"os"
 	"os/signal"
 	"runtime/debug"
 	"sync"
 	"syscall"
+	"time"
 
 	"github.com/gin-contrib/cors"
 	"github.com/sirupsen/logrus"
@@ -22,10 +25,17 @@ import (
 type WebuiApp struct {
 	cfg      *factory.Config
 	webuiCtx *webui_context.WEBUIContext
+
+	wg            *sync.WaitGroup
+	server        *http.Server
+	billingServer *billing.BillingDomain
 }
 
 func NewApp(cfg *factory.Config) (*WebuiApp, error) {
-	webui := &WebuiApp{cfg: cfg}
+	webui := &WebuiApp{
+		cfg: cfg,
+		wg:  &sync.WaitGroup{},
+	}
 	webui.SetLogEnable(cfg.GetLogEnable())
 	webui.SetLogLevel(cfg.GetLogLevel())
 	webui.SetReportCaller(cfg.GetLogReportCaller())
@@ -87,6 +97,7 @@ func (a *WebuiApp) Start(tlsKeyLogPath string) {
 
 	logger.InitLog.Infoln("Server started")
 
+	a.wg.Add(1)
 	signalChannel := make(chan os.Signal, 1)
 	signal.Notify(signalChannel, os.Interrupt, syscall.SIGTERM)
 	go func() {
@@ -99,7 +110,7 @@ func (a *WebuiApp) Start(tlsKeyLogPath string) {
 
 		<-signalChannel
 		a.Terminate()
-		os.Exit(0)
+		a.wg.Done()
 	}()
 
 	go func() {
@@ -110,6 +121,8 @@ func (a *WebuiApp) Start(tlsKeyLogPath string) {
 				logger.InitLog.Errorln(retry_err)
 				logger.InitLog.Warningln("The registration to NRF failed, resulting in limited functionalities.")
 			}
+		} else {
+			a.webuiCtx.IsRegistered = true
 		}
 	}()
 
@@ -135,37 +148,66 @@ func (a *WebuiApp) Start(tlsKeyLogPath string) {
 	self := webui_context.GetSelf()
 	self.UpdateNfProfiles()
 
-	wg := sync.WaitGroup{}
-
 	if billingServer.Enable {
-		wg.Add(1)
-		self.BillingServer = billing.OpenServer(&wg)
-		if self.BillingServer == nil {
+		a.wg.Add(1)
+		a.billingServer = billing.OpenServer(a.wg)
+		if a.billingServer == nil {
 			logger.InitLog.Errorln("Billing Server open error.")
 		}
 	}
 
 	router.NoRoute(ReturnPublic())
 
+	var addr string
 	if webServer != nil {
-		logger.InitLog.Infoln(router.Run(webServer.IP + ":" + webServer.PORT))
+		addr = webServer.IP + ":" + webServer.PORT
 	} else {
-		logger.InitLog.Infoln(router.Run(":5000"))
+		addr = ":5000"
 	}
 
-	wg.Wait()
+	a.server = &http.Server{
+		Addr:    addr,
+		Handler: router,
+	}
+	go func() {
+		logger.MainLog.Infof("Http server listening on %+v", addr)
+		if err := a.server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
+			logger.MainLog.Fatalf("listen: %s\n", err)
+		}
+	}()
+
+	logger.MainLog.Infoln("wait all routine stopped")
+	a.wg.Wait()
 }
 
 func (a *WebuiApp) Terminate() {
-	logger.InitLog.Infoln("Terminating WebUI-AF...")
+	logger.MainLog.Infoln("Terminating WebUI-AF...")
+
+	if a.billingServer != nil {
+		a.billingServer.Stop()
+	}
+
+	if a.server != nil {
+		logger.MainLog.Infoln("stopping HTTP server")
+
+		ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
+		defer cancel()
+		if err := a.server.Shutdown(ctx); err != nil {
+			logger.MainLog.Fatal("HTTP server forced to shutdown: ", err)
+		}
+	}
 
 	// Deregister with NRF
-	problemDetails, err := webui_context.SendDeregisterNFInstance()
-	if problemDetails != nil {
-		logger.InitLog.Errorf("Deregister NF instance Failed Problem[%+v]", problemDetails)
-	} else if err != nil {
-		logger.InitLog.Errorf("Deregister NF instance Error[%+v]", err)
-	} else {
-		logger.InitLog.Infof("Deregister from NRF successfully")
+	if a.webuiCtx.IsRegistered {
+		problemDetails, err := webui_context.SendDeregisterNFInstance()
+		if problemDetails != nil {
+			logger.InitLog.Errorf("Deregister NF instance Failed Problem[%+v]", problemDetails)
+		} else if err != nil {
+			logger.InitLog.Errorf("Deregister NF instance Error[%+v]", err)
+		} else {
+			logger.InitLog.Infof("Deregister from NRF successfully")
+		}
 	}
+
+	logger.MainLog.Infoln("WebUI-AF Terminated")
 }
diff --git a/config/webuicfg.yaml b/config/webuicfg.yaml
index 6f55547ccab49c1514dbbe97a586d961681eab3f..232a56f8b1e982bf9d9d42ee5335074b07ba1ea4 100644
--- a/config/webuicfg.yaml
+++ b/config/webuicfg.yaml
@@ -14,8 +14,8 @@ configuration:
   billingServer:
     enable: true
     hostIPv4: 127.0.0.1
-    listenPort: 2122
-    port: 2121
+    listenPort: 2121
+    port: 2122
     tls:
       pem: cert/chf.pem
       key: cert/chf.key