Add handling of post payment for subscriptions #799

This commit is contained in:
Ramon Gutierrez 2024-10-23 20:46:31 +08:00
parent 33f48647b6
commit f7ba91892b
6 changed files with 95 additions and 38 deletions

View file

@ -236,6 +236,10 @@ services:
arguments:
$em: "@doctrine.orm.entity_manager"
$ic: "@App\\Service\\InsuranceConnector"
$fcmclient: "@App\\Service\\FCMSender"
$lc: "@App\\Service\\LoyaltyConnector"
$sub_months: "%subscription_months%"
$loyalty_point_multiplier: "%loyalty_php_point_multiplier%"
tags:
- name: doctrine.orm.entity_listener
event: 'postUpdate'
@ -328,8 +332,9 @@ services:
# FCM sender
App\Service\FCMSender:
arguments:
$server_key: "%env(FCM_SERVER_KEY)%"
$sender_id: "%env(FCM_SENDER_ID)%"
$project_id: "%env(FCM_PROJECT_ID)%"
$base_uri: "%env(FCM_BASE_URI)%"
$creds_file: "%env(FCM_CREDENTIALS_PATH)%"
# price tier manager
App\Service\PriceTierManager:

View file

@ -228,6 +228,7 @@ class SubscriptionController extends ApiController
]);
if (empty($sub_obj)) {
error_log("no sub found!");
return new ApiResponse(false, 'Invalid subscription provided.');
}
@ -295,7 +296,7 @@ class SubscriptionController extends ApiController
"loyalty_fcm_body_add_points",
[],
[],
['points' => $points_amount],
['%points%' => number_format($points_amount)],
);
}

View file

