Пример #1
0
def læs_lokation(lokation: str) -> GeometriObjekt:
    """Skab GeometriObjekt ud fra en brugerangivet lokationskoordinat"""

    lok = lokation.split()
    assert len(lok) in (
        2,
        4,
    ), f"Lokation '{lokation}' matcher ikke format: 55.443322 [N] 12.345678 [Ø]."
    if len(lok) == 2:
        lok = [lok[0], "", lok[1], ""]
    try:
        e = float(lok[2].replace(",", "."))
        n = float(lok[0].replace(",", "."))
    except ValueError as ex:
        fire.cli.print(
            f"Ikke-numerisk lokationskoordinat anført: {lokation} ({ex})")
        sys.exit(1)

    # Håndter verdenshjørner Nn/ØøEe/VvWw/Ss
    if lok[3].upper() in ("S", "N"):
        lok = [lok[2], lok[3], lok[0], lok[1]]
    if lok[1].upper() == "S":
        n = -n
    if lok[3].upper() in ("W", "V"):
        e = -e

    # Håndter UTM zone 32 og geografiske koordinater ensartet
    e, n = normaliser_lokationskoordinat(e, n)

    go = GeometriObjekt()
    go.geometri = Point([e, n])
    return go
Пример #2
0
def test_punkt_geometri():
    p = Punkt()
    go = GeometriObjekt()
    go.geometri = Point([1, 2])
    p.geometriobjekter.append(go)
    assert p.geometri.koordinater[0] == 1
    assert p.geometri.koordinater[1] == 2
Пример #3
0
def test_indset_punkt_with_invalid_sagsevent_eventtype(firedb: FireDb,
                                                       sag: Sag):
    p = Punkt()
    go = GeometriObjekt()
    go.geometri = Point([1, 1])
    p.geometriobjekter.append(go)
    with pytest.raises(Exception, match="KOMMENTAR"):
        firedb.indset_punkt(Sagsevent(sag=sag, eventtype=EventType.KOMMENTAR),
                            p)
Пример #4
0
def test_indset_punkt(firedb: FireDb, sag: Sag):
    p = Punkt()
    go = GeometriObjekt()
    go.geometri = Point([1, 1])
    p.geometriobjekter.append(go)

    firedb.indset_sagsevent(
        Sagsevent(
            sag=sag,
            sagseventinfos=[
                SagseventInfo(beskrivelse="Testindsættelse af et punkt")
            ],
            eventtype=EventType.PUNKT_OPRETTET,
            punkter=[p],
        ))
Пример #5
0
def test_unit_tilknyt_landsnumre_fejl_punkttyper_exceptions(dummydb, mocker):
    """
    Test at der er smides en exception ved ugyldige FikspunktsTyper.
    """
    pktid = fire.uuid()

    pit_landsnr = PunktInformationType(name="IDENT:landsnr")
    mocker.patch("fire.api.FireDb.hent_punktinformationtype",
                 return_value=pit_landsnr)
    mocker.patch("fire.api.FireDb._opmålingsdistrikt_fra_punktid",
                 return_value=[("K-63", pktid)])
    mocker.patch(
        "fire.api.FireDb._løbenumre_i_distrikt",
        return_value=[str(i).zfill(5) for i in range(1, 9)],
    )

    punkter = [
        Punkt(
            id=pktid,
            geometriobjekter=[GeometriObjekt(geometri=Point((56.15, 10.20)))])
    ]
    fikspunktstyper = [FikspunktsType.VANDSTANDSBRÆT]

    with pytest.raises(NotImplementedError):
        dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)

    fikspunktstyper = ["IKKE_EN_FIKSPUNKSTYPE"]
    with pytest.raises(ValueError):
        dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)
