Ergebnis des Senior-Reviews über dev/2026-07-22 (Konzept 22.07., Feedback 24.07.,
Plan 19.08.). Rechnerisch war nichts zu korrigieren: Payline-Punkte und Provision
des Prognose-Blocks (N4) stimmen exakt mit der Provisions-Engine überein
(54.718,5 P. bzw. 3.772,88 EUR gegengerechnet an User 454). Behoben sind
Darstellungs- und Konsistenzfehler, die der Beraterin als falsche Zahlen
aufgefallen wären:
- "+N neu" schrumpfte rückwirkend, der Bestand daneben nicht: newAboCount() nutzte
weiter activeAbo(), während aboStockCount() auf das Monatsende zurückrechnet.
Beide teilen sich jetzt aboStockQuery(); die Jahres-Wachstumstabelle ebenso.
- Level-Kachel widersprach sich ("Zum nächsten Level Diamant fehlen X" über
"Karriere-Level: Diamant"): Text auf die Monats-Qualifikation umformuliert
(de/en/es/fr), Überschrift "Qualifikation in diesem Monat", Karriere-Level nur
noch bei Abweichung.
- Firstlines-Kachel zählte alle direkten Partner, "Teampartner gesamt" daneben nur
aktive (F1): Kachel nutzt jetzt isActiveConsultant(), die Detailseite listet
weiter alle und weist beide Zahlen aus.
- Neupartnerzahlen vergangener Monate sanken auf dem Home-Dashboard, sobald
Jahresgebühren ausliefen: neue User::newPartnerReferenceDate() (laufender Monat =
heute, abgeschlossener Monat = Monatsende). Dabei die drei Inline-Kopien der
Neupartner-Regel auf scopeNewPartnerIn()/isNewPartnerIn() zusammengeführt.
- Top-3-Karte ließ den Betrachter aus, obwohl "ich gehört in die Liste" in der
Juli-Runde für alle anderen Ranglisten umgesetzt wurde: zählt jetzt mit, inkl.
is_self und "ich"-Badge.
- Neues Profilfoto zeigte bis zu 6 h ein totes Bild: die URL steckt nicht mehr im
Cache, sondern entsteht beim Lesen (withProfileImages()).
- Test-Regression seit der Juli-Runde: Unit/Services/BackofficeDashboardServiceTest
fiel über die fehlende Spalte status_points (kam mit nonPaylinePoints() dazu).
- Kleinigkeiten: ProfileImageController gab die komplette Exception als
Flash-Message aus (jetzt Log + Sprachkey), BackofficeDrilldownService formatierte
Datumsangaben hart auf d.m.Y statt über Util::formatDateDB().
Tests: neuer HomeMonthlyStatsTest (buildMonthlyStats war ungetestet) plus Tests für
Stichtags-Zählung und Foto-Cache. Fünf Tests kodierten das alte Verhalten
(Betrachter zählt nicht mit, abgelaufener Account zählt nie) und wurden auf die
neue Semantik umgestellt, jeweils mit Gegenprobe. Suite: 861 grün (vorher 855),
89 rot — ausschließlich die in docs/2026-06-11-test-suite-vorbestehende-fehler.md
dokumentierten Altlasten.
Offen und bewusst nicht enthalten:
- Deploy-Schritt: backoffice:store-statistics-snapshots --force (vorher dumpen).
Kein vorhandener Snapshot enthält recruiter_ranking, Mai/Juni zusätzlich weder
non_payline_points noch die Führungskräfte-"gesamt"-Spalten; der Cron überspringt
vorhandene Snapshots ohne --force. Achtung: die Neuberechnung ist nicht
verlustfrei.
- TreeHtmlRendererTest/TreeCalcBotIntegrationTest: die Abo-Badges machten den
Renderer datenbankabhängig; die Dateien waren schon vorher rot und gehören in die
separate Test-Aufräumaufgabe.
- deleteImage bleibt ein GET-Route (gleiches Muster wie das Shop-Bild).
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
51 lines
4.8 KiB
PHP
51 lines
4.8 KiB
PHP
<?php
|
||
|
||
return [
|
||
'shipping_country_was_not_found' => 'Erreur : le pays de livraison est introuvable',
|
||
'shipping_country_was_not_correctly' => 'Erreur : le pays de livraison n’a pas été correctement traité dans le panier',
|
||
'shopping_cart_was_shipping_free' => 'Erreur : le panier a été indiqué comme exempt de frais de livraison',
|
||
'shipping_cost_cannot_be_0' => 'Erreur : les frais de livraison ne peuvent pas être 0',
|
||
'shipping_costs_were_not_calculated_correctly' => 'Erreur : les frais de livraison n’ont pas été correctement calculés',
|
||
'compensation_products_cannot_be_0' => 'Erreur : les produits de compensation ne peuvent pas être 0.',
|
||
'link_for_homeparty_not_found' => 'Le lien pour l’Auszeitparty est introuvable ou n’est plus actif.',
|
||
'contact_delete' => 'Contact supprimé',
|
||
'error_occurred_with_order' => 'Une erreur est survenue lors de la commande',
|
||
'abo_deaktivert' => 'Option d’abonnement désactivée',
|
||
'error_checkbox_not_confirm' => 'Erreur : case non confirmée',
|
||
'no_change_made' => 'aucune modification effectuée',
|
||
'booked_package_has_been_changed' => 'le package réservé a été modifié.',
|
||
'cancel_membership_is_requested' => 'La résiliation de l’adhésion a été demandée',
|
||
'file_upload_failed' => 'Le fichier n’a pas pu être téléversé. Merci de réessayer.',
|
||
'file_uploaded' => 'Fichier téléversé',
|
||
'file_empty' => 'Fichier vide"',
|
||
'file_deleted' => 'Fichier supprimé',
|
||
'file_not_found' => 'Fichier introuvable',
|
||
'country_account_has_been_changed__cost_has_been_reset' => 'Le pays de facturation a été modifié et le panier a été réinitialisé',
|
||
'your_shopping_cart_is_empty_please_add_products_first.' => 'Votre panier est vide, veuillez d’abord ajouter des produits',
|
||
'homeparty_guest_delete' => 'Invité Auszeitparty supprimé',
|
||
'homeparty_delete' => 'Auszeitparty supprimée',
|
||
'VATID_could_not_be_validated' => 'Le numéro de TVA n’a pas pu être validé, veuillez vérifier la saisie',
|
||
'VATID_successfully_entered' => 'Numéro de TVA saisi avec succès',
|
||
'VATID_german_not_allowed' => 'Les numéros de TVA allemands ne peuvent pas être utilisés ici. L’autoliquidation ne s’applique qu’aux numéros de TVA étrangers de l’UE.',
|
||
'VATID_no_longer_valid_taxes_applied' => 'Ton numéro de TVA n’est plus valide. La TVA sera donc appliquée à cette commande.',
|
||
'reverse_charge_procedure_and_VATID_deleted' => 'Procédure d’autoliquidation et numéro de TVA supprimés',
|
||
'no_id_card_deposited_please_upload_first' => 'Aucune pièce d’identité déposée, veuillez d’abord la téléverser',
|
||
'no_trade_licence_deposited_please_upload_first' => 'Aucun extrait d’activité déposé, veuillez d’abord le téléverser',
|
||
'please_enter_reason_why_you_not_need_trade_licence' => 'Veuillez indiquer pourquoi vous n’avez pas besoin d’un extrait d’activité',
|
||
'please_select_compensation_product' => 'Veuillez sélectionner un produit de compensation',
|
||
'please_select_count_compensation_products' => 'Veuillez sélectionner :count produits de compensation',
|
||
'user_not_found' => 'Le conseiller est introuvable.<br>Le compte a été désactivé ou supprimé.',
|
||
'shopping_cart_was_not_user_shop' => 'Erreur : le conseiller n’a pas de boutique, la commande ne peut pas continuer',
|
||
'shopping_instance_not_found' => 'Erreur : aucune ShoppingInstance trouvée',
|
||
'shopping_user_not_found' => 'Erreur : aucun ShoppingUser trouvé',
|
||
'account_released' => 'Compte activé',
|
||
'cart_product_not_allowed_for_order_type' => 'Le panier contient des articles qui ne sont pas prévus pour ce type de commande. Veuillez vider le panier et sélectionner uniquement les produits adaptés à cette commande.',
|
||
'cart_max_weight_reached' => "Le poids d'expédition maximal est atteint. Aucun autre produit ne peut être ajouté.",
|
||
'gdpr_delete_success' => 'Suppression RGPD exécutée : Toutes les données personnelles ont été anonymisées de manière irréversible.',
|
||
'gdpr_delete_customer_success' => 'Suppression RGPD exécutée : Toutes les données personnelles du client ont été anonymisées de manière irréversible.',
|
||
'gdpr_delete_customer_button' => 'Supprimer le client (RGPD)',
|
||
'gdpr_confirm_checkbox_missing' => 'Veuillez confirmer la suppression RGPD via la case à cocher.',
|
||
'gdpr_error_is_admin' => "Suppression RGPD impossible : Le compte dispose de droits d'administrateur. Veuillez d'abord retirer les droits d'administrateur.",
|
||
'gdpr_error_active_abo' => "Suppression RGPD impossible : Un abonnement actif existe encore. Veuillez d'abord résilier l'abonnement.",
|
||
'gdpr_error_customer_is_member' => "Suppression RGPD impossible : Cette fiche client appartient à un compte de conseiller. Veuillez utiliser la suppression RGPD dans l'administration des utilisateurs.",
|
||
];
|