Compare commits
6 Commits
404b902d88
...
e62316c477
Author | SHA1 | Date | |
---|---|---|---|
e62316c477 | |||
24ddb0c278 | |||
536f3390aa | |||
fadd8e73b6 | |||
12ccf658bf | |||
e30d1257e5 |
32
README.rst
32
README.rst
@ -7,7 +7,8 @@ Description
|
||||
===========
|
||||
|
||||
*Mia! Accounting* is an accounting module for Flask_ applications.
|
||||
It implements `double-entry bookkeeping`_, and generates the following
|
||||
It is designed both for mobile and desktop environments. It
|
||||
implements `double-entry bookkeeping`_. It generates the following
|
||||
accounting reports:
|
||||
|
||||
* Trial balance
|
||||
@ -18,6 +19,18 @@ In addition, *Mia! Accounting* tracks offsets for unpaid payables and
|
||||
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
|
||||
============
|
||||
|
||||
@ -27,22 +40,10 @@ Install *Mia! Accounting* with ``pip``:
|
||||
|
||||
pip install mia-accounting
|
||||
|
||||
You may also download the from the `PyPI project page`_ or the
|
||||
You may also download from the `PyPI project page`_ or the
|
||||
`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
|
||||
=============
|
||||
|
||||
@ -191,9 +192,9 @@ Authors
|
||||
|
||||
.. _Flask: https://flask.palletsprojects.com
|
||||
.. _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
|
||||
.. _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
|
||||
.. _release page: https://github.com/imacat/mia-accounting/releases
|
||||
.. _Git repository: https://github.com/imacat/mia-accounting
|
||||
@ -204,6 +205,5 @@ Authors
|
||||
.. _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/
|
||||
.. _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 = '1.3.0'
|
||||
release = '1.3.1'
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
|
||||
|
@ -2,7 +2,8 @@ Introduction
|
||||
============
|
||||
|
||||
*Mia! Accounting* is an accounting module for Flask_ applications.
|
||||
It implements `double-entry bookkeeping`_, and generates the following
|
||||
It is designed both for mobile and desktop environments. It
|
||||
implements `double-entry bookkeeping`_. It generates the following
|
||||
accounting reports:
|
||||
|
||||
* Trial balance
|
||||
@ -13,6 +14,18 @@ In addition, *Mia! Accounting* tracks offsets for unpaid payables and
|
||||
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
|
||||
------------
|
||||
|
||||
@ -22,22 +35,10 @@ Install *Mia! Accounting* with ``pip``:
|
||||
|
||||
pip install mia-accounting
|
||||
|
||||
You may also download the from the `PyPI project page`_ or the
|
||||
You may also download from the `PyPI project page`_ or the
|
||||
`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
|
||||
-------------
|
||||
|
||||
@ -110,9 +111,9 @@ 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
|
||||
.. _test site: https://github.com/imacat/mia-accounting/tree/main/tests/test_site
|
||||
.. _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
|
||||
.. _release page: https://github.com/imacat/mia-accounting/releases
|
||||
.. _Git repository: https://github.com/imacat/mia-accounting
|
||||
@ -121,6 +122,5 @@ Refer to the `documentation on Read the Docs`_.
|
||||
.. _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/
|
||||
.. _documentation on Read the Docs: https://mia-accounting.readthedocs.io
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
[project]
|
||||
name = "mia-accounting"
|
||||
version = "1.3.0"
|
||||
version = "1.3.1"
|
||||
description = "A Flask accounting module."
|
||||
readme = "README.rst"
|
||||
requires-python = ">=3.11"
|
||||
|
@ -51,12 +51,14 @@ First written: 2023/1/26
|
||||
{{ A_("Currencies") }}
|
||||
</a>
|
||||
</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") }}">
|
||||
<i class="fa-solid fa-link-slash"></i>
|
||||
{{ A_("Unmatched Offsets") }}
|
||||
</a>
|
||||
</li>
|
||||
{% if accounting_can_edit() %}
|
||||
<li>
|
||||
<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>
|
||||
{{ A_("Unmatched Offsets") }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if accounting_can_admin() %}
|
||||
<li>
|
||||
<a class="dropdown-item {% if request.endpoint and request.endpoint.startswith("accounting.option.") %} active {% endif %}" href="{{ url_for("accounting.option.detail") }}">
|
||||
|
@ -22,7 +22,8 @@ import typing as t
|
||||
from secrets import token_urlsafe
|
||||
|
||||
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_babel_js import BabelJS
|
||||
from flask_sqlalchemy import SQLAlchemy
|
||||
@ -86,7 +87,8 @@ def create_app(is_testing: bool = False) -> Flask:
|
||||
and auth.current_user().username == "admin"
|
||||
|
||||
def unauthorized(self) -> Response:
|
||||
return redirect("/login")
|
||||
from accounting.utils.next_uri import append_next
|
||||
return redirect(append_next(url_for("auth.login-form")))
|
||||
|
||||
@property
|
||||
def cls(self) -> t.Type[auth.User]:
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
"""
|
||||
from flask import Blueprint, render_template, Flask, redirect, url_for, \
|
||||
session, request, g
|
||||
session, request, g, Response
|
||||
|
||||
from . import db
|
||||
|
||||
@ -44,11 +44,13 @@ class User(db.Model):
|
||||
|
||||
|
||||
@bp.get("login", endpoint="login-form")
|
||||
def show_login_form() -> str:
|
||||
def show_login_form() -> str | Response:
|
||||
"""Shows the login form.
|
||||
|
||||
:return: The login form.
|
||||
"""
|
||||
if "user" in session:
|
||||
return redirect(url_for("accounting-report.default"))
|
||||
return render_template("login.html")
|
||||
|
||||
|
||||
@ -58,11 +60,12 @@ def login() -> redirect:
|
||||
|
||||
: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",
|
||||
"nobody"}:
|
||||
return redirect(url_for("auth.login"))
|
||||
return redirect(inherit_next(url_for("auth.login")))
|
||||
session["user"] = request.form.get("username")
|
||||
return redirect(url_for("home.home"))
|
||||
return redirect(or_next(url_for("accounting-report.default")))
|
||||
|
||||
|
||||
@bp.post("logout", endpoint="logout")
|
||||
|
@ -21,4 +21,12 @@ First written: 2023/1/27
|
||||
#}
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block header %}{% block title %}{{ _("Home") }}{% endblock %}{% endblock %}
|
||||
{% block header %}{% block title %}{{ _("Mia! Accounting Live Demonstration") }}{% 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,6 +27,9 @@ First written: 2023/1/27
|
||||
|
||||
<form action="{{ url_for("auth.login") }}" method="post">
|
||||
<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="editor">{{ _("Editor") }}</button>
|
||||
<button class="btn btn-primary" type="submit" name="username" value="admin">{{ _("Administrator") }}</button>
|
||||
|
@ -9,8 +9,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"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-04-06 02:34+0800\n"
|
||||
"PO-Revision-Date: 2023-04-06 02:34+0800\n"
|
||||
"POT-Creation-Date: 2023-04-11 22:18+0800\n"
|
||||
"PO-Revision-Date: 2023-04-11 22:18+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"
|
||||
@ -25,7 +25,6 @@ msgid "en"
|
||||
msgstr "zh-Hant"
|
||||
|
||||
#: tests/test_site/templates/base.html:46
|
||||
#: tests/test_site/templates/home.html:24
|
||||
msgid "Home"
|
||||
msgstr "首頁"
|
||||
|
||||
@ -42,19 +41,39 @@ msgstr "登入"
|
||||
msgid "Error:"
|
||||
msgstr "錯誤:"
|
||||
|
||||
#: tests/test_site/templates/login.html:30
|
||||
#: tests/test_site/templates/home.html:24
|
||||
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"
|
||||
msgstr "讀報表者"
|
||||
|
||||
#: tests/test_site/templates/login.html:31
|
||||
#: tests/test_site/templates/login.html:34
|
||||
msgid "Editor"
|
||||
msgstr "記帳者"
|
||||
|
||||
#: tests/test_site/templates/login.html:32
|
||||
#: tests/test_site/templates/login.html:35
|
||||
msgid "Administrator"
|
||||
msgstr "管理者"
|
||||
|
||||
#: tests/test_site/templates/login.html:33
|
||||
#: tests/test_site/templates/login.html:36
|
||||
msgid "Nobody"
|
||||
msgstr "沒有權限者"
|
||||
|
||||
|
@ -103,6 +103,7 @@ def get_client(app: Flask, username: str) -> tuple[httpx.Client, str]:
|
||||
csrf_token: str = get_csrf_token(client)
|
||||
response: httpx.Response = client.post("/login",
|
||||
data={"csrf_token": csrf_token,
|
||||
"next": "/",
|
||||
"username": username})
|
||||
assert response.status_code == 302
|
||||
assert response.headers["Location"] == "/"
|
||||
|
Loading…
Reference in New Issue
Block a user