diff --git a/Makefile b/Makefile index 7c3c25a256b1cd92fb50cd551728a9a7e1fef5a0..3dd614c86ac23378503faeb83ea56ac0ea4bf49c 100644 --- a/Makefile +++ b/Makefile @@ -18,6 +18,7 @@ help: @echo "Application:" @echo " run Run the application on port ${PORT}" @echo " shell Access the Django shell" + @echo " sync Sync with the old contract registry" @echo "" @echo "Database:" @echo " migrations Generate migrations" @@ -47,6 +48,9 @@ run: venv shell: venv ${VENV}/bin/python manage.py shell --settings=${SETTINGS} +sync: + ${VENV}/bin/python manage.py import_old_contracts https://github.com/pirati-web/smlouvy.pirati.cz.git gh-pages --settings=${SETTINGS} --delete -v 3 + migrations: venv ${VENV}/bin/python manage.py makemigrations --settings=${SETTINGS} diff --git a/contracts/admin.py b/contracts/admin.py index 264fb42788d820632c060a502af93b91e4ecc925..593e03216894c850170f3fc8b922ac7ac40155e9 100644 --- a/contracts/admin.py +++ b/contracts/admin.py @@ -363,7 +363,9 @@ class ContractAdmin( AutocompleteFilterFactory("Typ", "types"), AutocompleteFilterFactory("Spisovna", "filing_area"), AutocompleteFilterFactory("Problém", "issues"), - AutocompleteFilterFactory("Naše smluvná strana", "contractee_signatures__contractee"), + AutocompleteFilterFactory( + "Naše smluvná strana", "contractee_signatures__contractee" + ), AutocompleteFilterFactory("Jiná smluvní strana", "signee_signatures__signee"), "is_approved", "is_valid", diff --git a/contracts/management/commands/import_old_contracts.py b/contracts/management/commands/import_old_contracts.py index 4fcc2485d281e0984e472ded7a133e07b6f49e3f..36a3b9e416f290261f1736fd9e15495626ec8f46 100644 --- a/contracts/management/commands/import_old_contracts.py +++ b/contracts/management/commands/import_old_contracts.py @@ -2,6 +2,7 @@ import io import os import re import string +import shutil from datetime import date, datetime import yaml @@ -15,14 +16,15 @@ from git import Repo from ...models import ( Contract, + Contractee, + ContracteeSignature, + ContracteeSignatureRepresentative, ContractFile, ContractFilingArea, + ContractIssue, ContractType, - Contractee, Signee, SigneeSignature, - ContracteeSignature, - ContracteeSignatureRepresentative, SigneeSignatureRepresentative, ) @@ -56,6 +58,11 @@ class Command(BaseCommand): type=str, help="Directory to store the cloned repository in", ) + parser.add_argument( + "--delete", + action="store_true", + help="Delete the old temporary storage directory, if it exists.", + ) parser.add_argument( "--existing", action="store_true", @@ -67,14 +74,19 @@ class Command(BaseCommand): help="Purge all previous contracts, types and filing areas before the import.", ) + def use_issue(self, contract, name: str) -> None: + try: + issue = ContractIssue.objects.get(name=name) + except ContractIssue.DoesNotExist: + issue = ContractIssue(name=name) + + return issue + def normalize_type(self, type_name: str) -> str: type_name = string.capwords(type_name) patterns = ( - ( - r"\s\s+", - " " - ), + (r"\s\s+", " "), (r" O ", " o "), (r" S ", " s "), (r" K ", " k "), @@ -150,30 +162,12 @@ class Command(BaseCommand): type_name = type_name.strip() patterns = ( - ( - r"\s\s+", - " " - ), - ( - r"^Kraské sdružení Praha$", - "Krajské sdružení Praha" - ), - ( - r"^republikové předsednictvo$", - "Republikové předsednictvo" - ), - ( - r"^KS ", - "Krajské sdružení " - ), - ( - r"^(MS |místní sdružení )", - "Místní sdružení " - ), - ( - r"^(Ústecký kraj|Ustecký kraj)$", - "Krajské sdružení Ústecký kraj" - ), + (r"\s\s+", " "), + (r"^Kraské sdružení Praha$", "Krajské sdružení Praha"), + (r"^republikové předsednictvo$", "Republikové předsednictvo"), + (r"^KS ", "Krajské sdružení "), + (r"^(MS |místní sdružení )", "Místní sdružení "), + (r"^(Ústecký kraj|Ustecký kraj)$", "Krajské sdružení Ústecký kraj"), ( r"^Moravskoslezský kraj$", "Krajské sdružení Moravskoslezský kraj", @@ -186,130 +180,40 @@ class Command(BaseCommand): r"Jihočeská kraj", "Jihočeský kraj", ), - ( - r"^(Krajského |krajské |Kajské )", - "Krajské " - ), - ( - "^Poslanecký klub České pirátské strany$", - "Poslanecký klub" - ), - ( - r"Středočeký", - "Středočeský" - ), - ( - r"^Zahraničního odboru$", - "Zahraniční odbor" - ), - ( - r"JčK", - "Jihočeský kraj" - ), - ( - r"SčK", - "Středočeský kraj" - ), - ( - r"(ÚsK|UsK)", - "Ústecký kraj" - ), - ( - r"JmK", - "Jihomoravský kraj" - ), - ( - r"PaK", - "Pardubický kraj" - ), - ( - r"KhK", - "Královehradecký kraj" - ), - ( - r"(Prsonální|personální)", - "Personální" - ), - ( - r"^administrativní ", - "Administrativní " - ), - ( - r"technický", - "Technický" - ), - ( - r"Mediálni", - "Technický" - ), - ( - r"^řešitel ", - "Řešitel " - ), - ( - r"^předsednictvo ", - "Předsednictvo " - ), - ( - r"olomoucký", - "Olomoucký" - ), - ( - r"^místní ", - "Místní " - ), - ( - r"^celostátní ", - "Celostátní " - ), - ( - r"odbor", - "Odbor" - ), - ( - r"PKS", - "Předsednictvo krajského sdružení" - ), - ( - r"( KS | Krajského sdružení )", - " krajského sdružení " - ), + (r"^(Krajského |krajské |Kajské )", "Krajské "), + ("^Poslanecký klub České pirátské strany$", "Poslanecký klub"), + (r"Středočeký", "Středočeský"), + (r"^Zahraničního odboru$", "Zahraniční odbor"), + (r"JčK", "Jihočeský kraj"), + (r"SčK", "Středočeský kraj"), + (r"(ÚsK|UsK)", "Ústecký kraj"), + (r"JmK", "Jihomoravský kraj"), + (r"PaK", "Pardubický kraj"), + (r"KhK", "Královehradecký kraj"), + (r"(Prsonální|personální)", "Personální"), + (r"^administrativní ", "Administrativní "), + (r"technický", "Technický"), + (r"Mediálni", "Technický"), + (r"^řešitel ", "Řešitel "), + (r"^předsednictvo ", "Předsednictvo "), + (r"olomoucký", "Olomoucký"), + (r"^místní ", "Místní "), + (r"^celostátní ", "Celostátní "), + (r"odbor", "Odbor"), + (r"PKS", "Předsednictvo krajského sdružení"), + (r"( KS | Krajského sdružení )", " krajského sdružení "), ( r"^(Předsednictvo krajského sdružení |Předsednictvo |Místní předsednictvo )", - "" - ), - ( - r"^Krajské předsednictvo ", - "Krajské sdružení " - ), - ( - r"ého kraje$", - "ý kraj" - ), - ( - r"^Olomouc$", - "Místní sdružení Olomouc" - ), - ( - r"^Olomoucký kraj$", - "Krajské sdružení Olomoucký kraj" - ), - ( - r"^Pardubický kraj$", - "Krajské sdružení Pardubický kraj" - ), - ( - r"^Jihočeský kraj$", - "Krajské sdružení Jihočeský kraj" - ), - ( - r"^Královehradecký kraj$", - "Krajské sdružení Královehradecký kraj" - ), - ( - r"^Pardubický kraj$", - "Krajské sdružení Pardubický kraj" - ), + "", + ), + (r"^Krajské předsednictvo ", "Krajské sdružení "), + (r"ého kraje$", "ý kraj"), + (r"^Olomouc$", "Místní sdružení Olomouc"), + (r"^Olomoucký kraj$", "Krajské sdružení Olomoucký kraj"), + (r"^Pardubický kraj$", "Krajské sdružení Pardubický kraj"), + (r"^Jihočeský kraj$", "Krajské sdružení Jihočeský kraj"), + (r"^Královehradecký kraj$", "Krajské sdružení Královehradecký kraj"), + (r"^Pardubický kraj$", "Krajské sdružení Pardubický kraj"), ) for pattern in patterns: @@ -321,10 +225,7 @@ class Command(BaseCommand): area_name = string.capwords(area_name) patterns = ( - ( - r"\s\s+", - " " - ), + (r"\s\s+", " "), ( r"^(Cenrální Spisovna|Censtrální Spisovna|Centrála|Centrálách Archiv Str" r"any|Centrála Strany|Centrální Achiv Strany|Centrální Archiv|Centralni " @@ -414,22 +315,13 @@ class Command(BaseCommand): filename = string.capwords(filename) patterns = ( - ( - r"\s\s+", - " " - ), + (r"\s\s+", " "), ( r"^((P|p)odepsaná (V|v)erze|Strojově Čitelná Verze)$", "Anonymizovaná verze", ), - ( - r"^(P|p)odepsaná (V|v)erze 2$", - "Anonymizovaná verze 2" - ), - ( - r"^(U|u)pravitelná (V|v)erze$", - "Upravitelná verze" - ) + (r"^(P|p)odepsaná (V|v)erze 2$", "Anonymizovaná verze 2"), + (r"^(U|u)pravitelná (V|v)erze$", "Upravitelná verze"), ) for pattern in patterns: @@ -473,17 +365,16 @@ class Command(BaseCommand): return parsed_metadata def assign_signing_party_metadata( - self, - slug: str, - contract: Contract, - signing_party: dict + self, slug: str, contract: Contract, signing_party: dict ) -> tuple[ - Contract|Signee, - list[ContracteeSignatureRepresentative|SigneeSignatureRepresentative], + Contract | Signee, + list[ContractIssue], + list[ContracteeSignatureRepresentative | SigneeSignatureRepresentative], bool, - int + int, ]: issue_count = 0 + issues = [] if ( "jméno" not in signing_party @@ -491,7 +382,10 @@ class Command(BaseCommand): and "název společnosti" not in signing_party ): issue_count += 1 - contract.notes += f"Nepojmenovaná smluvní strana, zdrojová data: {signing_party}\n" + contract.notes += ( + f"Nepojmenovaná smluvní strana, zdrojová data: {signing_party}\n" + ) + issues.append(self.use_issue(contract, "Špatně pojmenovaná smluvní strana")) if self.verbosity >= 2: self.stderr.write( @@ -503,114 +397,44 @@ class Command(BaseCommand): return issue_count name = signing_party.get( - "jméno", - signing_party.get( - "název", - signing_party.get("název společnosti") - ) + "jméno", signing_party.get("název", signing_party.get("název společnosti")) ).strip() patterns = ( - ( - r"\s\s+", - " " - ), - ( - r"^(1\. Pirátská s\.r\.o|1\.Pirátská s\.r\.o\.)$", - "1. Pirátská s.r.o." - ), - ( - r"České pojišťovna, a.s.", - "Česká pojišťovna, a.s." - ), - ( - r"Datrolex, s.r.o.", - "DATROLEX, s.r.o." - ), - ( - r"^Jiri ", - "Jiří " - ), + (r"\s\s+", " "), + (r"^(1\. Pirátská s\.r\.o|1\.Pirátská s\.r\.o\.)$", "1. Pirátská s.r.o."), + (r"České pojišťovna, a.s.", "Česká pojišťovna, a.s."), + (r"Datrolex, s.r.o.", "DATROLEX, s.r.o."), + (r"^Jiri ", "Jiří "), ( ( r"^(Křesťanská a demokratická unie – Československá strana lidová|" r"Křesťansko demokratická unie – Československá strana lidová|Křes" r"ťanská a demokratická unie - Československá strana lidová)$" ), - "Křesťanská a demokratická unie – Československá strana lidová" - ), - ( - r"LN - Audit s\.r\.o\." - "LN-AUDIT s.r.o." - ), - ( - r"Olga Richteová", - "Olga Richterová" + "Křesťanská a demokratická unie – Československá strana lidová", ), + (r"LN - Audit s\.r\.o\." "LN-AUDIT s.r.o."), + (r"Olga Richteová", "Olga Richterová"), ( r"^(politické hnutí Změna|PolitickéHnutí Změna)$", - "Politické hnutí Změna" - ), - ( - r"^Systemický institut s\.r\.o\$", - "Systemický institut, s.r.o." - ), - ( - r"^Václav fořtík$", - "Václav Fořtík" - ), - ( - r"^Vodafone$", - "Vodafone Czech Republic a.s." - ), - ( - r"^VojtěchHolík$", - "Vojtěch Holík" - ), - ( - r"^Vojtech ", - "Vojtěch " - ), - ( - r"^Zdenek ", - "Zdeněk " - ), - ( - r" Bohmova$", - " Bohmová" - ), - ( - r" (KUdláčková|Kudlláčková)$", - " Kudláčková" - ), - ( - r"^Jiří knotek$", - "Jiří Knotek" - ), - ( - r"^JIří Roubíček$", - "Jiří Roubíček" - ), - ( - r"^Koalice Vlasta\. z\.s\.$", - "Koalice Vlasta, z.s." - ), - ( - r"^Mikuáš ", - "Mikuláš " - ), - ( - r"^Strana zelených$", - "Strana Zelených" - ), - ( - r"^Systemický institut s\.r\.o\.$", - "Systemický institut, s.r.o." - ), - ( - r"^Adéla hradilová$", - "Adéla Hradilová" - ) + "Politické hnutí Změna", + ), + (r"^Systemický institut s\.r\.o\$", "Systemický institut, s.r.o."), + (r"^Václav fořtík$", "Václav Fořtík"), + (r"^Vodafone$", "Vodafone Czech Republic a.s."), + (r"^VojtěchHolík$", "Vojtěch Holík"), + (r"^Vojtech ", "Vojtěch "), + (r"^Zdenek ", "Zdeněk "), + (r" Bohmova$", " Bohmová"), + (r" (KUdláčková|Kudlláčková)$", " Kudláčková"), + (r"^Jiří knotek$", "Jiří Knotek"), + (r"^JIří Roubíček$", "Jiří Roubíček"), + (r"^Koalice Vlasta\. z\.s\.$", "Koalice Vlasta, z.s."), + (r"^Mikuáš ", "Mikuláš "), + (r"^Strana zelených$", "Strana Zelených"), + (r"^Systemický institut s\.r\.o\.$", "Systemický institut, s.r.o."), + (r"^Adéla hradilová$", "Adéla Hradilová"), ) for pattern in patterns: @@ -648,6 +472,11 @@ class Command(BaseCommand): if not isinstance(signing_party_value, str): issue_count += 1 contract.notes += f"Špatně zadané sídlo smluvní strany: {signing_party_value}\n" + issues.append( + self.use_issue( + contract, "Špatně zadané sídlo smluvní strany" + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -669,21 +498,31 @@ class Command(BaseCommand): instance.address_street_with_number = "" if "road" in address: - instance.address_street_with_number = string.capwords(address["road"]) + instance.address_street_with_number = string.capwords( + address["road"] + ) if "house_number" in address: - instance.address_street_with_number += f" {address['house_number']}" + instance.address_street_with_number += ( + f" {address['house_number']}" + ) for address_key, address_value in address.items(): match address_key: case "city": if "district" not in address: - instance.address_district = string.capwords(address_value) + instance.address_district = string.capwords( + address_value + ) case "house": if "city" not in address and "district" not in address: - instance.address_district = string.capwords(address_value) + instance.address_district = string.capwords( + address_value + ) case "city_district": - instance.address_district = string.capwords(address_value) + instance.address_district = string.capwords( + address_value + ) case "postcode": instance.address_zip = string.capwords(address_value) @@ -692,9 +531,14 @@ class Command(BaseCommand): if is_contractee: continue - if not isinstance(signing_party_value, int|str): + if not isinstance(signing_party_value, int | str): issue_count += 1 - contract.notes += f"Špatně zadané IČO smluvní strany: {signing_party_value}\n" + contract.notes += ( + f"Špatně zadané IČO smluvní strany: {signing_party_value}\n" + ) + issues.append( + self.use_issue(contract, "Špatně zadané IČO smluvní strany") + ) if self.verbosity >= 2: self.stderr.write( @@ -707,9 +551,14 @@ class Command(BaseCommand): instance.ico_number = str(signing_party_value) case "zástupce": - if not isinstance(signing_party_value, str|list): + if not isinstance(signing_party_value, str | list): issue_count += 1 contract.notes += f"Špatně zadaný zástupce smluvní strany: {signing_party_value}\n" + issues.append( + self.use_issue( + contract, "Špatně zadaný zástupce smluvní strany" + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -722,11 +571,7 @@ class Command(BaseCommand): continue if isinstance(signing_party_value, str): - signing_party_value = re.sub( - r",$", - "", - signing_party_value - ) + signing_party_value = re.sub(r",$", "", signing_party_value) self.normalization_count += 1 function = None @@ -737,6 +582,12 @@ class Command(BaseCommand): else: issue_count += 1 contract.notes += f"Špatně zadaná funkce zástupce smluvní strany: {signing_party['funkce']}\n" + issues.append( + self.use_issue( + contract, + "Špatně zadaná funkce zástupce smluvní strany", + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -747,15 +598,19 @@ class Command(BaseCommand): ) representatives.append( - representative_model( - name=signing_party_value - ) + representative_model(name=signing_party_value) ) else: for representative_name in signing_party_value: if not isinstance(representative_name, str): issue_count += 1 contract.notes += f"Špatně zadaný jeden ze zástupců smluvní strany: {representative_name}\n" + issues.append( + self.use_issue( + contract, + "Špatně zadaný zástupce smluvní strany", + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -767,22 +622,21 @@ class Command(BaseCommand): continue - representative_name = re.sub( - r",$", - "", - representative_name - ) + representative_name = re.sub(r",$", "", representative_name) self.normalization_count += 1 representatives.append( - representative_model( - name=signing_party_value - ) + representative_model(name=signing_party_value) ) case "orgán": if not isinstance(signing_party_value, str): issue_count += 1 contract.notes += f"Špatně zadaný orgán smluvní strany: {signing_party_value}\n" + issues.append( + self.use_issue( + contract, "Špatně zadaný orgán smluvní strany" + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -844,10 +698,13 @@ class Command(BaseCommand): ) & ( ( - models.Q(address_street_with_number=instance.address_street_with_number) + models.Q( + address_street_with_number=instance.address_street_with_number + ) if instance.address_street_with_number is not None else models.Q(address_street_with_number__isnull=True) - ) | ( + ) + | ( models.Q(date_of_birth=instance.date_of_birth) if model is Signee and instance.date_of_birth is not None else ( @@ -874,12 +731,18 @@ class Command(BaseCommand): if len(existing_instances) != 0: for position, existing_instance in enumerate(existing_instances): - if existing_instance.ico_number is None and instance.ico_number is not None: + if ( + existing_instance.ico_number is None + and instance.ico_number is not None + ): existing_instance.ico_number = instance.ico_number existing_instance.save() instance = existing_instance break - elif existing_instance.ico_number == instance.ico_number or instance.ico_number is None: + elif ( + existing_instance.ico_number == instance.ico_number + or instance.ico_number is None + ): instance = existing_instance break elif position == len(existing_instances) - 1: @@ -887,7 +750,7 @@ class Command(BaseCommand): else: instance.save() - return instance, representatives, is_contractee, issue_count + return instance, issues, representatives, is_contractee, issue_count def assign_contract_data( self, @@ -901,6 +764,7 @@ class Command(BaseCommand): signees = [] contractees = [] files = [] + issues = [] is_already_imported = False observed_issues_count = 0 @@ -918,6 +782,9 @@ class Command(BaseCommand): elif value is not None: observed_issues_count += 1 contract.notes += f"Špatně zadaný začátek platnosti: {value}\n" + issues.append( + self.use_issue(contract, "Špatně zadaný začátek platnosti") + ) if self.verbosity >= 2: self.stderr.write( @@ -934,6 +801,9 @@ class Command(BaseCommand): ): observed_issues_count += 1 contract.notes += f"Špatně zadaný konec platnosti: {value}\n" + issues.append( + self.use_issue(contract, "Špatně zadaný konec platnosti") + ) if self.verbosity >= 2: self.stderr.write( @@ -969,6 +839,7 @@ class Command(BaseCommand): elif not isinstance(value, list): observed_issues_count += 1 contract.notes += f"Špatně zadané typy: {value}\n" + issues.append(self.use_issue(contract, "Špatně zadané typy")) if self.verbosity >= 2: self.stderr.write( @@ -982,7 +853,8 @@ class Command(BaseCommand): for type_name in value: if not isinstance(type_name, str): observed_issues_count += 1 - contract.notes += f"Nezaevidovaný typ: {type_name}\n" + contract.notes += f"Špatně zadaný typ: {type_name}\n" + issues.append(self.use_issue(contract, "Špatně zadaný typ")) if self.verbosity >= 2: self.stderr.write( @@ -1024,6 +896,7 @@ class Command(BaseCommand): else: observed_issues_count += 1 contract.notes += f"Neznámý stav: {value}\n" + issues.append(self.use_issue(contract, "Neznámý právní stav")) if self.verbosity >= 2: self.stderr.write( @@ -1044,6 +917,9 @@ class Command(BaseCommand): contract.notes += ( f"Původní, špatně zadané náklady: {value}\n" ) + issues.append( + self.use_issue(contract, "Špatně zadané náklady") + ) if self.verbosity >= 2: self.stderr.write( @@ -1071,6 +947,9 @@ class Command(BaseCommand): ): observed_issues_count += 1 contract.notes += f"Původní, neropoznané náklady: {value}\n" + issues.append( + self.use_issue(contract, "Špatně zadané náklady") + ) if self.verbosity >= 2: self.stderr.write( @@ -1086,6 +965,7 @@ class Command(BaseCommand): elif value not in (None, "0"): observed_issues_count += 1 contract.notes += f"Původní, neropoznané náklady: {value}\n" + issues.append(self.use_issue(contract, "Špatně zadané náklady")) if self.verbosity >= 2: self.stderr.write( @@ -1110,6 +990,9 @@ class Command(BaseCommand): else: observed_issues_count += 1 contract.notes += f"Špatně zadaná spisovna: {value}\n" + issues.append( + self.use_issue(contract, "Špatně zadaná spisovna") + ) if self.verbosity >= 2: self.stderr.write( @@ -1120,7 +1003,12 @@ class Command(BaseCommand): case "smluvní strany": if not isinstance(value, list): observed_issues_count += 1 - contract.notes += f"Špatně zadané smluvní strany, nejsou seznam: {value}\n" + contract.notes += ( + f"Špatně zadané smluvní strany, nejsou seznam: {value}\n" + ) + issues.append( + self.use_issue(contract, "Špatně zadaný smluvní strany") + ) if self.verbosity >= 2: self.stderr.write( @@ -1134,7 +1022,12 @@ class Command(BaseCommand): for signing_party in value: if not isinstance(signing_party, dict): observed_issues_count += 1 - contract.notes += f"Špatně zadaná smluvní strana: {signing_party}\n" + contract.notes += ( + f"Špatně zadaná smluvní strana: {signing_party}\n" + ) + issues.append( + self.use_issue(contract, "Špatně zadaná smluvní strana") + ) if self.verbosity >= 2: self.stderr.write( @@ -1145,10 +1038,17 @@ class Command(BaseCommand): continue - instance, representatives, is_contractee, signing_party_issue_count = ( - self.assign_signing_party_metadata(slug, contract, signing_party) + ( + instance, + signing_party_issues, + representatives, + is_contractee, + signing_party_issue_count, + ) = self.assign_signing_party_metadata( + slug, contract, signing_party ) + issues += signing_party_issues observed_issues_count += signing_party_issue_count # Store representatives in relation to the instance, hacky but good enough @@ -1162,6 +1062,7 @@ class Command(BaseCommand): if not isinstance(value, list): observed_issues_count += 1 contract.notes += f"Špatně zadané soubory.\n" + issues.append(self.use_issue(contract, "Špatně zadané soubory")) if self.verbosity >= 2: self.stderr.write( @@ -1175,7 +1076,14 @@ class Command(BaseCommand): for file_data in value: if not isinstance(file_data, dict): observed_issues_count += 1 - contract.notes += f"Špatně zadané informace o souboru: {file_data}.\n" + contract.notes += ( + f"Špatně zadané informace o souboru: {file_data}.\n" + ) + issues.append( + self.use_issue( + contract, "Špatně zadané informace o souboru" + ) + ) if self.verbosity >= 2: self.stderr.write( @@ -1195,6 +1103,9 @@ class Command(BaseCommand): if not isinstance(file_value, str): observed_issues_count += 1 contract.notes += f"Špatně zadaný název souboru {file_key}: {file_value}.\n" + issues.append( + self.use_issue(contract, "Neplatný název souboru") + ) if self.verbosity >= 2: self.stderr.write( @@ -1205,14 +1116,16 @@ class Command(BaseCommand): continue - file_path = os.path.join( - contract_root, - file_value - ) + file_path = os.path.join(contract_root, file_value) if not os.path.isfile(file_path): observed_issues_count += 1 - contract.notes += f"Neexistující soubor: {file_value}.\n" + contract.notes += ( + f"Neexistující soubor: {file_value}.\n" + ) + issues.append( + self.use_issue(contract, "Neexistující soubor") + ) if self.verbosity >= 2: self.stderr.write( @@ -1228,7 +1141,7 @@ class Command(BaseCommand): file = ContractFile( contract=contract, name=self.normalize_filename(file_key), - is_public=True + is_public=True, ) file.file.save( @@ -1302,8 +1215,12 @@ class Command(BaseCommand): for file in files: file.save() + for issue in issues: + issue.save() + contract.filing_area = filing_area contract.types.set(types) + contract.issues.set(issues) contract.save() else: self.already_imported_count += 1 @@ -1428,7 +1345,7 @@ class Command(BaseCommand): (options["directory"] if options["directory"] is not None else "git"), ) - if os.path.exists(git_dir): + if os.path.exists(git_dir) and not options["delete"]: if not options["existing"]: if self.verbosity >= 1: self.stderr.write( @@ -1445,6 +1362,12 @@ class Command(BaseCommand): if self.verbosity >= 2: self.stdout.write("Using existing git storage directory.") else: + if options["delete"] and os.path.exists(git_dir): + if self.verbosity >= 2: + self.stdout.write("Deleting old git storage directory.") + + shutil.rmtree(git_dir) + if self.verbosity >= 2: self.stdout.write("Cloning repository.") diff --git a/contracts/migrations/0053_alter_contractfile_file.py b/contracts/migrations/0053_alter_contractfile_file.py index aa0900d944457b4e00028d0ee4a751df7f62d332..b5fefd1c6fa3aba07b7cedbbd7d815fee1496ba0 100644 --- a/contracts/migrations/0053_alter_contractfile_file.py +++ b/contracts/migrations/0053_alter_contractfile_file.py @@ -1,19 +1,22 @@ # Generated by Django 4.1.4 on 2023-04-21 12:10 -import contracts.models from django.db import migrations +import contracts.models + class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0052_remove_contract_legal_state_contract_is_valid'), + ("contracts", "0052_remove_contract_legal_state_contract_is_valid"), ] operations = [ migrations.AlterField( - model_name='contractfile', - name='file', - field=contracts.models.ContractFileField(upload_to=contracts.models.get_contract_file_loaction, verbose_name='Soubor'), + model_name="contractfile", + name="file", + field=contracts.models.ContractFileField( + upload_to=contracts.models.get_contract_file_loaction, + verbose_name="Soubor", + ), ), ] diff --git a/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py b/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py index 7a6ea981dc7c481caa8939e22dafcdc9cb5b9232..52d1ce4ff5182c5a11d9e6b9df574bb24679e659 100644 --- a/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py +++ b/contracts/migrations/0054_alter_signee_address_zip_alter_signee_ico_number.py @@ -4,20 +4,31 @@ from django.db import migrations, models class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0053_alter_contractfile_file'), + ("contracts", "0053_alter_contractfile_file"), ] operations = [ migrations.AlterField( - model_name='signee', - name='address_zip', - field=models.CharField(blank=True, help_text='Veřejné pouze, když typ není nastaven na fyzickou osobu.', max_length=256, null=True, verbose_name='PSČ'), + model_name="signee", + name="address_zip", + field=models.CharField( + blank=True, + help_text="Veřejné pouze, když typ není nastaven na fyzickou osobu.", + max_length=256, + null=True, + verbose_name="PSČ", + ), ), migrations.AlterField( - model_name='signee', - name='ico_number', - field=models.CharField(blank=True, help_text='U právnických a podnikajících fyzických osob musí být vyplněno. Vyplněním můžeš automaticky načíst data z ARES.', max_length=256, null=True, verbose_name='IČO'), + model_name="signee", + name="ico_number", + field=models.CharField( + blank=True, + help_text="U právnických a podnikajících fyzických osob musí být vyplněno. Vyplněním můžeš automaticky načíst data z ARES.", + max_length=256, + null=True, + verbose_name="IČO", + ), ), ] diff --git a/contracts/migrations/0055_alter_contractee_address_zip_and_more.py b/contracts/migrations/0055_alter_contractee_address_zip_and_more.py index ea6c711dbaea760820bac281ddbe866dbe8e9d02..1bbcaaead5596e9a3ed11cb27999276ad4daa13c 100644 --- a/contracts/migrations/0055_alter_contractee_address_zip_and_more.py +++ b/contracts/migrations/0055_alter_contractee_address_zip_and_more.py @@ -1,24 +1,34 @@ # Generated by Django 4.1.4 on 2023-04-21 22:52 -import contracts.models from django.db import migrations, models +import contracts.models + class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0054_alter_signee_address_zip_alter_signee_ico_number'), + ("contracts", "0054_alter_signee_address_zip_alter_signee_ico_number"), ] operations = [ migrations.AlterField( - model_name='contractee', - name='address_zip', - field=models.CharField(default=contracts.models.get_default_contractee_zip, max_length=256, verbose_name='PSČ'), + model_name="contractee", + name="address_zip", + field=models.CharField( + default=contracts.models.get_default_contractee_zip, + max_length=256, + verbose_name="PSČ", + ), ), migrations.AlterField( - model_name='contractee', - name='ico_number', - field=models.CharField(blank=True, default=contracts.models.get_default_contractee_ico_number, max_length=256, null=True, verbose_name='IČO'), + model_name="contractee", + name="ico_number", + field=models.CharField( + blank=True, + default=contracts.models.get_default_contractee_ico_number, + max_length=256, + null=True, + verbose_name="IČO", + ), ), ] diff --git a/contracts/migrations/0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more.py b/contracts/migrations/0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more.py index c3ae4aa8b22da4923091d84c165a616e0d50124a..c80d53df487dc8a2b924de82067876fcac22c760 100644 --- a/contracts/migrations/0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more.py +++ b/contracts/migrations/0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more.py @@ -4,20 +4,19 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0055_alter_contractee_address_zip_and_more'), + ("contracts", "0055_alter_contractee_address_zip_and_more"), ] operations = [ migrations.RenameField( - model_name='contracteesignaturerepresentative', - old_name='contractee_signature', - new_name='signature', + model_name="contracteesignaturerepresentative", + old_name="contractee_signature", + new_name="signature", ), migrations.RenameField( - model_name='signeesignaturerepresentative', - old_name='signee_signature', - new_name='signature', + model_name="signeesignaturerepresentative", + old_name="signee_signature", + new_name="signature", ), ] diff --git a/contracts/migrations/0057_alter_contract_options_alter_contractee_options_and_more.py b/contracts/migrations/0057_alter_contract_options_alter_contractee_options_and_more.py index 78898b509d833d2bcee3aaf617b7c950d072f7c1..37e8323528e972094deedab264181334dc7e38b4 100644 --- a/contracts/migrations/0057_alter_contract_options_alter_contractee_options_and_more.py +++ b/contracts/migrations/0057_alter_contract_options_alter_contractee_options_and_more.py @@ -4,34 +4,77 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more'), + ( + "contracts", + "0056_rename_contractee_signature_contracteesignaturerepresentative_signature_and_more", + ), ] operations = [ migrations.AlterModelOptions( - name='contract', - options={'ordering': ('-created_on', '-updated_on', '-name'), 'permissions': [('approve', 'Schválit / zrušit schválení'), ('view_confidential', 'Zobrazit tajné informace'), ('edit_when_approved', 'Upravit schválené'), ('delete_when_approved', 'Odstranit schválené'), ('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí'), ('can_edit_contract_settings', 'Can edit Smlouva settings')], 'verbose_name': 'Smlouva', 'verbose_name_plural': 'Smlouvy'}, + name="contract", + options={ + "ordering": ("-created_on", "-updated_on", "-name"), + "permissions": [ + ("approve", "Schválit / zrušit schválení"), + ("view_confidential", "Zobrazit tajné informace"), + ("edit_when_approved", "Upravit schválené"), + ("delete_when_approved", "Odstranit schválené"), + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ("can_edit_contract_settings", "Can edit Smlouva settings"), + ], + "verbose_name": "Smlouva", + "verbose_name_plural": "Smlouvy", + }, ), migrations.AlterModelOptions( - name='contractee', - options={'ordering': ['-name', '-department'], 'permissions': [('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí')], 'verbose_name': 'Naše smluvní strana', 'verbose_name_plural': 'Naše smluvní strany'}, + name="contractee", + options={ + "ordering": ["-name", "-department"], + "permissions": [ + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ], + "verbose_name": "Naše smluvní strana", + "verbose_name_plural": "Naše smluvní strany", + }, ), migrations.AlterModelOptions( - name='contractfilingarea', - options={'ordering': ['-name'], 'verbose_name': 'Spisovna', 'verbose_name_plural': 'Spisovny'}, + name="contractfilingarea", + options={ + "ordering": ["-name"], + "verbose_name": "Spisovna", + "verbose_name_plural": "Spisovny", + }, ), migrations.AlterModelOptions( - name='contractissue', - options={'ordering': ['-name'], 'verbose_name': 'Problém se smlouvou', 'verbose_name_plural': 'Problémy se smlouvami'}, + name="contractissue", + options={ + "ordering": ["-name"], + "verbose_name": "Problém se smlouvou", + "verbose_name_plural": "Problémy se smlouvami", + }, ), migrations.AlterModelOptions( - name='contracttype', - options={'ordering': ['-name'], 'verbose_name': 'Typ smlouvy', 'verbose_name_plural': 'Typy smluv'}, + name="contracttype", + options={ + "ordering": ["-name"], + "verbose_name": "Typ smlouvy", + "verbose_name_plural": "Typy smluv", + }, ), migrations.AlterModelOptions( - name='signee', - options={'ordering': ['-name', '-department'], 'permissions': [('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí')], 'verbose_name': 'Jiná smluvní strana', 'verbose_name_plural': 'Ostatní smluvní strany'}, + name="signee", + options={ + "ordering": ["-name", "-department"], + "permissions": [ + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ], + "verbose_name": "Jiná smluvní strana", + "verbose_name_plural": "Ostatní smluvní strany", + }, ), ] diff --git a/contracts/migrations/0058_alter_contract_options_alter_contractee_options_and_more.py b/contracts/migrations/0058_alter_contract_options_alter_contractee_options_and_more.py index c17f7b0ea88c220834059e244d1bdf97a1881fba..52f5e1f0dbb24bfcfb4f5b3b5d02387a6be89e56 100644 --- a/contracts/migrations/0058_alter_contract_options_alter_contractee_options_and_more.py +++ b/contracts/migrations/0058_alter_contract_options_alter_contractee_options_and_more.py @@ -4,34 +4,74 @@ from django.db import migrations class Migration(migrations.Migration): - dependencies = [ - ('contracts', '0057_alter_contract_options_alter_contractee_options_and_more'), + ("contracts", "0057_alter_contract_options_alter_contractee_options_and_more"), ] operations = [ migrations.AlterModelOptions( - name='contract', - options={'ordering': ('-created_on', '-updated_on', 'name'), 'permissions': [('approve', 'Schválit / zrušit schválení'), ('view_confidential', 'Zobrazit tajné informace'), ('edit_when_approved', 'Upravit schválené'), ('delete_when_approved', 'Odstranit schválené'), ('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí'), ('can_edit_contract_settings', 'Can edit Smlouva settings')], 'verbose_name': 'Smlouva', 'verbose_name_plural': 'Smlouvy'}, + name="contract", + options={ + "ordering": ("-created_on", "-updated_on", "name"), + "permissions": [ + ("approve", "Schválit / zrušit schválení"), + ("view_confidential", "Zobrazit tajné informace"), + ("edit_when_approved", "Upravit schválené"), + ("delete_when_approved", "Odstranit schválené"), + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ("can_edit_contract_settings", "Can edit Smlouva settings"), + ], + "verbose_name": "Smlouva", + "verbose_name_plural": "Smlouvy", + }, ), migrations.AlterModelOptions( - name='contractee', - options={'ordering': ['name', 'department'], 'permissions': [('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí')], 'verbose_name': 'Naše smluvní strana', 'verbose_name_plural': 'Naše smluvní strany'}, + name="contractee", + options={ + "ordering": ["name", "department"], + "permissions": [ + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ], + "verbose_name": "Naše smluvní strana", + "verbose_name_plural": "Naše smluvní strany", + }, ), migrations.AlterModelOptions( - name='contractfilingarea', - options={'ordering': ['name'], 'verbose_name': 'Spisovna', 'verbose_name_plural': 'Spisovny'}, + name="contractfilingarea", + options={ + "ordering": ["name"], + "verbose_name": "Spisovna", + "verbose_name_plural": "Spisovny", + }, ), migrations.AlterModelOptions( - name='contractissue', - options={'ordering': ['name'], 'verbose_name': 'Problém se smlouvou', 'verbose_name_plural': 'Problémy se smlouvami'}, + name="contractissue", + options={ + "ordering": ["name"], + "verbose_name": "Problém se smlouvou", + "verbose_name_plural": "Problémy se smlouvami", + }, ), migrations.AlterModelOptions( - name='contracttype', - options={'ordering': ['name'], 'verbose_name': 'Typ smlouvy', 'verbose_name_plural': 'Typy smluv'}, + name="contracttype", + options={ + "ordering": ["name"], + "verbose_name": "Typ smlouvy", + "verbose_name_plural": "Typy smluv", + }, ), migrations.AlterModelOptions( - name='signee', - options={'ordering': ['name', 'department'], 'permissions': [('edit_others', 'Upravit cizí'), ('delete_others', 'Odstranit cizí')], 'verbose_name': 'Jiná smluvní strana', 'verbose_name_plural': 'Ostatní smluvní strany'}, + name="signee", + options={ + "ordering": ["name", "department"], + "permissions": [ + ("edit_others", "Upravit cizí"), + ("delete_others", "Odstranit cizí"), + ], + "verbose_name": "Jiná smluvní strana", + "verbose_name_plural": "Ostatní smluvní strany", + }, ), ] diff --git a/contracts/models.py b/contracts/models.py index aaad5e1e6f86af244bee092cf7f36c26375d277e..114c3da823e855598c227c9bca478ea86296fdf9 100644 --- a/contracts/models.py +++ b/contracts/models.py @@ -8,8 +8,8 @@ from django.conf import settings from django.core.exceptions import ValidationError from django.core.validators import RegexValidator, URLValidator from django.db import models -from django.db.models.signals import post_save from django.db.models.fields.files import FieldFile +from django.db.models.signals import post_save from django.dispatch import receiver from django.urls import reverse from django.utils.safestring import mark_safe @@ -843,7 +843,9 @@ def get_contract_file_loaction(instance, filename): class ContractFileProxy(FieldFile): @property def url(self) -> str: - return reverse("contracts:download_contract_file", args=(str(self.instance.id),)) + return reverse( + "contracts:download_contract_file", args=(str(self.instance.id),) + ) class ContractFileField(models.FileField): diff --git a/package-lock.json b/package-lock.json index 555756a82080856216af658fc1ac4af15cb36bba..b57b2e441884312be7b106c23e62d1eb89ff4d60 100644 --- a/package-lock.json +++ b/package-lock.json @@ -515,9 +515,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001468", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz", - "integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==", + "version": "1.0.30001481", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", + "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==", "funding": [ { "type": "opencollective", @@ -526,6 +526,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -2568,9 +2572,9 @@ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==" }, "caniuse-lite": { - "version": "1.0.30001468", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001468.tgz", - "integrity": "sha512-zgAo8D5kbOyUcRAgSmgyuvBkjrGk5CGYG5TYgFdpQv+ywcyEpo1LOWoG8YmoflGnh+V+UsNuKYedsoYs0hzV5A==" + "version": "1.0.30001481", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001481.tgz", + "integrity": "sha512-KCqHwRnaa1InZBtqXzP98LPg0ajCVujMKjqKDhZEthIpAsJl/YEIa3YvXjGXPVqzZVguccuu7ga9KOE1J9rKPQ==" }, "chokidar": { "version": "3.5.3", diff --git a/shared/templates/shared/includes/base.html b/shared/templates/shared/includes/base.html index 2755e32994e14b2e262d52630180fec8ad7c6d8e..5520d1980abf67c68c5d7bffbbba687e26ca588a 100644 --- a/shared/templates/shared/includes/base.html +++ b/shared/templates/shared/includes/base.html @@ -60,7 +60,7 @@ <div class="container container--default navbar__content" :class="{'navbar__content--initialized': true}"> <div class="navbar__brand my-4 flex items-center lg:pr-8 lg:my-0"> <a href="/"> - <img src="https://styleguide.pirati.cz/2.12.x/images/logo-round-white.svg" class="w-8" /> + <img src="https://styleguide.pirati.cz/2.12.x/images/logo-round-white.svg" class="w-8"> </a> <a href="/" class="pl-4 font-bold text-xl hover:no-underline lg:border-r lg:border-grey-300 lg:pr-8">Registr smluv</a> </div> @@ -190,8 +190,8 @@ </a> <a href="https://nalodeni.pirati.cz" class="btn btn--icon btn--blue-300 btn--hoveractive text-lg btn--fullwidth sm:btn--autowidth"> <div class="btn__body-wrap"> - <div class="btn__body ">Naloď se</div> - <div class="btn__icon "><i class="ico--anchor"></i></div> + <div class="btn__body">Naloď se</div> + <div class="btn__icon"><i class="ico--anchor"></i></div> </div> </a> </div>