def test_opdatering_punktinformation(firedb, sag, punkt): pit = firedb.hent_punktinformationtype("IDENT:landsnr") pi1 = PunktInformation(infotype=pit, punkt=punkt, tekst="K-12-1231") firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Testindsættelse af punktinfo")], eventtype=EventType.PUNKTINFO_TILFOEJET, punktinformationer=[pi1], ) ) pi2 = PunktInformation(infotype=pit, punkt=punkt, tekst="K-22-2231") firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Testindsættelse af punktinfo")], eventtype=EventType.PUNKTINFO_TILFOEJET, punktinformationer=[pi2], ) ) infotyper = ( firedb.session.query(PunktInformation) .filter( PunktInformation.infotypeid == pit.infotypeid, PunktInformation.punktid == punkt.id, ) .all() ) assert len(infotyper) == 2 assert infotyper[0].registreringtil == infotyper[1].registreringfra assert infotyper[0].sagseventtilid == infotyper[1].sagseventfraid
def test_afregistrering_sagseventinfo(firedb: FireDb, sagsevent: Sagsevent): """ Test trigger sagseventinfo_bi_trg - Automatisk afrestrering af tidligere sagseventinfo. """ si1 = SagseventInfo(sagsevent=sagsevent, beskrivelse="Første udgave") firedb.session.add(si1) firedb.session.commit() si2 = SagseventInfo(sagsevent=sagsevent, beskrivelse="Første udgave") firedb.session.add(si1) firedb.session.commit() assert si1.registreringtil == si2.registreringfra assert si2.registreringtil is None
def test_indset_flere_observationer(firedb: FireDb, sag: Sag, punkt: Punkt): obstype = firedb.session.query(ObservationsType).first() sagsevent = Sagsevent(sag=sag, id=uuid(), eventtype=EventType.OBSERVATION_INDSAT) sagseventtekst = "Ilægning af flere observationer" sagseventinfo = SagseventInfo(beskrivelse=sagseventtekst) sagsevent.sagseventinfos.append(sagseventinfo) obs1 = Observation( antal=0, observationstype=obstype, observationstidspunkt=dt.datetime.utcnow(), opstillingspunkt=punkt, value1=0, value2=0, value3=0, value4=0, value5=0, value6=0, value7=0, value8=0, ) obs2 = Observation( antal=0, observationstype=obstype, observationstidspunkt=dt.datetime.utcnow(), opstillingspunkt=punkt, value1=0, value2=0, value3=0, value4=0, value5=0, value6=0, value7=0, value8=0, ) firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.OBSERVATION_INDSAT, sagseventinfos=[ SagseventInfo(beskrivelse="Testindsættelse af flere observationer") ], observationer=[obs1, obs2], ) )
def test_grafik_unikke_filnavne(firedb: FireDb, sag: Sag, sagsevent: Sagsevent): """Test at der ikke kan oprettes filnavnedupletter""" filnavn = f"{fire.uuid()}.png" sagsevent.eventtype = EventType.PUNKT_OPRETTET p1 = Punkt(sagsevent=sagsevent) p2 = Punkt(sagsevent=sagsevent) g1 = Grafik( punkt=p1, filnavn=filnavn, mimetype="image/png", type="skitse", grafik=b"\xf3\xf5\xf8\x98", ) g2 = Grafik( punkt=p2, filnavn=filnavn, mimetype="image/png", type="skitse", grafik=b"\xf3\xf5\xf8\x98", ) with pytest.raises(DatabaseError): firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[ SagseventInfo(beskrivelse="Test fejl ved filnavnduplet") ], eventtype=EventType.GRAFIK_INDSAT, grafikker=[g1, g2], ) ) firedb.session.rollback()
def fabrik(): e0 = Sagsevent( sag=sag, eventtype=EventType.KOMMENTAR, sagseventinfos=[SagseventInfo(beskrivelse="test")], ) firedb.session.add(e0) return e0
def test_indset_beregning( firedb: FireDb, sag: Sag, sagsevent: Sagsevent, punkt: Punkt, srid: Srid, observationstype: ObservationsType, ): o0 = Observation( sagsevent=sagsevent, observationstidspunkt=func.current_timestamp(), observationstype=observationstype, opstillingspunkt=punkt, ) firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[ SagseventInfo(beskrivelse="Testindsættelse af observation") ], eventtype=EventType.OBSERVATION_INDSAT, observationer=[o0], )) beregning = Beregning() beregning.observationer.append(o0) koordinat = Koordinat(srid=srid, punkt=punkt, x=0, y=0, z=0, sx=0, sy=0, sz=0) beregning.koordinater.append(koordinat) firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOORDINAT_BEREGNET, sagseventinfos=[SagseventInfo(beskrivelse="Testberegning")], beregninger=[beregning], koordinater=beregning.koordinater, )) assert koordinat.objektid is not None
def test_indset_punktinformation(firedb, sag, punkt, punktinformationtype): pi = PunktInformation(infotype=punktinformationtype, punkt=punkt) firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Testindsættelse af punktinfo")], eventtype=EventType.PUNKTINFO_TILFOEJET, punktinformationer=[pi], ) )
def punkt(uuid: str, sagsbehandler, **kwargs) -> None: """ Luk et punkt i FIRE databasen. Se `punkt_hjælp` for yderligere information. """ db = fire.cli.firedb sag = Sag( id=fire.uuid(), sagsinfos=[ Sagsinfo( behandler=sagsbehandler, beskrivelse="Lukning af objekt med 'fire luk'", aktiv="true", ) ], ) db.session.add(sag) db.session.flush() sagsevent = Sagsevent( sag=sag, eventtype=EventType.PUNKT_NEDLAGT, sagseventinfos=[ SagseventInfo(beskrivelse=f"'fire luk punkt {uuid}"), ], ) try: punkt = db.hent_punkt(uuid) except NoResultFound: fire.cli.print(f"Punkt med UUID {uuid} ikke fundet!") raise SystemExit try: # Indsæt alle objekter i denne session db.luk_punkt(punkt, sagsevent, commit=False) db.session.flush() db.luk_sag(sag, commit=False) db.session.flush() except DatabaseError as e: # rul tilbage hvis databasen smider en exception db.session.rollback() fire.cli.print(f"Der opstod en fejl - punkt id {uuid} IKKE lukket!") print(e) else: tekst = f"Er du sikker på at du vil lukke punktet {punkt.ident} ({uuid})?" spørgsmål = f"{STOP}\n\n" + click.style(tekst, bg="red", fg="white") spørgsmål += "\n\n\nLukning af punktet KAN IKKE rulles tilbage. Denne ændring er irreversibel,\n" spørgsmål += "tænkt dig grundigt om inden du siger ja." if bekræft(spørgsmål): db.session.commit() fire.cli.print(f"Punkt {punkt.ident} ({uuid} lukket!") else: db.session.rollback() fire.cli.print(f"Punkt {punkt.ident} ({uuid} IKKE lukket!")
def test_indset_sagsevent(firedb: FireDb, sag: Sag): sagseventinfo = SagseventInfo(beskrivelse="Testing testing") firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOMMENTAR, sagseventinfos=[sagseventinfo], )) s = firedb.hent_sag(sag.id) assert s.sagsevents[0].sagseventinfos[0].beskrivelse == "Testing testing"
def test_grafik_opdatering(firedb: FireDb, sag: Sag, punkt: Punkt): """Test at et nyt Grafik-objekt erstatter et gammelt korrekt""" filnavn = f"{fire.uuid()}.png" g1 = Grafik( punkt=punkt, filnavn=filnavn, mimetype="image/png", type="skitse", grafik=b"\xf3\xf5\xf8\x98", ) firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Testindsættelse af grafik")], eventtype=EventType.GRAFIK_INDSAT, grafikker=[g1], ) ) g2 = Grafik( punkt=punkt, filnavn=filnavn, mimetype="image/png", type="skitse", grafik=b"\xf3\xf5\xf8\x99", ) firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Opdatering af grafik")], eventtype=EventType.GRAFIK_INDSAT, grafikker=[g2], ) ) assert g1.registreringtil == g2.registreringfra assert g1.sagseventtilid == g2.sagseventfraid
def luk_sag(projektnavn: str, **kwargs) -> None: """Luk sag i databasen""" er_projekt_okay(projektnavn) sag = find_sag(projektnavn) # Find sagsmateriale og zip det for let indlæsning i databasen sagsmaterialer = [f"{projektnavn}.xlsx"] filoversigt = find_faneblad(projektnavn, "Filoversigt", arkdef.FILOVERSIGT) sagsmaterialer.extend(list(filoversigt["Filnavn"])) zipped = BytesIO() with ZipFile(zipped, "w") as zipobj: for fil in sagsmaterialer: zipobj.write(fil) # Tilføj materiale til sagsevent sagsevent = Sagsevent( sag=sag, eventtype=EventType.KOMMENTAR, sagseventinfos=[ SagseventInfo( beskrivelse=f"Sagsmateriale for {projektnavn}", materialer=[ SagseventInfoMateriale(materiale=zipped.getvalue()) ], ), ], ) fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) fire.cli.firedb.luk_sag(sag, commit=False) try: # Indsæt alle objekter i denne session fire.cli.firedb.session.flush() except: # rul tilbage hvis databasen smider en exception fire.cli.firedb.session.rollback() fire.cli.print( f"Der opstod en fejl - sag {sag.id} for '{projektnavn}' IKKE lukket!" ) else: spørgsmål = click.style( f"Er du sikker på at du vil lukke sagen {projektnavn}?", bg="red", fg="white", ) if bekræft(spørgsmål): fire.cli.firedb.session.commit() fire.cli.print(f"Sag {sag.id} for '{projektnavn}' lukket!") else: fire.cli.firedb.session.rollback() fire.cli.print(f"Sag {sag.id} for '{projektnavn}' IKKE lukket!")
def add_coordinates(sag, koordinater, beskrivelse): """ Tilføj koordinater og dertilhørende sagsevent til sag """ sagseventinfo = SagseventInfo(beskrivelse=beskrivelse) sagsevent = Sagsevent( id=str(uuid.uuid4()), sag=sag, eventtype=EventType.KOORDINAT_BEREGNET, sagseventinfos=[sagseventinfo], koordinater=koordinater, ) print("add_coordinates: " + beskrivelse) firedb.indset_sagsevent(sagsevent)
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], ))
def test_indset_sagsevent_materiale(firedb: FireDb, sag: Sag): blob = os.urandom(1000) sagseventinfo = SagseventInfo( beskrivelse="Testing testing", materialer=[SagseventInfoMateriale(materiale=blob)], ) firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOMMENTAR, sagseventinfos=[sagseventinfo], )) s = firedb.hent_sag(sag.id) assert s.sagsevents[0].sagseventinfos[0].materialer[0].materiale == blob
def main(): infotype = firedb.hent_punktinformationtype(ATTRIBUT) if infotype is None: firedb.indset_punktinformationtype( PunktInformationType( name=ATTRIBUT, anvendelse=fire.api.model.PunktInformationTypeAnvendelse.TEKST, beskrivelse="Fundamentalpunkt i referencesystemet angivet i TEKST", ) ) infotype = firedb.hent_punktinformationtype(ATTRIBUT) print(infotype) sagsinfo = Sagsinfo( aktiv="true", behandler="Kristian Evers", beskrivelse=sagsbeskrivelse ) sagid = str(uuid.uuid4()) firedb.indset_sag(Sag(id=sagid, sagsinfos=[sagsinfo])) sag = firedb.hent_sag(sagid) punktinformationer = [] for srid, identer in PUNKTER.items(): for ident in identer: try: punkt = firedb.hent_punkt(ident) except NoResultFound: print(f'fejl: {ident}') continue pi = PunktInformation(infotype=infotype, punkt=punkt, tekst=srid) punktinformationer.append(pi) sagseventinfo = SagseventInfo(beskrivelse=f"Indsættelse af {ATTRIBUT} attributter") sagsevent = Sagsevent( id=str(uuid.uuid4()), sag=sag, eventtype=fire.api.model.EventType.PUNKTINFO_TILFOEJET, sagseventinfos=[sagseventinfo], punktinformationer=punktinformationer, ) firedb.indset_sagsevent(sagsevent)
def main(): firedb.indset_punktinformationtype( PunktInformationType( name=ATTRIBUT, anvendelse=fire.api.model.PunktInformationTypeAnvendelse.FLAG, beskrivelse="Punkter i den oprindelige DVR90-udjævning", )) infotype = firedb.hent_punktinformationtype(ATTRIBUT) sagsinfo = Sagsinfo(aktiv="true", behandler="Kristian Evers", beskrivelse=sagsbeskrivelse) sagid = str(uuid.uuid4()) firedb.indset_sag(Sag(id=sagid, sagsinfos=[sagsinfo])) sag = firedb.hent_sag(sagid) with open(POINT_FILE) as f: punkter = [punkt.strip() for punkt in f.readlines()] punktinformationer = [] # interaktion med databasen er pokkers langsomt, vis fremdrift with click.progressbar(punkter, label="Punkter") as punkter_progress: for ident in punkter_progress: try: punkt = get_punkt(ident) except sqlalchemy.orm.exc.NoResultFound: print(f"Ident ikke fundet: {ident}") continue pi = PunktInformation(infotype=infotype, punkt=punkt) punktinformationer.append(pi) sagseventinfo = SagseventInfo( beskrivelse=f"Indsættelse af {ATTRIBUT} attibutter") sagsevent = Sagsevent( id=str(uuid.uuid4()), sag=sag, eventtype=fire.api.model.EventType.PUNKTINFO_TILFOEJET, sagseventinfos=[sagseventinfo], punktinformationer=punktinformationer, ) firedb.indset_sagsevent(sagsevent)
def test_grafik(firedb: FireDb, sag: Sag, punkt: Punkt): """Test oprettelse af et Grafik objekt)""" filnavn = f"{fire.uuid()}.png" with open(PNG, "rb") as f: g = Grafik( punkt=punkt, grafik=f.read(), type="skitse", mimetype="image/png", filnavn=filnavn, ) firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[SagseventInfo(beskrivelse="Testindsættelse af grafik")], eventtype=EventType.GRAFIK_INDSAT, grafikker=[g], ) )
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
def indsæt( ident: str, sti: Path, type: str, filnavn: str, sagsbehandler, **kwargs ) -> None: r""" Indsæt grafik i databasen. EKSEMPLER Indsæt skitse fra PNG-fil: > fire grafik indsæt K-01-01234 K-01-01234.png Anvend andet filnavn i databasen: > fire grafik indsæt G.M.902 IMG_5234.jpg --filnavn aarhus_domkirke.jpg Eksplicer grafiktype og filnavn: > fire grafik indsæt K-01-012345 C:\tmp\skitse.png --type skitse --filnavn K-01-012345.png """ db = fire.cli.firedb try: g = db.hent_grafik(filnavn) except NoResultFound: g = None if g: if ident not in g.punkt.identer: raise SystemExit( f"Kan ikke indsætte {filnavn} på {ident}," " allerede regisreret på {g.punkt.ident}" ) punkt = db.hent_punkt(ident) if not filnavn: filnavn = sti.name for grafik in punkt.grafikker: if grafik.filnavn == filnavn: spørgsmål = f"Grafik med filnavn {filnavn} allerede tilknyttet {punkt.ident} - vil du overskrive det?" if bekræft(spørgsmål, gentag=False): break else: raise SystemExit # sagshåndtering sag = Sag( id=fire.uuid(), sagsinfos=[ Sagsinfo( aktiv="true", behandler=sagsbehandler, beskrivelse="Indsættelse af ny grafik med 'fire grafik'", ) ], ) db.indset_sag(sag, commit=False) try: fire.cli.firedb.session.flush() except Exception as ex: fire.cli.firedb.session.rollback() raise SystemExit(ex) # opret grafik grafik = Grafik.fra_fil(punkt, sti) grafik.type = type grafik.filnavn = filnavn sagsevent = Sagsevent( sag=sag, eventtype=EventType.GRAFIK_INDSAT, sagseventinfos=[ SagseventInfo( beskrivelse=f"Grafik {filnavn} indsættes på punkt {punkt.ident}" ) ], grafikker=[grafik], ) db.indset_sagsevent(sagsevent, commit=False) db.luk_sag(sag, commit=False) try: # Indsæt alle objekter i denne session fire.cli.firedb.session.flush() except Exception as e: # rul tilbage hvis databasen smider en exception fire.cli.firedb.session.rollback() fire.cli.print(f"Der opstod en fejl - fil {filnavn} IKKE indsat!") else: spørgsmål = click.style( f"Er du sikker på at du vil tilknytte grafikken {filnavn} til {punkt.ident}?", bg="red", fg="white", ) if bekræft(spørgsmål): fire.cli.firedb.session.commit() fire.cli.print(f"fil {filnavn} tilknyttet {punkt.ident}!") else: fire.cli.firedb.session.rollback() fire.cli.print(f"fil {filnavn} IKKE tilknyttet {punkt.ident}!")
def slet(filnavn: str, sagsbehandler: str, **kwargs) -> None: """ Slet en grafik fra databasen. Grafikken identificeres ud fra sit filnavn. Filnavnet på en grafik kan findes ved opslag med ``fire info punkt <ident>``. """ db = fire.cli.firedb try: grafik = db.hent_grafik(filnavn) except NoResultFound: raise SystemExit(f"Fandt ikke {filnavn}!") punkt = grafik.punkt # sagshåndtering sag = Sag( id=fire.uuid(), sagsinfos=[ Sagsinfo( aktiv="true", behandler=sagsbehandler, beskrivelse="Afregistrering af grafik med `fire grafik slet`", ) ], ) db.indset_sag(sag, commit=False) try: fire.cli.firedb.session.flush() except Exception as ex: fire.cli.firedb.session.rollback() raise SystemExit(ex) sagsevent = Sagsevent( sag=sag, sagseventinfos=[ SagseventInfo( beskrivelse=f"Grafik {filnavn} for {punkt.ident} afregistreret" ) ], ) db.luk_grafik(grafik, sagsevent, commit=False) db.luk_sag(sag, commit=False) try: # Indsæt alle objekter i denne session fire.cli.firedb.session.flush() except Exception as e: # rul tilbage hvis databasen smider en exception fire.cli.firedb.session.rollback() fire.cli.print(f"Der opstod en fejl - fil {filnavn} IKKE slettet!") else: spørgsmål = click.style( f"Er du sikker på at du vil slettet grafikken {filnavn} tilhørende {punkt.ident}?", bg="red", fg="white", ) if bekræft(spørgsmål): fire.cli.firedb.session.commit() fire.cli.print(f"fil {filnavn} slettet fra {punkt.ident}!") else: fire.cli.firedb.session.rollback() fire.cli.print(f"fil {filnavn} IKKE slettet fra {punkt.ident}!")
def ilæg_nye_koter(projektnavn: str, sagsbehandler: str, **kwargs) -> None: """Registrer nyberegnede koter i databasen""" sag = find_sag(projektnavn) sagsgang = find_sagsgang(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}") punktoversigt = find_faneblad(projektnavn, "Endelig beregning", ARKDEF_PUNKTOVERSIGT) ny_punktoversigt = punktoversigt[0:0] DVR90 = fire.cli.firedb.hent_srid("EPSG:5799") registreringstidspunkt = func.current_timestamp() tid = gyldighedstidspunkt(projektnavn) # Generer sagsevent sagsevent = Sagsevent(sag=sag, id=uuid(), eventtype=EventType.KOORDINAT_BEREGNET) til_registrering = [] opdaterede_punkter = [] for punktdata in punktoversigt.to_dict(orient="records"): # Blanklinje, tilbageholdt, eller allerede registreret? if (pd.isna(punktdata["Ny kote"]) or punktdata["uuid"] != "" or punktdata["Udelad publikation"] == "x"): ny_punktoversigt = ny_punktoversigt.append(punktdata, ignore_index=True) continue punkt = fire.cli.firedb.hent_punkt(punktdata["Punkt"]) opdaterede_punkter.append(punkt) punktdata["uuid"] = sagsevent.id kote = Koordinat( srid=DVR90, punkt=punkt, t=tid, z=punktdata["Ny kote"], sz=punktdata["Ny σ"], ) til_registrering.append(kote) ny_punktoversigt = ny_punktoversigt.append(punktdata, ignore_index=True) if 0 == len(til_registrering): fire.cli.print("Ingen koter at registrere!", fg="yellow", bold=True) return # Vi vil ikke have alt for lange sagseventtekster (bl.a. fordi Oracle ikke # kan lide lange tekststrenge), så vi indsætter udeladelsesprikker hvis vi # opdaterer mere end 10 punkter ad gangen n = len(opdaterede_punkter) punktnavne = [p.ident for p in opdaterede_punkter] if n > 10: punktnavne[9] = "..." punktnavne[10] = punktnavne[-1] punktnavne = punktnavne[0:10] sagseventtekst = f"Opdatering af DVR90 kote til {', '.join(punktnavne)}" with open(f"{projektnavn}-resultat-endelig.html") as html: clob = "".join(html.readlines()) sagseventinfo = SagseventInfo( beskrivelse=sagseventtekst, htmler=[SagseventInfoHtml(html=clob)], ) sagsevent.sagseventinfos.append(sagseventinfo) sagsevent.koordinater = til_registrering fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) # Generer dokumentation til fanebladet "Sagsgang" # Variablen "registreringstidspunkt" har værdien "CURRENT_TIMESTAMP" # som udvirker mikrosekundmagi når den bliver skrevet til databasen, # men ikke er meget informativ for en menneskelig læser her i regne- # arkenes prosaiske verden. Derfor benytter vi pd.Timestamp.now(), # som ikke har mikrosekundmagi over sig, men som kan læses og giver # mening, selv om den ikke bliver eksakt sammenfaldende med det # tidsstempel hændelsen får i databasen. Det lever vi med. sagsgangslinje = { "Dato": pd.Timestamp.now(), "Hvem": sagsbehandler, "Hændelse": "Koteberegning", "Tekst": sagseventtekst, "uuid": sagsevent.id, } sagsgang = sagsgang.append(sagsgangslinje, ignore_index=True) fire.cli.print(sagseventtekst, fg="yellow", bold=True) fire.cli.print(f"Ialt {n} koter") try: fire.cli.firedb.session.flush() except Exception as ex: # rul tilbage hvis databasen smider en exception fire.cli.firedb.session.rollback() fire.cli.print( f"Der opstod en fejl - koter for '{projektnavn}' IKKE indlæst!") fire.cli.print(f"Mulig årsag: {ex}") else: spørgsmål = click.style("Du indsætter nu ", fg="white", bg="red") spørgsmål += click.style(f"{len(til_registrering)} kote(r) ", 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): fire.cli.firedb.session.commit() # Skriv resultater til resultatregneark resultater = {"Sagsgang": sagsgang, "Resultat": ny_punktoversigt} if skriv_ark(projektnavn, resultater): fire.cli.print( f"Koter registreret. Resultater skrevet til '{projektnavn}.xlsx'" )
def ilæg_observationer(projektnavn: str, sagsbehandler: str, **kwargs) -> None: """Registrer nye observationer i databasen""" sag = find_sag(projektnavn) sagsgang = find_sagsgang(projektnavn) fire.cli.print(f"Sags/projekt-navn: {projektnavn} ({sag.id})") fire.cli.print(f"Sagsbehandler: {sagsbehandler}") obstype_trig = fire.cli.firedb.hent_observationstype( "trigonometrisk_koteforskel") obstype_geom = fire.cli.firedb.hent_observationstype( "geometrisk_koteforskel") til_registrering = [] observationer = find_faneblad(projektnavn, "Observationer", ARKDEF_OBSERVATIONER) alle_kilder = ", ".join(sorted(list(set(observationer.Kilde)))) alle_uuider = observationer.uuid.astype(str) # Generer sagsevent sagsevent = Sagsevent(sag=sag, id=uuid(), eventtype=EventType.OBSERVATION_INDSAT) sagseventtekst = f"Ilægning af observationer fra {alle_kilder}" sagseventinfo = SagseventInfo(beskrivelse=sagseventtekst) sagsevent.sagseventinfos.append(sagseventinfo) # Generer dokumentation til fanebladet "Sagsgang" sagsgangslinje = { "Dato": pd.Timestamp.now(), "Hvem": sagsbehandler, "Hændelse": "observationsilægning", "Tekst": sagseventtekst, "uuid": sagsevent.id, } sagsgang = sagsgang.append(sagsgangslinje, ignore_index=True) for i, obs in enumerate(observationer.itertuples(index=False)): # Ignorer allerede registrerede observationer if str(obs.uuid) not in ["", "None", "nan"]: continue # Vi skal bruge fra- og til-punkterne for at kunne oprette et # objekt af typen Observation try: punktnavn = obs.Fra punkt_fra = fire.cli.firedb.hent_punkt(punktnavn) punktnavn = obs.Til punkt_til = fire.cli.firedb.hent_punkt(punktnavn) except NoResultFound: fire.cli.print(f"Ukendt punkt: '{punktnavn}'", fg="red", bg="white") sys.exit(1) # For nivellementsobservationer er gruppeidentifikatoren identisk # med journalsidenummeret side = obs.Journal.split(":")[0] if side.isnumeric(): gruppe = int(side) else: gruppe = None if obs.Type.upper() == "MTL": observation = Observation( antal=1, observationstype=obstype_trig, observationstidspunkt=obs.Hvornår, opstillingspunkt=punkt_fra, sigtepunkt=punkt_til, gruppe=gruppe, id=uuid(), value1=obs.ΔH, value2=obs.L, value3=obs.Opst, value4=obs.σ, value5=obs.δ, ) observation.sagsevent = sagsevent elif obs.Type.upper() == "MGL": observation = Observation( antal=1, observationstype=obstype_geom, observationstidspunkt=obs.Hvornår, opstillingspunkt=punkt_fra, sigtepunkt=punkt_til, gruppe=gruppe, id=uuid(), value1=obs.ΔH, value2=obs.L, value3=obs.Opst, value4= 0.0, # Refraktion, eta_1, er defineret som non-null, så vi sætter den til 0 istf. None value5=obs.σ, value6=obs.δ, value7= 0, # 1,2,3 henviser til 1.,2.,3. præcisionsnivellement. 0 til "ingen af dem" ) else: fire.cli.print(f"Ukendt observationstype: '{obs.Type}'", fg="red", bg="white") sys.exit(1) alle_uuider[i] = observation.id til_registrering.append(observation) # Gør klar til at persistere observationer["uuid"] = alle_uuider fire.cli.print(sagseventtekst, fg="yellow", bold=True) fire.cli.print(str(observationer[["Journal", "Fra", "Til", "uuid"]])) # Persister observationerne til databasen fire.cli.print(f"Skriver {len(til_registrering)} observationer") sagsevent.observationer = til_registrering fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) try: fire.cli.firedb.session.flush() except Exception as ex: # rul tilbage hvis databasen smider en exception fire.cli.firedb.session.rollback() fire.cli.print( f"Der opstod en fejl - observationer for '{projektnavn}' IKKE indlæst!" ) fire.cli.print(f"Mulig årsag: {ex}") else: spørgsmål = click.style("Du indsætter nu ", fg="white", bg="red") spørgsmål += click.style(f"{len(til_registrering)} observationer ", 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): fire.cli.firedb.session.commit() # Skriv resultater til resultatregneark resultater = {"Sagsgang": sagsgang, "Observationer": observationer} skriv_ark(projektnavn, resultater) fire.cli.print( f"Observationer registreret. Kopiér nu faneblade fra '{projektnavn}-resultat.xlsx' til '{projektnavn}.xlsx'" ) else: fire.cli.firedb.session.rollback() fire.cli.print(f"Observationer for '{projektnavn}' IKKE indlæst!")
def read(self, sags_id): sag = self.fireDb.hent_sag(sags_id) namespace = "{http://www.gnu.org/software/gama/gama-local-adjustment}" tree = ET.parse(self.input_stream) root = tree.getroot() beregning = Beregning() srid = self.fireDb.hent_srid("EPSG:5799") adjusted_element = root.find(namespace + "coordinates").find(namespace + "adjusted") cov_mat_values = ( root.find(namespace + "coordinates").find(namespace + "cov-mat").findall(namespace + "flt")) original_index_indicies = ( root.find(namespace + "coordinates").find(namespace + "original-index").findall(namespace + "ind")) for idx, point in enumerate(adjusted_element.iter(namespace + "point")): # Read values from the point z = point.find(namespace + "z").text point_id = point.find(namespace + "id").text # Read the correct entry in cov_mat_values cov_mat_index = int(original_index_indicies[idx].text) - 1 cov_mat_element = cov_mat_values[cov_mat_index] # Read value as float cov_mat_value = float(cov_mat_element.text) # .. and tale sqrt to find std_dev std_dev = math.sqrt(cov_mat_value) koordinat = Koordinat() koordinat.srid = srid koordinat.z = z koordinat.sz = std_dev koordinat.punkt = self.fireDb.hent_punkt(point_id) beregning.koordinater.append(koordinat) observation_id_list = [] observations_element = root.find(namespace + "observations") for idx, diff in enumerate( observations_element.iter(namespace + "height-diff")): observationId = diff.get("extern") observation_id_list.append(observationId) observation_list = self.fireDb.hent_observationer(observation_id_list) beregning.observationer.extend(observation_list) self.fireDb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOORDINAT_BEREGNET, sagseventinfos=[ SagseventInfo(beskrivelse="Beregning indlæst via GNU Gama") ], beregninger=[beregning], koordinater=beregning.koordinater, ))
def test_indset_beregning_invalidates_existing_koordinat( firedb: FireDb, sag: Sag, punkt: Punkt, srid: Srid, observation: Observation): firedb.indset_sagsevent( Sagsevent( sag=sag, sagseventinfos=[ SagseventInfo(beskrivelse="Testindsættelse af observation") ], eventtype=EventType.OBSERVATION_INDSAT, observationer=[observation], )) beregning = Beregning() beregning.observationer.append(observation) koordinat = Koordinat(srid=srid, punkt=punkt, x=0, y=0, z=0, sx=0, sy=0, sz=0) beregning.koordinater.append(koordinat) firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOORDINAT_BEREGNET, sagseventinfos=[SagseventInfo(beskrivelse="Testberegning")], beregninger=[beregning], koordinater=beregning.koordinater, )) # new beregning of the same observation with a new koordinat beregning2 = Beregning() beregning2.observationer.append(observation) koordinat2 = Koordinat( srid=srid, punkt=punkt, x=1, y=0, z=0, sx=0, sy=0, sz=0, ) beregning2.koordinater.append(koordinat2) firedb.indset_sagsevent( Sagsevent( sag=sag, eventtype=EventType.KOORDINAT_BEREGNET, sagseventinfos=[SagseventInfo(beskrivelse="Testberegning")], beregninger=[beregning2], koordinater=beregning2.koordinater, )) assert len(punkt.koordinater) == 2 assert len([k for k in punkt.koordinater if k.registreringtil is None]) == 1 assert koordinat2.srid is not None
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()
def ilæg_revision( projektnavn: str, sagsbehandler: str, **kwargs, ) -> None: """Læg reviderede punktdata i databasen""" sag = find_sag(projektnavn) sagsgang = find_sagsgang(projektnavn) fire.cli.print(f"Sags/projekt-navn: {projektnavn} ({sag.id})") fire.cli.print(f"Sagsbehandler: {sagsbehandler}") fire.cli.print("") revision = find_faneblad(f"{projektnavn}-revision", "Revision", ARKDEF_REVISION) # Tildel navne til endnu ikke oprettede punkter oprettelse = revision.query("Attribut == 'OPRET'") for i, _ in oprettelse.iterrows(): revision.loc[i, "Punkt"] = f"NYTPUNKT{i}" # Udfyld udeladte identer punkter = list(revision["Punkt"]) udfyldningsværdi = "" for i in range(len(punkter)): if punkter[i].strip() != "": udfyldningsværdi = punkter[i].strip() continue punkter[i] = udfyldningsværdi revision["Punkt"] = punkter # Find alle punkter, der skal nyoprettes nye_punkter = [] oprettelse = revision.query("Attribut == 'OPRET'") for row in oprettelse.to_dict("records"): if row["id"] == -1: continue punkt = opret_punkt(row["Ny værdi"]) fire.cli.print(f"Opretter nyt punkt {punkt.ident}: {row['Ny værdi']}") nye_punkter.append(punkt) # indsæt nyt punkt ID i Punkt kolonnen, for at kunne trække # dem ud med hent_punkt() senere erstat = lambda x: punkt.id if x == row["Punkt"] else x revision["Punkt"] = revision.Punkt.apply(erstat) revision = revision.query("Attribut != 'OPRET'") # Find alle lokationskoordinater, der skal korrigeres nye_lokationer = [] lokation = revision.query("Attribut == 'LOKATION'") lokation = lokation.query("`Ny værdi` != ''") for row in lokation.to_dict("records"): punkt = fire.cli.firedb.hent_punkt(row["Punkt"]) # gem her inden ny geometri tilknyttes punktet (λ1, φ1) = punkt.geometri.koordinater go = læs_lokation(row["Ny værdi"]) go.punkt = punkt nye_lokationer.append(go) (λ2, φ2) = go.koordinater g = Geod(ellps="GRS80") _, _, dist = g.inv(λ1, φ1, λ2, φ2) if dist >= 25: fire.cli.print( f" ADVARSEL: Ny lokationskoordinat afviger {dist:.0f} m fra den gamle", fg="yellow", bold=True, ) if len(nye_punkter) > 0 or len(nye_lokationer) > 0: sagsevent = Sagsevent( id=uuid(), sagsid=sag.id, sagseventinfos=[ SagseventInfo(beskrivelse="Oprettelse af nye punkter") ], eventtype=EventType.PUNKT_OPRETTET, punkter=nye_punkter, geometriobjekter=nye_lokationer, ) fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) sagsgang = opdater_sagsgang(sagsgang, sagsevent, sagsbehandler) flush() revision = revision.query("Attribut != 'LOKATION'") # Find alle koordinater, der skal oprettes # Først skal vi bruge alle gyldige koordinatsystemnavne srider = fire.cli.firedb.hent_srider() sridnavne = [srid.name.upper() for srid in srider] # Så itererer vi over hele rammen og ignorerer ikke-koordinaterne nye_koordinater = [] opdaterede_punkter = [] for r in revision.to_dict("records"): sridnavn = r["Attribut"].upper() if sridnavn not in sridnavne: continue try: koord = [float(k.replace(",", ".")) for k in r["Ny værdi"].split()] except ValueError as ex: fire.cli.print( f"Ukorrekt koordinatformat:\n{' '.join(r['Ny værdi'])}\n{ex}" ) fire.cli.print( "Skal være på formen: 'x y z t sx sy sz', hvor ubrugte værdier sættes til 'nan'" ) sys.exit(1) # Oversæt NaN til None koord = [None if isnan(k) else k for k in koord] # Tæt-på-kopi af kode fra "niv/ilæg_nye_koter.py". Her bør mediteres og overvejes # hvordan denne opgave kan parametriseres på en rimeligt generel måde, så den kan # udstilles i et "højniveau-API" srid = fire.cli.firedb.hent_srid(sridnavn) punkt = fire.cli.firedb.hent_punkt(r["Punkt"]) opdaterede_punkter.append(r["Punkt"]) # Det er ikke helt så nemt som i C at oversætte decimal-år til datetime år = trunc(koord[3]) rest = koord[3] - år startdato = datetime(år, 1, 1) årlængde = datetime(år + 1, 1, 1) - startdato tid = startdato + rest * årlængde koordinat = Koordinat( srid=srid, punkt=punkt, x=koord[0], y=koord[1], z=koord[2], t=tid, sx=koord[4], sy=koord[5], sz=koord[6], ) nye_koordinater.append(koordinat) # I Grønland er vi nødt til at duplikere geografiske koordinater til UTM24, # da Oracles indbyggede UTM-rutine er for ringe til at vi kan generere # udstillingskoordinater on-the-fly. if sridnavn in ("EPSG:4909", "EPSG:4747"): srid_utm24 = fire.cli.firedb.hent_srid("EPSG:3184") utm24 = Proj("proj=utm zone=24 ellps=GRS80", preserve_units=False) x, y = utm24(koord[0], koord[1]) koordinat = Koordinat( srid=srid_utm24, punkt=punkt, x=x, y=y, z=None, t=tid, sx=koord[4], sy=koord[5], sz=None, ) nye_koordinater.append(koordinat) n = len(opdaterede_punkter) if n > 0: punktnavne = sorted(list(set(opdaterede_punkter))) if len(punktnavne) > 10: punktnavne[9] = "..." punktnavne[10] = punktnavne[-1] punktnavne = punktnavne[0:10] koordinatoprettelsestekst = ( f"Opdatering af {n} koordinater til {', '.join(punktnavne)}") sagsevent = Sagsevent( id=uuid(), sagsid=sag.id, sagseventinfos=[ SagseventInfo(beskrivelse=koordinatoprettelsestekst) ], eventtype=EventType.KOORDINAT_BEREGNET, koordinater=nye_koordinater, ) fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) sagsgang = opdater_sagsgang(sagsgang, sagsevent, sagsbehandler) flush() # Så tager vi fat på punktinformationerne til_opret = [] til_ret = [] til_sluk = [] punkter_med_oprettelse = set() punkter_med_rettelse = set() punkter_med_slukning = set() # Først, tilknyt regionspunktinfo til nyoprettede punkter for p in nye_punkter: til_opret.append(opret_region_punktinfo(p)) # Find identer for alle punkter, der indgår i revisionen identer = tuple(sorted(set(revision["Punkt"]) - set(["nan", ""]))) fire.cli.print("") fire.cli.print(f"Behandler {len(identer)} punkter") # Så itererer vi over alle punkter for ident in identer: fire.cli.print(ident, fg="yellow", bold=True) # Hent punkt og alle relevante punktinformationer i databasen. # Her er det lidt sværere end for koordinaternes vedkommende: # Ved opdatering af eksisterende punkter vil vi gerne checke # infonøglerne, så vi er nødt til at hente det faktiske punkt, # med tilørende infonøgler, fra databasen try: punkt = fire.cli.firedb.hent_punkt(ident) infonøgler = { info.objektid: i for i, info in enumerate(punkt.punktinformationer) } except NoResultFound as ex: fire.cli.print( f"FEJL: Kan ikke finde punkt {ident}!", fg="yellow", bg="red", bold=True, ) fire.cli.print(f"Mulig årsag: {ex}") sys.exit(1) # Hent alle revisionselementer for punktet fra revisionsarket rev = revision.query(f"Punkt == '{ident}'") for r in rev.to_dict("records"): if r["Attribut"] in sridnavne: continue if r["id"] == 999999: continue if r["id"] == -1: continue pitnavn = r["Attribut"] if pitnavn == "": continue if r["Sluk"] and r["Ny værdi"]: fire.cli.print( f" * FEJL: 'Sluk' og 'Ny værdi' begge udfyldt: {r['Ny værdi']}", fg="red", bold=False, ) continue if r["Tekstværdi"] != "" and r["Tekstværdi"] == r["Ny værdi"]: fire.cli.print( f" ADVARSEL: Tekst i 'Ny værdi' identisk med udgangspunkt for {pitnavn}.", fg="yellow", bold=True, ) continue if pitnavn is None: fire.cli.print( " * Ignorerer uanført punktinformationstype", fg="red", bold=False, ) continue pit = fire.cli.firedb.hent_punktinformationtype(pitnavn) if pit is None: fire.cli.print( f" * Ignorerer ukendt punktinformationstype '{pitnavn}'", fg="red", bold=True, ) continue # Nyt punktinfo-element? if pd.isna(r["id"]): # ATTR:muligt_datumstabil+slukket == ikke eksisterende i DB # Indsat af fire niv udtræk-revision if pitnavn == "ATTR:muligt_datumstabil" and r["Sluk"]: continue fire.cli.print( f" Opretter nyt punktinfo-element: {pitnavn}") if pit.anvendelse == PunktInformationTypeAnvendelse.FLAG: if r["Ny værdi"]: fire.cli.print( f" BEMÆRK: {pitnavn} er et flag. Ny værdi '{r['Ny værdi']}' ignoreres", fg="yellow", bold=True, ) pi = PunktInformation(infotype=pit, punkt=punkt) elif pit.anvendelse == PunktInformationTypeAnvendelse.TEKST: # Ingen definitiv test her: Tom tekst kan være gyldig. # Men vi sørger for at den ikke er None tekst = r["Ny værdi"] if tekst is None or tekst == "": fire.cli.print( f" ADVARSEL: Tom tekst anført for {pitnavn}.", fg="yellow", bold=True, ) tekst = "" pi = PunktInformation(infotype=pit, punkt=punkt, tekst=tekst) else: try: # Både punktum og komma er accepterede decimalseparatorer tal = float(r["Ny værdi"].replace(",", ".")) except ValueError as ex: fire.cli.print( f" FEJL: {pitnavn} forventer numerisk værdi [{ex}].", fg="yellow", bold=True, ) tal = 0 pi = PunktInformation(infotype=pit, punkt=punkt, tal=tal) til_opret.append(pi) punkter_med_oprettelse.add(ident) continue # Ingen ændringer? - så afslutter vi og går til næste element. if r["Sluk"] == r["Ny værdi"] == "": continue # Herfra håndterer vi kun punktinformationer med indførte ændringer # Nu kan vi bruge objektid som heltal (ovenfor havde vi brug for NaN-egenskaben) oid = int(r["id"]) if r["Sluk"] == "x": try: pi = punkt.punktinformationer[infonøgler[oid]] except KeyError: fire.cli.print( f" * Ukendt id - ignorerer element '{oid}'", fg="red", bold=True, ) continue fire.cli.print(f" Slukker: {pitnavn}") # pi._registreringtil = func.current_timestamp() til_sluk.append(pi) punkter_med_slukning.add(punkt.ident) continue fire.cli.print(f" Retter punktinfo-element: {pitnavn}") if pit.anvendelse == PunktInformationTypeAnvendelse.FLAG: pi = PunktInformation(infotype=pit, punkt=punkt) elif pit.anvendelse == PunktInformationTypeAnvendelse.TEKST: # Fjern overflødigt whitespace og duplerede punktummer tekst = r["Ny værdi"] tekst = re.sub(r"[ \t]+", " ", tekst.strip()) tekst = re.sub(r"[.]+", ".", tekst) pi = PunktInformation(infotype=pit, punkt=punkt, tekst=tekst) else: try: tal = float(r["Ny værdi"]) except ValueError as ex: fire.cli.print( f" FEJL: {pitnavn} forventer numerisk værdi [{ex}].", fg="yellow", bold=True, ) tal = 0 pi = PunktInformation(infotype=pit, punkt=punkt, tal=tal) til_ret.append(pi) punkter_med_rettelse.add(punkt.ident) continue fikspunktstyper = [FikspunktsType.GI for _ in nye_punkter] landsnumre = fire.cli.firedb.tilknyt_landsnumre(nye_punkter, fikspunktstyper) til_opret.extend(landsnumre) for p in nye_punkter: punkter_med_oprettelse.add(p.ident) if len(til_opret) > 0 or len(til_ret) > 0: sagsevent = Sagsevent( id=uuid(), sagsid=sag.id, sagseventinfos=[ SagseventInfo(beskrivelse="Opdatering af punktinformationer") ], eventtype=EventType.PUNKTINFO_TILFOEJET, punktinformationer=[*til_opret, *til_ret], ) fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) sagsgang = opdater_sagsgang(sagsgang, sagsevent, sagsbehandler) flush() if len(til_sluk) > 0: sagsevent = Sagsevent( id=uuid(), sagsid=sag.id, sagseventinfos=[ SagseventInfo(beskrivelse="Lukning af punktinformationer") ], eventtype=EventType.PUNKTINFO_FJERNET, punktinformationer_slettede=til_sluk, ) fire.cli.firedb.indset_sagsevent(sagsevent, commit=False) sagsgang = opdater_sagsgang(sagsgang, sagsevent, sagsbehandler) flush() opret_tekst = f"- oprette {len(til_opret)} attributter fordelt på {len(punkter_med_oprettelse)} punkter" sluk_tekst = f"- slukke for {len(til_sluk)} attributter fordelt på {len(punkter_med_slukning)} punkter" ret_tekst = f"- rette {len(til_ret)} attributter fordelt på {len(punkter_med_rettelse)} punkter" lok_tekst = f"- rette {len(nye_lokationer)} lokationskoordinater" fire.cli.print("") fire.cli.print("-" * 50) fire.cli.print("Punkter færdigbehandlet, klar til at") fire.cli.print(opret_tekst) fire.cli.print(sluk_tekst) fire.cli.print(ret_tekst) fire.cli.print(lok_tekst) spørgsmål = click.style( f"Er du sikker på du vil indsætte ovenstående i {fire.cli.firedb.db}-databasen", fg="white", bg="red", ) if bekræft(spørgsmål): fire.cli.firedb.session.commit() skriv_ark(projektnavn, {"Sagsgang": sagsgang}) else: fire.cli.firedb.session.rollback()
sagsbeskrivelse = "Luk alle punkter fra REFGEO hvor MV_STATUS=-1" sagsinfo = Sagsinfo(aktiv="true", behandler="Kristian Evers", beskrivelse=sagsbeskrivelse) sagid = "af190b61-190b-413f-ba4d-432ecaca18d2" try: sag = firedb.hent_sag(sagid) except NoResultFound: sag = Sag(id=sagid, sagsinfos=[sagsinfo]) firedb.indset_sag(sag) sagsevent = Sagsevent( sag=sag, sagseventinfos=[ SagseventInfo(beskrivelse="Lukning af punkter med REFGEO MV_STATUS=-1") ], id=uuid(), eventtype=EventType.PUNKT_NEDLAGT, ) # Udtræk punkter statement = text(""" SELECT p.id FROM hvd_ref@refgeo hr JOIN conv_punkt cp ON hr.refnr=cp.refnr JOIN punkt p ON cp.id=p.id WHERE hr.mv_status=-1 """) refnumre = firedb.session.execute(statement) punktider = [refnr[0] for refnr in refnumre]