Coverage for jbank/management/commands/wsedi_upload.py: 0%

1# pylint: disable=logging-format-interpolation,too-many-locals

2 import logging

3 import traceback

4 from django.core.management.base import CommandParser

5 from jutil.xml import xml_to_dict

6 from jbank.models import Payout, PayoutStatus, PAYOUT_ERROR, PAYOUT_WAITING_UPLOAD, PAYOUT_UPLOADED, WsEdiConnection

7 from jbank.wsedi import wsedi_upload_file, wsedi_execute

8 from jutil.command import SafeCommand

9

10

11 logger = logging.getLogger(__name__)

12

13

14 class Command(SafeCommand):

15 help = """

16 Upload Finnish bank files

17 """

18

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)

26

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

34

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"])

42

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

47

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

54

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

83

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 )

106

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 )