307 lines
11 KiB
Python
307 lines
11 KiB
Python
|
#! env python3
|
||
|
# The Mia! Accounting Project.
|
||
|
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/4/9
|
||
|
|
||
|
# Copyright (c) 2023 imacat.
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
"""The sample data generation.
|
||
|
|
||
|
"""
|
||
|
from datetime import date, timedelta
|
||
|
|
||
|
import click
|
||
|
|
||
|
from testlib import Accounts, create_test_app, JournalEntryLineItemData, \
|
||
|
JournalEntryCurrencyData, JournalEntryData, \
|
||
|
BaseTestData
|
||
|
|
||
|
|
||
|
@click.command()
|
||
|
@click.argument("file")
|
||
|
def main(file) -> None:
|
||
|
"""Creates the sample data and output to a file."""
|
||
|
data: SampleData = SampleData(create_test_app(), "editor")
|
||
|
with open(file, "wt") as fp:
|
||
|
fp.write(data.json())
|
||
|
|
||
|
|
||
|
class SampleData(BaseTestData):
|
||
|
"""The sample data."""
|
||
|
|
||
|
def _init_data(self) -> None:
|
||
|
self.__add_recurring()
|
||
|
self.__add_offsets()
|
||
|
self.__add_meals()
|
||
|
|
||
|
def __add_recurring(self) -> None:
|
||
|
"""Adds the recurring data.
|
||
|
|
||
|
:return: None.
|
||
|
"""
|
||
|
self.__add_usd_recurring()
|
||
|
self.__add_twd_recurring()
|
||
|
|
||
|
def __add_usd_recurring(self) -> None:
|
||
|
"""Adds the recurring data in USD.
|
||
|
|
||
|
:return: None.
|
||
|
"""
|
||
|
today: date = date.today()
|
||
|
days: int
|
||
|
year: int
|
||
|
month: int
|
||
|
|
||
|
# Recurring in USD
|
||
|
j_date: date = date(today.year - 5, today.month, today.day)
|
||
|
j_date = j_date + timedelta(days=(4 - j_date.weekday()))
|
||
|
days = (today - j_date).days
|
||
|
while True:
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "2600",
|
||
|
Accounts.BANK, "Transfer", Accounts.SERVICE, "Payroll")
|
||
|
|
||
|
days = days - 1
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "1200",
|
||
|
Accounts.CASH, None, Accounts.BANK, "Withdraw")
|
||
|
days = days - 13
|
||
|
|
||
|
year = today.year - 5
|
||
|
month = today.month
|
||
|
while True:
|
||
|
month = month + 1
|
||
|
if month > 12:
|
||
|
year = year + 1
|
||
|
month = 1
|
||
|
days = (today - date(year, month, 1)).days
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "1800",
|
||
|
Accounts.RENT_EXPENSE, "Rent", Accounts.BANK, "Transfer")
|
||
|
|
||
|
def __add_twd_recurring(self) -> None:
|
||
|
"""Adds the recurring data in TWD.
|
||
|
|
||
|
:return: None.
|
||
|
"""
|
||
|
today: date = date.today()
|
||
|
|
||
|
year: int = today.year - 5
|
||
|
month: int = today.month
|
||
|
while True:
|
||
|
days: int = (today - date(year, month, 5)).days
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "50000",
|
||
|
Accounts.BANK, "薪資轉帳", Accounts.SERVICE, "薪水")
|
||
|
|
||
|
days = days - 1
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "25000",
|
||
|
Accounts.CASH, None, Accounts.BANK, "提款")
|
||
|
|
||
|
days = days - 4
|
||
|
if days < 0:
|
||
|
break
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "18000",
|
||
|
Accounts.RENT_EXPENSE, "房租", Accounts.BANK, "轉帳")
|
||
|
|
||
|
month = month + 1
|
||
|
if month > 12:
|
||
|
year = year + 1
|
||
|
month = 1
|
||
|
|
||
|
def __add_offsets(self) -> None:
|
||
|
"""Adds the offset data.
|
||
|
|
||
|
:return: None.
|
||
|
"""
|
||
|
days: int
|
||
|
year: int
|
||
|
month: int
|
||
|
description: str
|
||
|
line_item_or: JournalEntryLineItemData
|
||
|
line_item_of: JournalEntryLineItemData
|
||
|
|
||
|
# Full offset and unmatched in USD
|
||
|
description = "Speaking—Institute"
|
||
|
line_item_or = JournalEntryLineItemData(
|
||
|
Accounts.RECEIVABLE, description, "120")
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
40, [JournalEntryCurrencyData(
|
||
|
"USD", [line_item_or], [JournalEntryLineItemData(
|
||
|
Accounts.SERVICE, description, "120")])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.RECEIVABLE, description, "120",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
5, [JournalEntryCurrencyData(
|
||
|
"USD", [JournalEntryLineItemData(
|
||
|
Accounts.BANK, description, "120")],
|
||
|
[line_item_of])]))
|
||
|
self.__add_journal_entry(
|
||
|
30, "USD", "120",
|
||
|
Accounts.BANK, description, Accounts.SERVICE, description)
|
||
|
|
||
|
# Partial offset in USD
|
||
|
line_item_or = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "Computer", "1600")
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
60, [JournalEntryCurrencyData(
|
||
|
"USD", [JournalEntryLineItemData(
|
||
|
Accounts.MACHINERY, "Computer", "1600")],
|
||
|
[line_item_or])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "Computer", "800",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
35, [JournalEntryCurrencyData(
|
||
|
"USD", [line_item_of], [JournalEntryLineItemData(
|
||
|
Accounts.BANK, "Computer", "800")])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "Computer", "400",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
10, [JournalEntryCurrencyData(
|
||
|
"USD", [line_item_of], [JournalEntryLineItemData(
|
||
|
Accounts.CASH, "Computer", "400")])]))
|
||
|
|
||
|
# Full offset and unmatched in TWD
|
||
|
description = "演講費—母校"
|
||
|
line_item_or = JournalEntryLineItemData(
|
||
|
Accounts.RECEIVABLE, description, "3000")
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
45, [JournalEntryCurrencyData(
|
||
|
"TWD", [line_item_or], [JournalEntryLineItemData(
|
||
|
Accounts.SERVICE, description, "3000")])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.RECEIVABLE, description, "3000",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
6, [JournalEntryCurrencyData(
|
||
|
"TWD", [JournalEntryLineItemData(
|
||
|
Accounts.BANK, description, "3000")],
|
||
|
[line_item_of])]))
|
||
|
self.__add_journal_entry(
|
||
|
25, "TWD", "3000",
|
||
|
Accounts.BANK, description, Accounts.SERVICE, description)
|
||
|
|
||
|
# Partial offset in TWD
|
||
|
line_item_or = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "手機", "30000")
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
55, [JournalEntryCurrencyData(
|
||
|
"TWD", [JournalEntryLineItemData(
|
||
|
Accounts.MACHINERY, "手機", "30000")],
|
||
|
[line_item_or])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "手機", "16000",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
27, [JournalEntryCurrencyData(
|
||
|
"TWD", [line_item_of], [JournalEntryLineItemData(
|
||
|
Accounts.BANK, "手機", "16000")])]))
|
||
|
line_item_of = JournalEntryLineItemData(
|
||
|
Accounts.PAYABLE, "手機", "6000",
|
||
|
original_line_item=line_item_or)
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
8, [JournalEntryCurrencyData(
|
||
|
"TWD", [line_item_of], [JournalEntryLineItemData(
|
||
|
Accounts.CASH, "手機", "6000")])]))
|
||
|
|
||
|
def __add_meals(self) -> None:
|
||
|
"""Adds the meal data.
|
||
|
|
||
|
:return: None.
|
||
|
"""
|
||
|
days = 60
|
||
|
while days >= 0:
|
||
|
# Meals in USD
|
||
|
if days % 4 == 2:
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "2.9",
|
||
|
Accounts.MEAL, "Lunch—Coffee", Accounts.CASH, None)
|
||
|
else:
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "3.9",
|
||
|
Accounts.MEAL, "Lunch—Coffee", Accounts.CASH, None)
|
||
|
|
||
|
if days % 15 == 3:
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "5.45",
|
||
|
Accounts.MEAL, "Dinner—Pizza",
|
||
|
Accounts.PAYABLE, "Dinner—Pizza")
|
||
|
else:
|
||
|
self.__add_journal_entry(
|
||
|
days, "USD", "5.9",
|
||
|
Accounts.MEAL, "Dinner—Pasta", Accounts.CASH, None)
|
||
|
|
||
|
# Meals in TWD
|
||
|
if days % 5 == 3:
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "125",
|
||
|
Accounts.MEAL, "午餐—鄰家咖啡", Accounts.CASH, None)
|
||
|
else:
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "80",
|
||
|
Accounts.MEAL, "午餐—便當", Accounts.CASH, None)
|
||
|
|
||
|
if days % 15 == 3:
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "320",
|
||
|
Accounts.MEAL, "晚餐—牛排", Accounts.PAYABLE, "晚餐—牛排")
|
||
|
else:
|
||
|
self.__add_journal_entry(
|
||
|
days, "TWD", "100",
|
||
|
Accounts.MEAL, "晚餐—自助餐", Accounts.CASH, None)
|
||
|
|
||
|
days = days - 1
|
||
|
|
||
|
def __add_journal_entry(
|
||
|
self, days: int, currency: str, amount: str,
|
||
|
debit_account: str, debit_description: str | None,
|
||
|
credit_account: str, credit_description: str | None) -> None:
|
||
|
"""Adds a simple journal entry.
|
||
|
|
||
|
:param days: The number of days before today.
|
||
|
:param currency: The currency code.
|
||
|
:param amount: The amount.
|
||
|
:param debit_account: The debit account code.
|
||
|
:param debit_description: The debit description.
|
||
|
:param credit_account: The credit account code.
|
||
|
:param credit_description: The credit description.
|
||
|
:return: None.
|
||
|
"""
|
||
|
self._add_journal_entry(JournalEntryData(
|
||
|
days,
|
||
|
[JournalEntryCurrencyData(
|
||
|
currency,
|
||
|
[JournalEntryLineItemData(
|
||
|
debit_account, debit_description, amount)],
|
||
|
[JournalEntryLineItemData(
|
||
|
credit_account, credit_description, amount)])]))
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|