@@ -42,6 +42,7 @@ import { PaymentData } from './types/paymentData';
4242import cloudPaymentsApi from '../utils/cloudPaymentsApi' ;
4343import PlanModel from '../models/plan' ;
4444import { ClientApi , ClientService , CustomerReceiptItem , ReceiptApi , ReceiptTypes , TaxationSystem } from 'cloudpayments' ;
45+ import PromoCodeService from '../utils/promoCodeService' ;
4546
4647const PENNY_MULTIPLIER = 100 ;
4748
@@ -141,7 +142,7 @@ export default class CloudPaymentsWebhooks {
141142
142143 let workspace : WorkspaceModel ;
143144 let member : ConfirmedMemberDBScheme ;
144- let plan : PlanDBScheme ;
145+ let plan : PlanModel ;
145146 let planId : string ;
146147
147148 const { workspaceId, userId, tariffPlanId } = data ;
@@ -161,11 +162,36 @@ export default class CloudPaymentsWebhooks {
161162
162163 const recurrentPaymentSettings = data . cloudPayments ?. recurrent ;
163164
165+ if ( data . promoCodeValue && ! data . isCardLinkOperation ) {
166+ try {
167+ const promoCodeService = new PromoCodeService ( context . factories ) ;
168+ const promoPricing = await promoCodeService . getPricingForPlan ( data . promoCodeValue , data . userId , data . workspaceId , plan ) ;
169+
170+ if (
171+ promoPricing . promoCode . _id . toString ( ) !== data . promoCodeId ||
172+ promoPricing . finalAmount !== data . finalAmount ||
173+ promoPricing . originalAmount !== data . originalAmount ||
174+ promoPricing . discountAmount !== data . discountAmount
175+ ) {
176+ this . sendError ( res , CheckCodes . WRONG_AMOUNT , '[Billing / Check] Promo code payment data does not match current promo calculation' , body ) ;
177+
178+ return ;
179+ }
180+ } catch ( e ) {
181+ const error = e as Error ;
182+
183+ this . sendError ( res , CheckCodes . PAYMENT_COULD_NOT_BE_ACCEPTED , `[Billing / Check] Promo code is invalid: ${ error . toString ( ) } ` , body ) ;
184+
185+ return ;
186+ }
187+ }
188+
164189 /**
165190 * The amount will be considered correct if it is equal to the cost of the tariff plan.
166191 * Also, the cost will be correct if it is a payment to activate the subscription.
167192 */
168- const isRightAmount = + body . Amount === plan . monthlyCharge || recurrentPaymentSettings ?. startDate ;
193+ const expectedAmount = data . finalAmount ?? plan . monthlyCharge ;
194+ const isRightAmount = + body . Amount === expectedAmount || ( ! data . finalAmount && recurrentPaymentSettings ?. startDate ) ;
169195
170196 if ( ! isRightAmount ) {
171197 this . sendError ( res , CheckCodes . WRONG_AMOUNT , `[Billing / Check] Amount does not equal to plan monthly charge` , body ) ;
@@ -295,6 +321,23 @@ export default class CloudPaymentsWebhooks {
295321 if ( subscriptionId ) {
296322 await workspace . setSubscriptionId ( subscriptionId ) ;
297323 }
324+
325+ if ( data . promoCodeValue && ! data . isCardLinkOperation && data . benefitType ) {
326+ const promoCodeService = new PromoCodeService ( req . context . factories ) ;
327+ const promoCode = await promoCodeService . getValidPromoCode ( data . promoCodeValue , data . userId , data . workspaceId ) ;
328+
329+ await promoCodeService . createUsage ( {
330+ promoCode,
331+ userId : data . userId ,
332+ workspaceId : workspace . _id ,
333+ planId : tariffPlan . _id ,
334+ benefitType : data . benefitType ,
335+ originalAmount : data . originalAmount ,
336+ finalAmount : data . finalAmount ,
337+ discountAmount : data . discountAmount ,
338+ utm : data . promoUtm ,
339+ } ) ;
340+ }
298341 } catch ( e ) {
299342 const error = e as Error ;
300343
@@ -442,7 +485,7 @@ plan monthly charge: ${data.cloudPayments?.recurrent.amount} ${body.Currency}`
442485 */
443486 const userEmail = body . IssuerBankCountry === RUSSIA_ISO_CODE ? user . email : undefined ;
444487
445- await this . sendReceipt ( workspace , tariffPlan , userEmail ) ;
488+ await this . sendReceipt ( workspace , tariffPlan , userEmail , data . finalAmount ?? tariffPlan . monthlyCharge ) ;
446489
447490 let messageText = '' ;
448491
@@ -826,8 +869,9 @@ status: ${body.Status}`
826869 * @param workspace - workspace for which payment is made
827870 * @param tariff - paid tariff plan
828871 * @param userMail - user email address
872+ * @param amount - actual paid amount
829873 */
830- private async sendReceipt ( workspace : WorkspaceModel , tariff : PlanModel , userMail ?: string ) : Promise < void > {
874+ private async sendReceipt ( workspace : WorkspaceModel , tariff : PlanModel , userMail ?: string , amount = tariff . monthlyCharge ) : Promise < void > {
831875 /**
832876 * A general tax that applies to all commercial activities
833877 * involving the production and distribution of goods and the provision of services
@@ -836,9 +880,9 @@ status: ${body.Status}`
836880 const VALUE_ADDED_TAX = 0 ;
837881
838882 const item : CustomerReceiptItem = {
839- amount : tariff . monthlyCharge ,
883+ amount,
840884 label : `${ tariff . name } tariff plan` ,
841- price : tariff . monthlyCharge ,
885+ price : amount ,
842886 vat : VALUE_ADDED_TAX ,
843887 quantity : 1 ,
844888 } ;
0 commit comments