Skip to content

Commit

Permalink
Debug v20 - Fix amount of membership payments
Browse files Browse the repository at this point in the history
  • Loading branch information
eldy committed Jul 20, 2024
1 parent 442e798 commit 33a2c49
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 37 deletions.
6 changes: 5 additions & 1 deletion htdocs/adherents/admin/website.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@

if ($action == 'update') {
$public = GETPOST('MEMBER_ENABLE_PUBLIC');
$amount = price2num(GETPOST('MEMBER_NEWFORM_AMOUNT'), 'MT', 2);
if (GETPOST('MEMBER_NEWFORM_AMOUNT') !== '') {
$amount = price2num(GETPOST('MEMBER_NEWFORM_AMOUNT'), 'MT', 2);
} else {
$amount = '';
}
$minamount = GETPOST('MEMBER_MIN_AMOUNT');
$publiccounters = GETPOST('MEMBER_COUNTERS_ARE_PUBLIC');
$showtable = GETPOST('MEMBER_SHOW_TABLE');
Expand Down
18 changes: 9 additions & 9 deletions htdocs/langs/en_US/members.lang
Original file line number Diff line number Diff line change
Expand Up @@ -208,25 +208,25 @@ NewMemberbyWeb=New member added. Awaiting approval
NewMemberForm=New member form
SubscriptionsStatistics=Contributions statistics
NbOfSubscriptions=Number of contributions
AmountOfSubscriptions=Amount collected from contributions
AmountOfSubscriptions=Amount collected from membership payments
TurnoverOrBudget=Turnover (for a company) or Budget (for a foundation)
DefaultAmount=Default amount of contribution (used only if no amount is defined at member type level)
MinimumAmount=Minimum amount (used only when contribution amount is free)
CanEditAmount=Subscription amount can be defined by the member
DefaultAmount=Default amount of membership payment (used only if no amount is defined at member type level)
MinimumAmount=Minimum amount of membership payment (has priority on any default amounts)
CanEditAmount=Membership amount can be defined by the member
CanEditAmountDetail=Visitor can choose/edit amount of its contribution regardless of the member type
AmountIsLowerToMinimumNotice=The amount is lower than the minimum %s
MEMBER_NEWFORM_PAYONLINE=After the online registration, switch automatically to the online payment page
ByProperties=By nature
MembersStatisticsByProperties=Members statistics by nature
VATToUseForSubscriptions=VAT rate to use for contributions
NoVatOnSubscription=No VAT for contributions
ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS=Product used for contribution line into invoice: %s
VATToUseForSubscriptions=VAT rate to use for membership payment
NoVatOnSubscription=No VAT for membership payment
ADHERENT_PRODUCT_ID_FOR_SUBSCRIPTIONS=Product used for membership line into invoice: %s
NameOrCompany=Name or company
SubscriptionRecorded=Contribution recorded
NoEmailSentToMember=No email sent to member
EmailSentToMember=Email sent to member at %s
SendReminderForExpiredSubscriptionTitle=Send reminder by email for expired contributions
SendReminderForExpiredSubscription=Send reminder by email to members when contribution is about to expire (parameter is number of days before end of membership to send the reminder. It can be a list of days separated by a semicolon, for example '10;5;0;-5')
SendReminderForExpiredSubscriptionTitle=Send reminder by email for expired membership
SendReminderForExpiredSubscription=Send reminder by email to members when membership is about to expire (parameter is number of days before end of membership to send the reminder. It can be a list of days separated by a semicolon, for example '10;5;0;-5')
MembershipPaid=Membership paid for current period (until %s)
YouMayFindYourInvoiceInThisEmail=You may find your invoice attached to this email
XMembersClosed=%s member(s) closed
Expand Down
2 changes: 1 addition & 1 deletion htdocs/langs/fr_FR/members.lang
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ NbOfSubscriptions=Nombre de cotisations
AmountOfSubscriptions=Montant des cotisations
TurnoverOrBudget=Chiffre affaire (pour société) ou Budget (asso ou collectivité)
DefaultAmount=Montant de contribution par défaut (uniquement utilisé en l'absence de montant définit au niveau du type de membre)
MinimumAmount=Montant minimum (uniquement utilisé lorsque le montant de contribution est libre)
MinimumAmount=Montant minimum
CanEditAmount=Le montant de la cotisation peut être défini par l'adhérent
CanEditAmountDetail=Le visiteur peut choisir/modifier le montant de sa contribution quel que soit le type d'adhérent
AmountIsLowerToMinimumNotice=Le montant est inférieur au montant minimum de %s
Expand Down
42 changes: 32 additions & 10 deletions htdocs/public/members/new.php
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,8 @@ function llxFooterVierge()
$adh->lastname = GETPOST('lastname');
$adh->gender = GETPOST('gender');
$adh->civility_id = GETPOST('civility_id');
$adh->societe = GETPOST('societe');
$adh->company = GETPOST('societe');
$adh->societe = $adh->company;
$adh->address = GETPOST('address');
$adh->zip = GETPOST('zipcode');
$adh->town = GETPOST('town');
Expand Down Expand Up @@ -595,7 +596,7 @@ function initmorphy()
print $form->selectarray("typeid", $adht->liste_array(1), GETPOST('typeid') ? GETPOST('typeid') : $defaulttype, $isempty);
print '</td></tr>'."\n";
} else {
$adht->fetch(getDolGlobalString('MEMBER_NEWFORM_FORCETYPE'));
$adht->fetch(getDolGlobalInt('MEMBER_NEWFORM_FORCETYPE'));
print '<input type="hidden" id="typeid" name="typeid" value="' . getDolGlobalString('MEMBER_NEWFORM_FORCETYPE').'">';
}

Expand Down Expand Up @@ -680,6 +681,7 @@ function initmorphy()
$country_code = getCountry($country_id, 2, $db, $langs);
print $form->select_country($country_id, 'country_id');
print '</td></tr>';

// State
if (!getDolGlobalString('SOCIETE_DISABLE_STATE')) {
print '<tr><td>'.$langs->trans('State').'</td><td>';
Expand Down Expand Up @@ -761,23 +763,25 @@ function initturnover() {
}

if (getDolGlobalString('MEMBER_NEWFORM_PAYONLINE')) {
$typeid = $conf->global->MEMBER_NEWFORM_FORCETYPE ? $conf->global->MEMBER_NEWFORM_FORCETYPE : GETPOSTINT('typeid');
$typeid = getDolGlobalInt('MEMBER_NEWFORM_FORCETYPE', GETPOSTINT('typeid'));
$adht = new AdherentType($db);
$adht->fetch($typeid);
$caneditamount = $adht->caneditamount;
$amountbytype = $adht->amountByType(1); // Load the array of amount per type

// Set amount for the subscription:
// Set amount for the subscription from the the type and options:
// - First check the amount of the member type.
$amountbytype = $adht->amountByType(1); // Load the array of amount per type
$amount = empty($amountbytype[$typeid]) ? (isset($amount) ? $amount : 0) : $amountbytype[$typeid];
// - If not found, take the default amount only of the user is authorized to edit it
if ($caneditamount && empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
$amount = empty($amountbytype[$typeid]) ? 0 : $amountbytype[$typeid];
// - If not found, take the default amount only if the user is authorized to edit it
if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
$amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
}
// - If not set, we accept to have amount defined as parameter (for backward compatibility).
if (empty($amount)) {
$amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
}
// - If a min is set, we take it into account
$amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));

// Clean the amount
$amount = price2num($amount);
Expand Down Expand Up @@ -883,6 +887,9 @@ function initturnover() {
while ($i < $num) {
$objp = $db->fetch_object($result); // Load the member type and information on it

$caneditamount = $objp->caneditamount;
$amountbytype = $adht->amountByType(1); // Load the array of amount per type

print '<tr class="oddeven">';
// Label
print '<td>'.dol_escape_htmltag($objp->label).'</td>';
Expand All @@ -893,8 +900,23 @@ function initturnover() {
print '</td>';
// Amount
print '<td class="center"><span class="amount nowrap">';
$displayedamount = max(intval($objp->amount), intval(getDolGlobalInt("MEMBER_MIN_AMOUNT")));
$caneditamount = $objp->caneditamount;

// Set amount for the subscription from the the type and options:
// - First check the amount of the member type.
$amount = empty($amountbytype[$objp->rowid]) ? 0 : $amountbytype[$objp->rowid];
// - If not found, take the default amount only if the user is authorized to edit it
if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
$amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
}
// - If not set, we accept to have amount defined as parameter (for backward compatibility).
if (empty($amount)) {
$amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
}
// - If a min is set, we take it into account
$amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));

$displayedamount = $amount;

if ($objp->subscription) {
if ($displayedamount > 0 || !$caneditamount) {
print price($displayedamount, 1, $langs, 1, 0, -1, $conf->currency);
Expand Down
41 changes: 30 additions & 11 deletions htdocs/public/payment/newpayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -1522,14 +1522,14 @@

$member = new Adherent($db);
$adht = new AdherentType($db);
$subscription = new Subscription($db);

$result = $member->fetch('', $ref);
if ($result <= 0) {
$mesg = $member->error;
$error++;
} else {
$member->fetch_thirdparty();
$subscription = new Subscription($db);

$adht->fetch($member->typeid);
}
Expand All @@ -1538,7 +1538,7 @@
if ($action != 'dopayment') { // Do not change amount if we just click on first dopayment
$amount = $subscription->total_ttc;
if (GETPOST("amount", 'alpha')) {
$amount = GETPOST("amount", 'alpha');
$amount = price2num(GETPOST("amount", 'alpha'), 'MT', 2);
}
// If amount still not defined, we take amount of the type of member
if (empty($amount)) {
Expand Down Expand Up @@ -1618,16 +1618,22 @@
}
}

$amountbytype = $adht->amountByType(1);

$typeid = $adht->id;
$caneditamount = $adht->caneditamount;

if ($member->type) {
$oldtypeid = $member->typeid;
$newtypeid = (int) (GETPOSTISSET("typeid") ? GETPOSTINT("typeid") : $member->typeid);

if (getDolGlobalString('MEMBER_ALLOW_CHANGE_OF_TYPE')) {
require_once DOL_DOCUMENT_ROOT.'/adherents/class/adherent_type.class.php';
$adht = new AdherentType($db);
// Amount by member type
$amountbytype = $adht->amountByType(1);
$typeid = $newtypeid;
$adht->fetch($typeid); // Reload with the new type id
}

$caneditamount = $adht->caneditamount;

if (getDolGlobalString('MEMBER_ALLOW_CHANGE_OF_TYPE')) {
// Last member type
print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("LastMemberType");
print '</td><td class="CTableRow2">'.dol_escape_htmltag($member->type);
Expand All @@ -1639,7 +1645,8 @@

// list member type
if (!$action) {
// Set amount for the subscription
// Set amount for the subscription.
// If we change the type, we use the amount of the new type and not the amount of last subscription.
$amount = (!empty($amountbytype[$member->typeid])) ? $amountbytype[$member->typeid] : $member->last_subscription_amount;

print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("NewSubscription");
Expand All @@ -1659,16 +1666,28 @@
}
}

// Set amount for the subscription from the the type and options:
// - First check the amount of the member type if not previous payment.
$amount = ($member->last_subscription_amount ? $member->last_subscription_amount : (empty($amountbytype[$typeid]) ? 0 : $amountbytype[$typeid]));
// - If not found, take the default amount
if (empty($amount) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
$amount = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
}
// - If not set, we accept to have amount defined as parameter (for backward compatibility).
//if (empty($amount)) {
// $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
//}
// - If a min is set, we take it into account
$amount = max(0, (float) $amount, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));

// Amount
print '<tr class="CTableRow2"><td class="CTableRow2">'.$langs->trans("Amount");
// This place no longer allows amount edition
if (getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO')) {
print ' - <a href="' . getDolGlobalString('MEMBER_EXT_URL_SUBSCRIPTION_INFO').'" rel="external" target="_blank" rel="noopener noreferrer">'.$langs->trans("SeeHere").'</a>';
}
print '</td><td class="CTableRow2">';
if (getDolGlobalString('MEMBER_MIN_AMOUNT') && $amount) {
$amount = max(0, getDolGlobalString('MEMBER_MIN_AMOUNT'), $amount);
}

$caneditamount = $adht->caneditamount;
$minimumamount = !getDolGlobalString('MEMBER_MIN_AMOUNT') ? $adht->amount : max(getDolGlobalString('MEMBER_MIN_AMOUNT'), $adht->amount, $amount);

Expand Down
16 changes: 11 additions & 5 deletions htdocs/public/payment/paymentok.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,19 +485,25 @@
if (empty($adht->caneditamount)) { // If we didn't allow members to choose their membership amount (if the amount is allowed in edit mode, no need to check)
if ($object->status == $object::STATUS_DRAFT) { // If the member is not yet validated, we check that the amount is the same as expected.
$typeid = $object->typeid;
$amountbytype = $adht->amountByType(1); // Load the array of amount per type

// Set amount for the subscription:
// - First check the amount of the member type.
$amountbytype = $adht->amountByType(1); // Load the array of amount per type
$amountexpected = empty($amountbytype[$typeid]) ? 0 : $amountbytype[$typeid];
// - If not found, take the default amount
if (empty($amountexpected) && getDolGlobalString('MEMBER_NEWFORM_AMOUNT')) {
$amountexpected = getDolGlobalString('MEMBER_NEWFORM_AMOUNT');
}
// - If not set, we accept to have amount defined as parameter (for backward compatibility).
//if (empty($amount)) {
// $amount = (GETPOST('amount') ? price2num(GETPOST('amount', 'alpha'), 'MT', 2) : '');
//}
// - If a min is set, we take it into account
$amountexpected = max(0, (float) $amountexpected, (float) getDolGlobalInt("MEMBER_MIN_AMOUNT"));

if ($amountexpected && $amountexpected != $FinalPaymentAmt) {
$error++;
$errmsg = 'Value of FinalPayment ('.$FinalPaymentAmt.') differs from value expected for membership ('.$amountexpected.'). May be a hack to try to pay a different amount ?';
$errmsg = 'Value of FinalPayment ('.$FinalPaymentAmt.') propagated by payment page differs from the expected value for membership ('.$amountexpected.'). May be a hack to try to pay a different amount ?';
$postactionmessages[] = $errmsg;
$ispostactionok = -1;
dol_syslog("Failed to validate member (bad amount check): ".$errmsg, LOG_ERR, 0, '_payment');
Expand All @@ -506,13 +512,13 @@
}

// Security protection:
if (getDolGlobalString('MEMBER_MIN_AMOUNT')) {
if ($FinalPaymentAmt < $conf->global->MEMBER_MIN_AMOUNT) {
if (getDolGlobalInt('MEMBER_MIN_AMOUNT')) {
if ($FinalPaymentAmt < getDolGlobalInt('MEMBER_MIN_AMOUNT')) {
$error++;
$errmsg = 'Value of FinalPayment ('.$FinalPaymentAmt.') is lower than the minimum allowed (' . getDolGlobalString('MEMBER_MIN_AMOUNT').'). May be a hack to try to pay a different amount ?';
$postactionmessages[] = $errmsg;
$ispostactionok = -1;
dol_syslog("Failed to validate member (amount lower than minimum): ".$errmsg, LOG_ERR, 0, '_payment');
dol_syslog("Failed to validate member (amount propagated from payment page is lower than allowed minimum): ".$errmsg, LOG_ERR, 0, '_payment');
}
}

Expand Down

0 comments on commit 33a2c49

Please sign in to comment.