@ -10,7 +10,6 @@ use App\Service\PayMongoConnector;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use DateTime;
@ -72,9 +71,6 @@ class PayMongoController extends Controller
// TODO: work with paymongo to figure out a better way to standardize callbacks. For now we rely on the callback description
$description = $event['attributes']['description'];
// define if we earn loyalty points or not
$add_loyalty_points = false;
// set initial criteria
$criteria = [
'status' => TransactionStatus::PENDING,
@ -90,9 +86,6 @@ class PayMongoController extends Controller
// add to criteria
$criteria['ext_transaction_id'] = $desc_parts[1];
// we earn loyalty points
$add_loyalty_points = true;
break;
// insurance premium
@ -113,31 +106,8 @@ class PayMongoController extends Controller
// mark as paid
$obj->setStatus(TransactionStatus::PAID);
$obj->setDatePay(new DateTime());
$this->em->flush();
// add loyalty points if applicable
if ($add_loyalty_points) {
// get the customer
$cust = $obj->getCustomer();
// compute loyalty points to be added
// TODO: get a proper matrix for this. right now we are using a flat multiplier for demo purposes
$points_amount = ($obj->getAmount() / 100) * $this->getParameter('loyalty_php_point_multiplier');
// add loyalty points
$points_res = $this->lc->updatePoints($cust, $points_amount);
if ($points_res['success']) {
// notify the customer that points were added
$this->fcmclient->sendLoyaltyEvent(
$cust,
"loyalty_fcm_title_add_points",
"loyalty_fcm_body_add_points",
[],
[],
['points' => $points_amount],
);
}
}
}
return $this->json([

View file

@ -5,22 +5,34 @@ namespace App\EntityListener;
use Doctrine\ORM\Event\LifecycleEventArgs;
use Doctrine\ORM\EntityManagerInterface;
use App\Entity\Subscription;
use App\Entity\GatewayTransaction;
use App\Entity\InsuranceApplication;
use App\Service\InsuranceConnector;
use App\Ramcar\InsuranceApplicationStatus;
use App\Ramcar\TransactionStatus;
use App\Ramcar\SubscriptionStatus;
use App\Service\FCMSender;
use App\Service\LoyaltyConnector;
use DateTime;
class GatewayTransactionListener
{
protected $ic;
protected $em;
protected $fcmclient;
protected $lc;
protected $sub_months;
protected $loyalty_point_multiplier;
public function __construct(EntityManagerInterface $em, InsuranceConnector $ic)
public function __construct(EntityManagerInterface $em, InsuranceConnector $ic, FCMSender $fcmclient, LoyaltyConnector $lc, $sub_months, $loyalty_point_multiplier)
{
$this->em = $em;
$this->ic = $ic;
$this->fcmclient = $fcmclient;
$this->lc = $lc;
$this->sub_months = $sub_months;
$this->loyalty_point_multiplier = $loyalty_point_multiplier;
}
public function postUpdate(GatewayTransaction $gt_obj, LifecycleEventArgs $args)
@ -38,12 +50,16 @@ class GatewayTransactionListener
// only do something if the status has changed to paid
if ($prev_value !== $new_value && $new_value === TransactionStatus::PAID) {
// determine if we will add loyalty points for this transaction
// handle based on type
// TODO: add types here as we go. there's probably a better way to do this.
switch ($gt_obj->getType()) {
case 'insurance_premium':
return $this->handleInsurancePremium($gt_obj);
$this->handleInsurancePremium($gt_obj);
break;
case 'subscription':
$this->handleSubscription($gt_obj);
$this->addLoyaltyPoints($gt_obj);
default:
break;
}
@ -51,7 +67,7 @@ class GatewayTransactionListener
}
}
protected function handleInsurancePremium($gt_obj)
protected function handleInsurancePremium(GatewayTransaction $gt_obj)
{
// get insurance application object
$obj = $this->em->getRepository(InsuranceApplication::class)->findOneBy([
@ -74,5 +90,63 @@ class GatewayTransactionListener
}
}
}
protected function handleSubscription(GatewayTransaction $gt_obj)
{
$sub_id = $gt_obj->getMetadata()['subscription_id'];
// activate the sub
// TODO: put subscription management into a service
$sub = $this->em->getRepository(Subscription::class)->findOneBy([
'ext_api_id' => $sub_id,
]);
if (empty($sub)) {
// NOTE: this isn't supposed to happen
error_log("Subscription not found for ID: ". $sub_id);
} else {
// set sub date parameters
// TODO: this really needs to be in a service
$sub_start_date = new DateTime();
$sub_end_date = clone $sub_start_date;
$sub_end_date->modify('+' . $this->sub_months . ' month');
$sub->setStatus(SubscriptionStatus::ACTIVE)
->setDateStart($sub_start_date)
->setDateEnd($sub_end_date);
$this->em->flush();
// send notification about subscription
$this->fcmclient->sendSubscriptionEvent(
$sub,
"sub_fcm_title_active",
"sub_fcm_body_active",
);
}
}
protected function addLoyaltyPoints(GatewayTransaction $gt_obj)
{
$cust = $gt_obj->getCustomer();
// compute loyalty points to be added
// TODO: get a proper matrix for this. right now we are using a flat multiplier for demo purposes
$points_amount = ($gt_obj->getAmount() / 100) * $this->loyalty_point_multiplier;
// add loyalty points
$points_res = $this->lc->updatePoints($cust, $points_amount);
if ($points_res['success']) {
// notify the customer that points were added
$this->fcmclient->sendLoyaltyEvent(
$cust,
"loyalty_fcm_title_add_points",
"loyalty_fcm_body_add_points",
[],
[],
['%points%' => number_format($points_amount)],
);
}
}
}

View file

@ -89,6 +89,9 @@
"edwinhoksberg/php-fcm": {
"version": "1.0.0"
},
"firebase/php-jwt": {
"version": "v6.10.1"
},
"guzzlehttp/guzzle": {
"version": "6.3.0"
},

View file

@ -183,4 +183,8 @@ insurance_fcm_body_completed: 'Your insurance application has been processed!'
# fcm loyalty
loyalty_fcm_title_add_points: 'Hooray!'
loyalty_fcm_body_add_points: '{1} You have earned %points% point!|]1,Inf] You have earned %points% points!'
loyalty_fcm_body_add_points: 'You have earned %points% points! Check out our rewards catalog!'
# fcm subscription
sub_fcm_title_active: 'Subscription active!'
sub_fcm_body_active: 'Your Motolite PLATINUM subscription is now active. Have your new battery installed now!'