def handle(self, *args, **options):
        self.check_settings()
        self.check_export_directory()

        now = timezone.now()
        today = datetime.date.today()
        one_month_in_the_future = today + relativedelta(months=1)

        # TODO: Make configurable
        receivable_type_rent = ReceivableType.objects.get(pk=1)

        laske_export_log_entry = LaskeExportLog.objects.create(started_at=now)

        invoices = Invoice.objects.filter(
            due_date__gte=today,
            due_date__lte=one_month_in_the_future,
            sent_to_sap_at__isnull=True)

        sales_orders = []
        log_invoices = []

        if not invoices:
            self.stdout.write('No invoices to send. Exiting.')
            return

        for invoice in invoices:
            sales_order = SalesOrder()
            set_constant_laske_values(sales_order)

            adapter = InvoiceSalesOrderAdapter(
                invoice=invoice,
                sales_order=sales_order,
                receivable_type_rent=receivable_type_rent)
            adapter.set_values()

            # TODO: check sales_order validity
            sales_orders.append(sales_order)
            log_invoices.append(invoice)

        sales_order_container = SalesOrderContainer()
        sales_order_container.sales_orders = sales_orders

        laske_export_log_entry.invoices.set(log_invoices)

        export_filename = 'MTIL_IN_{}_{:08}.xml'.format(
            settings.LASKE_VALUES['sender_id'], laske_export_log_entry.id)

        xml_string = sales_order_container.to_xml_string()

        self.save_to_file(xml_string, export_filename)
        self.send(export_filename)

        # TODO: Log errors
        laske_export_log_entry.ended_at = timezone.now()
        laske_export_log_entry.is_finished = True
        laske_export_log_entry.save()
Exemple #2
0
    def export_invoices(self, invoices):
        """
        :type invoices: list of Invoice | Invoice
        :rtype: LaskeExportLog
        """
        if isinstance(invoices, Invoice) or isinstance(
                invoices, LandUseAgreementInvoice):
            invoices = [invoices]

        # TODO: Make configurable
        receivable_type_rent = ReceivableType.objects.get(pk=1)
        receivable_type_collateral = ReceivableType.objects.get(pk=8)

        now = timezone.now()
        laske_export_log_entry = LaskeExportLog.objects.create(started_at=now)

        sales_orders = []
        log_invoices = []
        invoice_count = 0

        self.write_to_output("Going through {} invoices".format(len(invoices)))

        for invoice in invoices:
            invoice_log_item = LaskeExportLogInvoiceItem(
                invoice=invoice, laskeexportlog=laske_export_log_entry)
            log_invoices.append(invoice_log_item)

            try:
                self.write_to_output(" Invoice id {}".format(invoice.id))

                # If this invoice is a credit note, but the credited invoice has
                # not been sent to SAP, don't send the credit invoice either.
                # TODO This doesn't check if the credited invoice would be sent
                #   in this same export. Need to check if the SAP can handle it.
                if invoice.type == InvoiceType.CREDIT_NOTE and (
                        not invoice.credited_invoice
                        or not invoice.credited_invoice.sent_to_sap_at):
                    if invoice.credited_invoice:
                        self.write_to_output(
                            " Not sending invoice id {} because the credited invoice (id {}) "
                            "has not been sent to SAP.".format(
                                invoice.id, invoice.credited_invoice.id))
                    else:
                        self.write_to_output(
                            " Not sending invoice id {} because the credited invoice is unknown."
                            .format(invoice.id))

                    continue

                if not invoice.invoicing_date:
                    invoice.invoicing_date = now.date()
                    invoice.save()

                sales_order = SalesOrder()
                set_constant_laske_values(sales_order)

                adapter = InvoiceSalesOrderAdapter(
                    invoice=invoice,
                    sales_order=sales_order,
                    receivable_type_rent=receivable_type_rent,
                    receivable_type_collateral=receivable_type_collateral,
                )
                adapter.set_values()

                sales_order.validate()

                sales_orders.append(sales_order)

                invoice_count += 1

                self.write_to_output(
                    " Added invoice id {} as invoice number {}".format(
                        invoice.id, invoice.number))

                invoice_log_item.status = LaskeExportLogInvoiceStatus.SENT
            except ValidationError as err:
                self.write_to_output(
                    "Validation error occurred in #{} ({}) invoice. Errors: {}"
                    .format(invoice.number, invoice.id,
                            "; ".join(err.messages)))
                logger.warning(err, exc_info=True)
                invoice_log_item.status = LaskeExportLogInvoiceStatus.FAILED
                invoice_log_item.information = json.dumps(err.message_dict)
            finally:
                invoice_log_item.save()

        if invoice_count > 0:
            self.write_to_output(
                "Added {} invoices to the export".format(invoice_count))

            sales_order_container = SalesOrderContainer()
            sales_order_container.sales_orders = sales_orders

            export_filename = "MTIL_IN_{}_{:08}.xml".format(
                settings.LASKE_VALUES["sender_id"], laske_export_log_entry.id)

            self.write_to_output("Export filename: {}".format(export_filename))

            xml_string = sales_order_container.to_xml_string()

            self.save_to_file(xml_string, export_filename)

            self.write_to_output("Sending...")

            self.send(export_filename)

            self.write_to_output("Done.")

            Invoice.objects.filter(id__in=[o.id for o in invoices]).update(
                sent_to_sap_at=now)

        # TODO: Log errors
        laske_export_log_entry.ended_at = timezone.now()
        laske_export_log_entry.is_finished = True
        laske_export_log_entry.save()

        return laske_export_log_entry
