コード例 #1
0
 def unregistered_obj(self, db: Session):
     auditlog.unregister(models.SimpleModel)
     obj = models.SimpleModel(text="No history")
     db.add(obj)
     db.commit()
     db.refresh(obj)
     return obj
コード例 #2
0
    def handle(self, *args, **options):
        code_to_city_name = read_post_codes(options['pcf_file'])

        from auditlog.registry import auditlog

        # Unregister Contact model from auditlog
        auditlog.unregister(Contact)

        contacts = Contact.objects.filter(city__isnull=True)
        self.stdout.write('{} contacts without city'.format(contacts.count()))

        for contact in contacts:
            if not contact.postal_code:
                self.stdout.write(
                    'Contact id {} has no postal code. Skipping.'.format(
                        contact.id))
                continue

            if contact.postal_code not in code_to_city_name.keys():
                self.stdout.write(
                    'Contact id {} has an unknown postal code "{}". Skipping.'.
                    format(contact.id, contact.postal_code))
                continue

            contact.city = code_to_city_name[contact.postal_code]
            contact.save()
コード例 #3
0
    def execute(self):
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        self.import_leases()
コード例 #4
0
ファイル: invoice_relations.py プロジェクト: hkotkanen/mvj
    def execute(self):
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        self.update_credit_notes()
        self.update_interest_invoices()
コード例 #5
0
    def handle(self, *args, **options):  # noqa: C901 TODO
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        detailed_plans = Area.objects.filter(type=AreaType.DETAILED_PLAN)

        if not detailed_plans:
            self.stdout.write(
                "Detailed plan: No detailed plans found in area table")
            return

        for detailed_plan in detailed_plans:
            match_data = {
                "identifier": detailed_plan.identifier,
            }

            detailed_plan_class = None
            if detailed_plan.metadata.get("state_name") == "Vireillä":
                detailed_plan_class = DetailedPlanClass.PENDING
            if detailed_plan.metadata.get("state_name") == "Voimassa":
                detailed_plan_class = DetailedPlanClass.EFFECTIVE
            lawfulness_date = detailed_plan.metadata.get("final_date")

            acceptor = ""
            plan_stage = ""
            diary_number = ""
            pre_detailed_plan = Area.objects.filter(
                type=AreaType.PRE_DETAILED_PLAN,
                identifier=detailed_plan.identifier)
            if pre_detailed_plan:
                acceptor = pre_detailed_plan.metadata.get("acceptor")
                plan_stage = pre_detailed_plan.metadata.get("plan_stage")
                diary_number = pre_detailed_plan.metadata.get("diary_number")

            other_data = {
                "acceptor": acceptor,
                "detailed_plan_class": detailed_plan_class,
                "plan_stage": plan_stage,
                "diary_number": diary_number,
                "lawfulness_date": lawfulness_date,
            }

            DetailedPlan.objects.update_or_create(defaults=other_data,
                                                  **match_data)
コード例 #6
0
    def handle(self, *args, **options):
        destination_path = (
            Path(settings.MEDIA_ROOT) / CollectionLetterTemplate.file.field.upload_to
        )
        if not self.check_is_directory_writable(destination_path):
            raise CommandError('Directory "" is not writable'.format(destination_path))

        source_path = Path(options["source_directory"])

        from auditlog.registry import auditlog

        auditlog.unregister(CollectionLetterTemplate)

        for name, template in TEMPLATE_NAMES.items():
            self.stdout.write(name)

            source_filename = source_path / template["filename"]
            if not source_filename.exists():
                self.stdout.write(
                    ' Template file "{}" does not exist in the source directory {}'.format(
                        template["filename"], source_path
                    )
                )
                continue

            try:
                clt = CollectionLetterTemplate.objects.get(name=name)
                self.stdout.write(" Template already exists. Overwriting.")
                destination_filename = clt.file.name
            except CollectionLetterTemplate.DoesNotExist:
                self.stdout.write(" Creating new template.")
                destination_filename = (
                    Path(CollectionLetterTemplate.file.field.upload_to)
                    / template["filename"]
                )
                CollectionLetterTemplate.objects.create(
                    name=name, file=str(destination_filename)
                )

            destination_path = Path(settings.MEDIA_ROOT) / destination_filename

            self.stdout.write(
                ' Copying "{}" to "{}"'.format(source_filename, destination_path)
            )

            copyfile(source_filename, destination_path)
コード例 #7
0
def log_event(request, start, end, action: int, extra=None):
    if start == None and end == None:
        raise ValueError('start and end cannot both be none!')

    object_key = start.id if start != None else end.id
    instance = start if start != None else end

    # Determine if instance has created/last updated
    # We don't want to log these fields

    exclude = []
    try:
        instance._meta.get_field('created')
        exclude.append('created')
    except:
        pass
    try:
        instance._meta.get_field('last_updated')
        exclude.append('last_updated')
    except:
        pass

    # Register the type to allow logging
    auditlog.register(type(instance), exclude_fields=exclude)

    log = LogEntry.objects.log_create(
        instance,
        object_pk=object_key,
        object_id=object_key,
        object_repr=str(start) if start != None else str(end),
        action=action,
        changes=model_instance_diff(start, end),
        actor_id=request.user.id,
        timestamp=timezone.now(),
        content_type_id=
        6,  # This is the id for auditlog listed in django_content_types table
        remote_addr=get_client_ip(request),
        additional_data=extra)

    # Unregister the type to disable auto (duplicate) logging
    auditlog.unregister(type(instance))
コード例 #8
0
    def handle(self, *args, **options):  # noqa: C901 TODO
        from auditlog.registry import auditlog

        logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout)

        verbosity = options.get("verbosity")
        if verbosity == 0:
            logger.setLevel(logging.WARNING)
        elif verbosity >= 2:
            logger.setLevel(logging.DEBUG)

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        for rent in Rent.objects.all().iterator():
            try:
                rent.calculate_payable_rent()
            except Exception as e:
                logger.exception(
                    "Failed to calculate payable rent (%s): %s" % (rent.id, str(e))
                )
                continue
