Пример #1
0
 def test_header_skipper_multiple_line_header(path_sf_card_viewer):
     """should"""
     expected = [[
         "2019/01/27", "", "", "", "", "", "", "195", "2896", "バス/路面等"
     ]]
     god_slayer = GodSlayerFactory(
         header=InstanceResource.HEADER_SF_CARD_VIEWER,
         encoding="shift_jis_2004").create(path_sf_card_viewer)
     GodSlayerChecker.assert_god_slayer(god_slayer, 1, expected)
Пример #2
0
 def test_record_reader(path_gold_point_card_plus):
     """should"""
     expected = [
         [
             "2018/7/3", "東京電力  電気料金等", "ご本人", "1回払い", "", "18/8", "11402",
             "11402", "", "", "", "", ""
         ],
         [
             "2018/7/4", "AMAZON.CO.JP", "ご本人", "1回払い", "", "18/8", "3456",
             "3456", "", "", "", "", ""
         ],
     ]
     god_slayer = GodSlayerFactory(
         encoding="shift_jis_2004").create(path_gold_point_card_plus)
     GodSlayerChecker.assert_god_slayer(god_slayer, 0, expected)
Пример #3
0
 def test_header_skipper(path_gold_point_card_plus_201912):
     """should"""
     expected = [
         ["2020/7/3", "東京電力  電気料金等", "11402", "1", "1", "11402", ""],
         [
             "2020/7/3", "AMAZON WEB SERVICES (AWS.AMAZON.CO)", "66", "1",
             "1", "66", "0.60 USD 110.712 07 03"
         ],
         ["2020/7/4", "AMAZON.CO.JP", "3456", "1", "1", "3456", ""],
     ]
     god_slayer = GodSlayerFactory(
         header=InstanceResource.REGEX_HEADER_GOLD_POINT_CARD_PLUS,
         footer=InstanceResource.REGEX_FOOTER_GOLD_POINT_CARD_PLUS,
         encoding="shift_jis_2004",
     ).create(path_gold_point_card_plus_201912)
     GodSlayerChecker.assert_god_slayer(god_slayer, 0, expected)
Пример #4
0
 def test_partition_skip_record_reader(path_view_card):
     """should"""
     expected = [
         [
             "2020/03/21", "板橋駅 オートチャージ", "3,000", "", "3,000", "1回払", "",
             "3,000", "", "   ", ""
         ],
         [
             "2020/03/31", "カード年会費", "524", "", "524", "1回払", "", "524", "",
             "   ", ""
         ],
     ]
     god_slayer = GodSlayerFactory(
         header=InstanceResource.HEADER_VIEW_CARD,
         partition=[r"^\*{4}-\*{4}-\*{4}-[0-9]{4}\s.*$"],
         encoding="shift_jis_2004",
     ).create(path_view_card)
     GodSlayerChecker.assert_god_slayer(god_slayer, 6, expected)
 def test_convert_string_to_int_or_none():
     """
     Argument should set into properties.
     Default encode should be UTF-8.
     Default csv herder should be None.
     """
     regex_csv_file_name = r".*waon.*\.csv"
     god_slayer_factory = GodSlayerFactory()
     input_row_data_class = WaonRowData
     input_row_factory = WaonRowFactory()
     zaim_row_factory_selector = WaonZaimRowConverterFactory()
     account_context = AccountContext(
         regex_csv_file_name,
         god_slayer_factory,
         input_row_data_class,
         input_row_factory,
         zaim_row_factory_selector,
     )
     assert account_context.regex_csv_file_name == regex_csv_file_name
     assert account_context.god_slayer_factory == god_slayer_factory
     assert account_context.input_row_data_class == input_row_data_class
     assert account_context.input_row_factory == input_row_factory
     assert account_context.zaim_row_converter_selector == zaim_row_factory_selector
