mirror of
https://github.com/ae-utbm/sith.git
synced 2025-04-09 15:36:30 +00:00
refactor eboutic command page
This commit is contained in:
parent
e35c1d1928
commit
d03c425a17
@ -9,7 +9,7 @@ repos:
|
||||
# Run the formatter.
|
||||
- id: ruff-format
|
||||
- repo: https://github.com/biomejs/pre-commit
|
||||
rev: "v0.1.0" # Use the sha / tag you want to point at
|
||||
rev: v0.6.1
|
||||
hooks:
|
||||
- id: biome-check
|
||||
additional_dependencies: ["@biomejs/biome@1.9.4"]
|
||||
|
@ -26,7 +26,7 @@ class EtransactionInfoController(ControllerBase):
|
||||
customer=customer, defaults=info.model_dump(exclude_none=True)
|
||||
)
|
||||
|
||||
@route.get("/data", url_name="etransaction_data", include_in_schema=False)
|
||||
@route.get("/data", url_name="etransaction_data")
|
||||
def fetch_etransaction_data(self):
|
||||
"""Generate the data to pay an eboutic command with paybox.
|
||||
|
||||
|
@ -1,56 +1,61 @@
|
||||
/**
|
||||
* @readonly
|
||||
* @enum {number}
|
||||
*/
|
||||
const BillingInfoReqState = {
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
SUCCESS: 1,
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
FAILURE: 2,
|
||||
// biome-ignore lint/style/useNamingConvention: this feels more like an enum
|
||||
SENDING: 3,
|
||||
};
|
||||
import { exportToHtml } from "#core:utils/globals";
|
||||
import {
|
||||
type BillingInfoSchema,
|
||||
etransactioninfoFetchEtransactionData,
|
||||
etransactioninfoPutUserBillingInfo,
|
||||
} from "#openapi";
|
||||
|
||||
enum BillingInfoReqState {
|
||||
Success = "0",
|
||||
Failure = "1",
|
||||
Sending = "2",
|
||||
}
|
||||
|
||||
exportToHtml("BillingInfoReqState", BillingInfoReqState);
|
||||
|
||||
document.addEventListener("alpine:init", () => {
|
||||
Alpine.store("billing_inputs", {
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: defined in eboutic_makecommand.jinja
|
||||
data: etData,
|
||||
Alpine.data("etransactionData", (initialData) => ({
|
||||
data: initialData,
|
||||
|
||||
async fill() {
|
||||
const button = document.getElementById("bank-submit-button") as HTMLButtonElement;
|
||||
button.disabled = true;
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: defined in eboutic_makecommand.jinja
|
||||
const res = await fetch(etDataUrl);
|
||||
if (res.ok) {
|
||||
this.data = await res.json();
|
||||
const res = await etransactioninfoFetchEtransactionData();
|
||||
if (res.response.ok) {
|
||||
this.data = res.data;
|
||||
button.disabled = false;
|
||||
}
|
||||
},
|
||||
});
|
||||
}));
|
||||
|
||||
Alpine.data("billing_infos", () => ({
|
||||
Alpine.data("billing_infos", (userId: number) => ({
|
||||
/** @type {BillingInfoReqState | null} */
|
||||
reqState: null,
|
||||
|
||||
async sendForm() {
|
||||
this.reqState = BillingInfoReqState.SENDING;
|
||||
this.reqState = BillingInfoReqState.Sending;
|
||||
const form = document.getElementById("billing_info_form");
|
||||
document.getElementById("bank-submit-button").disabled = true;
|
||||
const submitButton = document.getElementById(
|
||||
"bank-submit-button",
|
||||
) as HTMLButtonElement;
|
||||
submitButton.disabled = true;
|
||||
const payload = Object.fromEntries(
|
||||
Array.from(form.querySelectorAll("input, select"))
|
||||
.filter((elem) => elem.type !== "submit" && elem.value)
|
||||
.map((elem) => [elem.name, elem.value]),
|
||||
.filter((elem: HTMLInputElement) => elem.type !== "submit" && elem.value)
|
||||
.map((elem: HTMLInputElement) => [elem.name, elem.value]),
|
||||
);
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: defined in eboutic_makecommand.jinja
|
||||
const res = await fetch(billingInfoUrl, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify(payload),
|
||||
const res = await etransactioninfoPutUserBillingInfo({
|
||||
// biome-ignore lint/style/useNamingConvention: API is snake_case
|
||||
path: { user_id: userId },
|
||||
body: payload as unknown as BillingInfoSchema,
|
||||
});
|
||||
this.reqState = res.ok
|
||||
? BillingInfoReqState.SUCCESS
|
||||
: BillingInfoReqState.FAILURE;
|
||||
if (res.status === 422) {
|
||||
const errors = (await res.json()).detail.flatMap((err) => err.loc);
|
||||
this.reqState = res.response.ok
|
||||
? BillingInfoReqState.Success
|
||||
: BillingInfoReqState.Failure;
|
||||
if (res.response.status === 422) {
|
||||
const errors = await res.response
|
||||
.json()
|
||||
.detail.flatMap((err: Record<"loc", string>) => err.loc);
|
||||
for (const elem of Array.from(form.querySelectorAll("input")).filter((elem) =>
|
||||
errors.includes(elem.name),
|
||||
)) {
|
||||
@ -58,29 +63,27 @@ document.addEventListener("alpine:init", () => {
|
||||
elem.reportValidity();
|
||||
elem.oninput = () => elem.setCustomValidity("");
|
||||
}
|
||||
} else if (res.ok) {
|
||||
Alpine.store("billing_inputs").fill();
|
||||
} else if (res.response.ok) {
|
||||
this.$dispatch("billing-infos-filled");
|
||||
}
|
||||
},
|
||||
|
||||
getAlertColor() {
|
||||
if (this.reqState === BillingInfoReqState.SUCCESS) {
|
||||
if (this.reqState === BillingInfoReqState.Success) {
|
||||
return "green";
|
||||
}
|
||||
if (this.reqState === BillingInfoReqState.FAILURE) {
|
||||
if (this.reqState === BillingInfoReqState.Failure) {
|
||||
return "red";
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
||||
getAlertMessage() {
|
||||
if (this.reqState === BillingInfoReqState.SUCCESS) {
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: defined in eboutic_makecommand.jinja
|
||||
return billingInfoSuccessMessage;
|
||||
if (this.reqState === BillingInfoReqState.Success) {
|
||||
return gettext("Billing info registration success");
|
||||
}
|
||||
if (this.reqState === BillingInfoReqState.FAILURE) {
|
||||
// biome-ignore lint/correctness/noUndeclaredVariables: defined in eboutic_makecommand.jinja
|
||||
return billingInfoFailureMessage;
|
||||
if (this.reqState === BillingInfoReqState.Failure) {
|
||||
return gettext("Billing info registration failure");
|
||||
}
|
||||
return "";
|
||||
},
|
||||
|
@ -158,4 +158,3 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block additional_js %}
|
||||
<script src="{{ static('bundled/eboutic/makecommand-index.ts') }}" defer></script>
|
||||
<script type="module" src="{{ static('bundled/eboutic/makecommand-index.ts') }}"></script>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -56,7 +56,7 @@
|
||||
<div
|
||||
class="collapse"
|
||||
:class="{'shadow': collapsed}"
|
||||
x-data="{collapsed: !billingInfoExist}"
|
||||
x-data="{collapsed: !{{ "true" if billing_infos else "false" }}}"
|
||||
x-cloak
|
||||
>
|
||||
<div class="collapse-header clickable" @click="collapsed = !collapsed">
|
||||
@ -70,7 +70,7 @@
|
||||
<form
|
||||
class="collapse-body"
|
||||
id="billing_info_form"
|
||||
x-data="billing_infos"
|
||||
x-data="billing_infos({{ user.id }})"
|
||||
x-show="collapsed"
|
||||
x-transition.scale.origin.top
|
||||
@submit.prevent="await sendForm()"
|
||||
@ -79,7 +79,7 @@
|
||||
{{ billing_form }}
|
||||
<br />
|
||||
<div
|
||||
x-show="[BillingInfoReqState.SUCCESS, BillingInfoReqState.FAILURE].includes(reqState)"
|
||||
x-show="[BillingInfoReqState.Success, BillingInfoReqState.Failure].includes(reqState)"
|
||||
class="alert"
|
||||
:class="'alert-' + getAlertColor()"
|
||||
x-transition
|
||||
@ -92,19 +92,20 @@
|
||||
<input
|
||||
type="submit" class="btn btn-blue clickable"
|
||||
value="{% trans %}Validate{% endtrans %}"
|
||||
:disabled="reqState === BillingInfoReqState.SENDING"
|
||||
:disabled="reqState === BillingInfoReqState.Sending"
|
||||
>
|
||||
</form>
|
||||
</div>
|
||||
<br>
|
||||
{% if billing_infos_state == BillingInfoState.EMPTY %}
|
||||
<div class="alert alert-yellow">
|
||||
{% trans %}You must fill your billing infos if you want to pay with your credit
|
||||
card{% endtrans %}
|
||||
{% trans trimmed %}
|
||||
You must fill your billing infos if you want to pay with your credit card
|
||||
{% endtrans %}
|
||||
</div>
|
||||
{% elif billing_infos_state == BillingInfoState.MISSING_PHONE_NUMBER %}
|
||||
<div class="alert alert-yellow">
|
||||
{% trans %}
|
||||
{% trans trimmed %}
|
||||
The Crédit Agricole changed its policy related to the billing
|
||||
information that must be provided in order to pay with a credit card.
|
||||
If you want to pay with your credit card, you must add a phone number
|
||||
@ -112,8 +113,14 @@
|
||||
{% endtrans %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<form method="post" action="{{ settings.SITH_EBOUTIC_ET_URL }}" name="bank-pay-form">
|
||||
<template x-data x-for="[key, value] in Object.entries($store.billing_inputs.data)">
|
||||
<form
|
||||
method="post"
|
||||
action="{{ settings.SITH_EBOUTIC_ET_URL }}"
|
||||
name="bank-pay-form"
|
||||
x-data="etransactionData(initialEtData)"
|
||||
@billing-infos-filled.window="await fill()"
|
||||
>
|
||||
<template x-for="[key, value] in Object.entries(data)" :key="key">
|
||||
<input type="hidden" :name="key" :value="value">
|
||||
</template>
|
||||
<input
|
||||
@ -140,17 +147,11 @@
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
const billingInfoUrl = '{{ url("api:put_billing_info", user_id=request.user.id) }}';
|
||||
const etDataUrl = '{{ url("api:etransaction_data") }}';
|
||||
const billingInfoExist = {{ "true" if billing_infos else "false" }};
|
||||
const billingInfoSuccessMessage = "{% trans %}Billing info registration success{% endtrans %}";
|
||||
const billingInfoFailureMessage = "{% trans %}Billing info registration failure{% endtrans %}";
|
||||
|
||||
{% if billing_infos %}
|
||||
const etData = {{ billing_infos|safe }}
|
||||
{% else %}
|
||||
const etData = {}
|
||||
{% endif %}
|
||||
{% if billing_infos -%}
|
||||
const initialEtData = {{ billing_infos|safe }}
|
||||
{%- else -%}
|
||||
const initialEtData = {}
|
||||
{%- endif %}
|
||||
</script>
|
||||
{{ super() }}
|
||||
{% endblock %}
|
||||
|
@ -26,7 +26,9 @@ from cryptography.hazmat.primitives.hashes import SHA1
|
||||
from cryptography.hazmat.primitives.serialization import load_pem_public_key
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.auth.mixins import (
|
||||
LoginRequiredMixin,
|
||||
)
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
from django.db import DatabaseError, transaction
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
|
@ -6,7 +6,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-04-06 16:58+0200\n"
|
||||
"POT-Creation-Date: 2025-04-06 15:54+0200\n"
|
||||
"PO-Revision-Date: 2016-07-18\n"
|
||||
"Last-Translator: Maréchal <thomas.girod@utbm.fr\n"
|
||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||
@ -3831,25 +3831,18 @@ msgstr "Informations de facturation"
|
||||
|
||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja
|
||||
msgid ""
|
||||
"You must fill your billing infos if you want to pay with your credit\n"
|
||||
" card"
|
||||
"You must fill your billing infos if you want to pay with your credit card"
|
||||
msgstr ""
|
||||
"Vous devez renseigner vos coordonnées de facturation si vous voulez payer "
|
||||
"par carte bancaire"
|
||||
|
||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja
|
||||
msgid ""
|
||||
"\n"
|
||||
" The Crédit Agricole changed its policy related to the "
|
||||
"billing\n"
|
||||
" information that must be provided in order to pay with a "
|
||||
"credit card.\n"
|
||||
" If you want to pay with your credit card, you must add a "
|
||||
"phone number\n"
|
||||
" to the data you already provided.\n"
|
||||
" "
|
||||
"The Crédit Agricole changed its policy related to the billing information "
|
||||
"that must be provided in order to pay with a credit card. If you want to pay "
|
||||
"with your credit card, you must add a phone number to the data you already "
|
||||
"provided."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Le Crédit Agricole a changé sa politique relative aux informations à "
|
||||
"fournir pour effectuer un paiement par carte bancaire. De ce fait, si vous "
|
||||
"souhaitez payer par carte, vous devez rajouter un numéro de téléphone aux "
|
||||
@ -3876,14 +3869,6 @@ msgstr ""
|
||||
msgid "Pay with Sith account"
|
||||
msgstr "Payer avec un compte AE"
|
||||
|
||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja
|
||||
msgid "Billing info registration success"
|
||||
msgstr "Informations de facturation enregistrées"
|
||||
|
||||
#: eboutic/templates/eboutic/eboutic_makecommand.jinja
|
||||
msgid "Billing info registration failure"
|
||||
msgstr "Echec de l'enregistrement des informations de facturation."
|
||||
|
||||
#: eboutic/templates/eboutic/eboutic_payment_result.jinja
|
||||
msgid "Payment successful"
|
||||
msgstr "Le paiement a été effectué"
|
||||
|
@ -7,7 +7,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-03-28 13:52+0100\n"
|
||||
"POT-Creation-Date: 2025-04-06 15:47+0200\n"
|
||||
"PO-Revision-Date: 2024-09-17 11:54+0200\n"
|
||||
"Last-Translator: Sli <antoine@bartuccio.fr>\n"
|
||||
"Language-Team: AE info <ae.info@utbm.fr>\n"
|
||||
@ -201,10 +201,18 @@ msgstr "Types de produits réordonnés !"
|
||||
msgid "Product type reorganisation failed with status code : %d"
|
||||
msgstr "La réorganisation des types de produit a échoué avec le code : %d"
|
||||
|
||||
#: eboutic/static/eboutic/js/makecommand.js
|
||||
#: eboutic/static/bundled/eboutic/makecommand-index.ts
|
||||
msgid "Incorrect value"
|
||||
msgstr "Valeur incorrecte"
|
||||
|
||||
#: eboutic/static/bundled/eboutic/makecommand-index.ts
|
||||
msgid "Billing info registration success"
|
||||
msgstr "Informations de facturation enregistrées"
|
||||
|
||||
#: eboutic/static/bundled/eboutic/makecommand-index.ts
|
||||
msgid "Billing info registration failure"
|
||||
msgstr "Echec de l'enregistrement des informations de facturation."
|
||||
|
||||
#: sas/static/bundled/sas/pictures-download-index.ts
|
||||
msgid "pictures.%(extension)s"
|
||||
msgstr "photos.%(extension)s"
|
||||
|
Loading…
x
Reference in New Issue
Block a user