18 Commits

Author SHA1 Message Date
86c5b91697 Advanced to version 1.0.1. 2023-04-06 08:43:14 +08:00
9168840e64 Fixed an error in the example configuration. 2023-04-06 08:38:39 +08:00
21b9cfa8b8 Revised the documentation. 2023-04-06 08:31:19 +08:00
b0b3b3acb1 Moved the history section out from README.rst and intro.rst, to the new history.rst. 2023-04-06 08:21:32 +08:00
cb1d254cf0 Advanced to version 1.0.0. Hooray! 2023-04-06 02:55:19 +08:00
eb9ad57e72 Updated the translation. 2023-04-06 02:55:17 +08:00
ec26f8ef4d Added the documentation. 2023-04-06 02:54:45 +08:00
7ed29115ed Revised the inclusion in the base template of the test site. 2023-04-06 02:01:05 +08:00
95955197ac Updated the copyright year in pyproject.toml. 2023-04-05 22:50:54 +08:00
d5a0f79e4b Revised the Read the Docs configuration, and removed the redundant requirements.txt for Read the Docs. 2023-04-05 22:01:53 +08:00
6aa655aa64 Replaced setup.cfg with pyproject.toml for the package settings, and rewrote the packaging rules in MANIFEST.in. 2023-04-05 19:49:52 +08:00
6e532af26e Added the Read the Docs documentation link to README.rst. 2023-04-05 14:25:33 +08:00
fa1818d124 Added the Read the Docs configuration file. 2023-04-05 14:12:46 +08:00
f21ecc2aa9 Added requirements.txt for Read the Docs. 2023-04-05 14:07:37 +08:00
5ae1ab95ae Advanced to version 0.11.1. 2023-04-05 13:00:46 +08:00
7a5b3b78fc Removed the rows with zero balance from the income statement. 2023-04-05 12:59:50 +08:00
7df4051452 Removed the rows with zero balance from the trial balance. 2023-04-05 12:56:28 +08:00
85084c68fd Removed the rows with zero balance from the balance sheet. 2023-04-05 12:29:58 +08:00
16 changed files with 622 additions and 168 deletions

40
.readthedocs.yaml Normal file
View File

@ -0,0 +1,40 @@
# The Mia! Accounting Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2023/4/5
# 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.
# .readthedocs.yaml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Set the version of Python and other tools you might need
build:
os: ubuntu-22.04
tools:
python: "3.11"
# Build documentation in the docs/ directory with Sphinx
# If using Sphinx, optionally build your docs in additional formats such as PDF
formats: all
# Optionally declare the Python requirements required to build your docs
python:
install:
- method: pip
path: .

View File

