Compare commits
	
		
			18 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 86c5b91697 | |||
| 9168840e64 | |||
| 21b9cfa8b8 | |||
| b0b3b3acb1 | |||
| cb1d254cf0 | |||
| eb9ad57e72 | |||
| ec26f8ef4d | |||
| 7ed29115ed | |||
| 95955197ac | |||
| d5a0f79e4b | |||
| 6aa655aa64 | |||
| 6e532af26e | |||
| fa1818d124 | |||
| f21ecc2aa9 | |||
| 5ae1ab95ae | |||
| 7a5b3b78fc | |||
| 7df4051452 | |||
| 85084c68fd | 
							
								
								
									
										40
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								.readthedocs.yaml
									
									
									
									
									
										Normal 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: . | ||||
							
								
								
									
										21
									
								
								MANIFEST.in
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								MANIFEST.in
									
									
									
									
									
								
							| @@ -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 * | ||||
|   | ||||
							
								
								
									
										187
									
								
								README.rst
									
									
									
									
									
								
							
							
						
						
									
										187
									
								
								README.rst
									
									
									
									
									
								
							| @@ -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 | ||||
|   | ||||
| @@ -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
									
								
							
							
						
						
									
										61
									
								
								docs/source/examples.rst
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										57
									
								
								docs/source/history.rst
									
									
									
									
									
										Normal 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 | ||||
| @@ -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
									
								
							
							
						
						
									
										138
									
								
								docs/source/intro.rst
									
									
									
									
									
										Normal 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 | ||||
| @@ -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", | ||||
| ] | ||||
|   | ||||
							
								
								
									
										56
									
								
								setup.cfg
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								setup.cfg
									
									
									
									
									
								
							| @@ -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/** | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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] \ | ||||
|   | ||||
| @@ -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] \ | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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 --> | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user