Пример #6
0
class AccountContext(Generic[TypeVarInputRowData, TypeVarInputRow]):
    """This class implements recipe for converting steps for WAON CSV."""

    # pylint: disable=invalid-name
    GOD_SLAYER_FACTORY_SF_CARD_VIEWER: GodSlayerFactory = field(
        default=GodSlayerFactory(
            header=[
                "利用年月日", "定期", "鉄道会社名", "入場駅/事業者名", "定期", "鉄道会社名", "出場駅/降車場所",
                "利用額(円)", "残額(円)", "メモ"
            ],
            encoding="shift_jis_2004",
        ),
        init=False,
    )
    # pylint: disable=invalid-name
    GOD_SLAYER_FACTORY_AMAZON: GodSlayerFactory = field(
        default=GodSlayerFactory(
            header=[
                "注文日",
                "注文番号",
                "商品名",
                "付帯情報",
                "価格",
                "個数",
                "商品小計",
                "注文合計",
                "お届け先",
                "状態",
                "請求先",
                "請求額",
                "クレカ請求日",
                "クレカ請求額",
                "クレカ種類",
                "注文概要URL",
                "領収書URL",
                "商品URL",
            ],
            partition=[
                r"\d{4}/\d{1,2}/\d{1,2}",
                r".*",
                "(注文全体)",
                "",
                "",
                "",
                "",
                r"\d*",
                "",
                "",
                r".*",
                r"\d*",
                "",
                "",
                r".*",
                r".*",
                r".*",
                "",
            ],
            encoding="utf-8-sig",
        ),
        init=False,
    )
    regex_csv_file_name: str
    god_slayer_factory: GodSlayerFactory
    input_row_data_class: Type[TypeVarInputRowData]
    input_row_factory: InputRowFactory[TypeVarInputRowData, TypeVarInputRow]
    zaim_row_converter_selector: ZaimRowConverterFactory[TypeVarInputRow]

    def create_input_row_data_instance(
            self,
            list_input_row_standard_type_value: List[str]) -> InputRowData:
        """This method creates input row data instance by list data of input row."""
        # noinspection PyArgumentList
        return self.input_row_data_class(
            *list_input_row_standard_type_value)  # type: ignore

    def create_input_row_instance(
            self, input_row_data: TypeVarInputRowData) -> TypeVarInputRow:
        """This method creates input row instance by input row data instance."""
        return self.input_row_factory.create(input_row_data)

    def convert_input_row_to_zaim_row(self,
                                      input_row: TypeVarInputRow) -> ZaimRow:
        """This method converts input row into zaim row."""
        converter = self.zaim_row_converter_selector.create(input_row)
        return ZaimRowFactory.create(converter)