Пример #6
0
def test_unit_tilknyt_landsnumre_har_landsnr(dummydb, mocker):
    """
    Test at punkter der allerede har et landsnummer frasorteres.
    """

    pktid = fire.uuid()

    pit_landsnr = PunktInformationType(name="IDENT:landsnr")
    mocker.patch("fire.api.FireDb.hent_punktinformationtype",
                 return_value=pit_landsnr)
    mocker.patch("fire.api.FireDb._opmålingsdistrikt_fra_punktid",
                 return_value=[("K-63", pktid)])
    mocker.patch(
        "fire.api.FireDb._løbenumre_i_distrikt",
        return_value=[str(i).zfill(5) for i in range(1, 9)],
    )

    punkter = [
        Punkt(
            id=pktid,
            geometriobjekter=[GeometriObjekt(geometri=Point((56.15, 10.20)))],
            punktinformationer=[
                PunktInformation(infotype=pit_landsnr, tekst="K-63-00001")
            ],
        )
    ]
    fikspunktstyper = [FikspunktsType.GI]
    landsnumre = dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)

    assert len(landsnumre) == 0
Пример #7
0
def test_unit_tilknyt_landsnumre_flere_typer(dummydb, mocker):
    """
    Test løbenummerudvælgelse for flere typer fikspunktpunkter i samme kald.
    """

    punkt_ider = [fire.uuid() for _ in range(5)]

    se = (("K-63", pid) for pid in punkt_ider)
    mocker.patch(
        "fire.api.FireDb.hent_punktinformationtype",
        return_value=PunktInformationType(name="IDENT:landsnr"),
    )
    mocker.patch("fire.api.FireDb._opmålingsdistrikt_fra_punktid",
                 return_value=se)
    mocker.patch(
        "fire.api.FireDb._løbenumre_i_distrikt",
        return_value=[],
    )

    punkter = [
        Punkt(
            id=pktid,
            geometriobjekter=[GeometriObjekt(geometri=Point((56.15, 10.20)))])
        for pktid in punkt_ider
    ]

    fikspunktstyper = [
        FikspunktsType.GI,
        FikspunktsType.MV,
        FikspunktsType.HØJDE,
        FikspunktsType.JESSEN,
        FikspunktsType.HJÆLPEPUNKT,
    ]

    print(fikspunktstyper)
    print(punkter)
    landsnumre = dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)

    assert len(landsnumre) == 5

    forventede_landsnumre = [
        "K-63-00001",
        "K-63-00011",
        "K-63-09001",
        "K-63-81001",
        "K-63-90001",
    ]

    for landsnr, forventet in zip(landsnumre, forventede_landsnumre):
        assert landsnr.tekst == forventet
Пример #8
0
def test_unit_tilknyt_landsnumre_gi(dummydb, mocker):
    """
    Test løbenummerudvælgelse for GI-punkter hvor der er løbenumrene
    befinder sig i to intervaller. Specifikt testes om overgangen fra
    det første interval til det andet forløber som det skal.
    """

    punkt_ider = [fire.uuid() for _ in range(4)]

    se = (("K-63", pid) for pid in punkt_ider)
    mocker.patch(
        "fire.api.FireDb.hent_punktinformationtype",
        return_value=PunktInformationType(name="IDENT:landsnr"),
    )
    mocker.patch("fire.api.FireDb._opmålingsdistrikt_fra_punktid",
                 return_value=se)
    mocker.patch(
        "fire.api.FireDb._løbenumre_i_distrikt",
        return_value=[str(i).zfill(5) for i in range(1, 9)],
    )

    punkter = [
        Punkt(
            id=pktid,
            geometriobjekter=[GeometriObjekt(geometri=Point((56.15, 10.20)))])
        for pktid in punkt_ider
    ]

    fikspunktstyper = [
        FikspunktsType.GI,
        FikspunktsType.GI,
        FikspunktsType.GI,
        FikspunktsType.GI,
    ]

    print(fikspunktstyper)
    print(punkter)
    landsnumre = dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)

    assert len(landsnumre) == 4

    forventede_landsnumre = [
        "K-63-00009",
        "K-63-00010",
        "K-63-00801",
        "K-63-00802",
    ]

    for landsnr, forventet in zip(landsnumre, forventede_landsnumre):
        assert landsnr.tekst == forventet
