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

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
2import logging
3import os
4import traceback
5from django.core.management.base import CommandParser
6from jbank.models import (
7 Payout,
8 PAYOUT_ERROR,
9 PAYOUT_WAITING_PROCESSING,
10 PayoutStatus,
11 PAYOUT_WAITING_UPLOAD,
12 WsEdiConnection,
13)
14from jbank.sepa import (
15 Pain001,
16 PAIN001_REMITTANCE_INFO_MSG,
17 PAIN001_REMITTANCE_INFO_OCR_ISO,
18 PAIN001_REMITTANCE_INFO_OCR,
19)
20from jutil.command import SafeCommand
23logger = logging.getLogger(__name__)
26class 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 """
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")
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))
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)
58 for p in list(payouts):
59 assert isinstance(p, Payout)
60 try:
61 if options["verbose"]:
62 print(p)
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"])
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 )
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"])
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 )