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

# Coverage for jbank/management/commands/make_pain001.py : 0%

## 66 statements

Hot-keys on this page

r m x p toggle line displays

j k next/prev highlighted chunk

0 (zero) top of page

1 (one) first highlighted chunk

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

2 import logging

3 import os

4 import traceback

5 from django.core.management.base import CommandParser

6 from jbank.models import (

7 Payout,

8 PAYOUT_ERROR,

9 PAYOUT_WAITING_PROCESSING,

10 PayoutStatus,

11 PAYOUT_WAITING_UPLOAD,

12 WsEdiConnection,

13)

14 from jbank.sepa import (

15 Pain001,

16 PAIN001_REMITTANCE_INFO_MSG,

17 PAIN001_REMITTANCE_INFO_OCR_ISO,

18 PAIN001_REMITTANCE_INFO_OCR,

19)

20 from jutil.command import SafeCommand

21

22

23 logger = logging.getLogger(__name__)

24

25

26 class Command(SafeCommand):

27 help = """

28 Generates pain.001.001.03 compatible SEPA payment files from pending Payout objects.

29 By default generates files of Payouts in WAITING_PROCESSING state.

30 """

31

32 def add_arguments(self, parser: CommandParser):

33 parser.add_argument("dir", type=str)

34 parser.add_argument("--payout", type=int)

35 parser.add_argument("--verbose", action="store_true")

36 parser.add_argument("--ws", type=int)

37 parser.add_argument("--suffix", type=str, default="XL")

38 parser.add_argument("--xml-declaration", action="store_true")

39

40 def do(self, *args, **options):

41 target_dir = options["dir"]

42 if options["verbose"]:

43 logger.info("Writing pain.001 files to {}".format(target_dir))

44

45 payouts = Payout.objects.all()

46 if options["payout"]:

47 payouts = Payout.objects.filter(id=options["payout"])

48 else:

49 payouts = payouts.filter(state=PAYOUT_WAITING_PROCESSING)

50 if options["ws"]:

51 ws = WsEdiConnection.objects.get(id=options["ws"])

52 assert isinstance(ws, WsEdiConnection)

53 if ws and not ws.enabled:

54 logger.info("WS connection %s not enabled, exiting", ws)

55 return

56 payouts = payouts.filter(connection=ws)

57

58 for p in list(payouts):

59 assert isinstance(p, Payout)

60 try:

61 if options["verbose"]:

62 print(p)

63

64 if not p.msg_id:

65 p.generate_msg_id()

66 if not p.file_name:

67 p.file_name = p.msg_id + "." + options["suffix"]

68 p.save(update_fields=["file_name"])

69

70 pain001 = Pain001(

71 p.msg_id,

72 p.payer.name,

73 p.payer.account_number,

74 p.payer.bic,

75 p.payer.org_id,

76 p.payer.address_lines,

77 p.payer.country_code,

78 )

79 if options["xml_declaration"]:

80 pain001.xml_declaration = options["xml_declaration"]

81 if p.messages:

82 remittance_info = p.messages

83 remittance_info_type = PAIN001_REMITTANCE_INFO_MSG

84 else:

85 remittance_info = p.reference

86 remittance_info_type = (

87 PAIN001_REMITTANCE_INFO_OCR_ISO if remittance_info[:2] == "RF" else PAIN001_REMITTANCE_INFO_OCR

88 )

89 pain001.add_payment(

90 p.msg_id,

91 p.recipient.name,

92 p.recipient.account_number,

93 p.recipient.bic,

94 p.amount,

95 remittance_info,

96 remittance_info_type,

97 p.due_date,

98 )

99

100 p.full_path = full_path = os.path.join(target_dir, p.file_name)

101 if options["verbose"]:

102 print(p, "written to", full_path)

103 pain001.render_to_file(full_path)

104 logger.info("{} generated".format(full_path))

105 p.state = PAYOUT_WAITING_UPLOAD

106 p.save(update_fields=["full_path", "state"])

107

108 PayoutStatus.objects.create(

109 payout=p, file_name=p.file_name, msg_id=p.msg_id, status_reason="File generation OK"

110 )

111 except Exception as e:

112 short_err = "File generation failed: " + str(e)

113 long_err = "File generation failed ({}): ".format(p.file_name) + traceback.format_exc()

114 logger.error(long_err)

115 p.state = PAYOUT_ERROR

116 p.save(update_fields=["state"])

117 PayoutStatus.objects.create(

118 payout=p,

119 group_status=PAYOUT_ERROR,

120 file_name=p.file_name,

121 msg_id=p.msg_id,

122 status_reason=short_err[:255],

123 )