Пример #7
0
class Account(Enum):
    """This class implements constant of account in Zaim."""

    WAON = AccountContext(
        r".*waon.*\.csv",
        GodSlayerFactory(
            header=["取引年月日", "利用店舗", "利用金額(税込)", "利用区分", "チャージ区分"]),
        WaonRowData,
        WaonRowFactory(),
        WaonZaimRowConverterFactory(),
    )
    GOLD_POINT_CARD_PLUS = AccountContext(
        r".*gold_point_card_plus.*\.csv",
        GodSlayerFactory(encoding="shift_jis_2004"),
        GoldPointCardPlusRowData,
        GoldPointCardPlusRowFactory(),
        GoldPointCardPlusZaimRowConverterFactory(),
    )
    GOLD_POINT_CARD_PLUS_201912 = AccountContext(
        r".*gold_point_card_plus_201912.*\.csv",
        GodSlayerFactory(
            header=[
                r".* 様", r"[0-9\*]{4}-[0-9\*]{4}-[0-9\*]{4}-[0-9\*]{4}",
                "ゴールドポイントカードプラス"
            ],
            footer=["^$", "^$", "^$", "^$", "^$", r"^\d*$", "^$"],
            encoding="shift_jis_2004",
        ),
        GoldPointCardPlus201912RowData,
        GoldPointCardPlus201912RowFactory(),
        GoldPointCardPlus201912ZaimRowConverterFactory(),
    )
    GOLD_POINT_CARD_PLUS_202009 = AccountContext(
        r".*gold_point_card_plus_202009.*\.csv",
        GodSlayerFactory(
            header=[
                r".* 様", r"[0-9\*]{4}-[0-9\*]{4}-[0-9\*]{4}-[0-9\*]{4}",
                "ゴールドポイントカードプラス", "", "", "", ""
            ],
            footer=["^$", "^$", "^$", "^$", "^$", r"^\d*$", "^$"],
            encoding="shift_jis_2004",
        ),
        GoldPointCardPlus201912RowData,
        GoldPointCardPlus201912RowFactory(),
        GoldPointCardPlus201912ZaimRowConverterFactory(),
    )
    MUFG = AccountContext(
        r".*mufg.*\.csv",
        GodSlayerFactory(
            header=[
                "日付", "摘要", "摘要内容", "支払い金額", "預かり金額", "差引残高", "メモ", "未資金化区分",
                "入払区分"
            ],
            encoding="shift_jis_2004",
        ),
        MufgRowData,
        MufgRowFactory(),
        MufgZaimRowConverterFactory(),
    )
    PASMO = AccountContext(
        r".*pasmo.*\.csv",
        AccountContext.GOD_SLAYER_FACTORY_SF_CARD_VIEWER,
        SFCardViewerRowData,
        # On this timing, CONFIG is not loaded. So we wrap CONFIG by lambda.
        SFCardViewerRowFactory(lambda: CONFIG.pasmo),
        SFCardViewerZaimRowConverterFactory(lambda: CONFIG.pasmo),
    )
    AMAZON = AccountContext(
        r".*amazon.*\.csv",
        AccountContext.GOD_SLAYER_FACTORY_AMAZON,
        AmazonRowData,
        AmazonRowFactory(),
        AmazonZaimRowConverterFactory(),
    )
    AMAZON_201911 = AccountContext(
        r".*amazon_201911.*\.csv",
        AccountContext.GOD_SLAYER_FACTORY_AMAZON,
        Amazon201911RowData,
        Amazon201911RowFactory(),
        Amazon201911ZaimRowConverterFactory(),
    )
    VIEW_CARD = AccountContext(
        r".*view_card.*\.csv",
        GodSlayerFactory(
            header=[
                "ご利用年月日",
                "ご利用箇所",
                "ご利用額",
                "払戻額",
                "ご請求額(うち手数料・利息)",
                "支払区分(回数)",
                "今回回数",
                "今回ご請求額・弁済金(うち手数料・利息)",
                "現地通貨額",
                "通貨略称",
                "換算レート",
            ],
            partition=[r"^\*{4}-\*{4}-\*{4}-[0-9]{4}\s.*$"],
            encoding="shift_jis_2004",
        ),
        ViewCardRowData,
        ViewCardRowFactory(),
        ViewCardZaimRowConverterFactory(),
    )
    SUICA = AccountContext(
        r".*suica.*\.csv",
        AccountContext.GOD_SLAYER_FACTORY_SF_CARD_VIEWER,
        SFCardViewerRowData,
        # On this timing, CONFIG is not loaded. So we wrap CONFIG by lambda.
        SFCardViewerRowFactory(lambda: CONFIG.suica),
        SFCardViewerZaimRowConverterFactory(lambda: CONFIG.suica),
    )
    PAY_PAL = AccountContext(
        r".*pay_pal.*\.csv",
        GodSlayerFactory(header=PayPalRowData.HEADER),
        PayPalRowData,
        PayPalRowFactory(),
        PayPalZaimRowConverterFactory(),
    )

    @DynamicClassAttribute
    def value(self) -> AccountContext:
        """This method overwrite super method for type hint."""
        return super().value

    @staticmethod
    def create_by_path_csv_input(path: Path) -> Account:
        """This function create correct setting instance by argument."""
        # noinspection PyUnusedLocal
        account: Account
        matches = [
            account for account in Account
            if re.search(account.value.regex_csv_file_name, path.name)
        ]
        if not matches:
            raise ValueError(
                "can't detect account type by csv file name. Please confirm csv file name."
            )
        return max(matches,
                   key=lambda matched_account: len(matched_account.value.
                                                   regex_csv_file_name))

    def create_input_row_data_instance(
            self,
            list_input_row_standard_type_value: List[str]) -> InputRowData:
        """This method creates input row data instance by list data of input row."""
        return self.value.create_input_row_data_instance(
            list_input_row_standard_type_value)

    def create_input_row_instance(self,
                                  input_row_data: InputRowData) -> InputRow:
        """This method creates input row instance by input row data instance."""
        return self.value.create_input_row_instance(input_row_data)

    def convert_input_row_to_zaim_row(self, input_row: InputRow) -> ZaimRow:
        """This method converts input row into zaim row."""
        return self.value.convert_input_row_to_zaim_row(input_row)