コード例 #9
0
    def handle(self, *args, **options):  # noqa: C901 TODO
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        leases = Lease.objects.all()

        for lease in leases:
            self.stdout.write("Lease #{} {}:".format(lease.id,
                                                     lease.identifier))

            lease_areas = {
                la.get_normalized_identifier(): la
                for la in lease.lease_areas.all()
            }
            self.stdout.write(" Existing lease areas: {}".format(", ".join(
                lease_areas.keys())))

            areas = Area.objects.filter(type=AreaType.LEASE_AREA,
                                        identifier=str(lease.identifier))

            if not areas:
                self.stdout.write(
                    "Lease #{} {}: No lease areas found in area table".format(
                        lease.id, lease.identifier))

            for area in areas:
                plan_unit_ids_handled = []

                area_identifier = area.get_normalized_identifier()

                if area_identifier not in lease_areas.keys():
                    self.stdout.write(
                        "Lease #{} {}: Area id {} not in lease areas of lease!"
                        .format(lease.id, lease.identifier, area_identifier))
                    continue

                lease_areas[area_identifier].geometry = area.geometry
                lease_areas[area_identifier].save()
                self.stdout.write("  Lease area FOUND. SAVED.")

                # Clear all plots and plan units safely which aren't in contracts
                del_plots = (lease_areas[area_identifier].plots.exclude(
                    in_contract=True).delete())
                self.stdout.write(
                    "  Cleared existing current Plots ({}) not in contract".
                    format(del_plots))

                try:
                    # Get intersected areas with lease area's geometry but exclude the type of lease area and plot
                    # division and also geometries which only touches the lease area
                    intersected_areas = (Area.objects.filter(
                        geometry__intersects=area.geometry).exclude(type__in=[
                            AreaType.LEASE_AREA, AreaType.PLOT_DIVISION
                        ]).exclude(geometry__touches=area.geometry))
                except InternalError as e:
                    self.stdout.write(str(e))
                    continue

                for intersect_area in intersected_areas:
                    self.stdout.write("  #{} {} {}".format(
                        intersect_area.id,
                        intersect_area.identifier,
                        intersect_area.type,
                    ))

                    # As of 21.1.2020, there are about 250 of plan unit area objects that have {'area': None, ...}
                    # in their metadata json field. I suspect this is due to accidental duplications in the source db
                    # since it seems like there is usually another object with identical metadata and identifier fields
                    # (except also having a value for the 'area' key) to be found, which we want to actually use.
                    if not intersect_area.metadata.get("area"):
                        self.stdout.write(
                            "Lease #{} {}: DISCARD area {}: no 'area' value in metadata"
                            .format(lease.id, lease.identifier,
                                    intersect_area.id))
                        continue

                    try:
                        # Discard too small intersect area
                        intersection = (
                            intersect_area.geometry
                            & lease_areas[area_identifier].geometry)
                        intersection.transform(3879)
                        if intersection.area < 1:
                            self.stdout.write(
                                "Lease #{} {}: DISCARD area {}: intersection area too small"
                                .format(lease.id, lease.identifier,
                                        intersect_area.id))
                            continue
                    except GEOSException as e:
                        self.stdout.write(str(e))
                        continue

                    if (intersect_area.type == AreaType.REAL_PROPERTY
                            or intersect_area.type
                            == AreaType.UNSEPARATED_PARCEL):
                        # If the intersect area's type is real property (kiinteistö) or unseparated parcel (määräala)
                        # then update or create the intersect area to plots
                        match_data = {
                            "lease_area":
                            lease_areas[area_identifier],
                            "type":
                            PlotType[intersect_area.type.value.upper()],
                            "identifier":
                            intersect_area.get_denormalized_identifier(),
                            "is_master":
                            True,
                        }
                        rest_data = {
                            "area":
                            float(intersect_area.metadata.get("area")),
                            "section_area":
                            intersection.area,
                            "registration_date":
                            intersect_area.metadata.get("registration_date"),
                            "repeal_date":
                            intersect_area.metadata.get("repeal_date"),
                            "geometry":
                            intersect_area.geometry,
                        }
                        (plot, plot_created) = Plot.objects.update_or_create(
                            defaults=rest_data, **match_data)
                        self.stdout.write(
                            "Lease #{} {}: Plot #{} ({}) saved".format(
                                lease.id, lease.identifier, plot.id,
                                plot.type))
                    elif intersect_area.type == AreaType.PLAN_UNIT:
                        # Find the plot division (tonttijako) that intersects the most
                        plot_division_area = (Area.objects.filter(
                            geometry__intersects=intersect_area.geometry,
                            type=AreaType.PLOT_DIVISION,
                        ).extra(
                            select={
                                "interarea":
                                "ST_Area(ST_Transform(ST_Intersection(geometry, '{}'), 3879))"
                                .format(intersect_area.geometry)
                            }).order_by("-interarea").first())

                        # If the plot division area exist then create/update plan unit informations
                        if plot_division_area and plot_division_area.interarea > 0:
                            # Get or create plot division state
                            (
                                plot_division_state,
                                created,
                            ) = PlotDivisionState.objects.get_or_create(
                                name=plot_division_area.metadata.get(
                                    "state_name"))

                            # Get detailed plan area
                            detailed_plan_area = Area.objects.filter(
                                type=AreaType.DETAILED_PLAN,
                                identifier=intersect_area.metadata.get(
                                    "detailed_plan_identifier"),
                            ).first()

                            # The variable is unused for some reason
                            detailed_plan_latest_processing_date = None

                            # If detailed plan area exist, set the identifier
                            detailed_plan_identifier = None
                            if detailed_plan_area:
                                detailed_plan_identifier = detailed_plan_area.identifier

                            # Get or create plan unit type
                            (
                                plan_unit_type,
                                created,
                            ) = PlanUnitType.objects.get_or_create(
                                name=intersect_area.metadata.get("type_name"))

                            # Get or create plan unit state
                            (
                                plan_unit_state,
                                created,
                            ) = PlanUnitState.objects.get_or_create(
                                name=intersect_area.metadata.get("state_name"))

                            # If the intersect area has intended use name, get or create it to plan unit intended use
                            plan_unit_intended_use = None
                            if intersect_area.metadata.get(
                                    "intended_use_name"):
                                (
                                    plan_unit_intended_use,
                                    created,
                                ) = PlanUnitIntendedUse.objects.get_or_create(
                                    name=intersect_area.metadata.get(
                                        "intended_use_name"))

                            match_data = {
                                "lease_area":
                                lease_areas[area_identifier],
                                "identifier":
                                intersect_area.get_denormalized_identifier(),
                                "is_master":
                                True,
                            }
                            rest_data = {
                                "area":
                                float(intersect_area.metadata.get("area")),
                                "section_area":
                                intersection.area,
                                "geometry":
                                intersect_area.geometry,
                                "plot_division_identifier":
                                plot_division_area.identifier,
                                "plot_division_date_of_approval":
                                plot_division_area.metadata.get(
                                    "date_of_approval"),
                                "plot_division_effective_date":
                                plot_division_area.metadata.get(
                                    "effective_date"),
                                "plot_division_state":
                                plot_division_state,
                                "detailed_plan_identifier":
                                detailed_plan_identifier,
                                "detailed_plan_latest_processing_date":
                                detailed_plan_latest_processing_date,
                                "plan_unit_type":
                                plan_unit_type,
                                "plan_unit_state":
                                plan_unit_state,
                                "plan_unit_intended_use":
                                plan_unit_intended_use,
                                "plan_unit_status":
                                plan_unit_state.to_enum(),
                            }

                            # Get or create plan unit
                            (
                                plan_unit,
                                plan_unit_created,
                            ) = PlanUnit.objects.get_or_create(
                                defaults=rest_data, **match_data)
                            if not plan_unit_created:
                                for attr, value in rest_data.items():
                                    setattr(plan_unit, attr, value)
                                plan_unit.save()

                            self.stdout.write(
                                "Lease #{} {}: PlanUnit #{} saved".format(
                                    lease.id, lease.identifier, plan_unit.id))

                            plan_unit_ids_handled.append(plan_unit.id)

                PlanUnit.objects.filter(
                    lease_area=lease_areas[area_identifier]).exclude(
                        id__in=plan_unit_ids_handled).delete()
