feat: add prototype for go importer

This commit is contained in:
Marcel Arndt 2025-06-30 07:56:03 +02:00
parent c2b5f55d2d
commit 79da91df00
12 changed files with 480 additions and 0 deletions

View File

@ -0,0 +1,52 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ./cmd/synapse"
delay = 1000
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
silent = false
time = false
[misc]
clean_on_exit = false
[proxy]
app_port = 0
enabled = false
proxy_port = 0
[screen]
clear_on_rebuild = false
keep_scroll = true

View File

@ -0,0 +1,31 @@
package main
import (
"flag"
"os"
"synapse/internal/connector"
)
type config struct {
dispoliveApiKey string
}
func main() {
var cfg config
// ctx := context.Background()
flag.StringVar(&cfg.dispoliveApiKey, "dispolive-key", os.Getenv("DISPOLIVE_API_KEY"), "DispoLive Api Key")
flag.Parse()
dlds := new(connector.DispoliveLegacyDataSource)
dlds.Login()
// rawData, err := dlds.Read(ctx)
// if err != nil {
// panic(err.Error())
// }
// tData, err := transformer.TransformTourData(rawData)
// if err != nil {
// panic(err.Error())
// }
// println(len(rawData), len(tData))
}

3
plattform/synapse/go.mod Normal file
View File

@ -0,0 +1,3 @@
module synapse
go 1.23.2

View File

@ -0,0 +1,13 @@
package connector
import "time"
type DataSource interface {
Read() ([]byte, error)
}
var backoffSchedule = []time.Duration{
1 * time.Second,
3 * time.Second,
10 * time.Second,
}

View File

@ -0,0 +1,43 @@
package connector
import (
"context"
"fmt"
"io"
"net/http"
"os"
"time"
)
type DispoliveDataSource struct {
}
func (dc *DispoliveDataSource) Read(ctx context.Context) ([]byte, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, 1000*time.Millisecond)
defer cancel()
key := os.Getenv("DISPOLIVE_API_KEY")
if key == "" {
return []byte{}, fmt.Errorf("couldn't perform request: Dispolive API key not found")
}
req, err := http.NewRequestWithContext(ctxWithTimeout, "GET", "https://avicenna.dispolive.de/custom/open-api/fahrberichte/findByRange/2025-06-20_2025-06-21", nil)
if err != nil {
return []byte{}, fmt.Errorf("couldn't construct the request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("dispolive-api-version", "v1.0.1")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return []byte{}, fmt.Errorf("request returned an error: %w", err)
}
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return []byte{}, fmt.Errorf("couldn't read body: %w", err)
}
return body, nil
}

View File

