Start abacus upload manually from admin interface

This commit is contained in:
Daniel Egger 2024-05-31 18:57:52 +02:00
parent 516079ba10
commit f4729cb4c8
7 changed files with 94 additions and 39 deletions

View File

@ -1,7 +1,6 @@
<script setup lang="ts">
import WizardPage from "@/components/onboarding/WizardPage.vue";
import type { Ref } from "vue";
import { computed, ref, watch } from "vue";
import { computed, ref } from "vue";
import { type User, useUserStore } from "@/stores/user";
import PersonalAddress from "@/components/onboarding/PersonalAddress.vue";
import OrganisationAddress from "@/components/onboarding/OrganisationAddress.vue";

View File

@ -1,5 +1,6 @@
encrypted: env_secrets/caprover_myvbv-prod.env
encrypted: env_secrets/caprover_myvbv-stage.env
encrypted: env_secrets/caprover_vbv-develop.env
encrypted: env_secrets/local_chrigu.env
encrypted: env_secrets/local_daniel.env
encrypted: env_secrets/local_elia.env

View File

@ -108,7 +108,10 @@ class AbacusInvoiceUploadTestCase(BaseAbacusSftpServerTestCase):
self.assertTrue(os.path.exists(order_filepath))
with open(order_filepath) as order_file:
order_content = order_file.read()
assert "<ReferencePurchaseOrder>24021508331287484</ReferencePurchaseOrder>" in order_content
assert (
"<ReferencePurchaseOrder>24021508331287484</ReferencePurchaseOrder>"
in order_content
)
assert "<CustomerNumber>60000012</CustomerNumber>" in order_content
feuz_checkout_info.refresh_from_db()

View File

@ -1,14 +1,10 @@
from django.contrib import admin
from vbv_lernwelt.shop.invoice.abacus import abacus_ssh_upload
from vbv_lernwelt.shop.models import CheckoutInformation, Product
from vbv_lernwelt.shop.services import get_transaction_state
@admin.action(description="ABACUS: Create invoices")
def generate_invoice(modeladmin, request, queryset):
pass
@admin.action(description="DATATRANS: Sync transaction states")
def sync_transaction_state(modeladmin, request, queryset):
for checkout in queryset:
@ -23,18 +19,60 @@ def sync_transaction_state(modeladmin, request, queryset):
@admin.register(CheckoutInformation)
class CheckoutInformationAdmin(admin.ModelAdmin):
@admin.action(description="ABACUS: Upload invoice to SFTP server")
def abacus_upload_order(self, request, queryset):
success = True
for ci in queryset:
if not abacus_ssh_upload(ci):
success = False
if not success:
self.message_user(
request, f"Beim SFTP upload ist ein Fehler aufgetreten", level="error"
)
@staticmethod
def customer(obj):
return f"{obj.user.first_name} {obj.user.last_name} ({obj.user.email})"
@staticmethod
def debitor_number(obj):
return obj.user.abacus_debitor_number
def has_delete_permission(self, request, obj=None):
# Disable delete
return False
list_display = (
"product_sku",
"user",
customer,
"product_name",
"product_price",
"updated_at",
"created_at",
"state",
"invoice_transmitted_at",
"abacus_order_id",
debitor_number,
"abacus_ssh_upload_done",
)
search_fields = ["user__email"]
list_filter = ("state", "product_name")
actions = [generate_invoice, sync_transaction_state]
search_fields = [
"user__email",
"user__first_name",
"user__last_name",
"user__username",
"transaction_id",
"abacus_order_id",
"user__abacus_debitor_number",
]
list_filter = ("state", "product_name", "product_sku", "abacus_ssh_upload_done")
date_hierarchy = "created_at"
actions = [abacus_upload_order, sync_transaction_state]
readonly_fields = [
"user",
"transaction_id",
"state",
"product_price",
"webhook_history",
]
@admin.register(Product)

View File

@ -6,25 +6,44 @@ from xml.etree.ElementTree import Element, SubElement, tostring
import structlog
from vbv_lernwelt.shop.invoice.abacus_sftp_client import AbacusSftpClient
from vbv_lernwelt.shop.models import CheckoutInformation
from vbv_lernwelt.shop.models import CheckoutInformation, CheckoutState
logger = structlog.get_logger(__name__)
def abacus_ssh_upload(checkout_information: CheckoutInformation):
invoice_xml_filename, invoice_xml_content = create_invoice_xml(checkout_information)
customer_xml_filename, customer_xml_content = create_customer_xml(
checkout_information
)
if checkout_information.state != CheckoutState.PAID:
# only upload invoice if checkout is paid
return True
abacus_ssh_upload_invoice(
customer_xml_filename, customer_xml_content, folder="debitor"
)
try:
invoice_xml_filename, invoice_xml_content = create_invoice_xml(
checkout_information
)
customer_xml_filename, customer_xml_content = create_customer_xml(
checkout_information
)
if not checkout_information.abacus_ssh_upload_done:
abacus_ssh_upload_invoice(invoice_xml_filename, invoice_xml_content, folder="order")
checkout_information.abacus_ssh_upload_done = True
checkout_information.save()
abacus_ssh_upload_invoice(
customer_xml_filename, customer_xml_content, folder="debitor"
)
if not checkout_information.abacus_ssh_upload_done:
abacus_ssh_upload_invoice(
invoice_xml_filename, invoice_xml_content, folder="order"
)
checkout_information.abacus_ssh_upload_done = True
checkout_information.invoice_transmitted_at = datetime.datetime.now()
checkout_information.save()
return True
except Exception as e:
logger.warning(
"Error uploading invoice to Abacus SFTP",
checkout_information_id=checkout_information.id,
exception=str(e),
)
return False
def create_invoice_xml(checkout_information: CheckoutInformation):
@ -212,13 +231,9 @@ def abacus_ssh_upload_invoice(
filename: str, content_xml: str, folder: str = ""
) -> None:
invoice_io = BytesIO(content_xml.encode("utf-8"))
try:
with AbacusSftpClient() as sftp_client:
path = filename
if folder:
path = f"{folder}/{filename}"
with AbacusSftpClient() as sftp_client:
path = filename
if folder:
path = f"{folder}/{filename}"
sftp_client.putfo(invoice_io, path)
except Exception as e:
logger.error("Could not upload invoice", exc_info=e)
sftp_client.putfo(invoice_io, path)

View File

@ -1,5 +1,5 @@
from django.conf import settings
from paramiko.client import SSHClient, AutoAddPolicy
from paramiko.client import AutoAddPolicy, SSHClient
def _create_abacus_sftp_client():

View File

@ -4,15 +4,14 @@ from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('shop', '0013_checkoutinformation_abacus_order_id'),
("shop", "0013_checkoutinformation_abacus_order_id"),
]
operations = [
migrations.AddField(
model_name='checkoutinformation',
name='abacus_ssh_upload_done',
model_name="checkoutinformation",
name="abacus_ssh_upload_done",
field=models.BooleanField(default=False),
),
]