コード例 #10
0
ファイル: lease_relations.py プロジェクト: suutari-ai/mvj
    def execute(self):  # noqa: C901 'Command.handle' is too complex
        from auditlog.registry import auditlog

        # Unregister model from auditlog when importing
        auditlog.unregister(RelatedLease)

        lease_identifier_to_id = {}
        with connection.cursor() as django_cursor:
            django_cursor.execute("""
            SELECT l.id, lt.identifier leasetype, lm.identifier municipality, ld.identifier district, li.sequence
            FROM leasing_lease l
            JOIN leasing_leaseidentifier li ON l.identifier_id = li.id
            JOIN leasing_leasetype lt on li.type_id = lt.id
            JOIN leasing_municipality lm on li.municipality_id = lm.id
            JOIN leasing_district ld on li.district_id = ld.id
            ORDER BY lt.identifier, lm.identifier, ld.identifier, li.sequence
            """)

            for row in django_cursor.fetchall():
                identifier = "{}{}{:02}-{}".format(row[1], row[2], int(row[3]),
                                                   row[4])
                lease_identifier_to_id[identifier] = row[0]

        cursor = self.cursor

        query = """
            SELECT * FROM (
                SELECT ALKUOSA, JUOKSU, LIITTYY_ALKUOSA, LIITTYY_JUOKSU, ROW_NUMBER() OVER (ORDER BY ALKUOSA, JUOKSU) rn
                FROM VUOKRAUS
                WHERE LIITTYY_ALKUOSA != ALKUOSA OR LIITTYY_JUOKSU != JUOKSU
                AND TILA != 'S'
                ORDER BY ALKUOSA, JUOKSU
            ) t
            WHERE rn >= {}
            """.format(self.offset)

        cursor.execute(query)

        vuokraus_rows = rows_to_dict_list(cursor)
        vuokraus_count = len(vuokraus_rows)

        self.stdout.write("{} relations".format(vuokraus_count))

        count = 0
        found = 0
        for lease_row in vuokraus_rows:
            count += 1

            from_lease = "{}-{}".format(lease_row["LIITTYY_ALKUOSA"],
                                        lease_row["LIITTYY_JUOKSU"])
            to_lease = "{}-{}".format(lease_row["ALKUOSA"],
                                      lease_row["JUOKSU"])

            try:
                from_lease_id = lease_identifier_to_id[from_lease]
            except KeyError:
                self.stderr.write(
                    'From lease "{}" not found.'.format(from_lease))
                continue

            try:
                to_lease_id = lease_identifier_to_id[to_lease]
            except KeyError:
                self.stderr.write('To lease "{}" not found.'.format(to_lease))
                continue

            self.stdout.write(" {} #{} -> {} #{}".format(
                from_lease, from_lease_id, to_lease, to_lease_id))

            found += 1
            (related_lease,
             related_lease_created) = RelatedLease.objects.get_or_create(
                 from_lease_id=from_lease_id,
                 to_lease_id=to_lease_id,
                 type=LeaseRelationType.OTHER,
             )

        self.stdout.write("{}/{} found".format(found, count))
コード例 #11
0
ファイル: tests.py プロジェクト: zacqed/django-auditlog
 def setUp(self):
     auditlog.unregister(SimpleModel)
     self.obj = SimpleModel.objects.create(text='No history')