Пример #8
0
 def test_partition_skip_record_before_footer_reader(
         path_itabashiku_population):
     """should"""
     expected = [
         ["0", "4062", "2069", "1993"],
         ["1", "4279", "2171", "2108"],
         ["2", "4285", "2152", "2133"],
         ["3", "4434", "2268", "2166"],
         ["4", "4243", "2207", "2036"],
         ["5", "4369", "2283", "2086"],
         ["6", "4345", "2213", "2132"],
         ["7", "4117", "2163", "1954"],
         ["8", "4155", "2146", "2009"],
         ["9", "4031", "2151", "1880"],
         ["10", "3933", "1988", "1945"],
         ["11", "4137", "2161", "1976"],
         ["12", "3842", "2018", "1824"],
         ["13", "3898", "1925", "1973"],
         ["14", "3820", "1914", "1906"],
         ["15", "3869", "1986", "1883"],
         ["16", "3902", "1996", "1906"],
         ["17", "4139", "2133", "2006"],
         ["18", "4474", "2242", "2232"],
         ["19", "5382", "2632", "2750"],
         ["20", "5674", "2854", "2820"],
         ["21", "6331", "3090", "3241"],
         ["22", "7218", "3385", "3833"],
         ["23", "8700", "4042", "4658"],
         ["24", "8773", "4132", "4641"],
         ["25", "9247", "4411", "4836"],
         ["26", "8757", "4205", "4552"],
         ["27", "9015", "4302", "4713"],
         ["28", "8814", "4289", "4525"],
         ["29", "8446", "4125", "4321"],
         ["30", "8173", "4050", "4123"],
         ["31", "8334", "4157", "4177"],
         ["32", "8145", "4179", "3966"],
         ["33", "7986", "3956", "4030"],
         ["34", "8126", "4170", "3956"],
         ["35", "8342", "4293", "4049"],
         ["36", "8472", "4320", "4152"],
         ["37", "8375", "4288", "4087"],
         ["38", "8213", "4253", "3960"],
         ["39", "8392", "4343", "4049"],
         ["40", "8402", "4344", "4058"],
         ["41", "8555", "4461", "4094"],
         ["42", "8545", "4400", "4145"],
         ["43", "8839", "4605", "4234"],
         ["44", "8908", "4620", "4288"],
         ["45", "9319", "4751", "4568"],
         ["46", "9611", "4927", "4684"],
         ["47", "9448", "4842", "4606"],
         ["48", "9291", "4857", "4434"],
         ["49", "8962", "4640", "4322"],
         ["50", "8714", "4400", "4314"],
         ["51", "8620", "4485", "4135"],
         ["52", "8455", "4466", "3989"],
         ["53", "6323", "3295", "3028"],
         ["54", "7974", "4093", "3881"],
         ["55", "7523", "3942", "3581"],
         ["56", "6935", "3606", "3329"],
         ["57", "6750", "3433", "3317"],
         ["58", "6449", "3358", "3091"],
         ["59", "6197", "3254", "2943"],
         ["60", "5945", "3065", "2880"],
         ["61", "6113", "3162", "2951"],
         ["62", "5380", "2755", "2625"],
         ["63", "5527", "2771", "2756"],
         ["64", "5626", "2825", "2801"],
         ["65", "5717", "2885", "2832"],
         ["66", "5913", "2994", "2919"],
         ["67", "6100", "3099", "3001"],
         ["68", "6266", "3121", "3145"],
         ["69", "6845", "3443", "3402"],
         ["70", "7587", "3805", "3782"],
         ["71", "7696", "3725", "3971"],
         ["72", "7861", "3761", "4100"],
         ["73", "5344", "2533", "2811"],
         ["74", "4419", "1971", "2448"],
         ["75", "5497", "2546", "2951"],
         ["76", "5814", "2611", "3203"],
         ["77", "5589", "2446", "3143"],
         ["78", "5471", "2371", "3100"],
         ["79", "4757", "2059", "2698"],
         ["80", "4120", "1673", "2447"],
         ["81", "3882", "1586", "2296"],
         ["82", "4202", "1584", "2618"],
         ["83", "3957", "1471", "2486"],
         ["84", "3882", "1390", "2492"],
         ["85", "3163", "1137", "2026"],
         ["86", "3031", "1035", "1996"],
         ["87", "2681", "916", "1765"],
         ["88", "2220", "680", "1540"],
         ["89", "1980", "603", "1377"],
         ["90", "1653", "508", "1145"],
         ["91", "1442", "374", "1068"],
         ["92", "1141", "291", "850"],
         ["93", "919", "240", "679"],
         ["94", "782", "179", "603"],
         ["95", "521", "119", "402"],
         ["96", "375", "59", "316"],
         ["97", "308", "51", "257"],
         ["98", "187", "32", "155"],
         ["99", "131", "23", "108"],
         ["100", "91", "7", "84"],
         ["101", "57", "5", "52"],
         ["102", "43", "7", "36"],
     ]
     god_slayer = GodSlayerFactory(
         header=InstanceResource.HEADER_ITABASHIKU_POPULATION,
         partition=[r"^(総数)|(\d*〜\d*歳?)$", r"^\d*$", r"^\d*$", r"^\d*$"],
         footer=InstanceResource.FOOTER_ITABASHIKU_POPULATION,
         encoding="shift_jis_2004",
     ).create(path_itabashiku_population)
     GodSlayerChecker.assert_god_slayer_partition(god_slayer, expected)