|
| 1 | +# + |
| 2 | +import pandas as pd |
| 3 | + |
| 4 | +from sqlalchemy import create_engine |
| 5 | + |
| 6 | +import getpass |
| 7 | +import os |
| 8 | +# - |
| 9 | + |
| 10 | +from fagfunksjoner import ProjectRoot |
| 11 | + |
| 12 | +with ProjectRoot(): |
| 13 | + import Droplister.hjelpefunksjoner as hjfunk |
| 14 | + |
| 15 | +from itables import show |
| 16 | + |
| 17 | +# + |
| 18 | +aar4 = 2024 |
| 19 | +aar2 = str(aar4)[-2:] |
| 20 | + |
| 21 | +aar_før4 = aar4 - 1 # året før |
| 22 | +aar_før2 = str(aar_før4)[-2:] |
| 23 | +# - |
| 24 | + |
| 25 | +username = getpass.getuser() |
| 26 | +dsn = "DB1P" |
| 27 | +try: |
| 28 | + engine = create_engine(f"oracle+cx_oracle://{username}:{password}@{dsn}") |
| 29 | +except: |
| 30 | + print("Passord ikke skrevet inn") |
| 31 | + password = getpass.getpass(prompt='Oracle-passord: ') |
| 32 | + engine = create_engine(f"oracle+cx_oracle://{username}:{password}@{dsn}") |
| 33 | + |
| 34 | +# Opprett en tilkobling fra motoren |
| 35 | +conn = engine.connect() |
| 36 | + |
| 37 | + |
| 38 | + |
| 39 | +sporring = f""" |
| 40 | + SELECT * |
| 41 | + FROM DSBBASE.DLR_ENHET_I_DELREG |
| 42 | + WHERE DELREG_NR IN ('24{aar2}') |
| 43 | +""" |
| 44 | +SFU_enhet = pd.read_sql_query(sporring, conn) |
| 45 | +print(f"Rader: {SFU_enhet.shape[0]}\nKolonner: {SFU_enhet.shape[1]}") |
| 46 | + |
| 47 | + |
| 48 | +# Fjerner enheter uten ORGNR |
| 49 | +print(SFU_enhet['orgnr'].isna().sum()) |
| 50 | +SFU_enhet = SFU_enhet[SFU_enhet['orgnr'].notnull()] |
| 51 | +print(SFU_enhet['orgnr'].isna().sum()) |
| 52 | + |
| 53 | +SFU_enhet.columns = [x.upper() for x in SFU_enhet.columns] |
| 54 | + |
| 55 | +sporring = f""" |
| 56 | + SELECT * |
| 57 | + FROM DSBBASE.DLR_ENHET_I_DELREG_SKJEMA |
| 58 | + WHERE DELREG_NR IN ('24{aar2}') |
| 59 | +""" |
| 60 | +SFU_skjema = pd.read_sql_query(sporring, conn) |
| 61 | +print(f"Rader: {SFU_skjema.shape[0]}\nKolonner: {SFU_skjema.shape[1]}") |
| 62 | + |
| 63 | + |
| 64 | +SFU_skjema.columns = [x.upper() for x in SFU_skjema.columns] |
| 65 | + |
| 66 | +SFU = pd.merge( |
| 67 | + SFU_skjema, |
| 68 | + SFU_enhet, |
| 69 | + how='left', |
| 70 | + on='IDENT_NR', |
| 71 | + suffixes=("_skj","_enh"), |
| 72 | + indicator="_kobling" |
| 73 | +) |
| 74 | + |
| 75 | +SFU._kobling.value_counts() |
| 76 | + |
| 77 | +SFU['NAVN_NY'] = "" |
| 78 | + |
| 79 | +for navn_kol in ["NAVN1", "NAVN2", "NAVN3", "NAVN4", "NAVN5"]: |
| 80 | + SFU['NAVN_NY'] += SFU[navn_kol].fillna("") + " " |
| 81 | + |
| 82 | +SFU['NAVN_NY'] = SFU['NAVN_NY'].str.strip() |
| 83 | + |
| 84 | +SFU[['SKJEMA_TYPE_skj']].value_counts() |
| 85 | + |
| 86 | +skjemaer_som_ikke_skal_ha_påminnelse_februar = ['HELSE0X', 'HELSE0Y', 'HELSE40', 'RA-0595'] |
| 87 | + |
| 88 | +SFU = SFU[~SFU["SKJEMA_TYPE_skj"].isin(skjemaer_som_ikke_skal_ha_påminnelse_februar)] |
| 89 | + |
| 90 | +SFU_grouped = (SFU |
| 91 | + .groupby(["ORGNR_FORETAK", "ORGNR", "NAVN_NY"]) |
| 92 | + .agg( |
| 93 | + unike_skjema=("SKJEMA_TYPE_skj", "unique"), |
| 94 | + ant_skjema_som_skal_leveres=("SKJEMA_TYPE_skj", "nunique"), |
| 95 | + ant_levert=("KVITT_TYPE_skj", "count"), |
| 96 | + ) |
| 97 | +) |
| 98 | +SFU_grouped["leveringsprosent"] = ( |
| 99 | + SFU_grouped["ant_levert"] / SFU_grouped["ant_skjema_som_skal_leveres"] * 100 |
| 100 | +) |
| 101 | + |
| 102 | +SFU_grouped.leveringsprosent.value_counts() |
| 103 | + |
| 104 | +påminnelse = SFU_grouped[SFU_grouped['leveringsprosent'] < 100].sort_values('leveringsprosent', ascending=False).copy() |
| 105 | + |
| 106 | +cols = ( |
| 107 | + ["IDENT_NR", "NAVN_NY"] |
| 108 | + + [col for col in SFU if "ORGNR" in col] |
| 109 | + + [col for col in SFU if "H_VAR" in col] |
| 110 | + + [col for col in SFU if "TYPE" in col] |
| 111 | +) |
| 112 | +SFU2 = SFU[cols].copy() |
| 113 | + |
| 114 | +# + |
| 115 | +sporring = """ |
| 116 | +SELECT * |
| 117 | +FROM all_tables |
| 118 | +
|
| 119 | +ORDER BY table_name ASC |
| 120 | +""" |
| 121 | + |
| 122 | +tabeller = hjfunk.les_sql(sporring, conn) |
| 123 | +tabellnavn = ( |
| 124 | + tabeller |
| 125 | + [tabeller['TABLESPACE_NAME'] == "DSBBASE"] |
| 126 | + .TABLE_NAME.unique() |
| 127 | +) |
| 128 | +# - |
| 129 | + |
| 130 | +# `tabeller` inneholder alle tabellene i Oracle. Den er som et oppslagsverk for å finne hvor hvordan man skrive SQL-spørringer. Filtrerer ut tabellene i tråd med navnsystemet beskrevet over. |
| 131 | + |
| 132 | +mask_kostra = tabeller['OWNER'] == "KOSTRA_EXP" |
| 133 | +mask_helse = tabeller['TABLE_NAME'].str.startswith("HELSE") |
| 134 | +mask_årgang = tabeller['TABLE_NAME'].str.endswith(str(aar_før4)) |
| 135 | +skjemaer = tabeller[mask_kostra & mask_helse & mask_årgang].TABLE_NAME.unique() |
| 136 | + |
| 137 | +skjemaer |
| 138 | + |
| 139 | +# Velger ut de kolonnene jeg ønsker å ha med videre, men ser at kolonnenavnene ikke er likt på tvers av skjemaene. Har dermed manuelt gått gjennom tabellene og sett hva de heter. Legger til slutt en dictionary med oversikt over hvilke skjemaer som har hvilke kolonnenavn. |
| 140 | + |
| 141 | +utkols_o = ["FORETAKETS_ORGNR", "FORETAKETS_NAVN", "HELSEREGION_UTFYLT", |
| 142 | + "HELSEREGION_EPOST", "SKJEMA_TYPE", "AARGANG"] |
| 143 | + |
| 144 | +# Mangler FORETAKETS_NAVN i registeret (Vurdere å kople på). Setter inn |
| 145 | +# tom variabel KVARTAL og sletter denne senere |
| 146 | +utkols_0X0Y = ["ORG_NR", "KVARTAL", "SKJEMA_UTFYLT", |
| 147 | + "EPOSTADR", "SKJEMA_TYPE", |
| 148 | + "AARGANG"] |
| 149 | + |
| 150 | +utkols_48 = ['FORETAKETS_ORGNR', |
| 151 | + 'FORETAKETS_NAVN', |
| 152 | + 'HELSEREGION_KONTAKTPERSON', |
| 153 | + 'HELSEREGION_EPOST', |
| 154 | + 'SKJEMA_TYPE', |
| 155 | + 'AARGANG'] |
| 156 | + |
| 157 | +utkols_46P = ['FORETAK_ORGNR', |
| 158 | + 'FORETAK_NAVN', |
| 159 | + 'HELSEREGION_UTFYLT', |
| 160 | + 'HELSEREGION_EPOST', |
| 161 | + 'SKJEMA_TYPE', |
| 162 | + 'AARGANG'] |
| 163 | + |
| 164 | +skj_kol_dict = { |
| 165 | + 'HELSE0X': utkols_0X0Y, |
| 166 | + 'HELSE0Y': utkols_0X0Y, |
| 167 | + 'HELSE38O': utkols_o, |
| 168 | + 'HELSE38P': utkols_o, |
| 169 | + 'HELSE39': utkols_o, |
| 170 | + 'HELSE40': utkols_o, |
| 171 | + 'HELSE41': utkols_o, |
| 172 | + 'HELSE44O': utkols_o, |
| 173 | + 'HELSE44P': utkols_o, |
| 174 | + 'HELSE45O': utkols_o, |
| 175 | + 'HELSE45P': utkols_o, |
| 176 | + 'HELSE46O': utkols_o, |
| 177 | + 'HELSE46P': utkols_46P, |
| 178 | + 'HELSE46': utkols_o, |
| 179 | + 'HELSE47': utkols_o, |
| 180 | + 'HELSE48': utkols_48, |
| 181 | +} |
| 182 | + |
| 183 | + |
| 184 | +def hent_skjema(s): |
| 185 | + """ |
| 186 | + Funksjon som henter inn alle variable fra angitt tabell s. |
| 187 | + """ |
| 188 | + |
| 189 | + sporring = f""" |
| 190 | + SELECT * |
| 191 | + FROM KOSTRA_EXP.{s} |
| 192 | + """ |
| 193 | + df = hjfunk.les_sql(sporring, conn) |
| 194 | + return df |
| 195 | + |
| 196 | + |
| 197 | +# tar bort årgang fra tabellnavnet |
| 198 | +skj_dict = {} |
| 199 | +for skj in skjemaer: |
| 200 | + df = hent_skjema(skj) |
| 201 | + s = skj.replace("_" + str(aar_før4), "") |
| 202 | + skj_dict[s] = df |
| 203 | + |
| 204 | +# lager en tom dataframe og legger suksessivt til info til en stor mastertabell |
| 205 | +kontakt_df = pd.DataFrame() |
| 206 | + |
| 207 | +for skj in skj_dict: |
| 208 | + kolonner_temp = skj_kol_dict[skj] |
| 209 | + df_temp = skj_dict[skj][kolonner_temp].copy() |
| 210 | + |
| 211 | + if skj == "HELSE0X" or skj == "HELSE0Y": |
| 212 | + # brukte denne variabelen som dummy-variabel, fordi navn på foretak ikke |
| 213 | + # var med i denne tabellen |
| 214 | + df_temp['KVARTAL'] = "" |
| 215 | + |
| 216 | + # Har nå forsikret meg om at kolonnerekkefølgen er lik for alle tabeller |
| 217 | + # og gjør navneendring basert på rekkefølge |
| 218 | + df_temp.columns = ['ORGNR_FORETAK', 'NAVN_FORETAK', 'KONTAKTPERSON', 'EPOSTADR', 'SKJEMA_TYPE', 'AARGANG'] |
| 219 | + |
| 220 | + kontakt_df = pd.concat([kontakt_df, df_temp]) |
| 221 | + |
| 222 | + |
| 223 | +kontakt_df = kontakt_df.drop_duplicates() |
| 224 | + |
| 225 | +kontakt_df.ORGNR_FORETAK = pd.to_numeric(kontakt_df.ORGNR_FORETAK).astype('str').str.replace(".0", "") |
| 226 | + |
| 227 | +SFU3 = SFU2[SFU2['KVITT_TYPE_skj'].isna()].copy()[['ORGNR', 'ORGNR_FORETAK', 'NAVN_NY', 'SKJEMA_TYPE_skj', 'KVITT_TYPE_skj']] |
| 228 | + |
| 229 | + |
| 230 | + |
| 231 | +påminnelse_df = pd.merge( |
| 232 | + SFU3, |
| 233 | + kontakt_df, |
| 234 | + left_on=['ORGNR_FORETAK', 'SKJEMA_TYPE_skj'], |
| 235 | + right_on=['ORGNR_FORETAK', 'SKJEMA_TYPE'], |
| 236 | + how='left', |
| 237 | + indicator=True |
| 238 | +) |
| 239 | + |
| 240 | +påminnelse_df[påminnelse_df['_merge'] == 'left_only'] |
| 241 | + |
| 242 | +påminnelse_df['EPOSTADR_lower'] = påminnelse_df['EPOSTADR'].str.lower() |
| 243 | + |
| 244 | +påminnelse_grouped_epost = påminnelse_df.groupby(['EPOSTADR_lower', 'KONTAKTPERSON', 'ORGNR_FORETAK']).agg( |
| 245 | + SKJEMA_TYPER=('SKJEMA_TYPE', 'unique'), |
| 246 | + ORGNR=('ORGNR', 'unique'), |
| 247 | + NAVN=('NAVN_NY', 'unique') |
| 248 | +) |
| 249 | + |
| 250 | +påminnelse_grouped_epost = påminnelse_grouped_epost.reset_index() |
| 251 | + |
| 252 | +len(påminnelse_grouped_epost) |
| 253 | + |
| 254 | + |
| 255 | +def helse_to_skjema(s: str): |
| 256 | + return s.replace("HELSE", "") |
| 257 | + |
| 258 | + |
| 259 | +påminnelse_grouped_epost["SKJEMA_TYPER"] = ( |
| 260 | + påminnelse_grouped_epost["SKJEMA_TYPER"] |
| 261 | + .apply(lambda x: (", ").join(x)) |
| 262 | + .apply(helse_to_skjema) |
| 263 | +) |
| 264 | +påminnelse_grouped_epost["ORGNR"] = påminnelse_grouped_epost["ORGNR"].apply( |
| 265 | + lambda x: (", ").join(x) |
| 266 | +) |
| 267 | +påminnelse_grouped_epost["NAVN"] = påminnelse_grouped_epost["NAVN"].apply( |
| 268 | + lambda x: (", ").join(x) |
| 269 | +) |
| 270 | + |
| 271 | +påminnelse_grouped_epost |
| 272 | + |
| 273 | + |
| 274 | +def korrekt_navn(navnestreng: str) -> str: |
| 275 | + # Del opp strengen på mellomrom |
| 276 | + ordliste = navnestreng.split() |
| 277 | + ny_ordliste = [] |
| 278 | + |
| 279 | + for ord in ordliste: |
| 280 | + # Hvis ordet inneholder bindestrek, splitt på den og kapitaliser hver del |
| 281 | + if '-' in ord: |
| 282 | + deler = ord.split('-') |
| 283 | + nye_deler = [ |
| 284 | + delord[0].upper() + delord[1:].lower() if delord else "" |
| 285 | + for delord in deler |
| 286 | + ] |
| 287 | + nytt_ord = '-'.join(nye_deler) |
| 288 | + else: |
| 289 | + nytt_ord = ord[0].upper() + ord[1:].lower() if ord else "" |
| 290 | + ny_ordliste.append(nytt_ord) |
| 291 | + |
| 292 | + return " ".join(ny_ordliste) |
| 293 | + |
| 294 | + |
| 295 | +påminnelse_grouped_epost["KONTAKTPERSON"] = ( |
| 296 | + påminnelse_grouped_epost["KONTAKTPERSON"].str.lower().apply(korrekt_navn) |
| 297 | +) |
| 298 | + |
| 299 | +# + |
| 300 | +from pathlib import Path |
| 301 | + |
| 302 | +filepath = Path.cwd().parent.parent / "data_temp" / "påminnelse.xlsx" |
| 303 | +påminnelse_grouped_epost.to_excel(filepath, index=False) |
| 304 | +# - |
| 305 | + |
| 306 | + |
| 307 | + |
| 308 | + |
| 309 | + |
| 310 | + |
| 311 | + |
| 312 | + |
| 313 | + |
| 314 | + |
| 315 | + |
| 316 | + |
| 317 | + |
| 318 | + |
| 319 | + |
| 320 | +mangler_epost_list = påminnelse_df[påminnelse_df['_merge'] == 'left_only']['ORGNR_FORETAK'].to_list() |
| 321 | + |
| 322 | +mangler_df = SFU[SFU['ORGNR_FORETAK'].isin(mangler_epost_list)].copy() |
| 323 | + |
| 324 | +mangler_df[['ORGNR_FORETAK', 'ORGNR', 'NAVN_NY'] + [col for col in mangler_df.columns if 'POST' in col]] |
| 325 | + |
| 326 | + |
| 327 | + |
| 328 | + |
| 329 | + |
| 330 | + |
| 331 | + |
| 332 | + |
| 333 | + |
| 334 | +SFU_enhet[SFU_enhet['NAVN'].str.contains("HALL")][['NAVN', 'ORGNR', 'ORGNR_FORETAK']] |
| 335 | + |
| 336 | +SFU_skjema |
0 commit comments