コード例 #12
0
    def handle(self, *args,
               **options):  # noqa: C901 'Command.handle' is too complex TODO
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        leases = Lease.objects.all()

        for lease in leases:
            self.stdout.write('Lease #{} {}:'.format(lease.id,
                                                     lease.identifier))

            lease_areas = {
                normalize_identifier(la.identifier): la
                for la in lease.lease_areas.all()
            }
            self.stdout.write(' Existing lease areas: {}'.format(', '.join(
                lease_areas.keys())))

            areas = Area.objects.filter(type=AreaType.LEASE_AREA,
                                        identifier=str(lease.identifier))

            if not areas:
                self.stdout.write(' No lease areas found in area table')

            for area in areas:
                property_identifier = '{}-{}-{}-{}{}'.format(
                    area.metadata.get('municipality', '0')
                    if area.metadata.get('municipality') else '0',
                    area.metadata.get('district', '0')
                    if area.metadata.get('district') else '0',
                    area.metadata.get('group', '0')
                    if area.metadata.get('group') else '0',
                    area.metadata.get('unit', '0')
                    if area.metadata.get('unit') else '0',
                    '-{}'.format(area.metadata.get('mvj_unit', '0'))
                    if 'mvj_unit' in area.metadata else '',
                )
                area_identifier = normalize_identifier(property_identifier)
                self.stdout.write(' {} -> {}'.format(property_identifier,
                                                     area_identifier))

                if area_identifier not in lease_areas.keys():
                    self.stdout.write('  Lease area NOT FOUND!')
                    continue

                lease_areas[area_identifier].geometry = area.geometry
                lease_areas[area_identifier].save()
                self.stdout.write('  Lease area FOUND. SAVED.')

                try:
                    other_areas = Area.objects.filter(
                        geometry__intersects=area.geometry).exclude(type__in=[
                            AreaType.LEASE_AREA, AreaType.PLOT_DIVISION
                        ]).exclude(geometry__touches=area.geometry)
                except InternalError as e:
                    self.stdout.write(str(e))
                    continue

                for other_area in other_areas:
                    self.stdout.write('  #{} {} {}'.format(
                        other_area.id, other_area.identifier, other_area.type))

                    try:
                        intersection = other_area.geometry & lease_areas[
                            area_identifier].geometry
                        intersection.transform(3879)
                    except GEOSException as e:
                        self.stdout.write(str(e))
                        continue

                    self.stdout.write('   intersection area {} m^2'.format(
                        intersection.area))

                    # Discard too small intersecting areas
                    if intersection.area < 1:
                        self.stdout.write('   DISCARD')
                        continue

                    if other_area.type == AreaType.REAL_PROPERTY or other_area.type == AreaType.UNSEPARATED_PARCEL:
                        match_data = {
                            'lease_area':
                            lease_areas[area_identifier],
                            'type':
                            PlotType[other_area.type.value.upper()],
                            'identifier':
                            denormalize_identifier(other_area.identifier),
                            'in_contract':
                            False,
                        }
                        rest_data = {
                            'area':
                            float(other_area.metadata.get('area')),
                            'section_area':
                            intersection.area,
                            'registration_date':
                            other_area.metadata.get('registration_date'),
                            'repeal_date':
                            other_area.metadata.get('repeal_date'),
                            'geometry':
                            other_area.geometry,
                        }
                        (plot, plot_created) = Plot.objects.update_or_create(
                            defaults=rest_data, **match_data)
                        self.stdout.write('   Plot #{} ({}) saved.'.format(
                            plot.id, plot.type))
                    elif other_area.type == AreaType.PLAN_UNIT:
                        # Find the plot division that intersects the most
                        plot_area = Area.objects.filter(
                            geometry__intersects=other_area.geometry,
                            type=AreaType.PLOT_DIVISION
                        ).extra(
                            select={
                                'interarea':
                                'ST_Area(ST_Transform(ST_Intersection(geometry, \'{}\'), 3879))'
                                .format(other_area.geometry)
                            }).order_by('-interarea').first()

                        if plot_area and plot_area.interarea > 0:
                            (plot_division_state, created
                             ) = PlotDivisionState.objects.get_or_create(
                                 name=plot_area.metadata.get('state_name'))

                            detailed_plan_area = Area.objects.filter(
                                type=AreaType.DETAILED_PLAN,
                                identifier=other_area.metadata.get(
                                    'detailed_plan_identifier')).first()
                            if detailed_plan_area:
                                detailed_plan_identifier = detailed_plan_area.identifier
                                detailed_plan_latest_processing_date = None
                            else:
                                detailed_plan_identifier = None
                                detailed_plan_latest_processing_date = None

                            (plan_unit_type,
                             created) = PlanUnitType.objects.get_or_create(
                                 name=other_area.metadata.get('type_name'))
                            (plan_unit_state,
                             created) = PlanUnitState.objects.get_or_create(
                                 name=other_area.metadata.get('state_name'))
                            if other_area.metadata.get('intended_use_name'):
                                (plan_unit_intended_use, created
                                 ) = PlanUnitIntendedUse.objects.get_or_create(
                                     name=other_area.metadata.get(
                                         'intended_use_name'))
                            else:
                                plan_unit_intended_use = None

                            match_data = {
                                'lease_area':
                                lease_areas[area_identifier],
                                'identifier':
                                denormalize_identifier(other_area.identifier),
                                'in_contract':
                                False,
                            }
                            rest_data = {
                                'area':
                                float(other_area.metadata.get('area')),
                                'section_area':
                                intersection.area,
                                'geometry':
                                other_area.geometry,
                                'plot_division_identifier':
                                plot_area.identifier,
                                'plot_division_date_of_approval':
                                plot_area.metadata.get('date_of_approval'),
                                'plot_division_effective_date':
                                plot_area.metadata.get('effective_date'),
                                'plot_division_state':
                                plot_division_state,
                                'detailed_plan_identifier':
                                detailed_plan_identifier,
                                'detailed_plan_latest_processing_date':
                                detailed_plan_latest_processing_date,
                                'plan_unit_type':
                                plan_unit_type,
                                'plan_unit_state':
                                plan_unit_state,
                                'plan_unit_intended_use':
                                plan_unit_intended_use,
                            }

                            (plan_unit, plan_unit_created
                             ) = PlanUnit.objects.update_or_create(
                                 defaults=rest_data, **match_data)

                            self.stdout.write('   PlanUnit #{} saved.'.format(
                                plan_unit.id))

            self.stdout.write('')
