Refactor parser functionality: move ParseDettaglio and related tests to new parser package; remove unused utils functions
This commit is contained in:
parent
3b3d2e51ce
commit
0837f447fc
6 changed files with 638 additions and 525 deletions
|
|
@ -1,7 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"backend/parser"
|
||||
"backend/typedefs"
|
||||
"backend/utils"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
|
|
@ -64,7 +66,7 @@ func extractData_bkp(annuncio typedefs.AnnuncioBKP, extractedData chan typedefs.
|
|||
|
||||
var tmp typedefs.AnnuncioParsed = typedefs.AnnuncioParsed{}
|
||||
|
||||
codice := RemoveWhitespace(GetStringValue(annuncio.Codice))
|
||||
codice := utils.RemoveWhitespace(utils.GetStringValue(annuncio.Codice))
|
||||
tmp.Codice = codice
|
||||
tmp.Email = nil
|
||||
if annuncio.Proprietario != nil && annuncio.Proprietario.Cliente != nil && annuncio.Proprietario.Cliente.Nome != nil {
|
||||
|
|
@ -75,16 +77,16 @@ func extractData_bkp(annuncio typedefs.AnnuncioBKP, extractedData chan typedefs.
|
|||
tmp.Idlocatore = annuncio.Proprietario.Cliente.ID
|
||||
}
|
||||
|
||||
upperIndirizzo := MakeUppercase(GetStringValue(annuncio.Indirizzo))
|
||||
upperIndirizzo := utils.MakeUppercase(utils.GetStringValue(annuncio.Indirizzo))
|
||||
tmp.Indirizzo = &upperIndirizzo
|
||||
tmp.Civico = annuncio.Civico
|
||||
upperComune := MakeUppercase(GetStringValue(annuncio.Comune))
|
||||
upperComune := utils.MakeUppercase(utils.GetStringValue(annuncio.Comune))
|
||||
tmp.Comune = &upperComune
|
||||
tmp.Cap = annuncio.Cap
|
||||
tmp.Provincia = annuncio.Provincia
|
||||
tmp.Regione = annuncio.Regione
|
||||
tmp.Lat = CommaToDot(annuncio.Lat)
|
||||
tmp.Lon = CommaToDot(annuncio.Lon)
|
||||
tmp.Lat = utils.CommaToDot(annuncio.Lat)
|
||||
tmp.Lon = utils.CommaToDot(annuncio.Lon)
|
||||
tmp.Indirizzo_secondario = nil
|
||||
tmp.Civico_secondario = nil
|
||||
tmp.Lat_secondario = nil
|
||||
|
|
@ -93,12 +95,12 @@ func extractData_bkp(annuncio typedefs.AnnuncioBKP, extractedData chan typedefs.
|
|||
var tipo = tipologiaParser(*annuncio.Tipo)
|
||||
tmp.Tipo = &tipo
|
||||
|
||||
tmpanno := GetStringValue(annuncio.Anno)
|
||||
tmpanno := utils.GetStringValue(annuncio.Anno)
|
||||
if tmpanno != "0" && tmpanno != "" {
|
||||
tmp.Anno = &tmpanno
|
||||
}
|
||||
tmp.Prezzo = prezzoParse(annuncio.Prezzo)
|
||||
tmp.Consegna = parseConsegna(annuncio.Consegna)
|
||||
tmp.Prezzo = parser.ParsePrezzo(annuncio.Prezzo)
|
||||
tmp.Consegna = parser.ParseConsegna(annuncio.Consegna)
|
||||
tmp.Classe = annuncio.Classe
|
||||
|
||||
if annuncio.Categorie != nil && annuncio.Categorie.Categoria != nil {
|
||||
|
|
@ -117,7 +119,7 @@ func extractData_bkp(annuncio typedefs.AnnuncioBKP, extractedData chan typedefs.
|
|||
*tmp.Categorie = resultArray
|
||||
}
|
||||
|
||||
tmp.Mq = CommaToDot(annuncio.Mq)
|
||||
tmp.Mq = utils.CommaToDot(annuncio.Mq)
|
||||
tmp.Piano = annuncio.Piano
|
||||
tmp.Piano_palazzo = annuncio.PianoPalazzo
|
||||
tmp.Unita_condominio = annuncio.UnitaImmobiliari
|
||||
|
|
@ -128,7 +130,7 @@ func extractData_bkp(annuncio typedefs.AnnuncioBKP, extractedData chan typedefs.
|
|||
tmp.Numero_terrazzi = annuncio.NumeroTerrazzi
|
||||
tmp.Numero_box = annuncio.NumeroBox
|
||||
tmp.Numero_postiauto = annuncio.NumeroPostiauto
|
||||
tmpstato := GetStringValue(annuncio.Stato)
|
||||
tmpstato := utils.GetStringValue(annuncio.Stato)
|
||||
var tmpstatoString string
|
||||
if tmpstato == "1" {
|
||||
tmpstatoString = "Attivo"
|
||||
|
|
@ -240,7 +242,7 @@ func TestTipologieBkp() {
|
|||
var tipologie []string
|
||||
for _, r := range bkp.Annunci.Record {
|
||||
if r.Tipo != nil {
|
||||
if !contains(tipologie, *r.Tipo) {
|
||||
if !utils.Contains(tipologie, *r.Tipo) {
|
||||
tipologie = append(tipologie, *r.Tipo)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"backend/parser"
|
||||
"backend/typedefs"
|
||||
"backend/utils"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
|
|
@ -11,7 +13,6 @@ import (
|
|||
"reflect"
|
||||
"regexp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
|
@ -46,7 +47,7 @@ func (m *MiogestHandler) GetAnnunci() typedefs.AnnunciXML {
|
|||
}
|
||||
|
||||
func (m *MiogestHandler) GetAnnunciFromMiogest() {
|
||||
m.AnnunciXML = GetDataXML[typedefs.AnnunciXML]("http://partner.miogest.com/agenzie/infoalloggi.xml")
|
||||
m.AnnunciXML = utils.GetDataXML[typedefs.AnnunciXML]("http://partner.miogest.com/agenzie/infoalloggi.xml")
|
||||
m.annunci_cache_expires = time.Now().Add(1 * time.Hour)
|
||||
}
|
||||
|
||||
|
|
@ -71,7 +72,7 @@ func (m *MiogestHandler) GetCategorie() []typedefs.Categoria {
|
|||
}
|
||||
|
||||
func (m *MiogestHandler) GenerateCaratteristiche() {
|
||||
var result = GetDataXML[typedefs.DefaultCaratteristiche]("https://www.miogest.com/apps/revo.aspx?tipo=schede")
|
||||
var result = utils.GetDataXML[typedefs.DefaultCaratteristiche]("https://www.miogest.com/apps/revo.aspx?tipo=schede")
|
||||
var array typedefs.ListaCaratteristiche
|
||||
for _, tag := range result.Scheda {
|
||||
var c = typedefs.Caratteristica{Id: tag.Id, Tagxml: tag.Tagxml}
|
||||
|
|
@ -82,7 +83,7 @@ func (m *MiogestHandler) GenerateCaratteristiche() {
|
|||
}
|
||||
|
||||
func (m *MiogestHandler) GenerateCategorie() {
|
||||
var result = GetDataXML[typedefs.DefaultCategories]("https://www.miogest.com/apps/revo.aspx?tipo=categorie")
|
||||
var result = utils.GetDataXML[typedefs.DefaultCategories]("https://www.miogest.com/apps/revo.aspx?tipo=categorie")
|
||||
var listaCategorie []typedefs.Categoria
|
||||
for _, elem := range result.Cat {
|
||||
var c = typedefs.Categoria{Id: elem.ID, Nome: elem.Nome}
|
||||
|
|
@ -122,12 +123,12 @@ func (m *MiogestHandler) ParseAnnunci() {
|
|||
lista_codici := []string{}
|
||||
for i := range annunci.Annuncio {
|
||||
|
||||
lista_codici = append(lista_codici, RemoveWhitespace(*annunci.Annuncio[i].Codice))
|
||||
lista_codici = append(lista_codici, utils.RemoveWhitespace(*annunci.Annuncio[i].Codice))
|
||||
sem <- struct{}{}
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
defer func() { <-sem }()
|
||||
result := extractData_update(&annunci.Annuncio[i], contains(cod_image_to_update, *annunci.Annuncio[i].Codice))
|
||||
result := extractData_update(&annunci.Annuncio[i], utils.Contains(cod_image_to_update, *annunci.Annuncio[i].Codice))
|
||||
AnnunciArray.Annuncio = append(AnnunciArray.Annuncio, result)
|
||||
}(i)
|
||||
}
|
||||
|
|
@ -155,11 +156,12 @@ func strUpd(s string) *string {
|
|||
|
||||
func extractData_update(annuncio *typedefs.AnnuncioXML, updateImages bool) typedefs.AnnuncioParsed {
|
||||
var tmp typedefs.AnnuncioParsed = typedefs.AnnuncioParsed{}
|
||||
tmp.Codice = RemoveWhitespace(GetStringValue(annuncio.Codice))
|
||||
tmp.Codice = utils.RemoveWhitespace(utils.GetStringValue(annuncio.Codice))
|
||||
processLocatore(&tmp, annuncio)
|
||||
processIndirizzo(&tmp, annuncio)
|
||||
processTipologia(&tmp, annuncio)
|
||||
tmp.Consegna = parseConsegna(annuncio.Consegna)
|
||||
|
||||
tmp.Tipo = parser.ParseTipologia(annuncio.Tipologia, annuncio.Tipologia2)
|
||||
tmp.Consegna = parser.ParseConsegna(annuncio.Consegna)
|
||||
processCategorie(&tmp, annuncio)
|
||||
processDatiImmobile(&tmp, annuncio)
|
||||
tmp.Stato = annuncio.Stato
|
||||
|
|
@ -224,7 +226,7 @@ func extractData_update(annuncio *typedefs.AnnuncioXML, updateImages bool) typed
|
|||
if updateImages {
|
||||
processImages(&tmp, annuncio)
|
||||
}
|
||||
folders := GetPathDirsArray(filepath.Join(imgbasepath, tmp.Codice))
|
||||
folders := utils.GetPathDirsArray(filepath.Join(imgbasepath, tmp.Codice))
|
||||
for _, folder := range folders {
|
||||
folderpath := filepath.Join(filepath.Join(imgbasepath, tmp.Codice), folder)
|
||||
files, err := os.ReadDir(folderpath)
|
||||
|
|
@ -263,51 +265,26 @@ func processLocatore(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioXM
|
|||
}
|
||||
tmp.Numero = &number
|
||||
if annuncio.Clienti.Cliente.Cognome != nil && annuncio.Clienti.Cliente.Nome != nil {
|
||||
tmp.Locatore = strUpd(fmt.Sprintf("%s %s", MakeUppercase(*annuncio.Clienti.Cliente.Cognome), MakeUppercase(*annuncio.Clienti.Cliente.Nome)))
|
||||
tmp.Locatore = strUpd(fmt.Sprintf("%s %s", utils.MakeUppercase(*annuncio.Clienti.Cliente.Cognome), utils.MakeUppercase(*annuncio.Clienti.Cliente.Nome)))
|
||||
}
|
||||
tmp.Idlocatore = annuncio.Clienti.Cliente.Id
|
||||
}
|
||||
|
||||
func processIndirizzo(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioXML) {
|
||||
tmp.Indirizzo = strUpd(MakeUppercase(GetStringValue(annuncio.Indirizzo)))
|
||||
tmp.Indirizzo = strUpd(utils.MakeUppercase(utils.GetStringValue(annuncio.Indirizzo)))
|
||||
tmp.Civico = annuncio.Civico
|
||||
tmp.Comune = strUpd(MakeUppercase(GetStringValue(annuncio.Comune)))
|
||||
tmp.Comune = strUpd(utils.MakeUppercase(utils.GetStringValue(annuncio.Comune)))
|
||||
tmp.Cap = annuncio.Cap
|
||||
tmp.Provincia = annuncio.Provincia
|
||||
tmp.Regione = annuncio.Regione
|
||||
tmp.Lat = annuncio.Latitudine
|
||||
tmp.Lon = annuncio.Longitudine
|
||||
tmp.Indirizzo_secondario = strUpd(MakeUppercase(GetStringValue(annuncio.IndirizzoSecondario)))
|
||||
tmp.Indirizzo_secondario = strUpd(utils.MakeUppercase(utils.GetStringValue(annuncio.IndirizzoSecondario)))
|
||||
tmp.Civico_secondario = annuncio.CivicoSecondario
|
||||
tmp.Lat_secondario = annuncio.LatitudineSecondario
|
||||
tmp.Lon_secondario = annuncio.LongitudineSecondario
|
||||
}
|
||||
|
||||
func processTipologia(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioXML) {
|
||||
if annuncio.Tipologia == nil {
|
||||
tmp.Tipo = strUpd("Errore")
|
||||
return
|
||||
}
|
||||
if *annuncio.Tipologia == "V" {
|
||||
tmp.Tipo = strUpd("Vendita")
|
||||
return
|
||||
}
|
||||
if *annuncio.Tipologia == "I" {
|
||||
tmp.Tipo = strUpd("Cessione")
|
||||
return
|
||||
}
|
||||
if *annuncio.Tipologia == "A" {
|
||||
if *annuncio.Tipologia2 == "Residenziale" || *annuncio.Tipologia2 == "Turistico" || *annuncio.Tipologia2 == "Stanza" {
|
||||
tmp.Tipo = strUpd("Transitorio")
|
||||
} else {
|
||||
tmp.Tipo = strUpd("Stabile")
|
||||
}
|
||||
return
|
||||
}
|
||||
tmp.Tipo = strUpd("Errore")
|
||||
|
||||
}
|
||||
|
||||
func processCategorie(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioXML) {
|
||||
if annuncio.Categoria == nil {
|
||||
return
|
||||
|
|
@ -328,27 +305,13 @@ func processCategorie(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioX
|
|||
*tmp.Categorie = resultArray
|
||||
}
|
||||
|
||||
func prezzoParse(prezzo *string) int {
|
||||
zero := 0
|
||||
if prezzo == nil {
|
||||
return zero
|
||||
}
|
||||
f, err := strconv.ParseFloat(strings.TrimSpace(strings.ReplaceAll(*prezzo, ",", ".")), 64)
|
||||
if err != nil {
|
||||
log.Printf("Failed to parse price: %v", err)
|
||||
return zero
|
||||
}
|
||||
prezzoInt := int(f * 100) // Convert to cents
|
||||
return prezzoInt
|
||||
}
|
||||
|
||||
func processDatiImmobile(tmp *typedefs.AnnuncioParsed, annuncio *typedefs.AnnuncioXML) {
|
||||
tmpanno := GetStringValue(annuncio.Anno)
|
||||
tmpanno := utils.GetStringValue(annuncio.Anno)
|
||||
if tmpanno != "0" && tmpanno != "" {
|
||||
tmp.Anno = &tmpanno
|
||||
}
|
||||
|
||||
tmp.Prezzo = prezzoParse(annuncio.Prezzo)
|
||||
tmp.Prezzo = parser.ParsePrezzo(annuncio.Prezzo)
|
||||
tmp.Classe = annuncio.Classe
|
||||
if annuncio.Mq != nil {
|
||||
replaced := strings.ReplaceAll(*annuncio.Mq, ",", "")
|
||||
|
|
@ -420,7 +383,7 @@ func downloadImage(url, filename string) {
|
|||
}
|
||||
|
||||
func processWebpImages(path string) {
|
||||
array, err := GetPathsArray(path)
|
||||
array, err := utils.GetPathsArray(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
|
@ -442,7 +405,7 @@ func processWebpImages(path string) {
|
|||
}
|
||||
|
||||
func folderCleanup(codice string) error {
|
||||
folders := GetPathDirsArray(filepath.Join(imgbasepath, codice))
|
||||
folders := utils.GetPathDirsArray(filepath.Join(imgbasepath, codice))
|
||||
non_webp := []string{}
|
||||
for _, folder := range folders {
|
||||
folderpath := filepath.Join(imgbasepath, codice, folder)
|
||||
|
|
@ -490,130 +453,3 @@ func parseCaratteristiche(wrkrecord *typedefs.AnnuncioXML) map[string]interface{
|
|||
}
|
||||
return tmpCaratteristiche
|
||||
}
|
||||
|
||||
var mesiMapping = map[int]string{
|
||||
1: "Gennaio",
|
||||
2: "Febbraio",
|
||||
3: "Marzo",
|
||||
4: "Aprile",
|
||||
5: "Maggio",
|
||||
6: "Giugno",
|
||||
7: "Luglio",
|
||||
8: "Agosto",
|
||||
9: "Settembre",
|
||||
10: "Ottobre",
|
||||
11: "Novembre",
|
||||
12: "Dicembre",
|
||||
}
|
||||
|
||||
func parseConsegna(original *string) *int {
|
||||
currentMonth := int(time.Now().Month())
|
||||
if original == nil {
|
||||
return nil
|
||||
}
|
||||
if *original == "Libero" {
|
||||
return ¤tMonth
|
||||
} else {
|
||||
for k, v := range mesiMapping {
|
||||
if *original == v {
|
||||
return &k
|
||||
}
|
||||
}
|
||||
}
|
||||
return ¤tMonth
|
||||
}
|
||||
|
||||
func ParseDettaglio(dettaglio string) (disp_time *string, perm_arr *[]int, persone_arr *[]string, err error) {
|
||||
|
||||
dettaglio = strings.TrimSpace(dettaglio)
|
||||
if dettaglio == "" {
|
||||
return
|
||||
}
|
||||
|
||||
disp := getKeyValueUpToXorWhitespace(dettaglio, "disp:", "perm:")
|
||||
|
||||
perm := getKeyValueUpToXorWhitespace(dettaglio, "perm:", "persone:")
|
||||
|
||||
persone := getKeyValueUpToXorWhitespace(dettaglio, "persone:", "")
|
||||
|
||||
if disp != "" {
|
||||
// Validate date format
|
||||
_, err := time.Parse("02/01", disp)
|
||||
if err != nil {
|
||||
disp_time = nil
|
||||
} else {
|
||||
p := fmt.Sprintf("%s/%d", disp, time.Now().Year())
|
||||
disp_time = &p
|
||||
}
|
||||
}
|
||||
if perm != "" {
|
||||
parts := strings.Split(perm, "-")
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
num, err := strconv.Atoi(part)
|
||||
if err == nil {
|
||||
if perm_arr == nil {
|
||||
perm_arr = &[]int{}
|
||||
}
|
||||
*perm_arr = append(*perm_arr, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if persone != "" {
|
||||
parts := strings.Split(persone, "/")
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
if persone_arr == nil {
|
||||
persone_arr = &[]string{}
|
||||
}
|
||||
*persone_arr = append(*persone_arr, part)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func getKeyValueUpToXorWhitespace(input, key, stopstring string) string {
|
||||
input = strings.TrimSpace(input)
|
||||
i := strings.Index(input, key)
|
||||
if i == -1 {
|
||||
return ""
|
||||
}
|
||||
start := i + len(key)
|
||||
rest := strings.TrimSpace(input[start:])
|
||||
|
||||
// Find stopstring, whitespace, or repeated key
|
||||
stop_pos := len(rest)
|
||||
stops := []int{}
|
||||
|
||||
if stopstring != "" {
|
||||
if j := strings.Index(rest, stopstring); j != -1 {
|
||||
stops = append(stops, j)
|
||||
}
|
||||
}
|
||||
// Find whitespace
|
||||
if ws := strings.IndexAny(rest, " \n\r\t"); ws != -1 {
|
||||
stops = append(stops, ws)
|
||||
}
|
||||
// Find repeated key
|
||||
if k := strings.Index(rest, key); k != -1 {
|
||||
stops = append(stops, k)
|
||||
}
|
||||
// Use the earliest stop
|
||||
for _, s := range stops {
|
||||
if s < stop_pos {
|
||||
stop_pos = s
|
||||
}
|
||||
}
|
||||
|
||||
val := strings.TrimSpace(rest[:stop_pos])
|
||||
// Only take the first token before any whitespace or another key
|
||||
if idx := strings.IndexAny(val, " \n\r\t"); idx != -1 {
|
||||
val = val[:idx]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,208 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ptr[T any](v T) *T { return &v }
|
||||
|
||||
func TestParseDettaglio(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
wantDisp *string
|
||||
wantPerm *[]int
|
||||
wantPers *[]string
|
||||
}{
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp: perm: persone:",
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: perm:3-6 persone:single", // disp missing
|
||||
wantDisp: nil,
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm: persone:single", // perm missing
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: nil,
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:", // persone missing
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: perm: persone:", // all fields missing
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp:bad_date perm:3-6 persone:single", // invalid date
|
||||
wantDisp: nil,
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:abc-6 persone:single", // non-numeric perm
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3- persone:single", // trailing delimiter in perm
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:-6 persone:single", // leading delimiter in perm
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single/", // trailing delimiter in persone
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:/single", // leading delimiter in persone
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single//coppia", // double delimiter in persone
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single", "coppia"}),
|
||||
},
|
||||
{
|
||||
input: "perm:3-6 persone:single", // disp missing
|
||||
wantDisp: nil,
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6", // persone missing
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm: persone:", // perm empty
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "", // completely empty string
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: 01/10 perm: 3-6 persone: single ",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "persone:single perm:3-6 disp:01/10",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3--6 persone:single",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10\tperm:3-6\tpersone:single",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single/coppia!",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single", "coppia!"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 disp:02/11 perm:3-6 persone:single",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())), // Only first disp: is parsed
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10perm:3-6persone:single",
|
||||
wantDisp: ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: ptr([]int{3, 6}),
|
||||
wantPers: ptr([]string{"single"}),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
disp_time, perm_arr, persone_arr, _ := ParseDettaglio(tt.input)
|
||||
|
||||
//Handle *string comparison, including nil
|
||||
if tt.wantDisp != nil {
|
||||
if disp_time == nil {
|
||||
t.Errorf("disp_time: got nil, want %v, input: %v", *tt.wantDisp, tt.input)
|
||||
} else if *disp_time != *tt.wantDisp {
|
||||
t.Errorf("disp_time: got %v, want %v, input: %v", *disp_time, *tt.wantDisp, tt.input)
|
||||
}
|
||||
} else if disp_time != nil {
|
||||
t.Errorf("disp_time: got %v, want nil, input: %v", *disp_time, tt.input)
|
||||
}
|
||||
|
||||
// Handle *[]int comparison, including nil
|
||||
if tt.wantPerm != nil {
|
||||
if perm_arr == nil || len(*perm_arr) != len(*tt.wantPerm) {
|
||||
t.Errorf("perm_arr: got %v, want %v, input: %v", perm_arr, *tt.wantPerm, tt.input)
|
||||
} else {
|
||||
for i := range *perm_arr {
|
||||
if (*perm_arr)[i] != (*tt.wantPerm)[i] {
|
||||
t.Errorf("perm_arr[%d]: got %v, want %v, input: %v", i, (*perm_arr)[i], (*tt.wantPerm)[i], tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if perm_arr != nil && len(*perm_arr) != 0 {
|
||||
t.Errorf("perm_arr: got %v, want nil, input: %v", perm_arr, tt.input)
|
||||
}
|
||||
|
||||
// Handle *[]string comparison, including nil
|
||||
if tt.wantPers != nil {
|
||||
if persone_arr == nil || len(*persone_arr) != len(*tt.wantPers) {
|
||||
t.Errorf("persone_arr: got %v, want %v, input: %v", persone_arr, *tt.wantPers, tt.input)
|
||||
} else {
|
||||
for i := range *persone_arr {
|
||||
if (*persone_arr)[i] != (*tt.wantPers)[i] {
|
||||
t.Errorf("persone_arr[%d]: got %v, want %v, input: %v", i, (*persone_arr)[i], (*tt.wantPers)[i], tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if persone_arr != nil && len(*persone_arr) != 0 {
|
||||
t.Errorf("persone_arr: got %v, want nil, input: %v", persone_arr, tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
187
apps/backend/parser/parser.go
Normal file
187
apps/backend/parser/parser.go
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
package parser
|
||||
|
||||
import (
|
||||
"backend/utils"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ParseDettaglio(dettaglio string) (disp_time *string, perm_arr *[]int, persone_arr *[]string, err error) {
|
||||
|
||||
dettaglio = strings.TrimSpace(dettaglio)
|
||||
if dettaglio == "" {
|
||||
return
|
||||
}
|
||||
|
||||
disp := getKeyValueUpToXorWhitespace(dettaglio, "disp:", "perm:")
|
||||
|
||||
perm := getKeyValueUpToXorWhitespace(dettaglio, "perm:", "persone:")
|
||||
|
||||
persone := getKeyValueUpToXorWhitespace(dettaglio, "persone:", "")
|
||||
|
||||
if disp != "" {
|
||||
// Validate date format
|
||||
_, err := time.Parse("02/01", disp)
|
||||
if err != nil {
|
||||
disp_time = nil
|
||||
} else {
|
||||
p := fmt.Sprintf("%s/%d", disp, time.Now().Year())
|
||||
disp_time = &p
|
||||
}
|
||||
}
|
||||
if perm != "" {
|
||||
parts := strings.Split(perm, "-")
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
num, err := strconv.Atoi(part)
|
||||
if err == nil {
|
||||
if perm_arr == nil {
|
||||
perm_arr = &[]int{}
|
||||
}
|
||||
*perm_arr = append(*perm_arr, num)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if persone != "" {
|
||||
parts := strings.Split(persone, "/")
|
||||
for _, part := range parts {
|
||||
part = strings.TrimSpace(part)
|
||||
if part != "" {
|
||||
if persone_arr == nil {
|
||||
persone_arr = &[]string{}
|
||||
}
|
||||
*persone_arr = append(*persone_arr, part)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
func getKeyValueUpToXorWhitespace(input, key, stopstring string) string {
|
||||
input = strings.TrimSpace(input)
|
||||
i := strings.Index(input, key)
|
||||
if i == -1 {
|
||||
return ""
|
||||
}
|
||||
start := i + len(key)
|
||||
rest := strings.TrimSpace(input[start:])
|
||||
|
||||
// Find stopstring, whitespace, or repeated key
|
||||
stop_pos := len(rest)
|
||||
stops := []int{}
|
||||
|
||||
if stopstring != "" {
|
||||
if j := strings.Index(rest, stopstring); j != -1 {
|
||||
stops = append(stops, j)
|
||||
}
|
||||
}
|
||||
// Find whitespace
|
||||
if ws := strings.IndexAny(rest, " \n\r\t"); ws != -1 {
|
||||
stops = append(stops, ws)
|
||||
}
|
||||
// Find repeated key
|
||||
if k := strings.Index(rest, key); k != -1 {
|
||||
stops = append(stops, k)
|
||||
}
|
||||
// Use the earliest stop
|
||||
for _, s := range stops {
|
||||
if s < stop_pos {
|
||||
stop_pos = s
|
||||
}
|
||||
}
|
||||
|
||||
val := strings.TrimSpace(rest[:stop_pos])
|
||||
// Only take the first token before any whitespace or another key
|
||||
if idx := strings.IndexAny(val, " \n\r\t"); idx != -1 {
|
||||
val = val[:idx]
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
var mesiMapping = map[int]string{
|
||||
1: "Gennaio",
|
||||
2: "Febbraio",
|
||||
3: "Marzo",
|
||||
4: "Aprile",
|
||||
5: "Maggio",
|
||||
6: "Giugno",
|
||||
7: "Luglio",
|
||||
8: "Agosto",
|
||||
9: "Settembre",
|
||||
10: "Ottobre",
|
||||
11: "Novembre",
|
||||
12: "Dicembre",
|
||||
}
|
||||
|
||||
func ParseConsegna(original *string) *int {
|
||||
currentMonth := int(time.Now().Month())
|
||||
if original == nil {
|
||||
return nil
|
||||
}
|
||||
if *original == "Libero" {
|
||||
return ¤tMonth
|
||||
} else {
|
||||
for k, v := range mesiMapping {
|
||||
if *original == v {
|
||||
return &k
|
||||
}
|
||||
}
|
||||
}
|
||||
return ¤tMonth
|
||||
}
|
||||
|
||||
func ParsePrezzo(input *string) int {
|
||||
if input == nil || len(*input) == 0 {
|
||||
return 0
|
||||
}
|
||||
s := *input
|
||||
s = strings.ReplaceAll(s, "€", "")
|
||||
s = strings.ReplaceAll(s, " ", "")
|
||||
s = strings.ReplaceAll(s, ".", "")
|
||||
s = strings.ReplaceAll(s, ",", ".")
|
||||
re := regexp.MustCompile(`\d+(\.\d+)?`)
|
||||
match := re.FindString(s)
|
||||
if match == "" {
|
||||
return 0
|
||||
}
|
||||
f, err := strconv.ParseFloat(match, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return int(f * 100)
|
||||
}
|
||||
|
||||
func ParseTipologia(t1, t2 *string) (tipo *string) {
|
||||
|
||||
if t1 == nil {
|
||||
return utils.Ptr("Errore")
|
||||
}
|
||||
|
||||
if *t1 == "V" {
|
||||
return utils.Ptr("Vendita")
|
||||
}
|
||||
|
||||
if *t1 == "I" {
|
||||
return utils.Ptr("Cessione")
|
||||
}
|
||||
|
||||
if *t1 == "A" {
|
||||
if t2 != nil {
|
||||
normalized := strings.TrimSpace(*t2)
|
||||
normalized = strings.ToLower(normalized)
|
||||
switch normalized {
|
||||
case "residenziale", "turistico", "stanza":
|
||||
return utils.Ptr("Transitorio")
|
||||
}
|
||||
}
|
||||
return utils.Ptr("Stabile")
|
||||
}
|
||||
return utils.Ptr("Errore")
|
||||
|
||||
}
|
||||
418
apps/backend/parser/parser_test.go
Normal file
418
apps/backend/parser/parser_test.go
Normal file
|
|
@ -0,0 +1,418 @@
|
|||
package parser_test
|
||||
|
||||
import (
|
||||
"backend/parser"
|
||||
"backend/utils"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestParseDettaglio(t *testing.T) {
|
||||
tests := []struct {
|
||||
input string
|
||||
wantDisp *string
|
||||
wantPerm *[]int
|
||||
wantPers *[]string
|
||||
}{
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp: perm: persone:",
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: perm:3-6 persone:single", // disp missing
|
||||
wantDisp: nil,
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm: persone:single", // perm missing
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: nil,
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:", // persone missing
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: perm: persone:", // all fields missing
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp:bad_date perm:3-6 persone:single", // invalid date
|
||||
wantDisp: nil,
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:abc-6 persone:single", // non-numeric perm
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3- persone:single", // trailing delimiter in perm
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:-6 persone:single", // leading delimiter in perm
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single/", // trailing delimiter in persone
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:/single", // leading delimiter in persone
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single//coppia", // double delimiter in persone
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single", "coppia"}),
|
||||
},
|
||||
{
|
||||
input: "perm:3-6 persone:single", // disp missing
|
||||
wantDisp: nil,
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6", // persone missing
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm: persone:", // perm empty
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "", // completely empty string
|
||||
wantDisp: nil,
|
||||
wantPerm: nil,
|
||||
wantPers: nil,
|
||||
},
|
||||
{
|
||||
input: "disp: 01/10 perm: 3-6 persone: single ",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "persone:single perm:3-6 disp:01/10",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3--6 persone:single",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10\tperm:3-6\tpersone:single",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 perm:3-6 persone:single/coppia!",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single", "coppia!"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10 disp:02/11 perm:3-6 persone:single",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())), // Only first disp: is parsed
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
{
|
||||
input: "disp:01/10perm:3-6persone:single",
|
||||
wantDisp: utils.Ptr(fmt.Sprintf("01/10/%d", time.Now().Year())),
|
||||
wantPerm: utils.Ptr([]int{3, 6}),
|
||||
wantPers: utils.Ptr([]string{"single"}),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
disp_time, perm_arr, persone_arr, _ := parser.ParseDettaglio(tt.input)
|
||||
|
||||
//Handle *string comparison, including nil
|
||||
if tt.wantDisp != nil {
|
||||
if disp_time == nil {
|
||||
t.Errorf("disp_time: got nil, want %v, input: %v", *tt.wantDisp, tt.input)
|
||||
} else if *disp_time != *tt.wantDisp {
|
||||
t.Errorf("disp_time: got %v, want %v, input: %v", *disp_time, *tt.wantDisp, tt.input)
|
||||
}
|
||||
} else if disp_time != nil {
|
||||
t.Errorf("disp_time: got %v, want nil, input: %v", *disp_time, tt.input)
|
||||
}
|
||||
|
||||
// Handle *[]int comparison, including nil
|
||||
if tt.wantPerm != nil {
|
||||
if perm_arr == nil || len(*perm_arr) != len(*tt.wantPerm) {
|
||||
t.Errorf("perm_arr: got %v, want %v, input: %v", perm_arr, *tt.wantPerm, tt.input)
|
||||
} else {
|
||||
for i := range *perm_arr {
|
||||
if (*perm_arr)[i] != (*tt.wantPerm)[i] {
|
||||
t.Errorf("perm_arr[%d]: got %v, want %v, input: %v", i, (*perm_arr)[i], (*tt.wantPerm)[i], tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if perm_arr != nil && len(*perm_arr) != 0 {
|
||||
t.Errorf("perm_arr: got %v, want nil, input: %v", perm_arr, tt.input)
|
||||
}
|
||||
|
||||
// Handle *[]string comparison, including nil
|
||||
if tt.wantPers != nil {
|
||||
if persone_arr == nil || len(*persone_arr) != len(*tt.wantPers) {
|
||||
t.Errorf("persone_arr: got %v, want %v, input: %v", persone_arr, *tt.wantPers, tt.input)
|
||||
} else {
|
||||
for i := range *persone_arr {
|
||||
if (*persone_arr)[i] != (*tt.wantPers)[i] {
|
||||
t.Errorf("persone_arr[%d]: got %v, want %v, input: %v", i, (*persone_arr)[i], (*tt.wantPers)[i], tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if persone_arr != nil && len(*persone_arr) != 0 {
|
||||
t.Errorf("persone_arr: got %v, want nil, input: %v", persone_arr, tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseConsegna(t *testing.T) {
|
||||
tests := []struct {
|
||||
input *string
|
||||
wantConsegna *int
|
||||
}{
|
||||
// Test all Italian month names
|
||||
{
|
||||
input: utils.Ptr("Gennaio"),
|
||||
wantConsegna: utils.Ptr(1),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Febbraio"),
|
||||
wantConsegna: utils.Ptr(2),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Marzo"),
|
||||
wantConsegna: utils.Ptr(3),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Aprile"),
|
||||
wantConsegna: utils.Ptr(4),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Maggio"),
|
||||
wantConsegna: utils.Ptr(5),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Giugno"),
|
||||
wantConsegna: utils.Ptr(6),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Luglio"),
|
||||
wantConsegna: utils.Ptr(7),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Agosto"),
|
||||
wantConsegna: utils.Ptr(8),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Settembre"),
|
||||
wantConsegna: utils.Ptr(9),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Ottobre"),
|
||||
wantConsegna: utils.Ptr(10),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Novembre"),
|
||||
wantConsegna: utils.Ptr(11),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Dicembre"),
|
||||
wantConsegna: utils.Ptr(12),
|
||||
},
|
||||
// Test "Libero" (should return current month)
|
||||
{
|
||||
input: utils.Ptr("Libero"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test nil input
|
||||
{
|
||||
input: nil,
|
||||
wantConsegna: nil,
|
||||
},
|
||||
// Test empty string
|
||||
{
|
||||
input: utils.Ptr(""),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test lowercase (should return current month as default)
|
||||
{
|
||||
input: utils.Ptr("gennaio"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test with spaces
|
||||
{
|
||||
input: utils.Ptr("Gennaio "),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr(" Gennaio"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test with special characters
|
||||
{
|
||||
input: utils.Ptr("Gennaio!"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test abbreviated forms
|
||||
{
|
||||
input: utils.Ptr("Gen"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
{
|
||||
input: utils.Ptr("Feb"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test English month names
|
||||
{
|
||||
input: utils.Ptr("January"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test numeric strings
|
||||
{
|
||||
input: utils.Ptr("1"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test mixed cases
|
||||
{
|
||||
input: utils.Ptr("GEnNaIo"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
// Test completely unrelated strings
|
||||
{
|
||||
input: utils.Ptr("NotAMonth"),
|
||||
wantConsegna: utils.Ptr(int(time.Now().Month())),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
gotConsegna := parser.ParseConsegna(tt.input)
|
||||
|
||||
if tt.wantConsegna != nil {
|
||||
if gotConsegna == nil {
|
||||
t.Errorf("got nil, want %v, input: %v", *tt.wantConsegna, tt.input)
|
||||
} else if *gotConsegna != *tt.wantConsegna {
|
||||
t.Errorf("got %v, want %v, input: %v", *gotConsegna, *tt.wantConsegna, tt.input)
|
||||
}
|
||||
} else if gotConsegna != nil {
|
||||
t.Errorf("got %v, want nil, input: %v", *gotConsegna, tt.input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParsePrezzo(t *testing.T) {
|
||||
tests := []struct {
|
||||
input *string
|
||||
want int
|
||||
}{
|
||||
{input: utils.Ptr("100"), want: 10000},
|
||||
{input: utils.Ptr("€ 100"), want: 10000},
|
||||
{input: utils.Ptr("100€"), want: 10000},
|
||||
{input: utils.Ptr("€100"), want: 10000},
|
||||
{input: utils.Ptr("100 €"), want: 10000},
|
||||
{input: utils.Ptr("€ 100,50"), want: 10050},
|
||||
{input: utils.Ptr("100,50€"), want: 10050},
|
||||
{input: utils.Ptr("€100,50"), want: 10050},
|
||||
{input: utils.Ptr("100,50 €"), want: 10050},
|
||||
{input: utils.Ptr("€ 1.000"), want: 100000},
|
||||
{input: utils.Ptr("1.000€"), want: 100000},
|
||||
{input: utils.Ptr("€1.000"), want: 100000},
|
||||
{input: utils.Ptr("1.000 €"), want: 100000},
|
||||
{input: utils.Ptr("€ 1.000,50"), want: 100050},
|
||||
{input: utils.Ptr("1.000,50€"), want: 100050},
|
||||
{input: utils.Ptr("€1.000,50"), want: 100050},
|
||||
{input: utils.Ptr("1.000,50 €"), want: 100050},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := parser.ParsePrezzo(tt.input)
|
||||
|
||||
if got != tt.want {
|
||||
inputStr := ""
|
||||
if tt.input != nil {
|
||||
inputStr = *tt.input
|
||||
}
|
||||
t.Errorf("got %v, want %v, input: %v", got, tt.want, inputStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessTipologia(t *testing.T) {
|
||||
tests := []struct {
|
||||
t1, t2 *string
|
||||
want *string
|
||||
}{
|
||||
{t1: utils.Ptr("V"), want: utils.Ptr("Vendita")},
|
||||
{t1: utils.Ptr("I"), want: utils.Ptr("Cessione")},
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("Residenziale"), want: utils.Ptr("Transitorio")},
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("Turistico"), want: utils.Ptr("Transitorio")},
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("Stanza"), want: utils.Ptr("Transitorio")},
|
||||
{t1: utils.Ptr("A"), t2: nil, want: utils.Ptr("Stabile")},
|
||||
{t1: nil, want: utils.Ptr("Errore")},
|
||||
// Unknown t1 value
|
||||
{t1: utils.Ptr("X"), want: utils.Ptr("Errore")},
|
||||
// Lowercase t1 value
|
||||
{t1: utils.Ptr("v"), want: utils.Ptr("Errore")},
|
||||
// t1 is empty string
|
||||
{t1: utils.Ptr(""), want: utils.Ptr("Errore")},
|
||||
// t2 is empty string with t1 == "A"
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr(""), want: utils.Ptr("Stabile")},
|
||||
// t2 is unknown value with t1 == "A"
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("Commerciale"), want: utils.Ptr("Stabile")},
|
||||
// t2 is lowercase valid value with t1 == "A"
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("residenziale"), want: utils.Ptr("Transitorio")},
|
||||
// t2 is uppercase valid value with t1 == "A"
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr("RESIDENZIALE"), want: utils.Ptr("Transitorio")},
|
||||
// t2 is "Stanza" with extra spaces
|
||||
{t1: utils.Ptr("A"), t2: utils.Ptr(" Stanza "), want: utils.Ptr("Transitorio")},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
got := parser.ParseTipologia(tt.t1, tt.t2)
|
||||
|
||||
if got == nil || *got != *tt.want {
|
||||
t.Errorf("got %v, want %v, input t1: %v, t2: %v", *got, *tt.want, *tt.t1, *tt.t2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func MakeUppercase(s string) string {
|
||||
if s != "" && reflect.TypeOf(s).Kind() == reflect.String && len(s) > 0 {
|
||||
return strings.ToUpper(string(s[0])) + s[1:]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func CheckStringIfPresent(value *string) string {
|
||||
if value != nil {
|
||||
return strings.TrimSpace(*value)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func CheckStringIfPresentBool(value string) bool {
|
||||
if value != "" {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func fetchXML(url string) ([]byte, error) {
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return []byte{}, fmt.Errorf("GET error: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return []byte{}, fmt.Errorf("status error: %v", resp.StatusCode)
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return []byte{}, fmt.Errorf("read body: %v", err)
|
||||
}
|
||||
|
||||
return data, nil
|
||||
}
|
||||
|
||||
func GetDataXML[T any](url string) T {
|
||||
xmlBytes, err := fetchXML(url)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get XML: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
var result T
|
||||
err = xml.Unmarshal(xmlBytes, &result)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to unmarshal XML: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func GetPathsArray(path string) ([]string, error) {
|
||||
var paths []string
|
||||
|
||||
err := filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
func GetPathDirsArray(path string) []string {
|
||||
var folderNames []string
|
||||
files, err := os.ReadDir(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if file.IsDir() {
|
||||
folderNames = append(folderNames, file.Name())
|
||||
}
|
||||
}
|
||||
return folderNames
|
||||
}
|
||||
|
||||
func GetStringValue(strPtr *string) string {
|
||||
if strPtr != nil {
|
||||
return *strPtr
|
||||
}
|
||||
return ""
|
||||
}
|
||||
func RemoveWhitespace(str string) string {
|
||||
return strings.ReplaceAll(str, " ", "")
|
||||
}
|
||||
|
||||
func CommaToDot(str *string) *string {
|
||||
if str != nil {
|
||||
result := strings.ReplaceAll(*str, ",", ".")
|
||||
return &result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue