Exemplo n.º 1
0
    def test_cancel_line_item_in_order(self):
        original_quantity = 2
        order_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = order_item.current_price().amount * original_quantity
        data = {
            'line_items': [{'item_id': unicode(order_item.id), 'quantity': original_quantity}],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
                }
            }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id), data=json.dumps(data), content_type='application/json', headers=[('X-Requested-With', 'XMLHttpRequest'), ('Origin', app.config['BASE_URL'])])
        self.assertEquals(resp.status_code, 201)
        resp_json = json.loads(resp.data)['result']
        self.assertEquals(resp_json['final_amount'], total_amount)

        order = Order.query.get(resp_json['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment', order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order, online_payment=online_payment, amount=order_amounts.final_amount, currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        refund_amount = total_amount - 1
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data={'id': buid()}))
        pre_refund_transactions_count = order.refund_transactions.count()
        formdata = {
            'amount': refund_amount,
            'internal_note': 'internal reference',
            'refund_description': 'receipt description',
            'note_to_user': '******'
        }
        refund_form = OrderRefundForm(data=formdata, parent=order, meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)
        self.assertEquals(pre_refund_transactions_count + 1, order.refund_transactions.count())

        first_line_item = order.line_items[0]
        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data={'id': buid()}))
        process_line_item_cancellation(first_line_item)
        self.assertEquals(first_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        expected_refund_amount = total_amount - refund_amount
        refund_transaction1 = PaymentTransaction.query.filter_by(order=order, transaction_type=TRANSACTION_TYPE.REFUND).order_by(PaymentTransaction.created_at.desc()).first()
        self.assertEquals(refund_transaction1.amount, expected_refund_amount)
Exemplo n.º 2
0
def process_payment(order_id, pg_paymentid):
    order = Order.query.get(order_id)
    order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)

    online_payment = OnlinePayment.query.filter_by(
        pg_paymentid=pg_paymentid, order=order
    ).first()
    if online_payment is None:
        online_payment = OnlinePayment(pg_paymentid=pg_paymentid, order=order)

    rp_resp = razorpay.capture_payment(
        online_payment.pg_paymentid, order_amounts.final_amount
    )
    if rp_resp.status_code == 200:
        online_payment.confirm()
        db.session.add(online_payment)
        # Only INR is supported as of now
        transaction = PaymentTransaction(
            order=order,
            online_payment=online_payment,
            amount=order_amounts.final_amount,
            currency=CURRENCY.INR,
        )
        db.session.add(transaction)
        order.confirm_sale()
        db.session.add(order)
        invoice_organization = (
            order.organization.invoicer
            if order.organization.invoicer
            else order.organization
        )
        invoice = Invoice(order=order, organization=invoice_organization)
        db.session.add(invoice)
        db.session.commit()
        for line_item in order.line_items:
            line_item.confirm()
            db.session.add(line_item)
            if line_item.discount_coupon:
                line_item.discount_coupon.update_used_count()
                db.session.add(line_item.discount_coupon)
        db.session.commit()
        with app.test_request_context():
            send_receipt_mail.queue(order.id)
            return make_response(jsonify(message="Payment verified"), 201)
    else:
        online_payment.fail()
        db.session.add(online_payment)
        db.session.commit()
        raise PaymentGatewayError(
            "Online payment failed for order - {order} with the following details - {msg}".format(
                order=order.id, msg=rp_resp.content
            ),
            424,
            'Your payment failed. Please try again or contact us at {email}.'.format(
                email=order.organization.contact_email
            ),
        )