コード例 #13
0
    def handle(self, *args, **options):  # noqa
        from auditlog.registry import auditlog

        # Unregister models from auditlog
        auditlog.unregister(Collateral)

        wb = load_workbook(filename=options['excel_file'])
        sheet = wb.active

        max_row = sheet.max_row
        for row_num in range(2, max_row):
            lease_identifier_cell = sheet.cell(row=row_num,
                                               column=LEASE_IDENTIFIER_COLUMN)
            amount_cell = sheet.cell(row=row_num, column=AMOUNT_COLUMN)
            paid_date_cell = sheet.cell(row=row_num, column=PAID_DATE_COLUMN)
            returned_date_cell = sheet.cell(row=row_num,
                                            column=RETURNED_DATE_COLUMN)
            note_cell = sheet.cell(row=row_num, column=NOTE_COLUMN)

            if lease_identifier_cell.value is None:
                continue

            if lease_identifier_cell.value is None or amount_cell.value is None:
                amount = Decimal(0)
            else:
                try:
                    amount = Decimal(str(amount_cell.value))
                except decimal.InvalidOperation:
                    amount = Decimal(0)

            lease_identifier_cell_value = lease_identifier_cell.value.strip()
            # Fix typos in excel
            if lease_identifier_cell_value.startswith('S120-'):
                lease_identifier_cell_value = 'S0' + lease_identifier_cell_value[
                    1:]

            if lease_identifier_cell_value[0:2] == 'So':
                lease_identifier_cell_value = 'S0' + lease_identifier_cell_value[
                    2:]

            lease_identifiers = re.findall(r'[A-Z]\d{4}-\d+',
                                           lease_identifier_cell_value,
                                           re.IGNORECASE)
            if not lease_identifiers:
                continue

            paid_date = get_date_from_value(paid_date_cell.value)
            if not paid_date:
                # Try to find date from the lease identifier column
                paid_date = get_date_from_value(lease_identifier_cell.value)

            returned_date = get_date_from_value(returned_date_cell.value)

            for lease_identifier in lease_identifiers:
                try:
                    lease = Lease.objects.get_by_identifier(
                        lease_identifier.upper())
                except Lease.DoesNotExist:
                    self.stderr.write(
                        'Lease "{}" not found'.format(lease_identifier))
                    continue

                lease_contract = lease.contracts.filter(
                    type=1).first()  # 1 = Vuokrasopimus
                if not lease_contract:
                    self.stdout.write(
                        'Lease "{}" no lease contract found. Creating.'.format(
                            lease_identifier))
                    lease_contract = Contract.objects.create(
                        lease=lease,
                        type_id=1,
                        signing_note=
                        'Vakuuksien tuontia varten luotu tyhjä sopimus')

                (collateral,
                 collateral_created) = Collateral.objects.get_or_create(
                     contract=lease_contract,
                     type_id=2,  # 2 = Rahavakuus
                     total_amount=amount,
                     paid_date=paid_date,
                     returned_date=returned_date,
                     note=note_cell.value)