Exemple #3
0
def test_one_primary_and_nonprimary_addresses_in_leasearea(
    django_db_setup,
    lease_factory,
    rent_factory,
    contact_factory,
    tenant_factory,
    tenant_rent_share_factory,
    tenant_contact_factory,
    invoice_factory,
    invoice_row_factory,
    lease_area_factory,
    lease_area_address_factory,
):
    lease = lease_factory(type_id=1,
                          municipality_id=1,
                          district_id=5,
                          notice_period_id=1)

    rent_factory(
        lease=lease,
        cycle=RentCycle.APRIL_TO_MARCH,
        due_dates_type=DueDatesType.FIXED,
        due_dates_per_year=1,
    )

    lease_area = lease_area_factory(lease=lease,
                                    identifier=get_random_string(),
                                    area=1000,
                                    section_area=1000)
    lease_area_address_factory(
        lease_area=lease_area,
        is_primary=False,
        address="Jokutoinen osoite",
        postal_code="00550",
        city="Helsinki",
    )
    lease_area_address_factory(
        lease_area=lease_area,
        is_primary=True,
        address="Ensisijainen testiosoite",
        postal_code="00550",
        city="Helsinki",
    )
    lease_area_address_factory(
        lease_area=lease_area,
        is_primary=False,
        address="Toissijainen osoite",
        postal_code="00550",
        city="Helsinki",
    )

    tenant1 = tenant_factory(lease=lease,
                             share_numerator=1,
                             share_denominator=1,
                             reference="testreference")
    tenant_rent_share_factory(tenant=tenant1,
                              intended_use_id=1,
                              share_numerator=1,
                              share_denominator=1)
    contact1 = contact_factory(first_name="First name 1",
                               last_name="Last name 1",
                               type=ContactType.PERSON)
    tenant_contact_factory(
        type=TenantContactType.TENANT,
        tenant=tenant1,
        contact=contact1,
        start_date=datetime.date(year=2000, month=1, day=1),
    )

    billing_period_start_date = datetime.date(year=2017, month=7, day=1)
    billing_period_end_date = datetime.date(year=2017, month=12, day=31)

    invoice = invoice_factory(
        lease=lease,
        total_amount=Decimal("123.45"),
        billed_amount=Decimal("123.45"),
        outstanding_amount=Decimal("123.45"),
        recipient=contact1,
        billing_period_start_date=billing_period_start_date,
        billing_period_end_date=billing_period_end_date,
    )

    receivable_type = ReceivableType.objects.get(pk=1)

    invoice_row_factory(
        invoice=invoice,
        tenant=tenant1,
        receivable_type=receivable_type,
        billing_period_start_date=billing_period_start_date,
        billing_period_end_date=billing_period_end_date,
        amount=Decimal("123.45"),
    )

    sales_order = SalesOrder()

    adapter = InvoiceSalesOrderAdapter(invoice=invoice,
                                       sales_order=sales_order,
                                       receivable_type_rent=receivable_type)

    adapter.set_values()

    assert "Ensisijainen testiosoite" in adapter.get_bill_text()
    assert "Jokutoinen osoite" not in adapter.get_bill_text()
    assert "Toissijainen osoite" not in adapter.get_bill_text()
