Compare commits
No commits in common. "e62316c477c92375b108fff32bf7c72d65c29b30" and "404b902d88e454ca99cb9ed24a823f6f25bd74f1" have entirely different histories.
e62316c477
...
404b902d88
32
README.rst
32
README.rst
@ -7,8 +7,7 @@ Description
|
|||||||
===========
|
===========
|
||||||
|
|
||||||
*Mia! Accounting* is an accounting module for Flask_ applications.
|
*Mia! Accounting* is an accounting module for Flask_ applications.
|
||||||
It is designed both for mobile and desktop environments. It
|
It implements `double-entry bookkeeping`_, and generates the following
|
||||||
implements `double-entry bookkeeping`_. It generates the following
|
|
||||||
accounting reports:
|
accounting reports:
|
||||||
|
|
||||||
* Trial balance
|
* Trial balance
|
||||||
@ -19,18 +18,6 @@ In addition, *Mia! Accounting* tracks offsets for unpaid payables and
|
|||||||
receivables.
|
receivables.
|
||||||
|
|
||||||
|
|
||||||
Live Demonstration and Test Site
|
|
||||||
================================
|
|
||||||
|
|
||||||
There is a `live demonstration`_ for *Mia! Accounting*. It runs the
|
|
||||||
same code as the `test site`_ in the `source distribution`_. It is
|
|
||||||
the simplest website that works with *Mia! Accounting*. It is also
|
|
||||||
used in the automatic tests.
|
|
||||||
|
|
||||||
If you do not have a running Flask application or do not know how to
|
|
||||||
start one, you may start with the test site.
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
@ -40,10 +27,22 @@ Install *Mia! Accounting* with ``pip``:
|
|||||||
|
|
||||||
pip install mia-accounting
|
pip install mia-accounting
|
||||||
|
|
||||||
You may also download from the `PyPI project page`_ or the
|
You may also download the from the `PyPI project page`_ or the
|
||||||
`release page`_ on the `Git repository`_.
|
`release page`_ on the `Git repository`_.
|
||||||
|
|
||||||
|
|
||||||
|
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 or do not know how to
|
||||||
|
start one, you may start with the test site.
|
||||||
|
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
=============
|
=============
|
||||||
|
|
||||||
@ -192,9 +191,9 @@ Authors
|
|||||||
|
|
||||||
.. _Flask: https://flask.palletsprojects.com
|
.. _Flask: https://flask.palletsprojects.com
|
||||||
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
|
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
|
||||||
.. _live demonstration: https://accounting.imacat.idv.tw
|
|
||||||
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
|
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
|
||||||
.. _source distribution: https://pypi.org/project/mia-accounting/#files
|
.. _source distribution: https://pypi.org/project/mia-accounting/#files
|
||||||
|
.. _live demonstration: https://accounting.imacat.idv.tw
|
||||||
.. _PyPI project page: https://pypi.org/project/mia-accounting
|
.. _PyPI project page: https://pypi.org/project/mia-accounting
|
||||||
.. _release page: https://github.com/imacat/mia-accounting/releases
|
.. _release page: https://github.com/imacat/mia-accounting/releases
|
||||||
.. _Git repository: https://github.com/imacat/mia-accounting
|
.. _Git repository: https://github.com/imacat/mia-accounting
|
||||||
@ -205,5 +204,6 @@ Authors
|
|||||||
.. _Tempus-Dominus: https://getdatepicker.com
|
.. _Tempus-Dominus: https://getdatepicker.com
|
||||||
.. _UserUtilityInterface: https://mia-accounting.readthedocs.io/en/latest/accounting.utils.html#accounting.utils.user.UserUtilityInterface
|
.. _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
|
.. _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/
|
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
|
||||||
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io
|
.. _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'
|
project = 'Mia! Accounting'
|
||||||
copyright = '2023, imacat'
|
copyright = '2023, imacat'
|
||||||
author = 'imacat'
|
author = 'imacat'
|
||||||
release = '1.3.1'
|
release = '1.3.0'
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||||
|
@ -2,8 +2,7 @@ Introduction
|
|||||||
============
|
============
|
||||||
|
|
||||||
*Mia! Accounting* is an accounting module for Flask_ applications.
|
*Mia! Accounting* is an accounting module for Flask_ applications.
|
||||||
It is designed both for mobile and desktop environments. It
|
It implements `double-entry bookkeeping`_, and generates the following
|
||||||
implements `double-entry bookkeeping`_. It generates the following
|
|
||||||
accounting reports:
|
accounting reports:
|
||||||
|
|
||||||
* Trial balance
|
* Trial balance
|
||||||
@ -14,18 +13,6 @@ In addition, *Mia! Accounting* tracks offsets for unpaid payables and
|
|||||||
receivables.
|
receivables.
|
||||||
|
|
||||||
|
|
||||||
Live Demonstration and Test Site
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
There is a `live demonstration`_ for *Mia! Accounting*. It runs the
|
|
||||||
same code as the `test site`_ in the `source distribution`_. It is
|
|
||||||
the simplest website that works with *Mia! Accounting*. It is also
|
|
||||||
used in the automatic tests.
|
|
||||||
|
|
||||||
If you do not have a running Flask application or do not know how to
|
|
||||||
start one, you may start with the test site.
|
|
||||||
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
@ -35,10 +22,22 @@ Install *Mia! Accounting* with ``pip``:
|
|||||||
|
|
||||||
pip install mia-accounting
|
pip install mia-accounting
|
||||||
|
|
||||||
You may also download from the `PyPI project page`_ or the
|
You may also download the from the `PyPI project page`_ or the
|
||||||
`release page`_ on the `Git repository`_.
|
`release page`_ on the `Git repository`_.
|
||||||
|
|
||||||
|
|
||||||
|
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 or do not know how to
|
||||||
|
start one, you may start with the test site.
|
||||||
|
|
||||||
|
|
||||||
Prerequisites
|
Prerequisites
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
@ -111,9 +110,9 @@ Refer to the `documentation on Read the Docs`_.
|
|||||||
|
|
||||||
.. _Flask: https://flask.palletsprojects.com
|
.. _Flask: https://flask.palletsprojects.com
|
||||||
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
|
.. _double-entry bookkeeping: https://en.wikipedia.org/wiki/Double-entry_bookkeeping
|
||||||
.. _live demonstration: https://accounting.imacat.idv.tw
|
|
||||||
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
|
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
|
||||||
.. _source distribution: https://pypi.org/project/mia-accounting/#files
|
.. _source distribution: https://pypi.org/project/mia-accounting/#files
|
||||||
|
.. _live demonstration: https://accounting.imacat.idv.tw
|
||||||
.. _PyPI project page: https://pypi.org/project/mia-accounting
|
.. _PyPI project page: https://pypi.org/project/mia-accounting
|
||||||
.. _release page: https://github.com/imacat/mia-accounting/releases
|
.. _release page: https://github.com/imacat/mia-accounting/releases
|
||||||
.. _Git repository: https://github.com/imacat/mia-accounting
|
.. _Git repository: https://github.com/imacat/mia-accounting
|
||||||
@ -122,5 +121,6 @@ Refer to the `documentation on Read the Docs`_.
|
|||||||
.. _FontAwesome: https://fontawesome.com
|
.. _FontAwesome: https://fontawesome.com
|
||||||
.. _Decimal.js: https://mikemcl.github.io/decimal.js
|
.. _Decimal.js: https://mikemcl.github.io/decimal.js
|
||||||
.. _Tempus-Dominus: https://getdatepicker.com
|
.. _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/
|
.. _Bootstrap navigation bar: https://getbootstrap.com/docs/5.3/components/navbar/
|
||||||
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io
|
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "mia-accounting"
|
name = "mia-accounting"
|
||||||
version = "1.3.1"
|
version = "1.3.0"
|
||||||
description = "A Flask accounting module."
|
description = "A Flask accounting module."
|
||||||
readme = "README.rst"
|
readme = "README.rst"
|
||||||
requires-python = ">=3.11"
|
requires-python = ">=3.11"
|
||||||
|
@ -51,14 +51,12 @@ First written: 2023/1/26
|
|||||||
{{ A_("Currencies") }}
|
{{ A_("Currencies") }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
{% if accounting_can_edit() %}
|
<li>
|
||||||
<li>
|
<a class="dropdown-item {% if request.endpoint and request.endpoint.startswith("accounting.unmatched-offset.") %} active {% endif %}" href="{{ url_for("accounting.unmatched-offset.dashboard") }}">
|
||||||
<a class="dropdown-item {% if request.endpoint and request.endpoint.startswith("accounting.unmatched-offset.") %} active {% endif %}" href="{{ url_for("accounting.unmatched-offset.dashboard") }}">
|
<i class="fa-solid fa-link-slash"></i>
|
||||||
<i class="fa-solid fa-link-slash"></i>
|
{{ A_("Unmatched Offsets") }}
|
||||||
{{ A_("Unmatched Offsets") }}
|
</a>
|
||||||
</a>
|
</li>
|
||||||
</li>
|
|
||||||
{% endif %}
|
|
||||||
{% if accounting_can_admin() %}
|
{% if accounting_can_admin() %}
|
||||||
<li>
|
<li>
|
||||||
<a class="dropdown-item {% if request.endpoint and request.endpoint.startswith("accounting.option.") %} active {% endif %}" href="{{ url_for("accounting.option.detail") }}">
|
<a class="dropdown-item {% if request.endpoint and request.endpoint.startswith("accounting.option.") %} active {% endif %}" href="{{ url_for("accounting.option.detail") }}">
|
||||||
|
@ -22,8 +22,7 @@ import typing as t
|
|||||||
from secrets import token_urlsafe
|
from secrets import token_urlsafe
|
||||||
|
|
||||||
from click.testing import Result
|
from click.testing import Result
|
||||||
from flask import Flask, Blueprint, render_template, redirect, Response, \
|
from flask import Flask, Blueprint, render_template, redirect, Response
|
||||||
url_for
|
|
||||||
from flask.testing import FlaskCliRunner
|
from flask.testing import FlaskCliRunner
|
||||||
from flask_babel_js import BabelJS
|
from flask_babel_js import BabelJS
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
@ -87,8 +86,7 @@ def create_app(is_testing: bool = False) -> Flask:
|
|||||||
and auth.current_user().username == "admin"
|
and auth.current_user().username == "admin"
|
||||||
|
|
||||||
def unauthorized(self) -> Response:
|
def unauthorized(self) -> Response:
|
||||||
from accounting.utils.next_uri import append_next
|
return redirect("/login")
|
||||||
return redirect(append_next(url_for("auth.login-form")))
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def cls(self) -> t.Type[auth.User]:
|
def cls(self) -> t.Type[auth.User]:
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from flask import Blueprint, render_template, Flask, redirect, url_for, \
|
from flask import Blueprint, render_template, Flask, redirect, url_for, \
|
||||||
session, request, g, Response
|
session, request, g
|
||||||
|
|
||||||
from . import db
|
from . import db
|
||||||
|
|
||||||
@ -44,13 +44,11 @@ class User(db.Model):
|
|||||||
|
|
||||||
|
|
||||||
@bp.get("login", endpoint="login-form")
|
@bp.get("login", endpoint="login-form")
|
||||||
def show_login_form() -> str | Response:
|
def show_login_form() -> str:
|
||||||
"""Shows the login form.
|
"""Shows the login form.
|
||||||
|
|
||||||
:return: The login form.
|
:return: The login form.
|
||||||
"""
|
"""
|
||||||
if "user" in session:
|
|
||||||
return redirect(url_for("accounting-report.default"))
|
|
||||||
return render_template("login.html")
|
return render_template("login.html")
|
||||||
|
|
||||||
|
|
||||||
@ -60,12 +58,11 @@ def login() -> redirect:
|
|||||||
|
|
||||||
:return: The redirection to the home page.
|
:return: The redirection to the home page.
|
||||||
"""
|
"""
|
||||||
from accounting.utils.next_uri import inherit_next, or_next
|
|
||||||
if request.form.get("username") not in {"viewer", "editor", "admin",
|
if request.form.get("username") not in {"viewer", "editor", "admin",
|
||||||
"nobody"}:
|
"nobody"}:
|
||||||
return redirect(inherit_next(url_for("auth.login")))
|
return redirect(url_for("auth.login"))
|
||||||
session["user"] = request.form.get("username")
|
session["user"] = request.form.get("username")
|
||||||
return redirect(or_next(url_for("accounting-report.default")))
|
return redirect(url_for("home.home"))
|
||||||
|
|
||||||
|
|
||||||
@bp.post("logout", endpoint="logout")
|
@bp.post("logout", endpoint="logout")
|
||||||
|
@ -21,12 +21,4 @@ First written: 2023/1/27
|
|||||||
#}
|
#}
|
||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
|
||||||
{% block header %}{% block title %}{{ _("Mia! Accounting Live Demonstration") }}{% endblock %}{% endblock %}
|
{% block header %}{% block title %}{{ _("Home") }}{% endblock %}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<p>{{ _("This is the live demonstration of the Mia! Accounting project. Please <a href=\"/login?next=%%2Faccounting\">log in</a> to continue.") }}</p>
|
|
||||||
|
|
||||||
<p>{{ _("You may also want to check the <a href=\"https://mia-accounting.readthedocs.io\">full documentation</a> and the <a href=\"https://github.com/imacat/mia-accounting\">Github repository</a>.") }}</p>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
|
@ -27,9 +27,6 @@ First written: 2023/1/27
|
|||||||
|
|
||||||
<form action="{{ url_for("auth.login") }}" method="post">
|
<form action="{{ url_for("auth.login") }}" method="post">
|
||||||
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
||||||
{% if request.args.next %}
|
|
||||||
<input type="hidden" name="next" value="{{ request.args.next }}">
|
|
||||||
{% endif %}
|
|
||||||
<button class="btn btn-primary" type="submit" name="username" value="viewer">{{ _("Viewer") }}</button>
|
<button class="btn btn-primary" type="submit" name="username" value="viewer">{{ _("Viewer") }}</button>
|
||||||
<button class="btn btn-primary" type="submit" name="username" value="editor">{{ _("Editor") }}</button>
|
<button class="btn btn-primary" type="submit" name="username" value="editor">{{ _("Editor") }}</button>
|
||||||
<button class="btn btn-primary" type="submit" name="username" value="admin">{{ _("Administrator") }}</button>
|
<button class="btn btn-primary" type="submit" name="username" value="admin">{{ _("Administrator") }}</button>
|
||||||
|
@ -9,8 +9,8 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: mia-accounting-test-site 1.0.0\n"
|
"Project-Id-Version: mia-accounting-test-site 1.0.0\n"
|
||||||
"Report-Msgid-Bugs-To: imacat@mail.imacat.idv.tw\n"
|
"Report-Msgid-Bugs-To: imacat@mail.imacat.idv.tw\n"
|
||||||
"POT-Creation-Date: 2023-04-11 22:18+0800\n"
|
"POT-Creation-Date: 2023-04-06 02:34+0800\n"
|
||||||
"PO-Revision-Date: 2023-04-11 22:18+0800\n"
|
"PO-Revision-Date: 2023-04-06 02:34+0800\n"
|
||||||
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
|
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
|
||||||
"Language: zh_Hant\n"
|
"Language: zh_Hant\n"
|
||||||
"Language-Team: zh_Hant <imacat@mail.imacat.idv.tw>\n"
|
"Language-Team: zh_Hant <imacat@mail.imacat.idv.tw>\n"
|
||||||
@ -25,6 +25,7 @@ msgid "en"
|
|||||||
msgstr "zh-Hant"
|
msgstr "zh-Hant"
|
||||||
|
|
||||||
#: tests/test_site/templates/base.html:46
|
#: tests/test_site/templates/base.html:46
|
||||||
|
#: tests/test_site/templates/home.html:24
|
||||||
msgid "Home"
|
msgid "Home"
|
||||||
msgstr "首頁"
|
msgstr "首頁"
|
||||||
|
|
||||||
@ -41,39 +42,19 @@ msgstr "登入"
|
|||||||
msgid "Error:"
|
msgid "Error:"
|
||||||
msgstr "錯誤:"
|
msgstr "錯誤:"
|
||||||
|
|
||||||
#: tests/test_site/templates/home.html:24
|
#: tests/test_site/templates/login.html:30
|
||||||
msgid "Mia! Accounting Live Demonstration"
|
|
||||||
msgstr "Mia! Accounting 示範站"
|
|
||||||
|
|
||||||
#: tests/test_site/templates/home.html:28
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"This is the live demonstration of the Mia! Accounting project. Please <a"
|
|
||||||
" href=\"/login?next=%%2Faccounting\">log in</a> to continue."
|
|
||||||
msgstr "這是 Mia! Accounting 專案的示範站。請先<a href=\"/login?next=%%2Faccounting\">登入</a>。"
|
|
||||||
|
|
||||||
#: tests/test_site/templates/home.html:30
|
|
||||||
msgid ""
|
|
||||||
"You may also want to check the <a href=\"https://mia-"
|
|
||||||
"accounting.readthedocs.io\">full documentation</a> and the <a "
|
|
||||||
"href=\"https://github.com/imacat/mia-accounting\">Github repository</a>."
|
|
||||||
msgstr ""
|
|
||||||
"詳情請參閱<a href=\"https://mia-accounting.readthedocs.io\">完整說明文件</a>與<a "
|
|
||||||
"href=\"https://github.com/imacat/mia-accounting\">Github 專案庫</a>。"
|
|
||||||
|
|
||||||
#: tests/test_site/templates/login.html:33
|
|
||||||
msgid "Viewer"
|
msgid "Viewer"
|
||||||
msgstr "讀報表者"
|
msgstr "讀報表者"
|
||||||
|
|
||||||
#: tests/test_site/templates/login.html:34
|
#: tests/test_site/templates/login.html:31
|
||||||
msgid "Editor"
|
msgid "Editor"
|
||||||
msgstr "記帳者"
|
msgstr "記帳者"
|
||||||
|
|
||||||
#: tests/test_site/templates/login.html:35
|
#: tests/test_site/templates/login.html:32
|
||||||
msgid "Administrator"
|
msgid "Administrator"
|
||||||
msgstr "管理者"
|
msgstr "管理者"
|
||||||
|
|
||||||
#: tests/test_site/templates/login.html:36
|
#: tests/test_site/templates/login.html:33
|
||||||
msgid "Nobody"
|
msgid "Nobody"
|
||||||
msgstr "沒有權限者"
|
msgstr "沒有權限者"
|
||||||
|
|
||||||
|
@ -103,7 +103,6 @@ def get_client(app: Flask, username: str) -> tuple[httpx.Client, str]:
|
|||||||
csrf_token: str = get_csrf_token(client)
|
csrf_token: str = get_csrf_token(client)
|
||||||
response: httpx.Response = client.post("/login",
|
response: httpx.Response = client.post("/login",
|
||||||
data={"csrf_token": csrf_token,
|
data={"csrf_token": csrf_token,
|
||||||
"next": "/",
|
|
||||||
"username": username})
|
"username": username})
|
||||||
assert response.status_code == 302
|
assert response.status_code == 302
|
||||||
assert response.headers["Location"] == "/"
|
assert response.headers["Location"] == "/"
|
||||||
|
Loading…
Reference in New Issue
Block a user