Added the account management.

This commit is contained in:
2023-02-01 15:37:56 +08:00
parent 14638f574e
commit e9f6b769f4
24 changed files with 1549 additions and 5 deletions

View File

@ -0,0 +1,28 @@
{#
The Mia! Accounting Flask Project
create.html: The account creation form
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.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/1
#}
{% extends "accounting/account/include/form.html" %}
{% block header %}{% block title %}{{ A_("Add a New Account") }}{% endblock %}{% endblock %}
{% block back_url %}{{ request.args.get("next") or url_for("accounting.account.list") }}{% endblock %}
{% block action_url %}{{ url_for("accounting.account.store") }}{% endblock %}

View File

@ -0,0 +1,85 @@
{#
The Mia! Accounting Flask Project
detail.html: The account detail
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.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/1/31
#}
{% extends "accounting/base.html" %}
{% block header %}{% block title %}{{ obj }}{% endblock %}{% endblock %}
{% block content %}
<div class="btn-group mb-3">
<a class="btn btn-primary" href="{{ request.args.get("next") or url_for("accounting.account.list") }}">
<i class="fa-solid fa-circle-chevron-left"></i>
{{ A_("Back") }}
</a>
{% if can_edit_accounting() %}
<a class="btn btn-primary d-none d-md-inline" href="{{ url_for("accounting.account.edit", account=obj) + ("?next=" + request.args["next"] if "next" in request.args else "") }}">
<i class="fa-solid fa-gear"></i>
{{ A_("Settings") }}
</a>
<button class="btn btn-danger" type="button" data-bs-toggle="modal" data-bs-target="#delete-modal">
<i class="fa-solid fa-trash"></i>
{{ A_("Delete") }}
</button>
{% endif %}
</div>
{% if can_edit_accounting() %}
<div class="d-md-none material-fab">
<a class="btn btn-primary" href="{{ url_for("accounting.account.edit", account=obj) + ("?next=" + request.args["next"] if "next" in request.args else "") }}">
<i class="fa-solid fa-pen-to-square"></i>
</a>
</div>
{% endif %}
{% if can_edit_accounting() %}
<form id="delete-form" action="{{ url_for("accounting.account.delete", account=obj) }}" method="post">
<input id="csrf_token" type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<div class="modal fade" id="delete-modal" tabindex="-1" aria-labelledby="delete-model-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="delete-model-label">{{ A_("Delete Account Confirmation") }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
{{ A_("Do you really want to delete this account?") }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ A_("Cancel") }}</button>
<button type="submit" class="btn btn-danger">{{ A_("Confirm") }}</button>
</div>
</div>
</div>
</div>
</form>
{% endif %}
<div class="account col-sm-6">
<div class="account-title">{{ obj.title }}</div>
<div class="account-code">{{ obj.code }}</div>
<div class="small text-secondary fst-italic">
<div>{{ A_("Created") }} {{ obj.created_at }} {{ obj.created_by }}</div>
<div>{{ A_("Updated") }} {{ obj.updated_at }} {{ obj.updated_by }}</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,28 @@
{#
The Mia! Accounting Flask Project
edit.html: The account edit form
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.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/1
#}
{% extends "accounting/account/include/form.html" %}
{% block header %}{% block title %}{{ A_("%(account)s Settings", account=account) }}{% endblock %}{% endblock %}
{% block back_url %}{{ url_for("accounting.account.detail", account=account) + ("?next=" + request.args["next"] if "next" in request.args else "") }}{% endblock %}
{% block action_url %}{{ url_for("accounting.account.update", account=account) }}{% endblock %}

View File

@ -0,0 +1,115 @@
{#
The Mia! Accounting Flask Project
form.html: The account form
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.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/2/1
#}
{% extends "accounting/base.html" %}
{% block accounting_scripts %}
<script src="{{ url_for("accounting.static", filename="js/account-form.js") }}"></script>
{% endblock %}
{% block content %}
<div class="btn-group btn-actions mb-3">
<a class="btn btn-primary" role="button" href="{% block back_url %}{% endblock %}">
<i class="fa-solid fa-circle-chevron-left"></i>
{{ A_("Back") }}
</a>
</div>
<form id="account-form" action="{% block action_url %}{% endblock %}" method="post">
{{ form.csrf_token }}
{% if "next" in request.args %}
<input type="hidden" name="next" value="{{ request.args["next"] }}">
{% endif %}
<div class="form-floating mb-3">
<input id="account-base-code" type="hidden" name="base_code" value="{{ "" if form.base_code.data is none else form.base_code.data }}">
<div id="account-base" class="form-control clickable material-text-field {% if form.base_code.data %} not-empty {% endif %} {% if form.base_code.errors %} is-invalid {% endif %}" data-bs-toggle="modal" data-bs-target="#select-base-modal">
<label id="account-base-label" class="form-label" for="account-base">{{ A_("Base account") }}</label>
<div id="account-base-content">
{% if form.base_code.data %}
{% if form.base_code.errors %}
{{ A_("(Unknown)") }}
{% else %}
{{ form.selected_base }}
{% endif %}
{% endif %}
</div>
</div>
<div id="account-base-code-error" class="invalid-feedback">{% if form.base_code.errors %}{{ form.base_code.errors[0] }}{% endif %}</div>
</div>
<div class="form-floating mb-3">
<input id="account-title" class="form-control {% if form.title.errors %} is-invalid {% endif %}" type="text" name="title" value="{{ "" if form.title.data is none else form.title.data }}" placeholder=" " required="required">
<label class="form-label" for="account-title">{{ A_("Title") }}</label>
<div id="account-title-error" class="invalid-feedback">{% if form.title.errors %}{{ form.title.errors[0] }}{% endif %}</div>
</div>
<div class="d-none d-md-block">
<button class="btn btn-primary" type="submit">
<i class="fa-solid fa-floppy-disk"></i>
{{ A_("Save") }}
</button>
</div>
<div class="d-md-none material-fab">
<button class="btn btn-primary" type="submit">
<i class="fa-solid fa-floppy-disk"></i>
</button>
</div>
</form>
<div class="modal fade" id="select-base-modal" tabindex="-1" aria-labelledby="select-base-model-label" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="base-selector-model-label">{{ A_("Select Base Account") }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="input-group mb-2">
<input id="select-base-query" class="form-control form-control-sm" type="search" placeholder=" " required="required" aria-label="Search">
<label class="input-group-text" for="select-base-query">
<i class="fa-solid fa-magnifying-glass"></i>
{{ A_("Search") }}
</label>
</div>
<ul class="list-group list-base-selector">
{% for base in form.base_options %}
<li id="list-group-item-base-{{ base.code }}" class="list-group-item list-group-item-base clickable" data-code="{{ base.code }}" data-content="{{ base }}">
{{ base }}
</li>
{% endfor %}
</ul>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ A_("Cancel") }}</button>
{% if form.base_code.data %}
<button id="btn-clear-base" type="button" class="btn btn-danger">{{ A_("Clear") }}</button>
{% else %}
<button id="btn-clear-base" type="button" class="btn btn-secondary" disabled="disabled">{{ A_("Clear") }}</button>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,73 @@
{#
The Mia! Accounting Flask Project
list.html: The account list
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.
Author: imacat@mail.imacat.idv.tw (imacat)
First written: 2023/1/30
#}
{% extends "accounting/base.html" %}
{% block header %}{% block title %}{{ A_("Accounts") }}{% endblock %}{% endblock %}
{% block content %}
{% if can_edit_accounting() %}
<div class="btn-group mb-3 d-none d-md-block">
<a class="btn btn-primary" href="{{ url_for("accounting.account.create") }}">
<i class="fa-solid fa-user-plus"></i>
{{ A_("New") }}
</a>
</div>
<div class="d-md-none material-fab">
<a class="btn btn-primary" href="{{ url_for("accounting.account.create") }}">
<i class="fa-solid fa-plus"></i>
</a>
</div>
{% endif %}
<form action="{{ url_for("accounting.account.list") }}" method="get" role="search">
<div class="row">
<div class="col-sm-3">
<div class="input-group mb-2">
<input id="query" class="form-control form-control-sm" type="search" name="q" value="{{ request.args["q"] if "q" in request.args else "" }}" placeholder=" " required="required" aria-label="Search">
<button class="input-group-text" type="submit">
<label for="query">
<i class="fa-solid fa-magnifying-glass"></i>
{{ A_("Search") }}
</label>
</button>
</div>
</div>
</div>
</form>
{% if list %}
{% include "accounting/include/pagination.html" %}
<div class="list-group">
{% for item in list %}
<a class="list-group-item list-group-item-action" href="{{ url_for("accounting.account.detail", account=item) }}">
{{ item }}
</a>
{% endfor %}
</div>
{% else %}
<p>{{ A_("There is no data.") }}</p>
{% endif %}
{% endblock %}

View File

@ -21,6 +21,10 @@ First written: 2023/1/27
#}
{% extends "base.html" %}
{% block styles %}
<link rel="stylesheet" type="text/css" href="{{ url_for("accounting.static", filename="css/style.css") }}">
{% endblock %}
{% block scripts %}
<script src="{{ url_for("accounting.babel_catalog") }}"></script>
{% block accounting_scripts %}{% endblock %}

View File

@ -26,6 +26,12 @@ First written: 2023/1/26
{{ A_("Accounting") }}
</span>
<ul class="dropdown-menu">
<li>
<a class="dropdown-item {% if request.endpoint.startswith("accounting.account.") %} active {% endif %}" href="{{ url_for("accounting.account.list") }}">
<i class="fa-solid fa-list"></i>
{{ A_("Accounts") }}
</a>
</li>
<li>
<a class="dropdown-item {% if request.endpoint.startswith("accounting.base-account.") %} active {% endif %}" href="{{ url_for("accounting.base-account.list") }}">
<i class="fa-solid fa-list"></i>