2020-07-22 00:15:26 +08:00
|
|
|
|
# The accounting application of the Mia project.
|
|
|
|
|
# by imacat <imacat@mail.imacat.idv.tw>, 2020/7/22
|
|
|
|
|
|
|
|
|
|
# Copyright (c) 2020 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 command to populate the database with sample accounting data.
|
|
|
|
|
|
|
|
|
|
"""
|
2020-08-18 22:50:36 +08:00
|
|
|
|
import datetime
|
2020-07-22 08:17:20 +08:00
|
|
|
|
import random
|
2020-08-02 18:29:10 +08:00
|
|
|
|
import sys
|
2020-08-19 19:19:37 +08:00
|
|
|
|
from typing import Optional
|
2020-07-22 08:17:20 +08:00
|
|
|
|
|
2020-08-18 03:05:47 +08:00
|
|
|
|
from django.contrib.auth import get_user_model
|
2020-08-20 21:00:14 +08:00
|
|
|
|
from django.contrib.auth.base_user import BaseUserManager
|
2020-07-22 00:15:26 +08:00
|
|
|
|
from django.core.management import BaseCommand, CommandParser
|
2020-08-02 18:23:01 +08:00
|
|
|
|
from django.db import transaction
|
2020-07-22 08:22:01 +08:00
|
|
|
|
from django.utils import timezone
|
2020-07-22 00:15:26 +08:00
|
|
|
|
|
2020-08-19 19:19:37 +08:00
|
|
|
|
from accounting.utils import DataFiller
|
2020-07-22 00:15:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Command(BaseCommand):
|
|
|
|
|
"""Populates the database with sample accounting data."""
|
2020-08-19 19:19:37 +08:00
|
|
|
|
help = "Fills the database with sample accounting data."
|
|
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
|
super().__init__()
|
|
|
|
|
self._filler: Optional[DataFiller] = None
|
2020-07-22 00:15:26 +08:00
|
|
|
|
|
|
|
|
|
def add_arguments(self, parser):
|
|
|
|
|
"""Adds command line arguments to the parser.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
parser (CommandParser): The command line argument parser.
|
|
|
|
|
"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
def handle(self, *args, **options):
|
|
|
|
|
"""Runs the command.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
*args (list[str]): The command line arguments.
|
|
|
|
|
**options (dict[str,str]): The command line switches.
|
|
|
|
|
"""
|
2020-08-18 03:05:47 +08:00
|
|
|
|
user_model = get_user_model()
|
|
|
|
|
if user_model.objects.first() is not None:
|
2020-08-02 18:29:10 +08:00
|
|
|
|
print("Refused to fill in sample data with existing data.",
|
|
|
|
|
file=sys.stderr)
|
2020-07-23 01:15:46 +08:00
|
|
|
|
return
|
|
|
|
|
|
2020-08-02 18:23:01 +08:00
|
|
|
|
with transaction.atomic():
|
2020-08-20 21:00:14 +08:00
|
|
|
|
user_manager: BaseUserManager = user_model.objects
|
|
|
|
|
user_manager.create_superuser("admin", password="12345")
|
|
|
|
|
user = user_model.objects.first()
|
|
|
|
|
print("Created the user \"admin\" with password \"12345\".",
|
|
|
|
|
file=sys.stderr)
|
2020-08-02 18:23:01 +08:00
|
|
|
|
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler = DataFiller(user)
|
|
|
|
|
self._filler.add_accounts([
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(1, "assets", "資產", "资产"),
|
|
|
|
|
(2, "liabilities", "負債", "负债"),
|
|
|
|
|
(3, "owners’ equity", "業主權益", "业主权益"),
|
|
|
|
|
(4, "operating revenue", "營業收入", "营业收入"),
|
|
|
|
|
(5, "operating costs", "營業成本", "营业成本"),
|
|
|
|
|
(6, "operating expenses", "營業費用", "营业费用"),
|
|
|
|
|
(7,
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"non-operating revenue and expenses, other income (expense)",
|
2020-08-25 13:40:24 +08:00
|
|
|
|
"營業外收入及費用", "营业外收入及费用"),
|
|
|
|
|
(8, "income tax expense (or benefit)", "所得稅費用(或利益)",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"所得税费用(或利益)"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(9, "nonrecurring gain or loss", "非經常營業損益",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"非经常营业损益"),
|
|
|
|
|
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(11, "current assets", "流動資產", "流动资产"),
|
|
|
|
|
(111, "cash and cash equivalents", "現金及約當現金",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"现金及约当现金"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(1111, "petty cash/revolving funds", "庫存現金", "库存现金"),
|
|
|
|
|
(1112, "cash on hand", "零用金/週轉金", "零用金/周转金"),
|
|
|
|
|
(1113, "cash in banks", "銀行存款", "银行存款"),
|
|
|
|
|
(12, "current assets", "流動資產", "流动资产"),
|
|
|
|
|
(125, "prepaid expenses", "預付費用", "预付费用"),
|
|
|
|
|
(1255, "prepaid income tax", "預付所得稅", "预付所得税"),
|
|
|
|
|
(13, "funds and long-term investments", "基金及長期投資",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"基金及长期投资"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(131, "funds", "基金", "基金"),
|
|
|
|
|
(1314, "pension fund", "退休基金", "退休基金"),
|
|
|
|
|
(14, "property , plant, and equipment", "固定資產", "固定资产"),
|
|
|
|
|
(144, "machinery and equipment", "機(器)具及設備",
|
|
|
|
|
"机(器)具及设备"),
|
|
|
|
|
(1441, "machinery", "機(器)具", "机(器)具"),
|
|
|
|
|
|
|
|
|
|
(21, "current liabilities", "流動負債", "流动负债"),
|
|
|
|
|
(214, "accounts payable", "應付帳款", "应付帐款"),
|
|
|
|
|
(2141, "accounts payable", "應付帳款", "应付帐款"),
|
|
|
|
|
|
|
|
|
|
(33, "retained earnings (accumulated deficit)",
|
|
|
|
|
"保留盈餘(或累積虧損)", "保留盈余(或累积亏损)"),
|
|
|
|
|
(335,
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"retained earnings-unappropriated (or accumulated deficit)",
|
2020-08-25 13:40:24 +08:00
|
|
|
|
"未分配盈餘(或累積虧損)", "未分配盈余(或累积亏损)"),
|
|
|
|
|
(3351, "accumulated profit or loss", "累積盈虧", "累积盈亏"),
|
|
|
|
|
(3353, "net income or loss for current period", "本期損益",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"本期损益"),
|
|
|
|
|
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(46, "service revenue", "勞務收入", "劳务收入"),
|
|
|
|
|
(461, "service revenue", "勞務收入", "劳务收入"),
|
|
|
|
|
(4611, "service revenue", "勞務收入", "劳务收入"),
|
2020-08-02 18:23:01 +08:00
|
|
|
|
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(62, "general & administrative expenses", "管理及總務費用",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"管理及总务费用"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(625, "general & administrative expenses", "管理及總務費用",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"管理及总务费用"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(6254, "travelling expense, travel", "旅費", "旅费"),
|
|
|
|
|
(626, "general & administrative expenses", "管理及總務費用",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"管理及总务费用"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(6262, "insurance (expense)", "保險費", "保险费"),
|
|
|
|
|
(627, "general & administrative expenses", "管理及總務費用",
|
2020-08-02 18:23:01 +08:00
|
|
|
|
"管理及总务费用"),
|
2020-08-25 13:40:24 +08:00
|
|
|
|
(6272, "meal (expenses)", "伙食費", "伙食费"),
|
|
|
|
|
(6273, "employee benefits/welfare", "職工福利", "职工福利"),
|
2020-08-13 07:25:35 +08:00
|
|
|
|
])
|
2020-08-02 18:23:01 +08:00
|
|
|
|
|
2020-08-18 22:50:36 +08:00
|
|
|
|
self.add_payrolls(5)
|
|
|
|
|
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_income_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-15,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(1113, "ATM withdrawal", 2000)])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_transfer_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-14,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6254, "HSR—New Land→South Lake City", 1490)],
|
|
|
|
|
[(2141, "HSR—New Land→South Lake City", 1490)])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_transfer_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-14,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6273, "Movies—The Avengers", 80)],
|
|
|
|
|
[(2141, "Movies—The Avengers", 80)])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_transfer_transaction(
|
2020-08-04 09:56:02 +08:00
|
|
|
|
-13,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6273, "Movies—2001: A Space Odyssey", 80)],
|
|
|
|
|
[(2141, "Movies—2001: A Space Odyssey", 80)])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_transfer_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-11,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(2141, "Movies—The Avengers", 80)],
|
|
|
|
|
[(1113, "Movies—The Avengers", 80)])
|
2020-08-02 18:23:01 +08:00
|
|
|
|
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_expense_transaction(
|
2020-08-04 09:56:02 +08:00
|
|
|
|
-13,
|
2020-08-21 10:00:59 +08:00
|
|
|
|
[(6273, "Bus—2623—Uptown→City Park", 477543627.4775)])
|
2020-08-04 09:56:02 +08:00
|
|
|
|
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_expense_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-2,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6272, "Lunch—Spaghetti", random.randint(40, 200)),
|
|
|
|
|
(6272, "Drink—Tea", random.randint(40, 200))])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_expense_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-1,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
([(6272, "Lunch—Pizza", random.randint(40, 200)),
|
|
|
|
|
(6272, "Drink—Tea", random.randint(40, 200))]))
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_expense_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
-1,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6272, "Lunch—Spaghetti", random.randint(40, 200)),
|
|
|
|
|
(6272, "Drink—Soda", random.randint(40, 200))])
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_expense_transaction(
|
2020-08-02 18:23:01 +08:00
|
|
|
|
0,
|
2020-08-18 22:50:36 +08:00
|
|
|
|
[(6272, "Lunch—Salad", random.randint(40, 200)),
|
|
|
|
|
(6272, "Drink—Coffee", random.randint(40, 200))])
|
|
|
|
|
|
|
|
|
|
def add_payrolls(self, months: int):
|
|
|
|
|
"""Adds the payrolls for certain number of months.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
months: The number of months to add.
|
|
|
|
|
"""
|
|
|
|
|
today = timezone.localdate()
|
|
|
|
|
payday = today.replace(day=5)
|
|
|
|
|
if payday > today:
|
|
|
|
|
payday = self.previous_month(payday)
|
|
|
|
|
for i in range(months):
|
|
|
|
|
self.add_payroll(payday)
|
|
|
|
|
payday = self.previous_month(payday)
|
|
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
|
def previous_month(date: datetime.date):
|
|
|
|
|
"""Obtain the same day in the previous month.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
date: The date.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
The same day in the previous month.
|
|
|
|
|
"""
|
|
|
|
|
month = date.month - 1
|
|
|
|
|
if month < 1:
|
|
|
|
|
year = date.year - 1
|
|
|
|
|
return date.replace(year=year, month=12)
|
|
|
|
|
return date.replace(month=month)
|
|
|
|
|
|
|
|
|
|
def add_payroll(self, payday: datetime.date):
|
|
|
|
|
"""Adds the payroll for a payday.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
payday: The payday.
|
|
|
|
|
"""
|
|
|
|
|
income = random.randint(40000, 50000)
|
|
|
|
|
pension = 882 if income <= 40100\
|
|
|
|
|
else 924 if income <= 42000\
|
|
|
|
|
else 966 if income <= 43900\
|
|
|
|
|
else 1008
|
|
|
|
|
insurance = 564 if income <= 40100\
|
|
|
|
|
else 591 if income <= 42000\
|
|
|
|
|
else 618 if income <= 43900\
|
|
|
|
|
else 644 if income <= 45800\
|
|
|
|
|
else 678 if income <= 48200\
|
|
|
|
|
else 712
|
|
|
|
|
tax = round(income * 0.05)
|
|
|
|
|
savings = income - pension - insurance - tax
|
|
|
|
|
months = ["January", "February", "March", "April", "May", "June",
|
|
|
|
|
"July", "August", "September", "October", "November",
|
|
|
|
|
"December"]
|
|
|
|
|
month = payday.month - 1
|
|
|
|
|
if month < 1:
|
|
|
|
|
month = 12
|
|
|
|
|
month_text = months[month - 1]
|
2020-08-19 19:19:37 +08:00
|
|
|
|
self._filler.add_transfer_transaction(
|
2020-08-18 22:50:36 +08:00
|
|
|
|
payday,
|
|
|
|
|
[(1113, "Payroll Transfer", savings),
|
|
|
|
|
(1314, F"Pension for {month_text}", pension),
|
|
|
|
|
(6262, F"Health insurance for {month_text}", insurance),
|
|
|
|
|
(1255, "Income Tax", tax)],
|
|
|
|
|
[(4611, F"Payroll for {month_text}", income)])
|