コード例 #14
0
    def handle(self, *args, **options):  # noqa: C901 TODO
        from auditlog.registry import auditlog

        logging.basicConfig(level=logging.INFO, format="%(message)s", stream=sys.stdout)

        verbosity = options.get("verbosity")
        if verbosity == 0:
            LOG.setLevel(logging.WARNING)
        elif verbosity >= 2:
            LOG.setLevel(logging.DEBUG)

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        leases = Lease.objects.all()

        LOG.info("Processing %s objects.", leases.count())

        for lease in leases:
            LOG.debug("Lease #%s %s:", lease.id, lease.identifier)

            lease_areas = {
                la.get_normalized_identifier(): la for la in lease.lease_areas.all()
            }
            LOG.debug(" Existing lease areas: %s", ", ".join(lease_areas.keys()))

            areas = Area.objects.filter(
                type=AreaType.LEASE_AREA, identifier=str(lease.identifier)
            )

            if not areas:
                LOG.debug(
                    "Lease #%s %s: No lease areas found in area table",
                    lease.id,
                    lease.identifier,
                )

            for area in areas:
                plot_ids_handled = []
                plan_unit_ids_handled = []

                area_identifier = area.get_normalized_identifier()

                if area_identifier not in lease_areas.keys():
                    LOG.debug(
                        "Lease #%s %s: Area id %s not in lease areas of lease!",
                        lease.id,
                        lease.identifier,
                        area_identifier,
                    )
                    continue

                lease_areas[area_identifier].geometry = area.geometry
                lease_areas[area_identifier].save()

                try:
                    # Get intersected areas with lease area's geometry but exclude the type of lease area and plot
                    # division and also geometries which only touches the lease area
                    intersected_areas = (
                        Area.objects.filter(geometry__intersects=area.geometry)
                        .exclude(type__in=[AreaType.LEASE_AREA, AreaType.PLOT_DIVISION])
                        .exclude(geometry__touches=area.geometry)
                    )
                except InternalError:
                    LOG.exception("Failed to get intersected areas")
                    continue

                for intersect_area in intersected_areas:
                    LOG.debug(
                        "  #%s %s %s",
                        intersect_area.id,
                        intersect_area.identifier,
                        intersect_area.type,
                    )

                    # As of 21.1.2020, there are about 250 of plan unit area objects that have {'area': None, ...}
                    # in their metadata json field. I suspect this is due to accidental duplications in the source db
                    # since it seems like there is usually another object with identical metadata and identifier fields
                    # (except also having a value for the 'area' key) to be found, which we want to actually use.
                    if not intersect_area.metadata.get("area"):
                        LOG.debug(
                            "Lease #%s %s: DISCARD area %s: no 'area' value in metadata",
                            lease.id,
                            lease.identifier,
                            intersect_area.id,
                        )
                        continue

                    try:
                        # Discard too small intersect area
                        intersection = (
                            intersect_area.geometry
                            & lease_areas[area_identifier].geometry
                        )
                        intersection.transform(3879)
                        if intersection.area < 1:
                            LOG.debug(
                                "Lease #%s %s: DISCARD area %s: intersection area too small",
                                lease.id,
                                lease.identifier,
                                intersect_area.id,
                            )
                            continue
                    except GEOSException as e:
                        LOG.exception(
                            "Discarding too small intersect area failed %s", e
                        )
                        continue

                    if (
                        intersect_area.type == AreaType.REAL_PROPERTY
                        or intersect_area.type == AreaType.UNSEPARATED_PARCEL
                    ):
                        # If the intersect area's type is real property (kiinteistö) or unseparated parcel (määräala)
                        # then update or create the intersect area to plots
                        match_data = {
                            "lease_area": lease_areas[area_identifier],
                            "type": PlotType[intersect_area.type.value.upper()],
                            "identifier": intersect_area.get_denormalized_identifier(),
                            "is_master": True,
                        }
                        rest_data = {
                            "area": float(intersect_area.metadata.get("area")),
                            "section_area": intersection.area,
                            "registration_date": intersect_area.metadata.get(
                                "registration_date"
                            ),
                            "repeal_date": intersect_area.metadata.get("repeal_date"),
                            "geometry": intersect_area.geometry,
                            "master_timestamp": datetime.now(),
                        }
                        (plot, plot_created) = Plot.objects.get_or_create(
                            defaults=rest_data, **match_data
                        )
                        if not plot_created:
                            rest_data.pop("master_timestamp")
                            for attr, value in rest_data.items():
                                setattr(plot, attr, value)
                            plot.save()

                        plot_ids_handled.append(plot.id)

                        LOG.debug(
                            "Lease #%s %s: Plot #%s (%s) saved",
                            lease.id,
                            lease.identifier,
                            plot.id,
                            plot.type,
                        )

                    elif intersect_area.type == AreaType.PLAN_UNIT:
                        # Find the plot division (tonttijako) that intersects the most
                        plot_division_area = (
                            Area.objects.filter(
                                geometry__intersects=intersect_area.geometry,
                                type=AreaType.PLOT_DIVISION,
                            )
                            .extra(
                                select={
                                    "interarea": "ST_Area(ST_Transform(ST_Intersection(geometry, '{}'), 3879))".format(
                                        intersect_area.geometry
                                    )
                                }
                            )
                            .order_by("-interarea")
                            .first()
                        )

                        # If the plot division area exist then create/update plan unit informations
                        if plot_division_area and plot_division_area.interarea > 0:
                            # Get or create plot division state
                            (
                                plot_division_state,
                                created,
                            ) = PlotDivisionState.objects.get_or_create(
                                name=plot_division_area.metadata.get("state_name")
                            )

                            # Get detailed plan area
                            detailed_plan_area = Area.objects.filter(
                                type=AreaType.DETAILED_PLAN,
                                identifier=intersect_area.metadata.get(
                                    "detailed_plan_identifier"
                                ),
                            ).first()

                            # The variable is unused for some reason
                            detailed_plan_latest_processing_date = None

                            # If detailed plan area exist, set the identifier
                            detailed_plan_identifier = None
                            if detailed_plan_area:
                                detailed_plan_identifier = detailed_plan_area.identifier

                            # Get or create plan unit type
                            (
                                plan_unit_type,
                                created,
                            ) = PlanUnitType.objects.get_or_create(
                                name=intersect_area.metadata.get("type_name")
                            )

                            # Get or create plan unit state
                            (
                                plan_unit_state,
                                created,
                            ) = PlanUnitState.objects.get_or_create(
                                name=intersect_area.metadata.get("state_name")
                            )

                            # If the intersect area has intended use name, get or create it to plan unit intended use
                            plan_unit_intended_use = None
                            if intersect_area.metadata.get("intended_use_name"):
                                (
                                    plan_unit_intended_use,
                                    created,
                                ) = PlanUnitIntendedUse.objects.get_or_create(
                                    name=intersect_area.metadata.get(
                                        "intended_use_name"
                                    )
                                )

                            match_data = {
                                "lease_area": lease_areas[area_identifier],
                                "identifier": intersect_area.get_denormalized_identifier(),
                                "is_master": True,
                            }
                            rest_data = {
                                "area": float(intersect_area.metadata.get("area")),
                                "section_area": intersection.area,
                                "geometry": intersect_area.geometry,
                                "plot_division_identifier": plot_division_area.identifier,
                                "plot_division_date_of_approval": plot_division_area.metadata.get(
                                    "date_of_approval"
                                ),
                                "plot_division_effective_date": plot_division_area.metadata.get(
                                    "effective_date"
                                ),
                                "plot_division_state": plot_division_state,
                                "detailed_plan_identifier": detailed_plan_identifier,
                                "detailed_plan_latest_processing_date": detailed_plan_latest_processing_date,
                                "plan_unit_type": plan_unit_type,
                                "plan_unit_state": plan_unit_state,
                                "plan_unit_intended_use": plan_unit_intended_use,
                                "master_timestamp": datetime.now(),
                            }

                            # Set plan unit status
                            if plan_unit_state.to_enum() is not None:
                                rest_data[
                                    "plan_unit_status"
                                ] = plan_unit_state.to_enum()

                            # Get or create plan unit
                            (
                                plan_unit,
                                plan_unit_created,
                            ) = PlanUnit.objects.get_or_create(
                                defaults=rest_data, **match_data
                            )
                            if not plan_unit_created:
                                rest_data.pop("master_timestamp")
                                for attr, value in rest_data.items():
                                    setattr(plan_unit, attr, value)
                                plan_unit.save()

                            plan_unit_ids_handled.append(plan_unit.id)

                            LOG.debug(
                                "Lease #%s %s: PlanUnit #%s saved",
                                lease.id,
                                lease.identifier,
                                plan_unit.id,
                            )

                Plot.objects.filter(lease_area=lease_areas[area_identifier]).exclude(
                    id__in=plot_ids_handled
                ).delete()

                PlanUnit.objects.filter(
                    lease_area=lease_areas[area_identifier]
                ).exclude(id__in=plan_unit_ids_handled).delete()
コード例 #15
0
ファイル: tests.py プロジェクト: jjkester/django-auditlog
 def setUp(self):
     auditlog.unregister(SimpleModel)
     self.obj = SimpleModel.objects.create(text='No history')
