322 lines
7.7 KiB
Go
322 lines
7.7 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"fmt"
|
|
"gen_transit_point/model"
|
|
"gen_transit_point/utils"
|
|
"log"
|
|
"strings"
|
|
"time"
|
|
|
|
_ "github.com/lib/pq"
|
|
"github.com/opentracing/opentracing-go"
|
|
"github.com/xuri/excelize/v2"
|
|
"gorm.io/driver/postgres"
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
"gorm.io/gorm/logger"
|
|
)
|
|
|
|
func InitGormDB(host string, port int, user, pass, dbname, sslmode string) (*gorm.DB, error) {
|
|
dsn := fmt.Sprintf(
|
|
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s",
|
|
host, port, user, pass, dbname, sslmode,
|
|
)
|
|
|
|
gormDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{
|
|
PrepareStmt: true,
|
|
Logger: logger.Default.LogMode(logger.Warn),
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Setup connection pooling
|
|
sqlDB, err := gormDB.DB()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sqlDB.SetMaxIdleConns(10)
|
|
sqlDB.SetMaxOpenConns(100)
|
|
sqlDB.SetConnMaxLifetime(time.Hour)
|
|
|
|
return gormDB, nil
|
|
}
|
|
|
|
func main() {
|
|
ctx := context.Background()
|
|
now := time.Now()
|
|
|
|
dbhost := "127.0.0.1"
|
|
dbport := 5432
|
|
dbuser := "postgres"
|
|
dbpass := "postgres"
|
|
dbname := "oslogweb"
|
|
sslmode := "disable"
|
|
|
|
//prod
|
|
/* dbhost := ""
|
|
dbport := 5454
|
|
dbuser := "postgres"
|
|
dbpass := ""
|
|
dbname := "oslogweb"
|
|
sslmode := "require"
|
|
*/
|
|
|
|
gormDB, err := InitGormDB(dbhost, dbport, dbuser, dbpass, dbname, sslmode)
|
|
if err != nil {
|
|
log.Fatalf("Gagal init GORM: %v", err)
|
|
}
|
|
|
|
sqlDB, err := gormDB.DB()
|
|
if err != nil {
|
|
log.Fatalf("Gagal ambil sql.DB: %v", err)
|
|
}
|
|
|
|
if err := sqlDB.Ping(); err != nil {
|
|
log.Fatalf("Gagal ping database: %v", err)
|
|
}
|
|
|
|
fmt.Println("Koneksi ke DB berhasil ✅")
|
|
|
|
filename := "transit_point_indosps.xlsx"
|
|
f, err := excelize.OpenFile(filename)
|
|
if err != nil {
|
|
log.Fatalf("Gagal membuka file Excel: %v", err)
|
|
}
|
|
defer f.Close()
|
|
|
|
sheets := f.GetSheetList()
|
|
if len(sheets) == 0 {
|
|
log.Fatal("File Excel tidak memiliki sheet.")
|
|
}
|
|
|
|
sheetName := sheets[0]
|
|
|
|
fmt.Printf("Membaca sheet: %s\n", sheetName)
|
|
|
|
rows, err := f.GetRows(sheetName)
|
|
if err != nil {
|
|
log.Fatalf("Gagal membaca baris: %v", err)
|
|
}
|
|
|
|
excelData := []model.TransitPoint{}
|
|
//skip header nya jadi init dari 1 bukan 0
|
|
for i := 1; i < len(rows); i++ {
|
|
row := rows[i]
|
|
if len(row) < 5 {
|
|
continue
|
|
}
|
|
|
|
name := strings.TrimSpace(row[1])
|
|
if name == "" {
|
|
continue
|
|
}
|
|
|
|
address := strings.TrimSpace(row[2])
|
|
lat := strings.TrimSpace(row[3])
|
|
lon := strings.TrimSpace(row[4])
|
|
|
|
var latF, lonF float64
|
|
fmt.Sscanf(lat, "%f", &latF)
|
|
fmt.Sscanf(lon, "%f", &lonF)
|
|
|
|
excelData = append(excelData, model.TransitPoint{
|
|
CompanyID: 784,
|
|
Name: name,
|
|
Address: address,
|
|
Latitude: latF,
|
|
Longitude: lonF,
|
|
CreatedDate: utils.FormatToWithoutTZ(ctx, now),
|
|
CreatedBy: "system",
|
|
})
|
|
}
|
|
|
|
names := []string{}
|
|
for _, p := range excelData {
|
|
names = append(names, fmt.Sprintf("'%s'", strings.ReplaceAll(p.Name, "'", "''")))
|
|
}
|
|
|
|
filter := fmt.Sprintf("AND a.company_id=784 AND a.name IN (%s)", strings.Join(names, ","))
|
|
data, err := GetTransitPoints(ctx, gormDB, filter)
|
|
if err != nil {
|
|
log.Fatalf("Gagal GetTransitPoints: %v", err)
|
|
}
|
|
|
|
dbMap := map[string]model.TransitPoint{}
|
|
for _, d := range data {
|
|
dbMap[d.Name] = *d
|
|
}
|
|
|
|
for _, p := range excelData {
|
|
geomWkt := GenerateGeomWkt(ctx, gormDB, p.Longitude, p.Latitude, float64(100))
|
|
p.GeomWkt = geomWkt
|
|
p.ModifiedBy = "system"
|
|
p.ModifiedDate = utils.FormatToWithoutTZ(ctx, now)
|
|
if existing, exists := dbMap[p.Name]; exists {
|
|
if existing.Address != p.Address || existing.Latitude != p.Latitude || existing.Longitude != p.Longitude {
|
|
_, err := UpdateTransitPointDB(ctx, gormDB, &p)
|
|
if err != nil {
|
|
log.Printf("Gagal update %s: %v", p.Name, err)
|
|
} else {
|
|
fmt.Printf("Berhasil update: %s\n", p.Name)
|
|
}
|
|
}
|
|
} else {
|
|
_, err := InsertTransitPointDB(ctx, gormDB, &p)
|
|
if err != nil {
|
|
log.Printf("Gagal insert %s: %v", p.Name, err)
|
|
} else {
|
|
fmt.Printf("Berhasil insert: %s\n", p.Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func InsertTransitPointDB(ctx context.Context, db *gorm.DB, data *model.TransitPoint) (*model.TransitPoint, error) {
|
|
span, spanCtx := opentracing.StartSpanFromContext(ctx, "insertTransitPointDB")
|
|
defer span.Finish()
|
|
|
|
payload := data.BeforeCheck(spanCtx)
|
|
|
|
tx := db.WithContext(spanCtx).Begin().Scopes(payload.TableName(spanCtx))
|
|
if err := tx.Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if payload.GeomWkt.String != "" {
|
|
tx.Clauses(clause.Expr{SQL: "ST_GeomFromText(?, 4326)", Vars: []interface{}{payload.GeomWkt}})
|
|
}
|
|
|
|
tx.Create(&payload)
|
|
if err := tx.Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
if err := tx.Commit().Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
|
|
return payload.Convert(spanCtx), nil
|
|
}
|
|
|
|
func UpdateTransitPointDB(ctx context.Context, db *gorm.DB, data *model.TransitPoint) (*model.TransitPoint, error) {
|
|
span, spanCtx := opentracing.StartSpanFromContext(ctx, "updateTransitPointDB")
|
|
defer span.Finish()
|
|
|
|
payload := data.BeforeCheck(spanCtx)
|
|
|
|
tx := db.WithContext(spanCtx).Begin().Scopes(payload.TableName(spanCtx))
|
|
if err := tx.Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Update GeomWkt jika ada
|
|
if payload.GeomWkt.String != "" {
|
|
tx = tx.Model(&payload).Clauses(clause.Expr{
|
|
SQL: "geom = ST_GeomFromText(?, 4326)",
|
|
Vars: []interface{}{payload.GeomWkt},
|
|
})
|
|
}
|
|
|
|
tx = tx.Model(&payload).Where("id = ?", payload.ID).Updates(map[string]interface{}{
|
|
"address": payload.Address,
|
|
"latitude": payload.Latitude,
|
|
"longitude": payload.Longitude,
|
|
"modified_by": payload.ModifiedBy,
|
|
"modified_date": payload.ModifiedDate,
|
|
})
|
|
|
|
if tx.Error != nil {
|
|
tx.Rollback()
|
|
return nil, tx.Error
|
|
}
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
|
|
return payload.Convert(spanCtx), nil
|
|
}
|
|
|
|
func GenerateGeomWkt(ctx context.Context, db *gorm.DB, lon, lat, bufferRadius float64) string {
|
|
var value sql.NullString
|
|
tx := db.WithContext(ctx)
|
|
query := fmt.Sprintf("SELECT ST_AsText(ST_Buffer(ST_GeomFromText('POINT(%0.7f %0.7f)', 4326), 0.00001 * %v, 'quad_segs=2')) AS geom_text LIMIT 1", lon, lat, bufferRadius)
|
|
tx = tx.Raw(query)
|
|
tx.Row().Scan(&value)
|
|
return strings.TrimSpace(value.String)
|
|
}
|
|
|
|
func GetTransitPoints(ctx context.Context, db *gorm.DB, filter string) ([]*model.TransitPoint, error) {
|
|
|
|
tx := db.WithContext(ctx)
|
|
query := fmt.Sprintf(`SELECT a.id,a.company_id,a.customer_id,a.customer_ids,a.trip_group_transit_point_id,a.status,a.blacklist
|
|
,a.latitude,a.longitude,a.register_date,a.unregister_date,a.created_date,a.modified_date
|
|
,a.name,a.code,a.geocode,a.address,a.created_by,a.modified_by,a.pic_name,a.pic_phone,a.pic_mobile
|
|
,a.transit_point_type,a.remark,a.coords,a.fax,a.mobile_no,a.phone,a.image,a.zip_code,a.geom
|
|
FROM m_transit_point AS a
|
|
WHERE a.name IS NOT NULL AND a.name <> ''
|
|
%v`, filter)
|
|
|
|
fmt.Printf("query : %v\n", query)
|
|
|
|
rows, err := tx.Raw(query).Rows()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
data := []*model.TransitPoint{}
|
|
|
|
for rows.Next() {
|
|
dataScan := model.TransitPointDB{}
|
|
err := rows.Scan(
|
|
&dataScan.ID,
|
|
&dataScan.CompanyID,
|
|
&dataScan.CustomerID,
|
|
&dataScan.CustomerIDs,
|
|
&dataScan.TripGroupTransitPointID,
|
|
&dataScan.Status,
|
|
&dataScan.Blacklist,
|
|
&dataScan.Latitude,
|
|
&dataScan.Longitude,
|
|
&dataScan.RegisterDate,
|
|
&dataScan.UnregisterDate,
|
|
&dataScan.CreatedDate,
|
|
&dataScan.ModifiedDate,
|
|
&dataScan.Name,
|
|
&dataScan.Code,
|
|
&dataScan.Geocode,
|
|
&dataScan.Address,
|
|
&dataScan.CreatedBy,
|
|
&dataScan.ModifiedBy,
|
|
&dataScan.PicName,
|
|
&dataScan.PicPhone,
|
|
&dataScan.PicMobile,
|
|
&dataScan.TransitPointType,
|
|
&dataScan.Remark,
|
|
&dataScan.Coords,
|
|
&dataScan.Fax,
|
|
&dataScan.MobileNo,
|
|
&dataScan.Phone,
|
|
&dataScan.Image,
|
|
&dataScan.ZipCode,
|
|
&dataScan.GeomWkb,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
result := dataScan.Convert(ctx)
|
|
data = append(data, result)
|
|
}
|
|
|
|
return data, nil
|
|
}
|