Пример #9
0
def test_geometriobjekt_afregistrering(firedb: FireDb, sag: Sag):
    """
    Test at forudgående geometrier afregistreres korrekt ved indsættelse af ny.
    """

    p = firedb.hent_punkt("SKEJ")
    n = len(p.geometriobjekter)
    go = GeometriObjekt()
    go.geometri = Point([10.17983, 56.18759])
    go.punkt = p

    firedb.indset_sagsevent(
        Sagsevent(
            sag=sag,
            sagseventinfos=[SagseventInfo(beskrivelse="Opdater geometri")],
            eventtype=EventType.PUNKT_OPRETTET,
            geometriobjekter=[go],
        ))

    geom = p.geometriobjekter
    assert n + 1 == len(p.geometriobjekter)
    assert geom[-2].registreringtil == geom[-1].registreringfra
    assert geom[-2].sagseventtilid == geom[-1].sagseventfraid
Пример #10
0
def test_luk_punkt(
    firedb: FireDb,
    punkt: Punkt,
    sagsevent: Sagsevent,
    observationer: List[Observation],
    koordinat: Koordinat,
    punktinformationtype: PunktInformationType,
):
    # byg et punkt der har tilknyttet geometri, koordinat,
    # punktinfo og observationer
    geometri = GeometriObjekt(punkt=punkt,
                              geometri=Point([10, 55]),
                              sagsevent=sagsevent)
    firedb.session.add(geometri)
    observationer[0].opstillingspunkt = punkt
    observationer[1].sigtepunkt = punkt
    koordinat.punkt = punkt
    punkt.punktinformationer = [
        PunktInformation(infotype=punktinformationtype, sagsevent=sagsevent)
    ]
    firedb.session.commit()

    firedb.luk_punkt(punkt, sagsevent)
    assert punkt.registreringtil is not None
    assert punkt.sagsevent.eventtype == EventType.PUNKT_NEDLAGT
    assert punkt.sagseventtilid == sagsevent.id
    assert geometri.registreringtil is not None
    assert geometri.sagsevent.eventtype == EventType.PUNKT_NEDLAGT

    for koordinat in punkt.koordinater:
        assert koordinat.registreringtil is not None
        assert koordinat.sagsevent.eventtype == EventType.PUNKT_NEDLAGT
        assert koordinat.sagseventtilid == sagsevent.id

    for punktinfo in punkt.punktinformationer:
        assert punktinfo.registreringtil is not None
        assert punktinfo.sagsevent.eventtype == EventType.PUNKT_NEDLAGT
        assert punktinfo.sagseventtilid == sagsevent.id

    for observation in chain(punkt.observationer_fra, punkt.observationer_til):
        assert observation.registreringtil is not None
        assert observation.sagsevent.eventtype == EventType.PUNKT_NEDLAGT
        assert observation.sagseventtilid == sagsevent.id

    with pytest.raises(TypeError):
        firedb.luk_punkt(999)
Пример #11
0
def test_unit_tilknyt_landsnumre(dummydb, mocker):
    """
    Test at løbenumre tildeles korrekt med afsæt i allerede tildelte
    løbenumre.
    """
    punkt_ider = [fire.uuid() for _ in range(3)]

    se = (("K-63", pid) for pid in punkt_ider)
    mocker.patch(
        "fire.api.FireDb.hent_punktinformationtype",
        return_value=PunktInformationType(name="IDENT:landsnr"),
    )
    mocker.patch("fire.api.FireDb._opmålingsdistrikt_fra_punktid",
                 return_value=se)
    mocker.patch(
        "fire.api.FireDb._løbenumre_i_distrikt",
        return_value=["09001", "09002", "09003"],
    )

    punkter = [
        Punkt(
            id=pktid,
            geometriobjekter=[GeometriObjekt(geometri=Point((56.15, 10.20)))])
        for pktid in punkt_ider
    ]

    fikspunktstyper = [
        FikspunktsType.HØJDE,
        FikspunktsType.HØJDE,
        FikspunktsType.HØJDE,
    ]

    print(fikspunktstyper)
    print(punkter)
    landsnumre = dummydb.tilknyt_landsnumre(punkter, fikspunktstyper)

    assert len(landsnumre) == 3

    for i, landsnummer in enumerate(landsnumre, 4):
        assert landsnummer.tekst == f"K-63-0900{i}"