コード例 #16
0
ファイル: basis_of_rent.py プロジェクト: hkotkanen/mvj
    def execute(self):  # noqa: C901 'Command.handle' is too complex
        from auditlog.registry import auditlog

        # Unregister all models from auditlog when importing
        for model in list(auditlog._registry.keys()):
            auditlog.unregister(model)

        cursor = self.cursor

        query = """
            SELECT * FROM (
                SELECT p.*, ROW_NUMBER() OVER (ORDER BY ALKUPVM) rn
                FROM PERUSTE p
                ORDER BY ALKUPVM
            ) t
            WHERE rn >= {}
            """.format(self.offset)

        cursor.execute(query)

        peruste_rows = rows_to_dict_list(cursor)

        peruste_count = len(peruste_rows)

        count = 0
        if self.offset:
            count = self.offset - 1
            peruste_count += self.offset

        self.stdout.write('{} basis of rent rows'.format(peruste_count))

        for basis_of_rent_row in peruste_rows:
            count += 1
            self.stdout.write('PERUSTE #{} ({}/{})'.format(
                basis_of_rent_row['PERUSTE'], count, peruste_count))

            if basis_of_rent_row['KORTTELI'] is None:
                self.stdout.write(' KORTTELI missing. Skipping.')
                continue

            index = None
            if basis_of_rent_row['KK'] and basis_of_rent_row['VUOSI']:
                try:
                    index = Index.objects.get(month=basis_of_rent_row['KK'],
                                              year=basis_of_rent_row['VUOSI'])
                except Index.DoesNotExist:
                    self.stdout.write(
                        'Index VUOSI {} KK {} does not exist!'.format(
                            basis_of_rent_row['VUOSI'],
                            basis_of_rent_row['KK']))

            notes = []
            if basis_of_rent_row['PERUSTETXT']:
                notes.append(basis_of_rent_row['PERUSTETXT'].strip())

            if basis_of_rent_row['ALENNUSTXT']:
                notes.append(basis_of_rent_row['ALENNUSTXT'].strip())

            (basis_of_rent, created) = BasisOfRent.objects.get_or_create(
                plot_type_id=BASIS_OF_RENT_PLOT_TYPE_MAP[
                    basis_of_rent_row['TONTTITYYPPI']],
                start_date=basis_of_rent_row['ALKUPVM'].date()
                if basis_of_rent_row['ALKUPVM'] else None,
                end_date=basis_of_rent_row['LOPPUPVM'].date()
                if basis_of_rent_row['LOPPUPVM'] else None,
                detailed_plan_identifier=basis_of_rent_row['KAAVANO'],
                financing_id=FINANCING_MAP[basis_of_rent_row['RAHOITUSMUOTO']]
                if basis_of_rent_row['RAHOITUSMUOTO'] else None,
                management_id=MANAGEMENT_MAP[
                    basis_of_rent_row['HALLINTAMUOTO']]
                if basis_of_rent_row['HALLINTAMUOTO'] else None,
                lease_rights_end_date=basis_of_rent_row['VUOKRAUSOIKEUSPVM'].
                date() if basis_of_rent_row['VUOKRAUSOIKEUSPVM'] else None,
                index=index,
                note='\n\n'.join(notes) if notes else None,
            )

            property_identifier = get_real_property_identifier(
                basis_of_rent_row)

            (basis_of_rent_property_identifier,
             created) = BasisOfRentPropertyIdentifier.objects.get_or_create(
                 basis_of_rent=basis_of_rent, identifier=property_identifier)

            decision_column_prefixes = ['KLK', 'MUU']

            for decision_column_prefix in decision_column_prefixes:
                decision_maker_string = basis_of_rent_row['{}_PAATTAJA'.format(
                    decision_column_prefix)]
                decision_datetime = basis_of_rent_row['{}_PAATOSPVM'.format(
                    decision_column_prefix)]
                decision_section_string = basis_of_rent_row['{}_PYKALA'.format(
                    decision_column_prefix)]

                if not decision_maker_string or not decision_datetime:
                    continue

                (
                    basis_of_rent_decision, created
                ) = BasisOfRentDecision.objects.get_or_create(
                    basis_of_rent=basis_of_rent,
                    reference_number=None,  # TODO
                    decision_maker_id=DECISION_MAKER_MAP[decision_maker_string]
                    if decision_maker_string else None,
                    decision_date=decision_datetime.date()
                    if decision_datetime else None,
                    section=decision_section_string
                    if decision_section_string else None,
                )

            query = """
                SELECT *
                FROM PERUSTE_HINNAT
                WHERE PERUSTE = {}
                """.format(basis_of_rent_row['PERUSTE'])

            cursor.execute(query)

            hinta_rows = rows_to_dict_list(cursor)

            for rate_row in hinta_rows:
                build_permission_type = BASIS_OF_RENT_BUILD_PERMISSION_MAP[(
                    rate_row['RAKENNUSOIKEUSTYYPPI'], rate_row['ERITTELY'])]
                amount = rate_row['MUU_HINTA_ARVIO']
                area_unit = BASIS_OF_RENT_RATE_AREA_UNIT_MAP[
                    rate_row['MUU_HINTA_YKS']]

                if not amount:
                    amount = rate_row['KLK_HINTA_ARVIO']
                    area_unit = BASIS_OF_RENT_RATE_AREA_UNIT_MAP[
                        rate_row['KLK_HINTA_YKS']]

                    if not amount:
                        amount = rate_row['HINTA_ARVIO']
                        area_unit = BASIS_OF_RENT_RATE_AREA_UNIT_MAP[
                            rate_row['HINTA_YKS']]

                (basis_of_rent_rate,
                 created) = BasisOfRentRate.objects.get_or_create(
                     basis_of_rent=basis_of_rent,
                     build_permission_type_id=build_permission_type,
                     amount=amount,
                     area_unit=area_unit,
                 )
コード例 #17
0
ファイル: import_interest_rate.py プロジェクト: hkotkanen/mvj
    def handle(self, *args, **options):
        from auditlog.registry import auditlog

        auditlog.unregister(InterestRate)

        r = requests.get(
            'https://www.suomenpankki.fi/WebForms/ReportViewerPage.aspx',
            params={
                'report':
                '/tilastot/markkina-_ja_hallinnolliset_korot/viitekorko_fi',
                'output': 'xml',
            })

        if r.status_code != 200:
            raise CommandError('Failed to download interest rates')

        root = ElementTree.fromstring(r.content)

        for year_element in root.findall('.//{viitekorko_fi}matrix1_year'):
            current_year = int(year_element.attrib.get('txtb_year'))

            for period_element in year_element.findall(
                    './/{viitekorko_fi}matrix1_Period'):
                current_period_string = period_element.attrib.get('Period')
                period_match = re.match(
                    r'(?P<start_day>\d+)\.(?P<start_month>\d+)\..(?P<end_day>\d+)\.(?P<end_month>\d+)',
                    current_period_string)

                if not period_match:
                    continue

                start_date = datetime.date(
                    year=current_year,
                    month=int(period_match.group('start_month')),
                    day=int(period_match.group('start_day')))
                end_date = datetime.date(
                    year=current_year,
                    month=int(period_match.group('end_month')),
                    day=int(period_match.group('end_day')))

                currency_elements = period_element.findall(
                    './{viitekorko_fi}col_grp_currency_Collection/{viitekorko_fi}col_grp_currency'
                )

                rates = {}
                for currency_element in currency_elements:
                    interest_type_string = currency_element.attrib.get(
                        'txtb_currency')
                    if interest_type_string not in [
                            'Korkolain perusteella vahvistettu viitekorko',
                            'Viivästyskorko, kun velasta ei ole sovittu maksettavaksi korkoa'
                    ]:
                        continue

                    cell = currency_element.find('./{viitekorko_fi}Cell')
                    interest_value_string = cell.attrib.get('txtb_value', '')
                    if not interest_value_string:
                        continue

                    interest_value = Decimal(cell.attrib.get('txtb_value', ''))

                    rates[interest_type_string] = interest_value

                    self.stdout.write('{} - {} {}: {}'.format(
                        start_date, end_date, interest_type_string,
                        interest_value))

                InterestRate.objects.update_or_create(
                    start_date=start_date,
                    end_date=end_date,
                    reference_rate=rates[
                        'Korkolain perusteella vahvistettu viitekorko'],
                    penalty_rate=rates[
                        'Viivästyskorko, kun velasta ei ole sovittu maksettavaksi korkoa']
                )