Exemple #4
0
def test_ponumber_from_recipient_tenant(django_db_setup, lease_factory,
                                        rent_factory, contact_factory,
                                        tenant_factory,
                                        tenant_rent_share_factory,
                                        tenant_contact_factory,
                                        invoice_factory, invoice_row_factory):
    lease = lease_factory(
        type_id=1,
        municipality_id=1,
        district_id=5,
        notice_period_id=1,
    )

    rent_factory(
        lease=lease,
        cycle=RentCycle.APRIL_TO_MARCH,
        due_dates_type=DueDatesType.FIXED,
        due_dates_per_year=1,
    )

    tenant1 = tenant_factory(lease=lease,
                             share_numerator=1,
                             share_denominator=2,
                             reference='testreference1')
    tenant_rent_share_factory(tenant=tenant1,
                              intended_use_id=1,
                              share_numerator=1,
                              share_denominator=2)
    contact1 = contact_factory(first_name="First name 1",
                               last_name="Last name 1",
                               type=ContactType.PERSON)
    tenant_contact_factory(type=TenantContactType.TENANT,
                           tenant=tenant1,
                           contact=contact1,
                           start_date=datetime.date(year=2000, month=1, day=1))

    tenant2 = tenant_factory(lease=lease,
                             share_numerator=1,
                             share_denominator=2,
                             reference='testreference2')
    tenant_rent_share_factory(tenant=tenant2,
                              intended_use_id=1,
                              share_numerator=1,
                              share_denominator=2)
    contact2 = contact_factory(first_name="First name 2",
                               last_name="Last name 2",
                               type=ContactType.PERSON)
    tenant_contact_factory(type=TenantContactType.TENANT,
                           tenant=tenant2,
                           contact=contact2,
                           start_date=datetime.date(year=2000, month=1, day=1))

    billing_period_start_date = datetime.date(year=2017, month=7, day=1)
    billing_period_end_date = datetime.date(year=2017, month=12, day=31)

    invoice = invoice_factory(
        lease=lease,
        total_amount=Decimal('200'),
        billed_amount=Decimal('200'),
        outstanding_amount=Decimal('200'),
        recipient=contact2,
        billing_period_start_date=billing_period_start_date,
        billing_period_end_date=billing_period_end_date,
    )

    receivable_type = ReceivableType.objects.get(pk=1)

    invoice_row_factory(
        invoice=invoice,
        tenant=tenant1,
        receivable_type=receivable_type,
        billing_period_start_date=billing_period_start_date,
        billing_period_end_date=billing_period_end_date,
        amount=Decimal('100'),
    )
    invoice_row_factory(
        invoice=invoice,
        tenant=tenant2,
        receivable_type=receivable_type,
        billing_period_start_date=billing_period_start_date,
        billing_period_end_date=billing_period_end_date,
        amount=Decimal('100'),
    )

    sales_order = SalesOrder()

    adapter = InvoiceSalesOrderAdapter(invoice=invoice,
                                       sales_order=sales_order,
                                       receivable_type_rent=receivable_type)

    adapter.set_values()

    assert adapter.get_po_number() == 'testreference2'
Exemple #5
0
    def export_invoices(self, invoices):
        """
        :type invoices: list of Invoice | Invoice
        :rtype: LaskeExportLog
        """
        if isinstance(invoices, Invoice):
            invoices = [invoices]

        # TODO: Make configurable
        receivable_type_rent = ReceivableType.objects.get(pk=1)

        now = timezone.now()
        laske_export_log_entry = LaskeExportLog.objects.create(started_at=now)

        sales_orders = []
        log_invoices = []
        invoice_count = 0

        self.write_to_output('Going through {} invoices'.format(len(invoices)))

        for invoice in invoices:
            self.write_to_output(' Invoice id {}'.format(invoice.id))

            # If this invoice is a credit note, but the credited invoice has
            # not been sent to SAP, don't send the credit invoice either.
            # TODO This doesn't check if the credited invoice would be sent
            #   in this same export. Need to check if the SAP can handle it.
            if invoice.type == InvoiceType.CREDIT_NOTE and (
                    not invoice.credited_invoice
                    or not invoice.credited_invoice.sent_to_sap_at):
                if invoice.credited_invoice:
                    self.write_to_output(
                        ' Not sending invoice id {} because the credited invoice (id {}) '
                        'has not been sent to SAP.'.format(
                            invoice.id, invoice.credited_invoice.id))
                else:
                    self.write_to_output(
                        ' Not sending invoice id {} because the credited invoice is unknown.'
                        .format(invoice.id))

                continue

            # Zero amount invoices are currently sent to Laske. Uncomment this if desired otherwise.
            # if invoice.billed_amount == 0:
            #     self.write_to_output(' Not sending invoice id {} because the billed amount is 0'.format(invoice.id))
            #     continue

            if not invoice.invoicing_date:
                invoice.invoicing_date = now.date()
                invoice.save()

            sales_order = SalesOrder()
            set_constant_laske_values(sales_order)

            adapter = InvoiceSalesOrderAdapter(
                invoice=invoice,
                sales_order=sales_order,
                receivable_type_rent=receivable_type_rent)
            adapter.set_values()

            # TODO: check sales_order validity
            sales_orders.append(sales_order)
            log_invoices.append(invoice)

            invoice_count += 1

            self.write_to_output(
                ' Added invoice id {} as invoice number {}'.format(
                    invoice.id, invoice.number))

        if invoice_count > 0:
            self.write_to_output(
                'Added {} invoices to the export'.format(invoice_count))

            sales_order_container = SalesOrderContainer()
            sales_order_container.sales_orders = sales_orders

            laske_export_log_entry.invoices.set(log_invoices)

            export_filename = 'MTIL_IN_{}_{:08}.xml'.format(
                settings.LASKE_VALUES['sender_id'], laske_export_log_entry.id)

            self.write_to_output('Export filename: {}'.format(export_filename))

            xml_string = sales_order_container.to_xml_string()

            self.save_to_file(xml_string, export_filename)

            self.write_to_output('Sending...')

            self.send(export_filename)

            self.write_to_output('Done.')

            Invoice.objects.filter(id__in=[o.id for o in invoices]).update(
                sent_to_sap_at=now)

        # TODO: Log errors
        laske_export_log_entry.ended_at = timezone.now()
        laske_export_log_entry.is_finished = True
        laske_export_log_entry.save()

        return laske_export_log_entry