@ -15,17 +15,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
recursive-include src/accounting/static *
exclude src/accounting/static/js/dummy.js
include src/accounting/translations/*
include src/accounting/translations/*/LC_MESSAGES/*
include docs/*
include docs/source/*
include docs/source/_static/*
include docs/source/_templates/*
include tests/*
recursive-include src/accounting/templates *
recursive-include src/accounting/translations *
recursive-include src/accounting/data *
recursive-include docs *
recursive-exclude docs/build *
recursive-include tests *
exclude tests/test_temp.py
include tests/test_site/*
include tests/test_site/static/*
include tests/test_site/templates/*
include tests/test_site/translations/*
include tests/test_site/translations/*/LC_MESSAGES/*
recursive-exclude tests *.pyc
recursive-exclude tests/instance *

View File

@ -6,28 +6,173 @@ Mia! Accounting
Description
===========
This is the Mia! Accounting project. It is an accounting
module for the Flask_ applications.
*Mia! Accounting* is an accounting module for Flask_ applications.
It implements `double-entry bookkeeping`_, and generates the following
accounting reports:
* Trial balance
* Income statement
* Balance sheet
In addition, *Mia! Accounting* tracks offsets for unpaid payables and
receivables.
You may try the `live demonstration`_.
Install
=======
Installation
============
Install ``mia-accounting`` with ``pip``.
Install *Mia! Accounting* with ``pip``:
::
pip install mia-accounting
You may also download the from the `PyPI project page`_ or the
`release page`_ on the `Git repository`_.
Usage
=====
This needs to be done. Currently, you can refer to the test site
located in the test directory on the `Mia! Accounting repository`_.
Prerequisites
=============
The test site is running as the
`live demonstration for Mia! Accounting`_.
You need a running Flask application with database user login.
The primary key of the user data model must be integer.
The following front-end JavaScript libraries must be loaded. You may
download it locally or use CDN_.
* Bootstrap_ 5.2.3 or above
* FontAwesome_ 6.2.1 or above
* `Decimal.js`_ 6.4.3 or above
* `Tempus-Dominus`_ 6.4.3 or above
Configuration
=============
You need to pass the Flask *app* and an implementation of
`UserUtilityInterface`_ to the `init_app`_ function.
``UserUtilityInterface`` contains everything *Mia! Accounting* needs.
The following is an example configuration for *Mia! Accounting*.
::
from flask import Response, redirect
from .auth import current_user()
from .modules import User
def create_app(test_config=None) -> Flask:
app: Flask = Flask(__name__)
... (Configuration of SQLAlchemy, CSRF, Babel_JS, ... etc) ...
import accounting
class UserUtils(accounting.UserUtilityInterface[User]):
def can_view(self) -> bool:
return True
def can_edit(self) -> bool:
return "editor" in current_user().roles
def can_admin(self) -> bool:
return current_user().is_admin
def unauthorized(self) -> Response:
return redirect("/login")
@property
def cls(self) -> t.Type[User]:
return User
@property
def pk_column(self) -> Column:
return User.id
@property
def current_user(self) -> User | None:
return current_user()
def get_by_username(self, username: str) -> User | None:
return User.query.filter(User.username == username).first()
def get_pk(self, user: User) -> int:
return user.id
accounting.init_app(app, UserUtils())
... (Any other configuration) ...
return app
Database Initialization
=======================
After the configuration, you need to run
`flask_sqlalchemy.SQLAlchemy.create_all`_ to create the
database tables that *Mia! Accounting* uses.
*Mia! Accounting* adds three console commands:
* ``accounting-init-base``
* ``accounting-init-accounts``
* ``accounting-init-currencies``
After database tables are created, run
``accounting-init-base`` first, and then the other two commands.
::
% flask --app myapp accounting-init-base
% flask --app myapp accounting-init-accounts
% flask --app myapp accounting-init-currencies
Navigation Menu
===============
Include the navigation menu in the `Bootstrap navigation bar`_ in your
base template:
::
<nav class="navbar navbar-expand-lg bg-body-tertiary bg-dark navbar-dark">
<div class="container-fluid">
...
<div id="collapsible-navbar" class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
...
{% include "accounting/include/nav.html" %}
...
</ul>
...
</div>
</div>
</nav>
Check your Flask application and see how it works.
Test Site and Live Demonstration
================================
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application, you may start with the
test site.
Documentation
=============
Refer to the `documentation on Read the Docs`_.
Copyright
@ -55,6 +200,22 @@ Authors
| imacat@mail.imacat.idv.tw
| 2023/1/27
.. _Flask: https://flask.palletsprojects.com
.. _Mia! Accounting repository: https://github.com/imacat/mia-accounting
.. _live demonstration for Mia! Accounting: https://accounting.imacat.idv.tw
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
.. _live demonstration: https://accounting.imacat.idv.tw
.. _PyPI project page: https://pypi.org/project/mia-accounting
.. _release page: https://github.com/imacat/mia-accounting/releases
.. _Git repository: https://github.com/imacat/mia-accounting
.. _CDN: https://en.wikipedia.org/wiki/Content_delivery_network
.. _Bootstrap: https://getbootstrap.com
.. _FontAwesome: https://fontawesome.com
.. _Decimal.js: https://mikemcl.github.io/decimal.js
.. _Tempus-Dominus: https://getdatepicker.com
.. _UserUtilityInterface: https://mia-accounting.readthedocs.io/en/latest/accounting.utils.html#accounting.utils.user.UserUtilityInterface
.. _init_app: https://mia-accounting.readthedocs.io/en/latest/accounting.html#accounting.init_app
.. _flask_sqlalchemy.SQLAlchemy.create_all: https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/api/#flask_sqlalchemy.SQLAlchemy.create_all
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io

View File

@ -13,7 +13,7 @@ sys.path.insert(0, os.path.abspath('../../src/'))
project = 'Mia! Accounting'
copyright = '2023, imacat'
author = 'imacat'
release = '0.11.0'
release = '1.0.1'
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration

61
docs/source/examples.rst Normal file
View File

@ -0,0 +1,61 @@
Examples
========
.. _example-userutils:
An Example Configuration
------------------------
The following is an example configuration for *Mia! Accounting*.
::
from flask import Response, redirect
from .auth import current_user()
from .modules import User
def create_app(test_config=None) -> Flask:
app: Flask = Flask(__name__)
... (Configuration of SQLAlchemy, CSRF, Babel_JS, ... etc) ...
import accounting
class UserUtils(accounting.UserUtilityInterface[User]):
def can_view(self) -> bool:
return True
def can_edit(self) -> bool:
return "editor" in current_user().roles
def can_admin(self) -> bool:
return current_user().is_admin
def unauthorized(self) -> Response:
return redirect("/login")
@property
def cls(self) -> t.Type[User]:
return User
@property
def pk_column(self) -> Column:
return User.id
@property
def current_user(self) -> User | None:
return current_user()
def get_by_username(self, username: str) -> User | None:
return User.query.filter(User.username == username).first()
def get_pk(self, user: User) -> int:
return user.id
accounting.init_app(app, UserUtils())
... (Any other configuration) ...
return app

57
docs/source/history.rst Normal file
View File

@ -0,0 +1,57 @@
History
=======
I created my own private accounting application in Perl_/mod_perl_ in
2007, as part of my personal website. The first revision was made
using Perl/Mojolicious_ in 2019, with the aim of making it
mobile-friendly using Bootstrap_, and with modern back-end and
front-end technologies such as jQuery.
The second revision was done in Python_/Django_ in 2020, as I was
looking to change my career from PHP_/Laravel_ to Python, but lacked
experience with large Python projects. I needed something in my
portfolio and decided to work on the somewhat outdated Mojolicious
project.
Despite having no prior experience with Django, I spent two months
working late nights to create the `Mia! Accounting Django`_
application. It took me another 1.5 months to make it an independent
module, which I later released as an open source project on PyPI.
The application worked nicely for my household bookkeeping for two
years. However, new demands arose over time, especially with tracking
payables and receivables. This was critical `during the pandemic`_ as
more payments were made online with credit cards.
The biggest issue I encountered was with
`Django's MTV architectural pattern`_. Django takes over the control
flow. I had to override several parts of the `class-based views`_ for
different but yet simple control flow logic. In the end, it became
very difficult to track whether things went wrong because I overrode
something or because it just wouldn't work with the basic assumption
of the class-based views. By the time I realized it, it was too late
for me to drop Django's MTV and rewrite everything from class-based
views to function-based views.
Therefore, I decided to turn to microframeworks_ like Flask_. After
working with modularized Flask and FastAPI_ applications for two
years, I returned to the project and wrote its third revision using
Flask in 2023.
.. _Perl: https://www.perl.org
.. _mod_perl: https://perl.apache.org
.. _Mojolicious: https://mojolicious.org
.. _Bootstrap: https://getbootstrap.com
.. _jQuery: https://jquery.com
.. _Python: https://www.python.org
.. _Django: https://www.djangoproject.com
.. _PHP: https://www.php.net
.. _Laravel: https://laravel.com
.. _Mia! Accounting Django: https://github.com/imacat/mia-accounting-django
.. _during the pandemic: https://en.wikipedia.org/wiki/COVID-19_pandemic
.. _FastAPI: https://fastapi.tiangolo.com
.. _Django's MTV architectural pattern: https://docs.djangoproject.com/en/dev/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names
.. _class-based views: https://docs.djangoproject.com/en/4.2/topics/class-based-views/
.. _microframeworks: https://en.wikipedia.org/wiki/Microframework
.. _Flask: https://flask.palletsprojects.com

View File

@ -10,6 +10,11 @@ Welcome to Mia! Accounting's documentation!
:maxdepth: 2
:caption: Contents:
intro
accounting
examples
history
Indices and tables

138
docs/source/intro.rst Normal file
View File

@ -0,0 +1,138 @@
Introduction
============
*Mia! Accounting* is an accounting module for Flask_ applications.
It implements `double-entry bookkeeping`_, and generates the following
accounting reports:
* Trial balance
* Income statement
* Balance sheet
In addition, *Mia! Accounting* tracks offsets for unpaid payables and
receivables.
You may try the `live demonstration`_.
Installation
------------
Install *Mia! Accounting* with ``pip``:
::
pip install mia-accounting
You may also download the from the `PyPI project page`_ or the
`release page`_ on the `Git repository`_.
Prerequisites
-------------
You need a running Flask application with database user login.
The primary key of the user data model must be integer.
The following front-end JavaScript libraries must be loaded. You may
download it locally or use CDN_.
* Bootstrap_ 5.2.3 or above
* FontAwesome_ 6.2.1 or above
* `Decimal.js`_ 6.4.3 or above
* `Tempus-Dominus`_ 6.4.3 or above
Configuration
-------------
You need to pass the Flask *app* and an implementation of
:py:class:`accounting.utils.user.UserUtilityInterface` to the
:py:func:`accounting.init_app` function. ``UserUtilityInterface``
contains everything *Mia! Accounting* needs.
See an example in :ref:`example-userutils`.
Database Initialization
-----------------------
After the configuration, you need to run
`flask_sqlalchemy.SQLAlchemy.create_all`_ to create the
database tables that *Mia! Accounting* uses.
*Mia! Accounting* adds three console commands:
* ``accounting-init-base``
* ``accounting-init-accounts``
* ``accounting-init-currencies``
After database tables are created, run
``accounting-init-base`` first, and then the other two commands.
::
% flask --app myapp accounting-init-base
% flask --app myapp accounting-init-accounts
% flask --app myapp accounting-init-currencies
Navigation Menu
---------------
Include the navigation menu in the `Bootstrap navigation bar`_ in your
base template:
::
<nav class="navbar navbar-expand-lg bg-body-tertiary bg-dark navbar-dark">
<div class="container-fluid">
...
<div id="collapsible-navbar" class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
...
{% include "accounting/include/nav.html" %}
...
</ul>
...
</div>
</div>
</nav>
Check your Flask application and see how it works.
Test Site and Live Demonstration
--------------------------------
You may find a working example in the `test site`_ in the
`source distribution`_. It is the simplest website that works with
*Mia! Accounting*. It is used in the automatic tests. It is the same
code run for `live demonstration`_.
If you do not have a running Flask application, you may start with the
test site.
Documentation
-------------
Refer to the `documentation on Read the Docs`_.
.. _Flask: https://flask.palletsprojects.com
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
.. _live demonstration: https://accounting.imacat.idv.tw
.. _PyPI project page: https://pypi.org/project/mia-accounting
.. _release page: https://github.com/imacat/mia-accounting/releases
.. _Git repository: https://github.com/imacat/mia-accounting
.. _CDN: https://en.wikipedia.org/wiki/Content_delivery_network
.. _Bootstrap: https://getbootstrap.com
.. _FontAwesome: https://fontawesome.com
.. _Decimal.js: https://mikemcl.github.io/decimal.js
.. _Tempus-Dominus: https://getdatepicker.com
.. _flask_sqlalchemy.SQLAlchemy.create_all: https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/api/#flask_sqlalchemy.SQLAlchemy.create_all
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
.. _source distribution: https://pypi.org/project/mia-accounting/#files
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io

View File

@ -1,7 +1,7 @@
# The Mia! Accounting Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2022/8/21
# Copyright (c) 2022 imacat.
# Copyright (c) 2022-2023 imacat.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,6 +15,51 @@
# See the License for the specific language governing permissions and
# limitations under the License.
[project]
name = "mia-accounting"
version = "1.0.1"
description = "A Flask accounting module."
readme = "README.rst"
requires-python = ">=3.11"
authors = [
{name = "imacat", email = "imacat@mail.imacat.idv.tw"},
]
keywords = ["mia", "accounting", "flask"]
classifiers = [
"Programming Language :: Python :: 3",
"License :: OSI Approved :: Apache Software License",
"Operating System :: OS Independent",
"Framework :: Flask",
"Topic :: Office/Business :: Financial :: Accounting",
]
dependencies = [
"flask",
"Flask-SQLAlchemy",
"Flask-WTF",
"Flask-Babel >= 3",
"Flask-Babel-JS",
]
[project.optional-dependencies]
test = [
"unittest",
"httpx",
"OpenCC",
]
[project.urls]
"Documentation" = "https://mia-accounting.readthedocs.io"
"Repository" = "https://github.com/imacat/mia-accounting"
"Bug Tracker" = "https://github.com/imacat/mia-accounting/issues"
"Demonstration" = "https://accounting.imacat.idv.tw"
[build-system]
requires = ["setuptools>=42"]
build-backend = "setuptools.build_meta"
[tool.setuptools.exclude-package-data]
"*" = [
"babel.cfg",
"*.pot",
"*.po",
]

View File

@ -1,56 +0,0 @@
# The Mia! Accounting Project.
# Author: imacat@mail.imacat.idv.tw (imacat), 2022/8/21
# Copyright (c) 2022-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.
[metadata]
name = mia-accounting
version = 0.11.0
author = imacat
author_email = imacat@mail.imacat.idv.tw
description = The Mia! Accounting project.
long_description = file: README.rst
long_description_content_type = text/x-rst
url = https://github.com/imacat/mia-accounting
project_urls =
Bug Tracker = https://github.com/imacat/mia-accounting/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: Apache Software License
Operating System :: OS Independent
Framework :: Flask
Topic :: Office/Business :: Financial :: Accounting
[options]
package_dir =
= src
python_requires = >=3.11
install_requires =
flask
Flask-SQLAlchemy
Flask-WTF
Flask-Babel >= 3
Flask-Babel-JS
tests_require =
unittest
httpx
OpenCC
[options.package_data]
accounting =
static/**
templates/**
translations/*/LC_MESSAGES/*.mo
data/**

View File

@ -137,6 +137,7 @@ class AccountCollector:
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id, Account.base_code, Account.no)\
.having(balance_func != 0)\
.order_by(Account.base_code, Account.no)
account_balances: list[sa.Row] \
= db.session.execute(select_balance).all()

View File

@ -269,6 +269,7 @@ class IncomeStatement(BaseReport):
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id)\
.having(balance_func != 0)\
.order_by(Account.base_code, Account.no)
balances: list[sa.Row] = db.session.execute(select_balances).all()
accounts: dict[int, Account] \

View File

@ -191,6 +191,7 @@ class TrialBalance(BaseReport):
.join(JournalEntry).join(Account)\
.filter(*conditions)\
.group_by(Account.id)\
.having(balance_func != 0)\
.order_by(Account.base_code, Account.no)
balances: list[sa.Row] = db.session.execute(select_balances).all()
accounts: dict[int, Account] \

View File

@ -1,15 +1,15 @@
# Chinese (Traditional) translations for the Mia! Accounting project.
# Copyright (C) 2023 imacat
# This file is distributed under the same license as the Mia! Accounting
# Flask project.
# project.
# imacat <imacat@mail.imacat.idv.tw>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: Mia! Accounting 0.0.0\n"
"Project-Id-Version: mia-accounting 1.0.0\n"
"Report-Msgid-Bugs-To: imacat@mail.imacat.idv.tw\n"
"POT-Creation-Date: 2023-03-23 00:45+0800\n"
"PO-Revision-Date: 2023-03-23 00:46+0800\n"
"POT-Creation-Date: 2023-04-06 02:34+0800\n"
"PO-Revision-Date: 2023-04-06 02:34+0800\n"
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
"Language: zh_Hant\n"
"Language-Team: zh_Hant <imacat@mail.imacat.idv.tw>\n"
@ -20,10 +20,10 @@ msgstr ""
"Generated-By: Babel 2.12.1\n"
#: src/accounting/forms.py:33
#: src/accounting/static/js/journal-entry-form.js:980
#: src/accounting/static/js/journal-entry-line-item-editor.js:430
#: src/accounting/static/js/option-form.js:530
#: src/accounting/static/js/option-form.js:796
#: src/accounting/static/js/journal-entry-form.js:1065
#: src/accounting/static/js/journal-entry-line-item-editor.js:411
#: src/accounting/static/js/option-form.js:537
#: src/accounting/static/js/option-form.js:803
msgid "Please select the account."
msgstr "請選擇科目。"
@ -35,22 +35,22 @@ msgstr "沒有這個貨幣。"
msgid "The account does not exist."
msgstr "沒有這個科目。"
#: src/accounting/models.py:563
#: src/accounting/models.py:562
#, python-format
msgid "Cash Disbursement Journal Entry#%(id)s"
msgstr "現金支出傳票#%(id)s"
#: src/accounting/models.py:566
#: src/accounting/models.py:565
#, python-format
msgid "Cash Receipt Journal Entry#%(id)s"
msgstr "現金收入傳票#%(id)s"
#: src/accounting/models.py:567
#: src/accounting/models.py:566
#, python-format
msgid "Transfer Journal Entry#%(id)s"
msgstr "轉帳傳票#%(id)s"
#: src/accounting/models.py:700
#: src/accounting/models.py:699
#, python-format
msgid "%(date)s %(description)s %(amount)s"
msgstr "%(date)s %(description)s %(amount)s"
@ -92,7 +92,7 @@ msgid "A nominal account does not need offset."
msgstr "虛科目不需抵銷。"
#: src/accounting/account/forms.py:75
#: src/accounting/static/js/account-form.js:181
#: src/accounting/static/js/account-form.js:189
msgid "Please select the base account."
msgstr "請選擇基本科目。"
@ -160,8 +160,8 @@ msgstr "不能用這個代碼。"
#: src/accounting/currency/forms.py:62 src/accounting/option/forms.py:124
#: src/accounting/option/forms.py:148
#: src/accounting/static/js/currency-form.js:153
#: src/accounting/static/js/option-form.js:525
#: src/accounting/static/js/option-form.js:780
#: src/accounting/static/js/option-form.js:532
#: src/accounting/static/js/option-form.js:787
msgid "Please fill in the name."
msgstr "請填上名稱。"
@ -218,23 +218,23 @@ msgid "The currency must not be changed when there is offset."
msgstr "抵銷過不可變更貨幣。"
#: src/accounting/journal_entry/forms/currency.py:99
#: src/accounting/static/js/journal-entry-form.js:729
#: src/accounting/static/js/journal-entry-form.js:773
msgid "Please add some line items."
msgstr "請加上分錄。"
#: src/accounting/journal_entry/forms/currency.py:112
#: src/accounting/static/js/journal-entry-form.js:516
#: src/accounting/static/js/journal-entry-form.js:522
msgid "The totals of the debit and credit amounts do not match."
msgstr "借方貸方合計不符。 "
#: src/accounting/journal_entry/forms/journal_entry.py:48
#: src/accounting/static/js/journal-entry-form.js:270
#: src/accounting/static/js/period-chooser.js:273
#: src/accounting/static/js/journal-entry-form.js:264
#: src/accounting/static/js/period-chooser.js:265
msgid "Please fill in the date."
msgstr "請填上日期。"
#: src/accounting/journal_entry/forms/journal_entry.py:64
#: src/accounting/static/js/journal-entry-form.js:275
#: src/accounting/static/js/journal-entry-form.js:269
msgid "The date cannot be earlier than the original line items."
msgstr "日期不可早於原始分錄。"
@ -243,7 +243,7 @@ msgid "The date cannot be later than the offset items."
msgstr "日期不可晚於抵銷日期。"
#: src/accounting/journal_entry/forms/journal_entry.py:88
#: src/accounting/static/js/journal-entry-form.js:305
#: src/accounting/static/js/journal-entry-form.js:299
msgid "Please add some currencies."
msgstr "請加上貨幣。"
@ -284,12 +284,12 @@ msgid "A receivable line item cannot start from credit."
msgstr "不可由貸方新建應收款。"
#: src/accounting/journal_entry/forms/line_item.py:180
#: src/accounting/static/js/journal-entry-line-item-editor.js:455
#: src/accounting/static/js/journal-entry-line-item-editor.js:436
msgid "Please fill in a positive amount."
msgstr "金額請填正數。"
#: src/accounting/journal_entry/forms/line_item.py:222
#: src/accounting/static/js/journal-entry-line-item-editor.js:461
#: src/accounting/static/js/journal-entry-line-item-editor.js:442
#, python-format
msgid ""
"The amount must not exceed the net balance %(balance)s of the original "
@ -297,7 +297,7 @@ msgid ""
msgstr "金額不可超過原始分錄凈額 %(balance)s 。"
#: src/accounting/journal_entry/forms/line_item.py:243
#: src/accounting/static/js/journal-entry-line-item-editor.js:469
#: src/accounting/static/js/journal-entry-line-item-editor.js:450
#, python-format
msgid "The amount must not be less than the offset total %(total)s."
msgstr "金額不可低於抵銷總額 %(total)s 。"
@ -327,8 +327,8 @@ msgid "This account is not for expense."
msgstr "科目不是支出科目。"
#: src/accounting/option/forms.py:137 src/accounting/option/forms.py:161
#: src/accounting/static/js/option-form.js:535
#: src/accounting/static/js/option-form.js:813
#: src/accounting/static/js/option-form.js:542
#: src/accounting/static/js/option-form.js:820
msgid "Please fill in the description template."
msgstr "請填上摘要範本。"
@ -408,18 +408,18 @@ msgstr "去年"
msgid "All"
msgstr "全部"
#: src/accounting/report/reports/balance_sheet.py:422
#: src/accounting/report/reports/balance_sheet.py:426
#: src/accounting/report/reports/balance_sheet.py:438
#: src/accounting/report/reports/balance_sheet.py:440
#: src/accounting/report/reports/balance_sheet.py:423
#: src/accounting/report/reports/balance_sheet.py:427
#: src/accounting/report/reports/balance_sheet.py:439
#: src/accounting/report/reports/balance_sheet.py:441
#: src/accounting/report/reports/income_expenses.py:189
#: src/accounting/report/reports/income_expenses.py:423
#: src/accounting/report/reports/income_statement.py:299
#: src/accounting/report/reports/income_statement.py:300
#: src/accounting/report/reports/ledger.py:171
#: src/accounting/report/reports/ledger.py:380
#: src/accounting/report/reports/trial_balance.py:228
#: src/accounting/report/reports/trial_balance.py:229
#: src/accounting/templates/accounting/journal-entry/disbursement/detail.html:43
#: src/accounting/templates/accounting/journal-entry/include/form-debit-credit.html:37
#: src/accounting/templates/accounting/journal-entry/include/form-debit-credit.html:38
#: src/accounting/templates/accounting/journal-entry/receipt/detail.html:43
#: src/accounting/templates/accounting/journal-entry/transfer/detail.html:39
#: src/accounting/templates/accounting/journal-entry/transfer/detail.html:55
@ -455,7 +455,7 @@ msgstr "日期"
#: src/accounting/report/reports/income_expenses.py:407
#: src/accounting/report/reports/journal.py:156
#: src/accounting/report/reports/trial_balance.py:224
#: src/accounting/report/reports/trial_balance.py:225
#: src/accounting/templates/accounting/journal-entry/include/journal-entry-line-item-editor-modal.html:57
#: src/accounting/templates/accounting/option/include/recurring-item-editor-modal.html:39
#: src/accounting/templates/accounting/report/include/toolbar-buttons.html:90
@ -527,7 +527,7 @@ msgstr "稅後淨利"
msgid "net income or loss for current period"
msgstr "本期損益"
#: src/accounting/report/reports/income_statement.py:300
#: src/accounting/report/reports/income_statement.py:301
#: src/accounting/templates/accounting/journal-entry/include/journal-entry-line-item-editor-modal.html:65
#: src/accounting/templates/accounting/report/income-statement.html:55
msgid "Amount"
@ -543,7 +543,7 @@ msgstr "貨幣"
#: src/accounting/report/reports/journal.py:157
#: src/accounting/report/reports/ledger.py:367
#: src/accounting/report/reports/trial_balance.py:224
#: src/accounting/report/reports/trial_balance.py:225
#: src/accounting/templates/accounting/journal-entry/transfer/detail.html:33
#: src/accounting/templates/accounting/journal-entry/transfer/include/form-currency.html:30
#: src/accounting/templates/accounting/report/journal.html:57
@ -555,7 +555,7 @@ msgstr "借方"
#: src/accounting/report/reports/journal.py:157
#: src/accounting/report/reports/ledger.py:367
#: src/accounting/report/reports/trial_balance.py:225
#: src/accounting/report/reports/trial_balance.py:226
#: src/accounting/templates/accounting/journal-entry/transfer/detail.html:49
#: src/accounting/templates/accounting/journal-entry/transfer/include/form-currency.html:41
#: src/accounting/templates/accounting/report/journal.html:58
@ -581,17 +581,17 @@ msgstr "貸方"
msgid "Search"
msgstr "搜尋"
#: src/accounting/report/utils/report_chooser.py:89
msgid "Journal"
msgstr "日記簿"
#: src/accounting/report/utils/report_chooser.py:92
msgid "Income and Expenses Log"
msgstr "收支帳"
#: src/accounting/report/utils/report_chooser.py:99
#: src/accounting/report/utils/report_chooser.py:105
msgid "Ledger"
msgstr "分類帳"
#: src/accounting/report/utils/report_chooser.py:114
msgid "Income and Expenses Log"
msgstr "收支帳"
#: src/accounting/report/utils/report_chooser.py:117
msgid "Journal"
msgstr "日記簿"
#: src/accounting/report/utils/report_chooser.py:127
msgid "Trial Balance"
@ -605,110 +605,110 @@ msgstr "損益表"
msgid "Balance Sheet"
msgstr "資產負債表"
#: src/accounting/static/js/account-form.js:198
#: src/accounting/static/js/account-form.js:206
msgid "Please fill in the title."
msgstr "請填上標題。"
#: src/accounting/static/js/description-editor.js:756
#: src/accounting/static/js/description-editor.js:934
#: src/accounting/static/js/description-editor.js:951
#: src/accounting/static/js/description-editor.js:1129
msgid "Please fill in the tag."
msgstr "請填上標籤。"
#: src/accounting/static/js/description-editor.js:766
#: src/accounting/static/js/description-editor.js:954
#: src/accounting/static/js/description-editor.js:961
#: src/accounting/static/js/description-editor.js:1149
msgid "Please fill in the origin."
msgstr "請填上起點。"
#: src/accounting/static/js/description-editor.js:776
#: src/accounting/static/js/description-editor.js:964
#: src/accounting/static/js/description-editor.js:971
#: src/accounting/static/js/description-editor.js:1159
msgid "Please fill in the destination."
msgstr "請填上終點。"
#: src/accounting/static/js/description-editor.js:944
#: src/accounting/static/js/description-editor.js:1139
msgid "Please fill in the route."
msgstr "請填上路線名稱。"
#: src/accounting/static/js/description-editor.js:998
#: src/accounting/static/js/description-editor.js:1192
msgid "January"
msgstr "一月"
#: src/accounting/static/js/description-editor.js:998
#: src/accounting/static/js/description-editor.js:1192
msgid "February"
msgstr "二月"
#: src/accounting/static/js/description-editor.js:998
#: src/accounting/static/js/description-editor.js:1192
msgid "March"
msgstr "三月"
#: src/accounting/static/js/description-editor.js:998
#: src/accounting/static/js/description-editor.js:1192
msgid "April"
msgstr "四月"
#: src/accounting/static/js/description-editor.js:999
#: src/accounting/static/js/description-editor.js:1193
msgid "May"
msgstr "五月"
#: src/accounting/static/js/description-editor.js:999
#: src/accounting/static/js/description-editor.js:1193
msgid "June"
msgstr "六月"
#: src/accounting/static/js/description-editor.js:999
#: src/accounting/static/js/description-editor.js:1193
msgid "July"
msgstr "七月"
#: src/accounting/static/js/description-editor.js:999
#: src/accounting/static/js/description-editor.js:1193
msgid "August"
msgstr "八月"
#: src/accounting/static/js/description-editor.js:1000
#: src/accounting/static/js/description-editor.js:1194
msgid "September"
msgstr "九月"
#: src/accounting/static/js/description-editor.js:1000
#: src/accounting/static/js/description-editor.js:1194
msgid "October"
msgstr "十月"
#: src/accounting/static/js/description-editor.js:1000
#: src/accounting/static/js/description-editor.js:1194
msgid "November"
msgstr "十一月"
#: src/accounting/static/js/description-editor.js:1000
#: src/accounting/static/js/description-editor.js:1194
msgid "December"
msgstr "十二月"
#: src/accounting/static/js/journal-entry-form.js:985
#: src/accounting/static/js/journal-entry-line-item-editor.js:449
#: src/accounting/static/js/journal-entry-form.js:1070
#: src/accounting/static/js/journal-entry-line-item-editor.js:430
msgid "Please fill in the amount."
msgstr "請填上金額。"
#: src/accounting/static/js/journal-entry-form.js:1012
#: src/accounting/static/js/journal-entry-form.js:1092
#: src/accounting/templates/accounting/journal-entry/include/detail-line-items.html:34
#: src/accounting/templates/accounting/journal-entry/include/form-line-item.html:38
#, python-format
msgid "Offset %(item)s"
msgstr "抵銷 %(item)s"
#: src/accounting/static/js/period-chooser.js:278
#: src/accounting/static/js/period-chooser.js:270
msgid "The date is too early."
msgstr "日期太早。"
#: src/accounting/static/js/period-chooser.js:377
#: src/accounting/static/js/period-chooser.js:369
msgid "Please fill in the start date."
msgstr "請填上開始日期。"
#: src/accounting/static/js/period-chooser.js:382
#: src/accounting/static/js/period-chooser.js:374
msgid "The start date is too early."
msgstr "開始日期太早。"
#: src/accounting/static/js/period-chooser.js:387
#: src/accounting/static/js/period-chooser.js:379
msgid "The start date cannot be beyond the end date."
msgstr "開始日期不可晚於結束日期。"
#: src/accounting/static/js/period-chooser.js:405
#: src/accounting/static/js/period-chooser.js:397
msgid "Please fill in the end date."
msgstr "請填上結束日期。"
#: src/accounting/static/js/period-chooser.js:410
#: src/accounting/static/js/period-chooser.js:402
msgid "The end date cannot be beyond the start date."
msgstr "結束日期不可早於開始日期。"
@ -777,7 +777,7 @@ msgstr "你確定要刪掉這個科目嗎?"
#: src/accounting/templates/accounting/account/include/form.html:112
#: src/accounting/templates/accounting/currency/detail.html:79
#: src/accounting/templates/accounting/journal-entry/include/account-selector-modal.html:49
#: src/accounting/templates/accounting/journal-entry/include/description-editor-modal.html:193
#: src/accounting/templates/accounting/journal-entry/include/description-editor-modal.html:194
#: src/accounting/templates/accounting/journal-entry/include/detail.html:84
#: src/accounting/templates/accounting/journal-entry/include/journal-entry-line-item-editor-modal.html:70
#: src/accounting/templates/accounting/option/include/recurring-account-selector-modal.html:48
@ -824,7 +824,7 @@ msgstr "科目管理"
#: src/accounting/templates/accounting/account/list.html:32
#: src/accounting/templates/accounting/currency/list.html:32
#: src/accounting/templates/accounting/journal-entry/include/form-debit-credit.html:44
#: src/accounting/templates/accounting/journal-entry/include/form-debit-credit.html:45
#: src/accounting/templates/accounting/journal-entry/include/form.html:64
#: src/accounting/templates/accounting/option/include/form-recurring-expense-income.html:37
#: src/accounting/templates/accounting/report/include/toolbar-buttons.html:26
@ -839,6 +839,8 @@ msgstr "新增"
#: src/accounting/templates/accounting/journal-entry/include/account-selector-modal.html:46
#: src/accounting/templates/accounting/journal-entry/include/original-line-item-selector-modal.html:51
#: src/accounting/templates/accounting/journal-entry/order.html:82
#: src/accounting/templates/accounting/option/detail.html:67
#: src/accounting/templates/accounting/option/detail.html:83
#: src/accounting/templates/accounting/option/include/recurring-account-selector-modal.html:45
#: src/accounting/templates/accounting/report/balance-sheet.html:110
#: src/accounting/templates/accounting/report/income-expenses.html:113
@ -858,7 +860,7 @@ msgstr "%(base)s下的科目"
#: src/accounting/templates/accounting/account/include/form.html:75
#: src/accounting/templates/accounting/account/order.html:62
#: src/accounting/templates/accounting/currency/include/form.html:57
#: src/accounting/templates/accounting/journal-entry/include/description-editor-modal.html:194
#: src/accounting/templates/accounting/journal-entry/include/description-editor-modal.html:195
#: src/accounting/templates/accounting/journal-entry/include/form.html:80
#: src/accounting/templates/accounting/journal-entry/include/journal-entry-line-item-editor-modal.html:71
#: src/accounting/templates/accounting/journal-entry/order.html:61
@ -950,6 +952,7 @@ msgstr "貨幣"
#: src/accounting/templates/accounting/include/nav.html:58
#: src/accounting/templates/accounting/option/detail.html:24
#: src/accounting/templates/accounting/option/detail.html:41
#: src/accounting/templates/accounting/option/form.html:29
msgid "Settings"
msgstr "設定"
@ -1112,7 +1115,7 @@ msgstr "新增現金收入傳票"
msgid "Add a New Transfer Journal Entry"
msgstr "新增轉帳傳票"
#: src/accounting/templates/accounting/option/detail.html:43
#: src/accounting/templates/accounting/option/detail.html:44
#: src/accounting/templates/accounting/option/form.html:51
msgid "Default Currency"
msgstr "預設貨幣"
@ -1122,13 +1125,13 @@ msgstr "預設貨幣"
msgid "Default Account for the Income and Expenses Log"
msgstr "收支帳預設科目"
#: src/accounting/templates/accounting/option/detail.html:52
#: src/accounting/templates/accounting/option/detail.html:54
#: src/accounting/templates/accounting/option/form.html:66
#: src/accounting/templates/accounting/option/form.html:92
msgid "Recurring Expense"
msgstr "常用支出"
#: src/accounting/templates/accounting/option/detail.html:58
#: src/accounting/templates/accounting/option/detail.html:70
#: src/accounting/templates/accounting/option/form.html:72
#: src/accounting/templates/accounting/option/form.html:96
msgid "Recurring Income"

View File

@ -51,7 +51,7 @@ First written: 2023/1/27
<div id="collapsible-navbar" class="collapse navbar-collapse">
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
{% include "/accounting/include/nav.html" %}
{% include "accounting/include/nav.html" %}
</ul>
<!-- The right side -->

View File

@ -1,16 +1,16 @@
# Chinese (Traditional) translations for the Mia! Accounting
# Demonstration website.
# Test website.
# Copyright (C) 2023 imacat
# This file is distributed under the same license as the Mia! Accounting
# Flask Demonstration project.
# project.
# imacat <imacat@mail.imacat.idv.tw>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: Mia! Accounting Demonstration 0.0.0\n"
"Project-Id-Version: mia-accounting-test-site 1.0.0\n"
"Report-Msgid-Bugs-To: imacat@mail.imacat.idv.tw\n"
"POT-Creation-Date: 2023-03-24 08:32+0800\n"
"PO-Revision-Date: 2023-03-24 08:33+0800\n"
"POT-Creation-Date: 2023-04-06 02:34+0800\n"
"PO-Revision-Date: 2023-04-06 02:34+0800\n"
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
"Language: zh_Hant\n"
"Language-Team: zh_Hant <imacat@mail.imacat.idv.tw>\n"