コード例 #18
0
    def handle(self, *args, **options):
        from auditlog.registry import auditlog

        auditlog.unregister(InterestRate)

        r = requests.get(
            "https://www.suomenpankki.fi/WebForms/ReportViewerPage.aspx",
            params={
                "report":
                "/tilastot/markkina-_ja_hallinnolliset_korot/viitekorko_fi",
                "output": "xml",
            },
        )

        if r.status_code != 200:
            raise CommandError("Failed to download interest rates")

        root = ElementTree.fromstring(r.content)

        for year_element in root.findall(".//{viitekorko_fi}matrix1_year"):
            current_year = int(year_element.attrib.get("txtb_year"))

            for period_element in year_element.findall(
                    ".//{viitekorko_fi}matrix1_Period"):
                current_period_string = period_element.attrib.get("Period")
                period_match = re.match(
                    r"(?P<start_day>\d+)\.(?P<start_month>\d+)\..(?P<end_day>\d+)\.(?P<end_month>\d+)",
                    current_period_string,
                )

                if not period_match:
                    continue

                start_date = datetime.date(
                    year=current_year,
                    month=int(period_match.group("start_month")),
                    day=int(period_match.group("start_day")),
                )
                end_date = datetime.date(
                    year=current_year,
                    month=int(period_match.group("end_month")),
                    day=int(period_match.group("end_day")),
                )

                currency_elements = period_element.findall(
                    "./{viitekorko_fi}col_grp_currency_Collection/{viitekorko_fi}col_grp_currency"
                )

                rates = {}
                for currency_element in currency_elements:
                    interest_type_string = currency_element.attrib.get(
                        "txtb_currency")
                    if interest_type_string not in [
                            "Korkolain perusteella vahvistettu viitekorko",
                            "Viivästyskorko, kun velasta ei ole sovittu maksettavaksi korkoa",
                    ]:
                        continue

                    cell = currency_element.find("./{viitekorko_fi}Cell")
                    interest_value_string = cell.attrib.get("txtb_value", "")
                    if not interest_value_string:
                        continue

                    interest_value = Decimal(cell.attrib.get("txtb_value", ""))

                    rates[interest_type_string] = interest_value

                    self.stdout.write("{} - {} {}: {}".format(
                        start_date, end_date, interest_type_string,
                        interest_value))

                InterestRate.objects.update_or_create(
                    start_date=start_date,
                    end_date=end_date,
                    reference_rate=rates[
                        "Korkolain perusteella vahvistettu viitekorko"],
                    penalty_rate=rates[
                        "Viivästyskorko, kun velasta ei ole sovittu maksettavaksi korkoa"],
                )
コード例 #19
0
def importa_contratos():
    auditlog.unregister(Contrato)
    auditlog.unregister(ContratoUnidade)
    auditlog.unregister(DocumentoFiscal)
    auditlog.unregister(FiscaisUnidade)
    auditlog.unregister(Divisao)
    auditlog.unregister(Nucleo)
    auditlog.unregister(Unidade)
    auditlog.unregister(Coad)

    cria_coad()

    digecon = cria_digecon()
    nucleos = cria_nucleos(digecon)

    dotacoes = {}

    apaga_contratos()

    for index, row in df.iterrows():
        tc = row['TC'].strip()
        eol_unidade = row['EOL_UNIDADE'].strip()

        print(f'Cont:{index} Importando Linha:{row["LINHA"]} TC:{tc}')

        empresa_data = {'nome': row['EMPRESA'], 'cnpj': clean_id(row['CNPJ'])}
        empresa_contratada = importa_empresa(empresa_data)

        servico = de_para_servicos(row["OBJETO"])
        tipo_servico = importa_tipo_servico({'nome': servico})

        equipamento = de_para_equipamento(row['EQP'])

        delta = row['TERMINO'] - row['INICIO']
        vigencia_em_dias = delta.days

        unidade_data = {
            'codigo_eol': eol_unidade,
            'cep': row['CEP_UNIDADE'],
            'nome': row['NOME_UNIDADE'],
            'equipamento': equipamento,
            'tipo_unidade': row['EQP']
        }
        unidade = importa_unidade(unidade_data)

        contrato_data = {
            'termo_contrato': tc,
            'processo': row['PROCESSO'],
            'tipo_servico': tipo_servico,
            'nucleo_responsavel': nucleos[equipamento],
            'empresa_contratada': empresa_contratada,
            'data_ordem_inicio': row['INICIO'],
            'vigencia_em_dias': vigencia_em_dias,
            'situacao': Contrato.SITUACAO_ATIVO,
            'estado_contrato': de_para_estado(row['SITUACAO'], ),
            'data_encerramento': row['TERMINO']
        }

        contrato = importa_contrato(contrato_data)

        contrato_detalhe_data = {
            'contrato': contrato,
            'unidade': unidade,
            'valor_mensal': row['TOTAL_MENSAL'],
            # TODO Rever a gravação de dotações em função de mudanças do modelo após importação inicial.
            # 'dotacao_orcamentaria': row['DOTACAO'],
            'lote': row['LOTE'],
        }

        importa_contrato_detalhe(contrato_detalhe_data)

        # Grava dotacoes do contrato
        if contrato.termo_contrato not in dotacoes:
            dotacoes[contrato.termo_contrato] = set()

        dotacoes[contrato.termo_contrato].add(row['DOTACAO'])

    importa_dres()

    grava_dotacoes(dotacoes)

    if __name__ == '__main__':
        importa_contratos()