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()
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
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()
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'
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