Пример #12
0
def ilæg_nye_punkter(projektnavn: str, sagsbehandler: str, **kwargs) -> None:
    """Registrer nyoprettede punkter i databasen"""
    er_projekt_okay(projektnavn)
    sag = find_sag(projektnavn)
    sagsgang = find_sagsgang(projektnavn)

    fire.cli.print(f"Sags/projekt-navn: {projektnavn}  ({sag.id})")
    fire.cli.print(f"Sagsbehandler:     {sagsbehandler}")

    # Opbyg oversigt over nyetablerede punkter
    nyetablerede = find_faneblad(projektnavn, "Nyetablerede punkter",
                                 arkdef.NYETABLEREDE_PUNKTER)
    n = nyetablerede.shape[0]

    if n == 0:
        fire.cli.print("Ingen nyetablerede punkter at registrere")
        return

    landsnummer_pit = fire.cli.firedb.hent_punktinformationtype(
        "IDENT:landsnr")
    beskrivelse_pit = fire.cli.firedb.hent_punktinformationtype(
        "ATTR:beskrivelse")
    bemærkning_pit = fire.cli.firedb.hent_punktinformationtype(
        "ATTR:bemærkning")
    h_over_terræn_pit = fire.cli.firedb.hent_punktinformationtype(
        "AFM:højde_over_terræn")
    attr_gi_pit = fire.cli.firedb.hent_punktinformationtype("ATTR:GI_punkt")
    attr_mv_pit = fire.cli.firedb.hent_punktinformationtype("ATTR:MV_punkt")
    attr_højde_pit = fire.cli.firedb.hent_punktinformationtype(
        "ATTR:højdefikspunkt")
    attr_vandstand_pit = fire.cli.firedb.hent_punktinformationtype(
        "ATTR:vandstandsmåler")
    assert landsnummer_pit is not None, "IDENT:landsnr ikke fundet i database"
    assert beskrivelse_pit is not None, "ATTR:beskrivelse ikke fundet i database"
    assert bemærkning_pit is not None, "ATTR:bemærkning ikke fundet i database"
    assert h_over_terræn_pit is not None, "AFM:højde_over_terræn ikke fundet i database"
    assert attr_gi_pit is not None, "ATTR:GI_punkt ikke fundet i database"
    assert attr_mv_pit is not None, "ATTR:MV_punkt ikke fundet i database"
    assert attr_højde_pit is not None, "ATTR:højdefikspunkt ikke fundet i database"
    assert attr_vandstand_pit is not None, "ATTR:vandstandsmåler ikke fundet i database"

    punkter = {}
    fikspunktstyper = []
    punktinfo = []

    # Opret punkter
    fire.cli.print(f"Behandler punkter")
    # Index frasorterer automatisk blanke linjer og er dermed mere robust.
    # Bemærkes, at felter med usynlige tegn som mellemrum IKKE resulterer
    # i en tom linje og en sådan vil fremtvinge en fejl pga ugyldigt input
    for i in nyetablerede.index:
        # Et tomt tekstfelt kan repræsenteres på en del forskellige måder...
        # Punkter udstyret med uuid er allerede registrerede
        if str(nyetablerede.uuid[i]) not in ["", "None", "nan"]:
            continue

        lokation = normaliser_lokationskoordinat(nyetablerede["Øst"][i],
                                                 nyetablerede["Nord"][i], "DK")

        # Skab nyt punktobjekt
        punkter[i] = Punkt(
            id=uuid(),
            geometriobjekter=[GeometriObjekt(geometri=Point(lokation))],
        )

        try:
            fikspunktstype = FIKSPUNKTSYPER[nyetablerede["Fikspunktstype"]
                                            [i].upper()]
        except KeyError:
            fire.cli.print(
                f"FEJL: '{nyetablerede['Fikspunktstype'][i]}' er ikke en gyldig fikspunktsype! Vælg mellem GI, MV, HØJDE, JESSEN og VANDSTANDSBRÆT",
                bg="red",
                bold=True,
            )
            sys.exit(1)

        fikspunktstyper.append(fikspunktstype)

    # sagsevent for punkter
    er = "er" if len(punkter) > 1 else ""
    sagsevent_punkter = Sagsevent(
        sag=sag,
        eventtype=EventType.PUNKT_OPRETTET,
        sagseventinfos=[
            SagseventInfo(
                beskrivelse=f"Oprettelse af punkt{er} ifm. {projektnavn}", )
        ],
        punkter=list(punkter.values()),
    )
    fire.cli.firedb.indset_sagsevent(sagsevent_punkter, commit=False)
    fire.cli.firedb.session.flush()  # hvis noget ikke virker får vi fejl her!

    # Generer dokumentation til fanebladet "Sagsgang"
    sagsgangslinje = {
        "Dato": sagsevent_punkter.registreringfra,
        "Hvem": sagsbehandler,
        "Hændelse": "punktoprettelse",
        "Tekst": sagsevent_punkter.sagseventinfos[0].beskrivelse,
        "uuid": sagsevent_punkter.id,
    }
    sagsgang = sagsgang.append(sagsgangslinje, ignore_index=True)

    # Opret punktinfo
    fire.cli.print(f"Behandler punktinformationer")
    for i, punkt in punkter.items():
        # Tilføj punktets højde over terræn som punktinformation, hvis anført
        try:
            ΔH = float(nyetablerede["Højde over terræn"][i])
        except (TypeError, ValueError):
            ΔH = 0
        if math.isnan(ΔH):
            ΔH = 0.0
        if not pd.isna(nyetablerede["Højde over terræn"][i]):
            pi_h = PunktInformation(
                infotype=h_over_terræn_pit,
                punkt=punkt,
                tal=ΔH,
            )
            punktinfo.append(pi_h)

        # Tilføj punktets afmærkning som punktinformation, selv hvis ikke anført
        afm_id = 4999  # AFM:4999 = "ukendt"
        afm_ids = {
            "ukendt": 4999,
            "bolt": 2700,
            "lodret bolt": 2701,
            "skruepløk": 2950,
            "ingen": 5998,
        }

        if not pd.isna(nyetablerede["Afmærkning"][i]):
            # Afmærkningsbeskrivelse
            afm = str(nyetablerede["Afmærkning"][i]).lower()
            # Første ord i afmærkningsbeskrivelsen
            afm_første = afm.split()[0].rstrip(":;,.- ").lstrip("afm:")

            if afm_første.isnumeric():
                afm_id = int(afm_første)
            else:
                afm_id = afm_ids.get(afm, 4999)

            afmærkning_pit = fire.cli.firedb.hent_punktinformationtype(
                f"AFM:{afm_id}")
            if afmærkning_pit is None:
                afm_id = 4999
                afmærkning_pit = fire.cli.firedb.hent_punktinformationtype(
                    "AFM:4999")
            beskrivelse = (afmærkning_pit.beskrivelse.replace(
                "-\n", "").replace("\n", " ").rstrip(".").strip())

        if afm_id == 4999:
            fire.cli.print(
                f"ADVARSEL: Nyoprettet punkt index {i} har ingen gyldig afmærkning anført",
                fg="red",
                bg="white",
                bold=True,
            )

        # Grundet den lidt kluntede løsning med AFM:nnnn punktinfo er fx AFM:2700 (bolt)
        # registreret som en tekst-punktinformation (frem for flag, som ville være den
        # ideelle løsning) og tekst attributten skal derfor udfyldes. Vi bruger
        # tekstnøgle til afm_ids.
        afm_txts = {v: k for k, v in afm_ids.items()}
        punktinfo.append(
            PunktInformation(
                infotype=afmærkning_pit,
                punkt=punkt,
                tekst=afm_txts[afm_id].capitalize(),
            ))

        # Tilføj punktbeskrivelsen som punktinformation, hvis anført
        beskrivelse = nyetablerede["Beskrivelse"][i]
        if pd.isna(beskrivelse) or beskrivelse == "":
            navn = nyetablerede["Foreløbigt navn"][i]
            fire.cli.print(
                f"FEJL: Beskrivelse for punkt '{navn}' ikke angivet!",
                fg="white",
                bg="red",
                bold=True,
            )
            fire.cli.firedb.session.rollback()
            raise SystemExit
        punktinfo.append(
            PunktInformation(
                infotype=beskrivelse_pit,
                punkt=punkt,
                tekst=beskrivelse,
            ))

        # Tilknyt regionskode til punktet
        punktinfo.append(opret_region_punktinfo(punkt))

        # Tilknyt ATTR:bemærkning
        punktinfo.append(
            PunktInformation(
                infotype=bemærkning_pit,
                punkt=punkt,
                tekst=f"Nyetb. {datetime.now().year} {sagsbehandler}",
            ))

    # tilknyt diverse punktinfo baseret på fikspunktstypen
    gi_punkter = []
    for punkt, fikspunktstype in zip(punkter.values(), fikspunktstyper):
        if fikspunktstype == FikspunktsType.GI:
            gi_punkter.append(punkt)
            punktinfo.append(
                PunktInformation(infotype=attr_gi_pit, punkt=punkt))

        if fikspunktstype == FikspunktsType.HØJDE:
            punktinfo.append(
                PunktInformation(infotype=attr_højde_pit, punkt=punkt))

        if fikspunktstype == FikspunktsType.MV:
            punktinfo.append(
                PunktInformation(infotype=attr_mv_pit, punkt=punkt))

        if fikspunktstype == FikspunktsType.VANDSTANDSBRÆT:
            punktinfo.append(
                PunktInformation(infotype=attr_vandstand_pit, punkt=punkt))

    # Tilknyt G.I-numre
    gi_identer = fire.cli.firedb.tilknyt_gi_numre(gi_punkter)
    punktinfo.extend(gi_identer)

    # Tilknyt landsnumre til punkter
    landsnumre = dict(
        zip(
            punkter.keys(),
            fire.cli.firedb.tilknyt_landsnumre(punkter.values(),
                                               fikspunktstyper),
        ))
    punktinfo.extend(landsnumre.values())

    # sagsevent for punktinfo
    sagsevent_punktinfo = Sagsevent(
        sag=sag,
        eventtype=EventType.PUNKTINFO_TILFOEJET,
        sagseventinfos=[
            SagseventInfo(
                beskrivelse=f"Oprettelse af punktinfo ifm. {projektnavn}", )
        ],
        punktinformationer=punktinfo,
    )
    fire.cli.firedb.indset_sagsevent(sagsevent_punktinfo, commit=False)
    fire.cli.firedb.session.flush()  # hvis noget ikke virker får vi fejl her!

    # Generer dokumentation til fanebladet "Sagsgang"
    sagsgangslinje = {
        "Dato": sagsevent_punktinfo.registreringfra,
        "Hvem": sagsbehandler,
        "Hændelse": "punktinfoindsættelse",
        "Tekst": sagsevent_punktinfo.sagseventinfos[0].beskrivelse,
        "uuid": sagsevent_punktinfo.id,
    }
    sagsgang = sagsgang.append(sagsgangslinje, ignore_index=True)

    # Opdater regneark
    for k in punkter.keys():
        nyetablerede.at[k, "uuid"] = punkter[k].id
        nyetablerede.at[k, "Landsnummer"] = landsnumre[k].tekst

    # Drop numerisk index
    nyetablerede = nyetablerede.reset_index(drop=True)

    # Forbered  resultater til resultatregneark
    resultater = {"Sagsgang": sagsgang, "Nyetablerede punkter": nyetablerede}

    spørgsmål = click.style("Du indsætter nu ", fg="white", bg="red")
    spørgsmål += click.style(f"{len(punkter)} punkter ",
                             fg="white",
                             bg="red",
                             bold=True)
    spørgsmål += click.style(f"i ", fg="white", bg="red")
    spørgsmål += click.style(f"{fire.cli.firedb.db}",
                             fg="white",
                             bg="red",
                             bold=True)
    spørgsmål += click.style("-databasen - er du sikker?",
                             fg="white",
                             bg="red")
    if bekræft(spørgsmål):
        # Indsæt rækker i database og skriv resultater til regneark
        fire.cli.firedb.session.commit()
        if skriv_ark(projektnavn, resultater):
            fire.cli.print(
                f"Punkter oprettet. Resultater skrevet til '{projektnavn}.xlsx'"
            )
    else:
        fire.cli.firedb.session.rollback()
Пример #13
0
def test_indset_punkt(firedb: FireDb, sag: Sag):
    p = Punkt()
    go = GeometriObjekt()
    go.geometri = Point([1, 1])
    p.geometriobjekter.append(go)
    firedb.indset_punkt(Sagsevent(sag=sag), p)