Coverage for jbank/management/commands/wsedi_upload.py: 0%
76 statements
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-27 13:36 +0700
« prev ^ index » next coverage.py v7.2.2, created at 2023-03-27 13:36 +0700
1# pylint: disable=logging-format-interpolation,too-many-locals
2import logging
3import traceback
4from django.core.management.base import CommandParser
5from jutil.xml import xml_to_dict
6from jbank.models import Payout, PayoutStatus, PAYOUT_ERROR, PAYOUT_WAITING_UPLOAD, PAYOUT_UPLOADED, WsEdiConnection
7from jbank.wsedi import wsedi_upload_file, wsedi_execute
8from jutil.command import SafeCommand
11logger = logging.getLogger(__name__)
14class Command(SafeCommand):
15 help = """
16 Upload Finnish bank files
17 """
19 def add_arguments(self, parser: CommandParser):
20 parser.add_argument("--payout", type=int)
21 parser.add_argument("--file-type", type=str, help="E.g. XL, NDCORPAYS, pain.001.001.03")
22 parser.add_argument("--verbose", action="store_true")
23 parser.add_argument("--force", action="store_true")
24 parser.add_argument("--default-ws", type=int)
25 parser.add_argument("--ws", type=int)
27 def do(self, *args, **options): # pylint: disable=too-many-branches
28 default_ws = WsEdiConnection.objects.get(id=options["default_ws"]) if options["default_ws"] else None
29 assert default_ws is None or isinstance(default_ws, WsEdiConnection)
30 file_type = options["file_type"]
31 if not file_type:
32 print("--file-type required (e.g. XL, NDCORPAYS, pain.001.001.03)")
33 return
35 payouts = Payout.objects.all()
36 if options["payout"]:
37 payouts = Payout.objects.filter(id=options["payout"])
38 else:
39 payouts = payouts.filter(state=PAYOUT_WAITING_UPLOAD)
40 if options["ws"]:
41 payouts = payouts.filter(connection_id=options["ws"])
43 for p in list(payouts.order_by("id").distinct()):
44 assert isinstance(p, Payout)
45 p.refresh_from_db()
46 ws_connection = p.connection or default_ws
48 if p.state != PAYOUT_WAITING_UPLOAD:
49 logger.info("Skipping {} since not in state PAYOUT_WAITING_UPLOAD".format(p))
50 continue
51 if ws_connection and not ws_connection.enabled:
52 logger.info("WS connection %s not enabled, skipping payment %s", ws_connection, p)
53 continue
55 response_code = ""
56 response_text = ""
57 try:
58 # upload file
59 logger.info("Uploading payment id={} {} file {}".format(p.id, file_type, p.full_path))
60 with open(p.full_path, "rt", encoding="utf-8") as fp:
61 file_content = fp.read()
62 p.state = PAYOUT_UPLOADED
63 p.save(update_fields=["state"])
64 if ws_connection:
65 content = wsedi_execute(
66 ws_connection,
67 "UploadFile",
68 file_content=file_content,
69 file_type=file_type,
70 verbose=options["verbose"],
71 )
72 data = xml_to_dict(content, array_tags=["FileDescriptor"])
73 else:
74 res = wsedi_upload_file(
75 file_content=file_content,
76 file_type=file_type,
77 file_name=p.file_name,
78 verbose=options["verbose"],
79 )
80 logger.info("HTTP response {}".format(res.status_code))
81 logger.info(res.text)
82 data = res.json()
84 # parse response
85 response_code = data.get("ResponseCode", "")[:4]
86 response_text = data.get("ResponseText", "")[:255]
87 if response_code != "00":
88 msg = "WS-EDI file {} upload failed: {} ({})".format(p.file_name, response_text, response_code)
89 logger.error(msg)
90 raise Exception("Response code {} ({})".format(response_code, response_text))
91 if "FileDescriptors" in data:
92 fds = data.get("FileDescriptors", {}).get("FileDescriptor", [])
93 fd = {} if not fds else fds[0]
94 file_reference = fd.get("FileReference", "")
95 if file_reference:
96 p.file_reference = file_reference
97 p.save(update_fields=["file_reference"])
98 PayoutStatus.objects.create(
99 payout=p,
100 msg_id=p.msg_id,
101 file_name=p.file_name,
102 response_code=response_code,
103 response_text=response_text,
104 status_reason="File upload OK",
105 )
107 except Exception as e:
108 long_err = "File upload failed ({}): ".format(p.file_name) + traceback.format_exc()
109 logger.error(long_err)
110 short_err = "File upload failed: " + str(e)
111 p.state = PAYOUT_ERROR
112 p.save(update_fields=["state"])
113 PayoutStatus.objects.create(
114 payout=p,
115 group_status=PAYOUT_ERROR,
116 msg_id=p.msg_id,
117 file_name=p.file_name,
118 response_code=response_code,
119 response_text=response_text,
120 status_reason=short_err[:255],
121 )