diff --git a/includes/i18n/de.php b/includes/i18n/de.php index d0f7e7150..7322836bb 100644 --- a/includes/i18n/de.php +++ b/includes/i18n/de.php @@ -78,6 +78,7 @@ 'split_views' => "Aufgeteilte Ansichten", 'category_split' => "Kategorien", 'household_split' => "Haushalt", + 'payment_method_split' => "Zahlungsmethode", // About page 'about_and_credits' => "Informationen und Danksagungen", 'license' => "Lizenz", diff --git a/includes/i18n/el.php b/includes/i18n/el.php index a956ca31c..f87082b3f 100644 --- a/includes/i18n/el.php +++ b/includes/i18n/el.php @@ -78,6 +78,7 @@ 'split_views' => "Διαχωρισμένες προβολές", 'category_split' => "Διαχωρισμός κατηγορίας", 'household_split' => "Διαχωρισμός νοικοκυριού", + 'payment_method_split' => "Διαχωρισμός τρόπου πληρωμής", // About page 'about_and_credits' => "Σχετικά και Credits", 'license' => "License", diff --git a/includes/i18n/en.php b/includes/i18n/en.php index 29deea186..5371fe149 100644 --- a/includes/i18n/en.php +++ b/includes/i18n/en.php @@ -44,7 +44,7 @@ "weeks" => "weeks", "months" => "months", "years" => "years", - "external_url" => "Visit Externarl URL", + "external_url" => "Visit External URL", "empty_page" => "Empty Page", // Subscription form "add_subscription" => "Add subscription", @@ -78,6 +78,7 @@ 'split_views' => "Split Views", 'category_split' => "Category Split", 'household_split' => "Household Split", + 'payment_method_split' => "Payment Method Split", // About page 'about_and_credits' => "About and Credits", 'license' => "License", diff --git a/includes/i18n/es.php b/includes/i18n/es.php index aa889d447..81630fc3e 100644 --- a/includes/i18n/es.php +++ b/includes/i18n/es.php @@ -78,6 +78,7 @@ 'split_views' => "Vistas Divididas", 'category_split' => "División por Categoría", 'household_split' => "División por Hogar", + 'payment_method_split' => "División por Método de Pago", // About page 'about_and_credits' => "Acerca de y Créditos", 'license' => "Licencia", diff --git a/includes/i18n/fr.php b/includes/i18n/fr.php index efe84aad2..c237a0719 100644 --- a/includes/i18n/fr.php +++ b/includes/i18n/fr.php @@ -78,6 +78,7 @@ 'split_views' => "Vues partagées", 'category_split' => "Répartition par catégorie", 'household_split' => "Répartition du ménage", + 'payment_method_split' => "Répartition par méthode de paiement", // Page À propos 'about_and_credits' => "À propos et crédits", 'license' => "Licence", diff --git a/includes/i18n/jp.php b/includes/i18n/jp.php index 3e6870529..da1ac483e 100644 --- a/includes/i18n/jp.php +++ b/includes/i18n/jp.php @@ -78,6 +78,7 @@ 'split_views' => "分割表示", 'category_split' => "カテゴリ別", 'household_split' => "世帯別", + 'payment_method_split' => "支払い方法別", // About page 'about_and_credits' => "概要とクレジット", 'license' => "License", diff --git a/includes/i18n/pt.php b/includes/i18n/pt.php index c34b3e02d..7297c8b33 100644 --- a/includes/i18n/pt.php +++ b/includes/i18n/pt.php @@ -78,6 +78,7 @@ 'split_views' => "Vistas Divididas", 'category_split' => "Por Categoria", 'household_split' => "Por Membro", + 'payment_method_split' => "Por Método de Pagamento", // About page 'about_and_credits' => "Sobre e Créditos", 'license' => "Licença", diff --git a/includes/i18n/tr.php b/includes/i18n/tr.php index 018ad1dfc..1053b7622 100644 --- a/includes/i18n/tr.php +++ b/includes/i18n/tr.php @@ -78,6 +78,7 @@ 'split_views' => "Bölünmüş Görünümler", 'category_split' => "Kategori Bölümü", 'household_split' => "Hane Bölümü", + 'payment_method_split' => "Ödeme Yöntemi Bölümü", // About page 'about_and_credits' => "Hakkında ve Teşekkürler", 'license' => "Lisans", diff --git a/includes/i18n/zh_cn.php b/includes/i18n/zh_cn.php index 611a3f3ca..ade6f2a82 100644 --- a/includes/i18n/zh_cn.php +++ b/includes/i18n/zh_cn.php @@ -83,6 +83,7 @@ 'split_views' => "拆分视图", 'category_split' => "分类视图", 'household_split' => "家庭视图", + 'payment_method_split' => "支付方式视图", // 关于页面 'about_and_credits' => "关于和鸣谢", diff --git a/includes/i18n/zh_tw.php b/includes/i18n/zh_tw.php index 3c2b79be3..c17d08086 100644 --- a/includes/i18n/zh_tw.php +++ b/includes/i18n/zh_tw.php @@ -83,6 +83,7 @@ 'split_views' => "分割表示", 'category_split' => "類別表示", 'household_split' => "家庭表示", + 'payment_method_split' => "付款方式表示", // 關於頁面 'about_and_credits' => "關於和致謝", diff --git a/scripts/dashboard.js b/scripts/dashboard.js index d56626f72..cf08b083f 100644 --- a/scripts/dashboard.js +++ b/scripts/dashboard.js @@ -145,7 +145,7 @@ function handleFileSelect(event) { } function deleteSubscription(id) { - if (confirm("Are you sure you want to delete this subscription?")) { + if (confirm(translate('confirm_delete_subscription'))) { fetch(`endpoints/subscription/delete.php?id=${id}`, { method: 'DELETE', }) diff --git a/scripts/i18n/de.js b/scripts/i18n/de.js index c696605d7..e9616f715 100644 --- a/scripts/i18n/de.js +++ b/scripts/i18n/de.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Fehler beim Laden des Abonnements", edit_subscription: "Abonnement bearbeiten", add_subscription: "Abonnement hinzufügen", + confirm_delete_subscription: "Sind Sie sicher, dass Sie dieses Abonnement löschen möchten?", // Settings network_response_error: "Netzwerkfehler", failed_add_member: "Hinzufügen von Mitglied fehlgeschlagen", diff --git a/scripts/i18n/el.js b/scripts/i18n/el.js index 1a7461d9b..b6e119652 100644 --- a/scripts/i18n/el.js +++ b/scripts/i18n/el.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Απέτυχε η φόρτωση της συνδρομής", edit_subscription: "Επεξεργασία συνδρομής", add_subscription: "Προσθήκη συνδρομής", + confirm_delete_subscription: "Είστε σίγουρος ότι θέλετε να διαγράψετε αυτή τη συνδρομή;", // Settings network_response_error: "Η ανταπόκριση του δικτύου δεν ήταν εντάξει", failed_add_member: "Αποτυχία προσθήκης μέλους", diff --git a/scripts/i18n/en.js b/scripts/i18n/en.js index aac61c9b3..d84bdfb58 100644 --- a/scripts/i18n/en.js +++ b/scripts/i18n/en.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Failed to load subscription", edit_subscription: "Edit subscription", add_subscription: "Add subscription", + confirm_delete_subscription: "Are you sure you want to delete this subscription?", // Settings network_response_error: "Network response was not ok", failed_add_member: "Failed to add member", diff --git a/scripts/i18n/es.js b/scripts/i18n/es.js index a2eb63926..d1dc3e398 100644 --- a/scripts/i18n/es.js +++ b/scripts/i18n/es.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Error al cargar la suscripción", edit_subscription: "Editar suscripción", add_subscription: "Añadir suscripción", + confirm_delete_subscription: "¿Estás seguro de que quieres eliminar esta suscripción?", // Settings network_response_error: "Error en la respuesta de la red", failed_add_member: "Error al añadir miembro", diff --git a/scripts/i18n/fr.js b/scripts/i18n/fr.js index cadc6ce6c..fb1406c58 100644 --- a/scripts/i18n/fr.js +++ b/scripts/i18n/fr.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Impossible de charger l'abonnement", edit_subscription: "Modifier l'abonnement", add_subscription: "Ajouter un abonnement", + confirm_delete_subscription: "Êtes-vous sûr de vouloir supprimer cet abonnement ?", // Paramètres network_response_error: "La réponse du réseau n'était pas correcte", failed_add_member: "Échec de l'ajout du membre", diff --git a/scripts/i18n/jp.js b/scripts/i18n/jp.js index 47fae7269..bb0d14d07 100644 --- a/scripts/i18n/jp.js +++ b/scripts/i18n/jp.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "定期購入の読み込みに失敗しました", edit_subscription: "定期購入の編集", add_subscription: "定期購入の追加", + confirm_delete_subscription: "この定期購入を削除してもよろしいですか?", // Settings network_response_error: "ネットワークの応答異常", failed_add_member: "世帯員の追加に失敗", diff --git a/scripts/i18n/pt.js b/scripts/i18n/pt.js index 4e4f337a9..ca2ae51cd 100644 --- a/scripts/i18n/pt.js +++ b/scripts/i18n/pt.js @@ -7,6 +7,7 @@ let i18n = { 'failed_to_load_subscription': 'Falha ao carregar a subscrição', 'edit_subscription': 'Editar subscrição', 'add_subscription': 'Adicionar subscrição', + 'confirm_delete_subscription': 'Tem a certeza de que deseja eliminar esta subscrição?', // Settings 'network_response_error': 'Erro de resposta de rede', 'failed_add_member': 'Falha ao adicionar membro', diff --git a/scripts/i18n/tr.js b/scripts/i18n/tr.js index 7fd8042aa..98140c204 100644 --- a/scripts/i18n/tr.js +++ b/scripts/i18n/tr.js @@ -7,6 +7,7 @@ let i18n = { failed_to_load_subscription: "Abonelik yüklenemedi", edit_subscription: "Aboneliği Düzenle", add_subscription: "Abonelik Ekle", + confirm_delete_subscription: "Bu aboneliği silmek istediğinizden emin misiniz?", // Ayarlar network_response_error: "Ağ yanıtı kabul edilmedi", failed_add_member: "Üye eklenemedi", diff --git a/scripts/i18n/zh_cn.js b/scripts/i18n/zh_cn.js index 9658d5c38..b0bdcea51 100644 --- a/scripts/i18n/zh_cn.js +++ b/scripts/i18n/zh_cn.js @@ -7,6 +7,7 @@ let i18n = { 'failed_to_load_subscription': "加载订阅失败", 'edit_subscription': "编辑订阅", 'add_subscription': "添加订阅", + 'confirm_delete_subscription': "您确定要删除此订阅吗?", // Settings 'network_response_error': "网络响应不正常", 'failed_add_member': '添加成员失败', diff --git a/scripts/i18n/zh_tw.js b/scripts/i18n/zh_tw.js index ed8488ed3..aae672427 100644 --- a/scripts/i18n/zh_tw.js +++ b/scripts/i18n/zh_tw.js @@ -7,6 +7,7 @@ let i18n = { 'failed_to_load_subscription': "讀取訂閱失敗", 'edit_subscription': "編輯訂閱", 'add_subscription': "新增訂閱", + 'confirm_delete_subscription': "您確定要刪除此訂閱嗎?", // Settings 'network_response_error': "網路無回應", 'failed_add_member': '新增成員失敗', diff --git a/scripts/stats.js b/scripts/stats.js index 98bbc628f..d67db3097 100644 --- a/scripts/stats.js +++ b/scripts/stats.js @@ -8,7 +8,13 @@ function loadGraph(container, dataPoints, currency, run) { datasets: [{ data: dataPoints.map(point => point.y), }], - labels: dataPoints.map(point => `${point.label} (${new Intl.NumberFormat(navigator.language, { style: 'currency', currency }).format(point.y)})`), + labels: dataPoints.map(point => { + if (currency) { + return `${point.label} (${new Intl.NumberFormat(navigator.language, { style: 'currency', currency }).format(point.y)})`; + } else { + return `${point.label} (${new Intl.NumberFormat(navigator.language).format(point.y)})`; + } + }), }, options: { animation: { diff --git a/stats.php b/stats.php index 7ab1262d3..2c6f67af7 100644 --- a/stats.php +++ b/stats.php @@ -60,6 +60,17 @@ function getPriceConverted($price, $currency, $database) { $categoryCost[$categoryId]['name'] = $row['name']; } +// Get payment methods +$categories = array(); +$query = "SELECT * FROM payment_methods WHERE enabled = 1"; +$result = $db->query($query); +while ($row = $result->fetchArray(SQLITE3_ASSOC)) { + $paymentMethodId = $row['id']; + $paymentMethodCount[$paymentMethodId] = $row; + $paymentMethodCount[$paymentMethodId]['count'] = 0; + $paymentMethodCount[$paymentMethodId]['name'] = $row['name']; +} + // Get code of main currency to display on statistics $query = "SELECT c.code FROM currencies c @@ -84,7 +95,7 @@ function getPriceConverted($price, $currency, $database) { $amountDueThisMonth = 0; $totalCostPerMonth = 0; -$query = "SELECT name, price, frequency, cycle, currency_id, next_payment, payer_user_id, category_id FROM subscriptions"; +$query = "SELECT name, price, frequency, cycle, currency_id, next_payment, payer_user_id, category_id, payment_method_id FROM subscriptions"; $result = $db->query($query); if ($result) { while ($row = $result->fetchArray(SQLITE3_ASSOC)) { @@ -100,11 +111,13 @@ function getPriceConverted($price, $currency, $database) { $next_payment = $subscription['next_payment']; $payerId = $subscription['payer_user_id']; $categoryId = $subscription['category_id']; + $paymentMethodId = $subscription['payment_method_id']; $originalSubscriptionPrice = getPriceConverted($price, $currency, $db); $price = getPricePerMonth($cycle, $frequency, $originalSubscriptionPrice); $totalCostPerMonth += $price; $memberCost[$payerId]['cost'] += $price; $categoryCost[$categoryId]['cost'] += $price; + $paymentMethodCount[$paymentMethodId]['count'] += 1; if ($price > $mostExpensiveSubscription) { $mostExpensiveSubscription = $price; } @@ -207,6 +220,18 @@ function getPriceConverted($price, $currency, $database) { $showMemberCostGraph = count($memberDataPoints) > 1; + $paymentMethodDataPoints = []; + foreach ($paymentMethodCount as $paymentMethod) { + if ($paymentMethod['count'] != 0) { + $paymentMethodDataPoints[] = [ + "label" => $paymentMethod['name'], + "y" => $paymentMethod["count"], + ]; + } + } + + $showPaymentMethodCountGraph = count($paymentMethodDataPoints) > 1; + if ($showMemberCostGraph) { ?>
@@ -231,6 +256,17 @@ function getPriceConverted($price, $currency, $database) { +
+
+ +
+ +
+
@@ -242,6 +278,7 @@ function getPriceConverted($price, $currency, $database) { window.onload = function() { loadGraph("categorySplitChart", , "", ); loadGraph("memberSplitChart", , "", ); + loadGraph("paymentMethidSplitChart", , "", ); }