Exemplo n.º 3
0
    def test_partial_refund_in_order(self):
        original_quantity = 5
        discounted_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = discounted_item.current_price().amount * original_quantity
        data = {
            'line_items': [{'item_id': unicode(discounted_item.id), 'quantity': original_quantity}],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
                }
            }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id), data=json.dumps(data), content_type='application/json', headers=[('X-Requested-With', 'XMLHttpRequest'), ('Origin', app.config['BASE_URL'])])
        self.assertEquals(resp.status_code, 201)
        resp_data = json.loads(resp.data)['result']
        self.assertEquals(resp_data['final_amount'], (total_amount - 5 * total_amount / decimal.Decimal(100)))

        order = Order.query.get(resp_data['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment', order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order, online_payment=online_payment, amount=order_amounts.final_amount, currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data={'id': buid()}))
        valid_refund_amount = 500

        formdata = {
            'amount': valid_refund_amount,
            'internal_note': 'internal reference',
            'note_to_user': '******',
            'refund_description': 'test refund'
        }
        refund_form = OrderRefundForm(data=formdata, parent=order, meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)

        refund_transactions = order.transactions.filter_by(transaction_type=TRANSACTION_TYPE.REFUND).all()
        self.assertIsInstance(refund_transactions[0].refunded_at, datetime.datetime)
        self.assertEquals(refund_transactions[0].amount, decimal.Decimal(valid_refund_amount))
        self.assertEquals(refund_transactions[0].internal_note, formdata['internal_note'])
        self.assertEquals(refund_transactions[0].note_to_user, formdata['note_to_user'])
        self.assertEquals(refund_transactions[0].refund_description, formdata['refund_description'])

        invalid_refund_amount = 100000000
        formdata = {
            'amount': invalid_refund_amount,
        }
        refund_form = OrderRefundForm(data=formdata, parent=order, meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            resp = process_partial_refund_for_order(partial_refund_args)

        self.assertEquals(resp.status_code, 403)
        refund_transactions = order.transactions.filter_by(transaction_type=TRANSACTION_TYPE.REFUND).all()
        self.assertEquals(refund_transactions[0].amount, decimal.Decimal(valid_refund_amount))

        resp = self.make_free_order()
        self.assertEquals(resp.status_code, 201)
        resp_data = json.loads(resp.data)['result']
        order = Order.query.get(resp_data.get('order_id'))
        invalid_refund_amount = 100000000

        formdata = {
            'amount': invalid_refund_amount,
        }
        refund_form = OrderRefundForm(data=formdata, parent=order, meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            refund_resp = process_partial_refund_for_order(partial_refund_args)

        self.assertEquals(refund_resp.status_code, 403)
Exemplo n.º 4
0
    def test_cancel_line_item_in_bulk_order(self):
        original_quantity = 5
        discounted_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = discounted_item.current_price().amount * original_quantity
        data = {
            'line_items': [{'item_id': unicode(discounted_item.id), 'quantity': original_quantity}],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
                }
            }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id), data=json.dumps(data), content_type='application/json', headers=[('X-Requested-With', 'XMLHttpRequest'), ('Origin', app.config['BASE_URL'])])
        self.assertEquals(resp.status_code, 201)
        resp_json = json.loads(resp.data)['result']
        self.assertEquals(resp_json['final_amount'], (total_amount - 5 * total_amount / decimal.Decimal(100)))

        order = Order.query.get(resp_json['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment', order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order, online_payment=online_payment, amount=order_amounts.final_amount, currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        first_line_item = order.line_items[0]
        to_be_void_line_items = order.line_items[1:]
        precancellation_order_amount = order.net_amount
        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data={'id': buid()}))
        process_line_item_cancellation(first_line_item)
        self.assertEquals(first_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        for void_line_item in to_be_void_line_items:
            self.assertEquals(void_line_item.status, LINE_ITEM_STATUS.VOID)
        expected_refund_amount = precancellation_order_amount - order.get_amounts(LINE_ITEM_STATUS.CONFIRMED).final_amount
        refund_transaction1 = PaymentTransaction.query.filter_by(order=order, transaction_type=TRANSACTION_TYPE.REFUND).first()
        self.assertEquals(refund_transaction1.amount, expected_refund_amount)

        second_line_item = order.confirmed_line_items[0]
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data={'id': buid()}))
        process_line_item_cancellation(second_line_item)
        self.assertEquals(second_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        refund_transaction2 = PaymentTransaction.query.filter_by(order=order, transaction_type=TRANSACTION_TYPE.REFUND).order_by(PaymentTransaction.created_at.desc()).first()
        self.assertEquals(refund_transaction2.amount, second_line_item.final_amount)

        # test failed cancellation
        third_line_item = order.confirmed_line_items[0]
        razorpay.refund_payment = MagicMock(
            return_value=MockResponse(
                response_data={
                    "error": {
                        "code": "BAD_REQUEST_ERROR",
                        "description": "The amount is invalid",
                        "field": "amount"
                    }
                },
                status_code=400
            ))
        self.assertRaises(PaymentGatewayError, lambda: process_line_item_cancellation(third_line_item))

        # refund the remaining amount paid, and attempt to cancel a line item
        # this should cancel the line item without resulting in a new refund transaction
        refund_amount = order.net_amount
        refund_dict = {'id': buid(), 'amount': refund_amount, 'internal_note': 'internal reference', 'note_to_user': '******'}
        razorpay.refund_payment = MagicMock(return_value=MockResponse(response_data=refund_dict))

        formdata = {
            'amount': refund_amount,
            'internal_note': 'internal reference',
            'refund_description': 'receipt description',
            'note_to_user': '******'
        }
        refund_form = OrderRefundForm(data=formdata, parent=order, meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)

        third_line_item = order.confirmed_line_items[0]
        pre_cancellation_transactions_count = order.refund_transactions.count()
        cancelled_refund_amount = process_line_item_cancellation(third_line_item)
        self.assertEquals(cancelled_refund_amount, decimal.Decimal(0))
        self.assertEquals(pre_cancellation_transactions_count, order.refund_transactions.count())

        # test free line item cancellation
        free_order_resp = self.make_free_order()
        free_order_resp_data = json.loads(free_order_resp.data)['result']
        free_order = Order.query.get(free_order_resp_data.get('order_id'))
        free_line_item = free_order.line_items[0]
        process_line_item_cancellation(free_line_item)
        self.assertEquals(free_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        self.assertEquals(free_order.transactions.count(), 0)
Exemplo n.º 5
0
    def test_partial_refund_in_order(self):
        original_quantity = 5
        discounted_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = discounted_item.current_price(
        ).amount * original_quantity
        data = {
            'line_items': [{
                'item_id': str(discounted_item.id),
                'quantity': original_quantity
            }],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
            }
        }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id),
                                data=json.dumps(data),
                                content_type='application/json',
                                headers=[('X-Requested-With',
                                          'XMLHttpRequest'),
                                         ('Origin', app.config['BASE_URL'])])
        self.assertEqual(resp.status_code, 201)
        resp_data = json.loads(resp.data)['result']
        self.assertEqual(
            resp_data['final_amount'],
            (total_amount - 5 * total_amount / decimal.Decimal(100)))

        order = Order.query.get(resp_data['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment',
                                       order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order,
                                         online_payment=online_payment,
                                         amount=order_amounts.final_amount,
                                         currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data={'id': buid()}))
        valid_refund_amount = 500

        formdata = {
            'amount': valid_refund_amount,
            'internal_note': 'internal reference',
            'note_to_user': '******',
            'refund_description': 'test refund'
        }
        refund_form = OrderRefundForm(data=formdata,
                                      parent=order,
                                      meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)

        refund_transactions = order.transactions.filter_by(
            transaction_type=TRANSACTION_TYPE.REFUND).all()
        self.assertIsInstance(refund_transactions[0].refunded_at,
                              datetime.datetime)
        self.assertEqual(refund_transactions[0].amount,
                         decimal.Decimal(valid_refund_amount))
        self.assertEqual(refund_transactions[0].internal_note,
                         formdata['internal_note'])
        self.assertEqual(refund_transactions[0].note_to_user,
                         formdata['note_to_user'])
        self.assertEqual(refund_transactions[0].refund_description,
                         formdata['refund_description'])

        invalid_refund_amount = 100000000
        formdata = {
            'amount': invalid_refund_amount,
        }
        refund_form = OrderRefundForm(data=formdata,
                                      parent=order,
                                      meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            resp = process_partial_refund_for_order(partial_refund_args)

        self.assertEqual(resp.status_code, 403)
        refund_transactions = order.transactions.filter_by(
            transaction_type=TRANSACTION_TYPE.REFUND).all()
        self.assertEqual(refund_transactions[0].amount,
                         decimal.Decimal(valid_refund_amount))

        resp = self.make_free_order()
        self.assertEqual(resp.status_code, 201)
        resp_data = json.loads(resp.data)['result']
        order = Order.query.get(resp_data.get('order_id'))
        invalid_refund_amount = 100000000

        formdata = {
            'amount': invalid_refund_amount,
        }
        refund_form = OrderRefundForm(data=formdata,
                                      parent=order,
                                      meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            refund_resp = process_partial_refund_for_order(partial_refund_args)

        self.assertEqual(refund_resp.status_code, 403)
Exemplo n.º 6
0
    def test_cancel_line_item_in_bulk_order(self):
        original_quantity = 5
        discounted_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = discounted_item.current_price(
        ).amount * original_quantity
        data = {
            'line_items': [{
                'item_id': str(discounted_item.id),
                'quantity': original_quantity
            }],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
            }
        }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id),
                                data=json.dumps(data),
                                content_type='application/json',
                                headers=[('X-Requested-With',
                                          'XMLHttpRequest'),
                                         ('Origin', app.config['BASE_URL'])])
        self.assertEqual(resp.status_code, 201)
        resp_json = json.loads(resp.data)['result']
        self.assertEqual(
            resp_json['final_amount'],
            (total_amount - 5 * total_amount / decimal.Decimal(100)))

        order = Order.query.get(resp_json['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment',
                                       order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order,
                                         online_payment=online_payment,
                                         amount=order_amounts.final_amount,
                                         currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        first_line_item = order.line_items[0]
        to_be_void_line_items = order.line_items[1:]
        precancellation_order_amount = order.net_amount
        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data={'id': buid()}))
        process_line_item_cancellation(first_line_item)
        self.assertEqual(first_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        for void_line_item in to_be_void_line_items:
            self.assertEqual(void_line_item.status, LINE_ITEM_STATUS.VOID)
        expected_refund_amount = precancellation_order_amount - order.get_amounts(
            LINE_ITEM_STATUS.CONFIRMED).final_amount
        refund_transaction1 = PaymentTransaction.query.filter_by(
            order=order, transaction_type=TRANSACTION_TYPE.REFUND).first()
        self.assertEqual(refund_transaction1.amount, expected_refund_amount)

        second_line_item = order.confirmed_line_items[0]
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data={'id': buid()}))
        process_line_item_cancellation(second_line_item)
        self.assertEqual(second_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        refund_transaction2 = PaymentTransaction.query.filter_by(
            order=order, transaction_type=TRANSACTION_TYPE.REFUND).order_by(
                PaymentTransaction.created_at.desc()).first()
        self.assertEqual(refund_transaction2.amount,
                         second_line_item.final_amount)

        # test failed cancellation
        third_line_item = order.confirmed_line_items[0]
        razorpay.refund_payment = MagicMock(
            return_value=MockResponse(response_data={
                "error": {
                    "code": "BAD_REQUEST_ERROR",
                    "description": "The amount is invalid",
                    "field": "amount"
                }
            },
                                      status_code=400))
        self.assertRaises(
            PaymentGatewayError,
            lambda: process_line_item_cancellation(third_line_item))

        # refund the remaining amount paid, and attempt to cancel a line item
        # this should cancel the line item without resulting in a new refund transaction
        refund_amount = order.net_amount
        refund_dict = {
            'id': buid(),
            'amount': refund_amount,
            'internal_note': 'internal reference',
            'note_to_user': '******'
        }
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data=refund_dict))

        formdata = {
            'amount': refund_amount,
            'internal_note': 'internal reference',
            'refund_description': 'receipt description',
            'note_to_user': '******'
        }
        refund_form = OrderRefundForm(data=formdata,
                                      parent=order,
                                      meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)

        third_line_item = order.confirmed_line_items[0]
        pre_cancellation_transactions_count = order.refund_transactions.count()
        cancelled_refund_amount = process_line_item_cancellation(
            third_line_item)
        self.assertEqual(cancelled_refund_amount, decimal.Decimal(0))
        self.assertEqual(pre_cancellation_transactions_count,
                         order.refund_transactions.count())

        # test free line item cancellation
        free_order_resp = self.make_free_order()
        free_order_resp_data = json.loads(free_order_resp.data)['result']
        free_order = Order.query.get(free_order_resp_data.get('order_id'))
        free_line_item = free_order.line_items[0]
        process_line_item_cancellation(free_line_item)
        self.assertEqual(free_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        self.assertEqual(free_order.transactions.count(), 0)
Exemplo n.º 7
0
    def test_cancel_line_item_in_order(self):
        original_quantity = 2
        order_item = Item.query.filter_by(name='t-shirt').first()
        total_amount = order_item.current_price().amount * original_quantity
        data = {
            'line_items': [{
                'item_id': str(order_item.id),
                'quantity': original_quantity
            }],
            'buyer': {
                'fullname': 'Testing',
                'phone': '9814141414',
                'email': '*****@*****.**',
            }
        }
        ic = ItemCollection.query.first()
        # make a purchase order
        resp = self.client.post('/ic/{ic}/order'.format(ic=ic.id),
                                data=json.dumps(data),
                                content_type='application/json',
                                headers=[('X-Requested-With',
                                          'XMLHttpRequest'),
                                         ('Origin', app.config['BASE_URL'])])
        self.assertEqual(resp.status_code, 201)
        resp_json = json.loads(resp.data)['result']
        self.assertEqual(resp_json['final_amount'], total_amount)

        order = Order.query.get(resp_json['order_id'])
        # Create fake payment and transaction objects
        online_payment = OnlinePayment(pg_paymentid='pg_testpayment',
                                       order=order)
        online_payment.confirm()
        order_amounts = order.get_amounts(LINE_ITEM_STATUS.PURCHASE_ORDER)
        transaction = PaymentTransaction(order=order,
                                         online_payment=online_payment,
                                         amount=order_amounts.final_amount,
                                         currency=CURRENCY.INR)
        db.session.add(transaction)
        order.confirm_sale()
        db.session.commit()

        refund_amount = total_amount - 1
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data={'id': buid()}))
        pre_refund_transactions_count = order.refund_transactions.count()
        formdata = {
            'amount': refund_amount,
            'internal_note': 'internal reference',
            'refund_description': 'receipt description',
            'note_to_user': '******'
        }
        refund_form = OrderRefundForm(data=formdata,
                                      parent=order,
                                      meta={'csrf': False})
        partial_refund_args = {
            'order': order,
            'form': refund_form,
            'request_method': 'POST'
        }
        with app.request_context(self.post_env):
            process_partial_refund_for_order(partial_refund_args)
        self.assertEqual(pre_refund_transactions_count + 1,
                         order.refund_transactions.count())

        first_line_item = order.line_items[0]
        # Mock Razorpay's API
        razorpay.refund_payment = MagicMock(return_value=MockResponse(
            response_data={'id': buid()}))
        process_line_item_cancellation(first_line_item)
        self.assertEqual(first_line_item.status, LINE_ITEM_STATUS.CANCELLED)
        expected_refund_amount = total_amount - refund_amount
        refund_transaction1 = PaymentTransaction.query.filter_by(
            order=order, transaction_type=TRANSACTION_TYPE.REFUND).order_by(
                PaymentTransaction.created_at.desc()).first()
        self.assertEqual(refund_transaction1.amount, expected_refund_amount)