Hide keyboard shortcuts

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-locals,too-many-branches 

2import base64 

3import logging 

4import os 

5import pytz 

6from django.core.management.base import CommandParser 

7from django.utils.timezone import now 

8from jutil.xml import xml_to_dict 

9from jbank.helpers import process_pain002_file_content, parse_start_and_end_date 

10from jbank.models import WsEdiConnection 

11from jbank.wsedi import wsedi_get, wsedi_execute 

12from jutil.command import SafeCommand 

13 

14 

15logger = logging.getLogger(__name__) 

16 

17 

18class Command(SafeCommand): 

19 help = """ 

20 Download Finnish bank files 

21 """ 

22 

23 def add_arguments(self, parser: CommandParser): 

24 parser.add_argument('path', type=str) 

25 parser.add_argument('--verbose', action='store_true') 

26 parser.add_argument('--overwrite', action='store_true') 

27 parser.add_argument('--file-type', type=str, help='E.g. TO, SVM, XP, NDCORPAYL, pain.002.001.03') 

28 parser.add_argument('--status', type=str, default='', help='E.g. DLD, NEW') 

29 parser.add_argument('--file-reference', type=str, help='Download single file based on file reference') 

30 parser.add_argument('--list-only', action='store_true') 

31 parser.add_argument('--process-pain002', action='store_true') 

32 parser.add_argument('--start-date', type=str) 

33 parser.add_argument('--end-date', type=str) 

34 parser.add_argument('--ws', type=int) 

35 

36 def do(self, *args, **options): # pylint: disable=too-many-statements 

37 ws = WsEdiConnection.objects.get(id=options['ws']) if options['ws'] else None 

38 assert ws is None or isinstance(ws, WsEdiConnection) 

39 if ws and not ws.enabled: 

40 logger.info('WS connection %s not enabled, exiting', ws) 

41 return 

42 

43 start_date, end_date = parse_start_and_end_date(pytz.timezone('Europe/Helsinki'), **options) 

44 path = os.path.abspath(options['path']) 

45 command = 'DownloadFileList' 

46 time_now = now() 

47 file_reference = options['file_reference'] 

48 if file_reference: 

49 command = 'DownloadFile' 

50 status = options['status'] 

51 file_type = options['file_type'] 

52 if command == 'DownloadFileList' and not file_type: 

53 print('--file-type required (e.g. TO, SVM, XP, NDCORPAYL, pain.002.001.03)') 

54 return 

55 if ws: 

56 content = wsedi_execute(ws, command=command, file_type=file_type, status=status, start_date=start_date, end_date=end_date, 

57 file_reference=file_reference, verbose=options['verbose']) 

58 data = xml_to_dict(content, array_tags=['FileDescriptor']) 

59 else: 

60 res = wsedi_get(command=command, file_type=file_type, status=status, file_reference=file_reference, verbose=options['verbose']) 

61 data = res.json() 

62 # "FileDescriptors": { 

63 # "FileDescriptor": [ 

64 # { 

65 # "FileReference": "535283541", 

66 # "TargetId": "NONE", 

67 # "UserFilename": "STOL001.FMV80KT2.WEBSER.PS", 

68 # "ParentFileReference": "1218", 

69 # "FileType": "TO", 

70 # "FileTimestamp": "2017-12-18T20:33:09.362+02:00", 

71 # "Status": "DLD", 

72 # "LastDownloadTimestamp": "2017-12-19T12:36:34.490+02:00", 

73 # "ForwardedTimestamp": "2017-12-18T20:33:09.362+02:00", 

74 # "Deletable": "false", 

75 # "CustomerNumber": "06720106", 

76 # "Modifier": "06720106", 

77 # "ModifiedTimestamp": "2017-12-19T12:36:34.490+02:00", 

78 # "SourceId": "A", 

79 # "Environment": "PRODUCTION" 

80 # }, 

81 # ... 

82 

83 if command == 'DownloadFileList': 

84 if 'FileDescriptors' in data and data['FileDescriptors'] is not None and 'FileDescriptor' in data['FileDescriptors']: 

85 for fd in data['FileDescriptors']['FileDescriptor']: 

86 file_reference = fd['FileReference'] 

87 file_type = fd['FileType'] 

88 file_basename = file_reference + '.' + file_type 

89 file_path = os.path.join(path, file_basename) 

90 if options['list_only']: 

91 print('{file_reference} ({file_type}/{status}): {user_filename} ({timestamp})'.format( 

92 file_reference=file_reference, file_type=file_type, status=fd.get('Status'), 

93 user_filename=fd.get('UserFilename'), timestamp=fd.get('FileTimestamp'))) 

94 continue 

95 if options['overwrite'] or not os.path.isfile(file_path): 

96 command = 'DownloadFile' 

97 if ws: 

98 content = wsedi_execute(ws, command=command, file_type=file_type, status='', file_reference=file_reference, 

99 verbose=options['verbose']) 

100 file_data = xml_to_dict(content) 

101 else: 

102 res = wsedi_get(command=command, file_type=file_type, status='', file_reference=file_reference, verbose=options['verbose']) 

103 file_data = res.json() 

104 if 'Content' not in file_data: 

105 logger.error('WS-EDI {} HTTP {} but Content block missing: {}'.format(command, res.status_code, file_data)) 

106 raise Exception("WS-EDI {} HTTP {} but Content block missing".format(command, res.status_code)) 

107 bcontent = base64.b64decode(file_data['Content']) 

108 with open(file_path, 'wb') as fp: 

109 fp.write(bcontent) 

110 logger.info('Wrote file {}'.format(file_path)) 

111 

112 # process selected files immediately 

113 if options['process_pain002'] and file_type in ['XP', 'pain.002.001.03', 'NDCORPAYL']: 

114 process_pain002_file_content(bcontent, file_path, created=time_now) 

115 else: 

116 print('Skipping old file {}'.format(file_path)) 

117 else: 

118 print('Empty file list downloaded') 

119 elif command == 'DownloadFile': 

120 bcontent = base64.b64decode(data['Content']) 

121 file_path = os.path.join(path, file_reference) 

122 if options['overwrite'] or not os.path.isfile(file_path): 

123 with open(file_path, 'wb') as fp: 

124 fp.write(bcontent) 

125 logger.info('Wrote file {}'.format(file_path)) 

126 else: 

127 print('Skipping old file {}'.format(file_path))