From 5cfcd0e3e5a6344edbc2e5e90a5973fc258c030d Mon Sep 17 00:00:00 2001 From: "shimoda.m@nds-tyo.co.jp" Date: Wed, 12 Oct 2022 14:58:50 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=83=AD=E3=83=BC=E3=82=AB=E3=83=AB?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E6=9B=B8=E3=81=8D=E8=BE=BC?= =?UTF-8?q?=E3=81=BF=E7=94=A8=E3=83=A2=E3=82=B8=E3=83=A5=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ecs/crm-datafetch/src/converter/converter.py | 1 + ecs/crm-datafetch/src/system_var/constants.py | 15 ++- ecs/crm-datafetch/src/writer/__init__.py | 0 ecs/crm-datafetch/src/writer/file_writer.py | 43 +++++++ ecs/crm-datafetch/tests/writer/__init__.py | 0 .../tests/writer/test_file_writer.py | 110 ++++++++++++++++++ 6 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 ecs/crm-datafetch/src/writer/__init__.py create mode 100644 ecs/crm-datafetch/src/writer/file_writer.py create mode 100644 ecs/crm-datafetch/tests/writer/__init__.py create mode 100644 ecs/crm-datafetch/tests/writer/test_file_writer.py diff --git a/ecs/crm-datafetch/src/converter/converter.py b/ecs/crm-datafetch/src/converter/converter.py index e1c01dcd..64e935d2 100644 --- a/ecs/crm-datafetch/src/converter/converter.py +++ b/ecs/crm-datafetch/src/converter/converter.py @@ -61,6 +61,7 @@ class CSVStringConverter: f'CSV変換に失敗しました カラム名:[{column}] 行番号: [{i}] エラー内容:[{e}]') def __write_csv_string(self, csv_data) -> str: + # TODO: CsvWriterに移管 try: with io.StringIO(newline='') as string_stream: writer = csv.writer(string_stream, delimiter=',', lineterminator='\r\n', diff --git a/ecs/crm-datafetch/src/system_var/constants.py b/ecs/crm-datafetch/src/system_var/constants.py index 93ffeb69..a568fc2f 100644 --- a/ecs/crm-datafetch/src/system_var/constants.py +++ b/ecs/crm-datafetch/src/system_var/constants.py @@ -72,11 +72,20 @@ UPLD_JP_NAME = 'CSVアップロード処理' UPD_JP_NAME = '前回取得日時ファイル更新' END_JP_NAME = '取得処理実施結果アップロード処理' -# CSVチェック +# CSV CSV_TRUE_VALUE = 1 CSV_FALSE_VALUE = 0 +CSV_LINE_TERMINATOR = '\r\n' +CSV_DELIMITER = ',' +CSV_QUOTE_CHAR = '"' -# オブジェクト変数 +# システム変数 + +FILE_CHAR_CODE = 'utf-8' +FILE_MODE_WRITE = 'w' + + +# CRM_取得オブジェクト情報ファイル関連 OBJECTS_KEY = 'objects' OBJECTS_TYPE = list OBJECT_NAME_KEY = 'object_name' @@ -94,6 +103,8 @@ UPLOAD_FILE_NAME_TYPE = str DATETIME_COLUMN_KEY = 'datetime_column' DATETIME_COLUMN_TYPE = str DATETIME_COLUMN_DEFAULT_VALUE = 'SystemModstamp' + +# 前回取得日時ファイル関連 LAST_FETCH_DATETIME_TO_KEY = 'last_fetch_datetime_to' LAST_FETCH_DATETIME_TO_TYPE = str LAST_FETCH_DATETIME_FROM_KEY = 'last_fetch_datetime_from' diff --git a/ecs/crm-datafetch/src/writer/__init__.py b/ecs/crm-datafetch/src/writer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/src/writer/file_writer.py b/ecs/crm-datafetch/src/writer/file_writer.py new file mode 100644 index 00000000..648ce17e --- /dev/null +++ b/ecs/crm-datafetch/src/writer/file_writer.py @@ -0,0 +1,43 @@ +import csv +import json +from abc import ABCMeta, abstractmethod + +from src.system_var.constants import (CSV_DELIMITER, CSV_LINE_TERMINATOR, + CSV_QUOTE_CHAR, FILE_CHAR_CODE, + FILE_MODE_WRITE) + + +class FileWriter(metaclass=ABCMeta): + + def __init__(self, file_path: str, content) -> None: + self._file_path = file_path + self._content = content + + @abstractmethod + def write(self) -> str: + """ファイルを書き出し、ファイルパスを返す + + Returns: + str: 書き出し先のファイルパス + """ + pass + + +class JsonWriter(FileWriter): + + def write(self) -> str: + with open(self._file_path, mode=FILE_MODE_WRITE, encoding=FILE_CHAR_CODE, newline='') as f: + json.dump(self._content, f, ensure_ascii=False, ) + + return self._file_path + + +class CsvWriter(FileWriter): + + def write(self) -> str: + with open(self._file_path, mode=FILE_MODE_WRITE, encoding=FILE_CHAR_CODE, newline='') as f: + writer = csv.writer(f, delimiter=CSV_DELIMITER, lineterminator=CSV_LINE_TERMINATOR, + quotechar=CSV_QUOTE_CHAR, doublequote=True, quoting=csv.QUOTE_ALL, + strict=True) + writer.writerows(self._content) + return self._file_path diff --git a/ecs/crm-datafetch/tests/writer/__init__.py b/ecs/crm-datafetch/tests/writer/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/ecs/crm-datafetch/tests/writer/test_file_writer.py b/ecs/crm-datafetch/tests/writer/test_file_writer.py new file mode 100644 index 00000000..73721788 --- /dev/null +++ b/ecs/crm-datafetch/tests/writer/test_file_writer.py @@ -0,0 +1,110 @@ +import os +import textwrap + +import pytest +from src.writer.file_writer import CsvWriter, JsonWriter + + +class TestJsonFileWriter: + + def test_write(self, tmpdir): + """ + Cases: + JSONファイルが書き込めること + Arranges: + + Expects: + JSONファイルが正しく書き込まれている + """ + # Arrange + file_name = 'test.json' + file_path = os.path.join(tmpdir, file_name) + content = {'test': 'テスト'} + + # Act + sut = JsonWriter(file_path, content) + sut.write() + + # Assert + with open(file_path) as f: + actual = f.read() + + assert actual == '{"test": "テスト"}' + + def test_raise_write_cause_file_path_not_exists(self): + """ + Cases: + 書き込み先が存在しない場合エラーとなること + Arranges: + + Expects: + エラーが発生する + """ + # Arrange + file_name = 'test.json' + file_path = os.path.join('invalid', file_name) + content = {'test': 'テスト'} + + # Act + sut = JsonWriter(file_path, content) + with pytest.raises(Exception): + sut.write() + + +class TestCsvFileWriter: + + def test_write(self, tmpdir): + """ + Cases: + CSVファイルが書き込めること + Arranges: + + Expects: + CSVファイルが正しく書き込まれている + """ + # Arrange + file_name = 'test.csv' + file_path = os.path.join(tmpdir, file_name) + content = [ + ["Id", "AccountId", "UserOrGroupId", "AccountAccessLevel", "OpportunityAccessLevel", "CaseAccessLevel", + "ContactAccessLevel", "RowCause", "LastModifiedDate", "LastModifiedById", "IsDeleted"], + ["TEST001", "test001", "", "1", "2", "3", "4", "テストのため1", "2022-06-01 09:00:00", "1234567.0", "0"], + ["TEST002", "test002", "", "5", "6", "7", "8", "テストのため2", "2022-06-03 01:30:30", "2.23", "1"], + ["TEST003", "test003", "", "9", "10", "11", "12", "テストのため3", "2022-06-04 08:50:50", "3.234567", "0"] + ] + + # Act + sut = CsvWriter(file_path, content) + sut.write() + + # Assert + with open(file_path, newline='') as f: + actual = f.read() + + expect = """\ + "Id","AccountId","UserOrGroupId","AccountAccessLevel","OpportunityAccessLevel","CaseAccessLevel","ContactAccessLevel","RowCause","LastModifiedDate","LastModifiedById","IsDeleted"\r\n\ + "TEST001","test001","","1","2","3","4","テストのため1","2022-06-01 09:00:00","1234567.0","0"\r\n\ + "TEST002","test002","","5","6","7","8","テストのため2","2022-06-03 01:30:30","2.23","1"\r\n\ + "TEST003","test003","","9","10","11","12","テストのため3","2022-06-04 08:50:50","3.234567","0"\r\n\ + """ + + assert actual == textwrap.dedent(expect) + + def test_raise_write_cause_file_path_not_exists(self): + """ + Cases: + 書き込み先が存在しない場合エラーとなること + Arranges: + + Expects: + エラーが発生する + """ + # Arrange + file_name = 'test.csv' + file_path = os.path.join('invalid', file_name) + content = {'test': 'テスト'} + + # Act + sut = CsvWriter(file_path, content) + with pytest.raises(Exception): + sut.write()