@ -0,0 +1,88 @@
package connector
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"strings"
"time"
)
const dispoliveBaseUrl = "https://avicenna.dispolive.de"
type DispoliveLegacyDataSource struct{}
func (dc *DispoliveLegacyDataSource) Read(ctx context.Context) ([]byte, error) {
ctxWithTimeout, cancel := context.WithTimeout(ctx, 1000*time.Millisecond)
defer cancel()
key := os.Getenv("DISPOLIVE_API_KEY")
if key == "" {
return []byte{}, fmt.Errorf("couldn't perform request: Dispolive API key not found")
}
req, err := http.NewRequestWithContext(ctxWithTimeout, "GET", "https://avicenna.dispolive.de/custom/open-api/fahrberichte/findByRange/2025-06-20_2025-06-21", nil)
if err != nil {
return []byte{}, fmt.Errorf("couldn't construct the request: %w", err)
}
req.Header.Set("Authorization", "Bearer "+key)
req.Header.Set("dispolive-api-version", "v1.0.1")
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return []byte{}, fmt.Errorf("request returned an error: %w", err)
}
body, err := io.ReadAll(res.Body)
res.Body.Close()
if err != nil {
return []byte{}, fmt.Errorf("couldn't read body: %w", err)
}
return body, nil
}
func (dc *DispoliveLegacyDataSource) Login() (string, error) {
username := os.Getenv("DISPOLIVE_USERNAME")
password := os.Getenv("DISPOLIVE_PASSWORD")
if username == "" || password == "" {
return "", fmt.Errorf("authentication not possible, no username or password")
}
return dc.login(username, password)
}
func (dc *DispoliveLegacyDataSource) login(username, password string) (string, error) {
ctxWithTimeout, cancel := context.WithTimeout(context.TODO(), 1000*time.Millisecond)
defer cancel()
payload := map[string]string{"username": username, "password": password}
jsonPayload, _ := json.Marshal(payload)
req, err := http.NewRequestWithContext(ctxWithTimeout, "POST", dispoliveBaseUrl+"/login", bytes.NewBuffer(jsonPayload))
if err != nil {
return "", fmt.Errorf("couldn't construct the request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("request returned an error: %w", err)
}
cookies := res.Header.Values("set-cookie")
cookieString := strings.Split(strings.Join(cookies, ";"), ";")
var authCookies = ""
for _, v := range cookieString {
if strings.Contains(v, "koa.sid") {
if authCookies == "" {
authCookies = v
} else {
authCookies = strings.Join([]string{authCookies, v}, "; ")
}
}
}
return authCookies, nil
}

View File

@ -0,0 +1,7 @@
package transformer
import "synapse/pkg/model"
func TransformTourData(rawData []byte) ([]model.TransformedTourModel, error) {
return []model.TransformedTourModel{}, nil
}

View File

@ -0,0 +1,186 @@
package model
import "time"
type ApiTourModel struct {
_ID string `json:"_id"`
Abrechnung struct {
Tarife []struct {
ID string `json:"_id"`
AbKm string `json:"abKm"`
Fahrtart []string `json:"fahrtart"`
KmBesetzt string `json:"kmBesetzt"`
PosNr string `json:"posNr"`
PosText string `json:"posText"`
Preis string `json:"preis"`
Tarif string `json:"tarif"`
TarifBerechnung string `json:"tarifBerechnung"`
TarifFrom string `json:"tarifFrom"`
TarifTo string `json:"tarifTo"`
VertragsID string `json:"vertragsId"`
VertragName string `json:"vertragName"`
TarifCheck int `json:"tarifCheck"`
Faktor int `json:"faktor"`
GesamtPosPreis string `json:"gesamtPosPreis"`
Linie int `json:"linie,omitempty"`
PlzArt string `json:"plzArt,omitempty"`
Transportart []string `json:"transportart,omitempty"`
BisUhrzeit string `json:"bisUhrzeit,omitempty"`
Di int `json:"di,omitempty"`
Do int `json:"do,omitempty"`
Fr int `json:"fr,omitempty"`
Mi int `json:"mi,omitempty"`
Mo int `json:"mo,omitempty"`
NoFeiertagVertrag int `json:"noFeiertagVertrag,omitempty"`
UhrzeitVertrag int `json:"uhrzeitVertrag,omitempty"`
VonUhrzeit string `json:"vonUhrzeit,omitempty"`
WochentagVertrag int `json:"wochentagVertrag,omitempty"`
Sa int `json:"sa,omitempty"`
So int `json:"so,omitempty"`
} `json:"tarife"`
} `json:"abrechnung"`
AuftraggeberCity string `json:"auftraggeberCity"`
AuftraggeberID string `json:"auftraggeberId"`
AuftraggeberInfo string `json:"auftraggeberInfo"`
AuftraggeberLand string `json:"auftraggeberLand"`
AuftraggeberName string `json:"auftraggeberName"`
AuftraggeberStreet string `json:"auftraggeberStreet"`
AuftraggeberSurname string `json:"auftraggeberSurname"`
AuftraggeberTelefon string `json:"auftraggeberTelefon"`
AuftraggeberZip string `json:"auftraggeberZip"`
AusrueckZeit string `json:"ausrueckZeit"`
BesetztKm float64 `json:"besetztKm"`
Birthday string `json:"birthday"`
Check string `json:"check"`
Color string `json:"color"`
CostStatus string `json:"costStatus"`
CreateTime string `json:"createTime"`
Date string `json:"date"`
DateIso time.Time `json:"date_iso"`
Direction string `json:"direction"`
DistanceDurationText string `json:"distanceDurationText"`
DistanceDurationValue int `json:"distanceDurationValue"`
DistanceStartWacheDurationValue int `json:"distanceStartWacheDurationValue"`
DistanceTargetWacheDurationValue int `json:"distanceTargetWacheDurationValue"`
DistanceText string `json:"distanceText"`
DistanceValue int `json:"distanceValue"`
EaSum string `json:"eaSum"`
Eigenanteil string `json:"eigenanteil"`
EinsatzNummer string `json:"einsatzNummer"`
EndTime string `json:"endTime"`
EndDate string `json:"end_date"`
EventLength string `json:"event_length"`
EventPid string `json:"event_pid"`
FirmName string `json:"firmName"`
Frei string `json:"frei"`
FreiTrigger int `json:"freiTrigger"`
Gefahren int `json:"gefahren"`
GefahreneFirma string `json:"gefahreneFirma"`
GefahreneKm string `json:"gefahreneKm"`
GesamtPreis float64 `json:"gesamtPreis"`
KkID string `json:"kkId"`
Krankenkasse string `json:"krankenkasse"`
LeerKm string `json:"leerKm"`
Materialfahrt bool `json:"materialfahrt"`
Month string `json:"month"`
Mwst int `json:"mwst"`
NettoPreis interface{} `json:"nettoPreis"`
PatCity string `json:"patCity"`
PatKasse string `json:"patKasse"`
PatName string `json:"patName"`
PatStreet string `json:"patStreet"`
PatSurname string `json:"patSurname"`
PatZip string `json:"patZip"`
PatientenLand string `json:"patientenLand"`
PreisBoEA float64 `json:"preisBoEA"`
PreisBrutto float64 `json:"preisBrutto"`
PreisEA int `json:"preisEA"`
PreisNetto float64 `json:"preisNetto"`
PreisSteuer int `json:"preisSteuer"`
RecPattern string `json:"rec_pattern"`
RecType string `json:"rec_type"`
SerienKategorName string `json:"serienKategorName"`
SerienKategorie string `json:"serienKategorie"`
Sonderleistungen []string `json:"sonderleistungen"`
StartBegin string `json:"startBegin"`
StartCity string `json:"startCity"`
StartEnd string `json:"startEnd"`
StartInfo string `json:"startInfo"`
StartInst interface{} `json:"startInst"`
StartInstitution string `json:"startInstitution"`
StartLat float64 `json:"startLat"`
StartLng float64 `json:"startLng"`
StartStreet string `json:"startStreet"`
StartTime string `json:"startTime"`
StartTimeArr []struct {
StartTime string `json:"startTime"`
SetDate string `json:"setDate"`
} `json:"startTimeArr"`
StartTimeBis string `json:"startTimeBis"`
StartZip string `json:"startZip"`
StartDate string `json:"start_date"`
TargetCity string `json:"targetCity"`
TargetInfo string `json:"targetInfo"`
TargetInstitution string `json:"targetInstitution"`
TargetLat float64 `json:"targetLat"`
TargetLng float64 `json:"targetLng"`
TargetStreet string `json:"targetStreet"`
TargetZip string `json:"targetZip"`
Termin bool `json:"termin"`
TransVorhanden string `json:"transVorhanden"`
TransportKrz string `json:"transportKrz"`
TransportName string `json:"transportName"`
Transportart string `json:"transportart"`
Type string `json:"type"`
VerordnungsID string `json:"verordnungsId"`
VerordnungsName string `json:"verordnungsName"`
VersNr string `json:"versNr"`
VersTName string `json:"versTName"`
VersType string `json:"versType"`
Ziel string `json:"ziel"`
ZielBegin string `json:"zielBegin"`
CarPlan string `json:"carPlan"`
PatientenHandy string `json:"patientenHandy"`
PatientenTelefon string `json:"patientenTelefon"`
CarName string `json:"carName"`
CarNo string `json:"carNo"`
Kennzeichen string `json:"kennzeichen"`
KeyFahrzeug string `json:"keyFahrzeug"`
SendStatusArrived bool `json:"sendStatusArrived"`
SendStatusRead bool `json:"sendStatusRead"`
Eday int `json:"_eday"`
FirstChunk bool `json:"_first_chunk"`
LastChunk bool `json:"_last_chunk"`
Length int `json:"_length"`
Sday int `json:"_sday"`
Sorder int `json:"_sorder"`
Sweek int `json:"_sweek"`
Timed bool `json:"_timed"`
ID string `json:"id"`
LadezeitMin int `json:"ladezeitMin"`
WatchDogAlert bool `json:"watchDogAlert"`
Endgen string `json:"endgen"`
GenAusstellungsDatum string `json:"genAusstellungsDatum"`
Startgen string `json:"startgen"`
VerordnungAusstellungsDatum string `json:"verordnungAusstellungsDatum"`
ZuzahlungBis string `json:"zuzahlungBis"`
ZuzahlungVon string `json:"zuzahlungVon"`
AppStatusKrz string `json:"appStatusKrz"`
Beifahrer string `json:"beifahrer"`
BeifahrerKrz string `json:"beifahrerKrz"`
BeifahrerName string `json:"beifahrerName"`
Fahrer string `json:"fahrer"`
FahrerKrz string `json:"fahrerKrz"`
FahrerName string `json:"fahrerName"`
DT string `json:"DT"`
AbrDate string `json:"abrDate"`
AbrNum string `json:"abrNum"`
AbrTime string `json:"abrTime"`
SendStatus struct {
Type string `json:"type"`
Date string `json:"date"`
} `json:"sendStatus"`
ZadStatus string `json:"zadStatus"`
Auftraggebercoop bool `json:"auftraggebercoop"`
Nomeet bool `json:"nomeet"`
}

View File

@ -0,0 +1,56 @@
package model
import "time"
type TransformedTourModel struct {
ID string `json:"id"`
Done bool `json:"done"`
Direction string `json:"direction"`
CarName string `json:"carName"`
OperationID string `json:"operationId"`
DriverID string `json:"driverId"`
DriverName string `json:"driverName"`
CodriverID string `json:"codriverId"`
CodriverName string `json:"codriverName"`
PatientID string `json:"patientId"`
PatientName string `json:"patientName"`
PatientSurname string `json:"patientSurname"`
PatientStreet string `json:"patientStreet"`
PatientZip string `json:"patientZip"`
PatientCity string `json:"patientCity"`
HealthInsurance string `json:"healthInsurance"`
HealthInsuranceNumber string `json:"healthInsuranceNumber"`
Type string `json:"type"`
Category string `json:"category"`
TransportType string `json:"transportType"`
OrdinanceType string `json:"ordinanceType"`
RangeEndDate time.Time `json:"rangeEndDate"`
StartInstitution string `json:"startInstitution"`
StartStreet string `json:"startStreet"`
StartZip string `json:"startZip"`
StartCity string `json:"startCity"`
TargetInstitution string `json:"targetInstitution"`
TargetStreet string `json:"targetStreet"`
TargetZip string `json:"targetZip"`
TargetCity string `json:"targetCity"`
StartDate time.Time `json:"startDate"`
Check int `json:"check"`
OccupiedKm float64 `json:"occupiedKm"`
TotalKm float64 `json:"totalKm"`
StartBegin string `json:"startBegin"`
StartEnd string `json:"startEnd"`
Target string `json:"target"`
TargetBegin string `json:"targetBegin"`
Empty string `json:"empty"`
HasInfection bool `json:"hasInfection"`
InfectionName string `json:"infectionName"`
RevenueDispoLive float64 `json:"revenueDispoLive"`
BillDate time.Time `json:"billDate"`
BillNumber string `json:"billNumber"`
Revenue float64 `json:"revenue"`
ConsumptionCosts float64 `json:"consumptionCosts"`
RevenueDeviation float64 `json:"revenueDeviation"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt time.Time `json:"deletedAt"`
TicketID string `json:"ticketId"`
}

BIN
plattform/synapse/synapse Executable file

Binary file not shown.

View File

@ -0,0 +1 @@
exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1exit status 1

BIN
plattform/synapse/tmp/main Executable file

Binary file not shown.