def factory_payment_account( payment_system_code: str = 'PAYBC', payment_method_code: str = 'CC', account_number='4101', bcol_user_id='test', auth_account_id: str = '1234', cfs_account_status: str = CfsAccountStatus.ACTIVE.value): """Return Factory.""" # Create a payment account account = PaymentAccount(auth_account_id=auth_account_id, bcol_user_id=bcol_user_id, bcol_account='TEST', payment_method=payment_method_code, pad_activation_date=datetime.now()).save() CfsAccount(cfs_party='11111', cfs_account=account_number, cfs_site='29921', account_id=account.id, status=cfs_account_status).save() if payment_system_code == PaymentSystem.BCOL.value: account.payment_method = PaymentMethod.DRAWDOWN.value elif payment_system_code == PaymentSystem.PAYBC.value: account.payment_method = payment_method_code return account
def test_internal_rs_back_active(session, public_user_mock): """12033 - Scenario 2. Routing slip is complete and a transaction is cancelled the balance is restored - Should move back to Active """ payment_response = PaymentService.create_invoice( get_routing_slip_payment_request(), get_auth_staff()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id')) account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None rs_number = '123456789' rs = factory_routing_slip(number=rs_number, payment_account_id=account_id, remaining_amount=50.00) rs.save() # Create another invoice with a routing slip. invoice = PaymentService.create_invoice(get_routing_slip_payment_request(), get_auth_staff()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id')) assert account_id == account_model.id rs = RoutingSlipModel.find_by_number(rs_number) assert rs.remaining_amount == 0.0 assert rs.status == RoutingSlipStatus.COMPLETE.name invoice = Invoice.find_by_id(invoice['id']) InternalPayService().process_cfs_refund(invoice) assert rs.status == RoutingSlipStatus.ACTIVE.name
def test_create_payment_record_with_internal_pay(session, public_user_mock): """Assert that the payment records are created.""" # Create invoice without routing slip. payment_response = PaymentService.create_invoice( get_routing_slip_payment_request(), get_auth_staff()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id')) account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None rs_number = '123456789' rs = factory_routing_slip(number=rs_number, payment_account_id=account_id, remaining_amount=50.00) rs.save() # Create another invoice with a routing slip. PaymentService.create_invoice(get_routing_slip_payment_request(), get_auth_staff()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_staff().get('account').get('id')) assert account_id == account_model.id rs = RoutingSlipModel.find_by_number(rs_number) assert rs.remaining_amount == 0.0 """12033 - Scenario 1. Manual transaction reduces RS to 0.00 Routing slip status becomes Completed """ assert rs.status == RoutingSlipStatus.COMPLETE.name
def test_activate_bcol_change_to_pad(session): """Test Activate account.""" # Create a pending account first, then call the job account = factory_create_pad_account( auth_account_id='1', payment_method=PaymentMethod.DRAWDOWN.value) CreateAccountTask.create_accounts() account = PaymentAccount.find_by_id(account.id) cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id( account.id) assert cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value, 'Created account has pending pad status' assert account.payment_method == PaymentMethod.DRAWDOWN.value ActivatePadAccountTask.activate_pad_accounts() cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id( account.id) assert cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value, \ 'Same day Job runs and shouldnt change anything.' account = PaymentAccount.find_by_id(account.id) assert account.payment_method == PaymentMethod.DRAWDOWN.value time_delay = current_app.config['PAD_CONFIRMATION_PERIOD_IN_DAYS'] with freeze_time(datetime.today() + timedelta(days=time_delay, minutes=1)): ActivatePadAccountTask.activate_pad_accounts() assert cfs_account.status == CfsAccountStatus.ACTIVE.value, \ 'After the confirmation period is over , status should be active' account = PaymentAccount.find_by_id(account.id) assert account.payment_method == PaymentMethod.PAD.value
def test_find_by_invalid_corp_number_and_corp_type_and_system(session): """Assert find works. Start with a blank database. """ payment_account = factory_payment_account() payment_account.save() assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'BCOL') is None assert PaymentAccount.find_by_corp_number_and_corp_type_and_system(None, None, None) is None
def test_rollback(session): """Assert rollback works. Start with a blank database. """ payment_account = factory_payment_account() payment_account.flush() assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'PAYBC') is not None payment_account.rollback() assert PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP0001234', 'CP', 'PAYBC') is None
def test_create_payment_record(session): """Assert that the payment records are created.""" payment_response = PaymentService.create_payment(get_payment_request(), 'test') account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP1234', 'CP', 'PAYBC') account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None # Create another payment with same request, the account should be the same PaymentService.create_payment(get_payment_request(), 'test') account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system('CP1234', 'CP', 'PAYBC') assert account_id == account_model.id
def test_create_payment_record(session, public_user_mock): """Assert that the payment records are created.""" payment_response = PaymentService.create_invoice(get_payment_request(), get_auth_basic_user()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id')) account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None # Create another payment with same request, the account should be the same PaymentService.create_invoice(get_payment_request(), get_auth_basic_user()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id')) assert account_id == account_model.id
def test_create_payment_record_with_direct_pay(session, public_user_mock): """Assert that the payment records are created.""" current_app.config['DIRECT_PAY_ENABLED'] = True payment_response = PaymentService.create_invoice( get_payment_request(), get_auth_basic_user(PaymentMethod.DIRECT_PAY.value)) account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id')) account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None # Create another payment with same request, the account should be the same PaymentService.create_invoice(get_payment_request(), get_auth_basic_user()) account_model = PaymentAccount.find_by_auth_account_id(get_auth_basic_user().get('account').get('id')) assert account_id == account_model.id
def _update_pad_activation_date(cls, cfs_account: CfsAccountModel, is_sandbox: bool, payment_account: PaymentAccountModel): """Update PAD activation date.""" is_pad = payment_account.payment_method == PaymentMethod.PAD.value # If the account is created for sandbox env, then set the status to ACTIVE and set pad activation time to now if is_pad and is_sandbox: cfs_account.status = CfsAccountStatus.ACTIVE.value payment_account.pad_activation_date = datetime.now() # override payment method for since pad has 3 days wait period elif is_pad: effective_pay_method, activation_date = PaymentAccount._get_payment_based_on_pad_activation( payment_account) payment_account.pad_activation_date = activation_date payment_account.payment_method = effective_pay_method
def test_get_monthly_statement_report_as_csv(session, client, jwt, app): """Assert that the monthly statement report is returning response.""" # Create a payment account and statement details, then get all statements for the account token = jwt.create_jwt(get_claims(), token_header) headers = { 'Authorization': f'Bearer {token}', 'content-type': 'application/json', 'Accept': ContentType.CSV.value } rv = client.post('/api/v1/payment-requests', data=json.dumps( get_payment_request(business_identifier='CP0002000')), headers=headers) payment: Payment = Payment.find_by_id(rv.json.get('id')) bcol_account: BcolPaymentAccount = BcolPaymentAccount.find_by_id( payment.invoices[0].bcol_account_id) pay_account: PaymentAccount = PaymentAccount.find_by_id( bcol_account.account_id) settings_model = factory_statement_settings( payment_account_id=pay_account.id, frequency=StatementFrequency.DAILY.value) statement_model = factory_statement( payment_account_id=pay_account.id, frequency=StatementFrequency.DAILY.value, statement_settings_id=settings_model.id) factory_statement_invoices(statement_id=statement_model.id, invoice_id=payment.invoices[0].id) rv = client.get( f'/api/v1/accounts/{pay_account.auth_account_id}/statements/{statement_model.id}', headers=headers) assert rv.status_code == 200
def test_statement_find_by_account(session): """Assert that the statement settings by id works.""" bcol_account = factory_premium_payment_account() bcol_account.save() payment = factory_payment() payment.save() i = factory_invoice(payment_account=bcol_account) i.save() factory_invoice_reference(i.id).save() settings_model = factory_statement_settings( payment_account_id=bcol_account.id, frequency=StatementFrequency.DAILY.value) statement_model = factory_statement( payment_account_id=bcol_account.id, frequency=StatementFrequency.DAILY.value, statement_settings_id=settings_model.id) factory_statement_invoices(statement_id=statement_model.id, invoice_id=i.id) payment_account = PaymentAccount.find_by_id(bcol_account.id) statements = StatementService.find_by_account_id( payment_account.auth_account_id, page=1, limit=10) assert statements is not None assert statements.get('total') == 1
def create_accounts(cls): # pylint: disable=too-many-locals """Find all pending accounts to be created in CFS. Steps: 1. Find all pending CFS accounts. 2. Create CFS accounts. 3. Publish a message to the queue if successful. """ # Pass payment method if offline account creation has be restricted based on payment method. pending_accounts: List[ CfsAccountModel] = CfsAccountModel.find_all_pending_accounts() current_app.logger.info( f'Found {len(pending_accounts)} CFS Accounts to be created.') if len(pending_accounts) == 0: return auth_token = get_token() for pending_account in pending_accounts: # Find the payment account and create the pay system instance. pay_account: PaymentAccountModel = PaymentAccountModel.find_by_id( pending_account.account_id) if pay_account.payment_method in (PaymentMethod.CASH.value, PaymentMethod.CHEQUE.value): routing_slip.create_cfs_account(pending_account, pay_account) else: cls._create_cfs_account(pending_account, pay_account, auth_token)
def test_update_statement_daily_to_daily(session): """Assert that going from daily to daily creates a new record.""" bcol_account = factory_premium_payment_account() bcol_account.save() payment = factory_payment() payment.save() i = factory_invoice(payment_account=bcol_account) i.save() factory_invoice_reference(i.id).save() factory_statement_settings(payment_account_id=bcol_account.id, frequency=StatementFrequency.DAILY.value) # update to weekly payment_account = PaymentAccount.find_by_id(bcol_account.id) statement_settings = StatementSettingsService.update_statement_settings(payment_account.auth_account_id, StatementFrequency.DAILY.value) assert statement_settings is not None assert statement_settings.get('frequency') == StatementFrequency.DAILY.value assert statement_settings.get('to_date') is None # daily to daily - assert daily should start by tomorow assert statement_settings.get('from_date') == (datetime.today() + timedelta(days=1)).strftime('%Y-%m-%d') # daily to daily - assert current active one is stil daily ending today current_statement_settings = StatementSettingsModel.find_active_settings(payment_account.auth_account_id, datetime.today()) assert current_statement_settings is not None assert current_statement_settings.frequency == StatementFrequency.DAILY.value assert current_statement_settings.to_date == datetime.today().date()
def test_create_ejv_payment_request(session, client, jwt, app): """Assert payment request works for EJV accounts.""" token = jwt.create_jwt(get_claims(role=Role.SYSTEM.value), token_header) headers = { 'Authorization': f'Bearer {token}', 'content-type': 'application/json' } # Create account first rv = client.post('/api/v1/accounts', data=json.dumps(get_gov_account_payload(account_id=1234)), headers=headers) auth_account_id = rv.json.get('authAccountId') payment_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id( auth_account_id) dist_code: DistributionCodeModel = DistributionCodeModel.find_by_active_for_account( payment_account.id) assert dist_code assert dist_code.account_id == payment_account.id token = jwt.create_jwt(get_claims(), token_header) headers = { 'Authorization': f'Bearer {token}', 'content-type': 'application/json', 'Account-Id': auth_account_id } rv = client.post('/api/v1/payment-requests', data=json.dumps(get_payment_request()), headers=headers) assert rv.json.get('paymentMethod') == PaymentMethod.EJV.value assert rv.json.get('statusCode') == InvoiceStatus.APPROVED.value
def delete_account(cls, auth_account_id: str) -> PaymentAccount: """Delete the payment account.""" current_app.logger.debug('<delete_account') pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id( auth_account_id) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( pay_account.id) # 1 - Check if account have any credits # 2 - Check if account have any PAD transactions done in last N (10) days. if pay_account.credit and pay_account.credit > 0: raise BusinessException(Error.OUTSTANDING_CREDIT) # Check if account is frozen. cfs_status: str = cfs_account.status if cfs_account else None if cfs_status == CfsAccountStatus.FREEZE.value: raise BusinessException(Error.FROZEN_ACCOUNT) if InvoiceModel.find_outstanding_invoices_for_account( pay_account.id, get_outstanding_txns_from_date()): # Check if there is any recent PAD transactions in N days. raise BusinessException(Error.TRANSACTIONS_IN_PROGRESS) # If CFS Account present, mark it as INACTIVE. if cfs_status and cfs_status != CfsAccountStatus.INACTIVE.value: cfs_account.status = CfsAccountStatus.INACTIVE.value # If account is active or pending pad activation stop PAD payments. if pay_account.payment_method == PaymentMethod.PAD.value \ and cfs_status in [CfsAccountStatus.ACTIVE.value, CfsAccountStatus.PENDING_PAD_ACTIVATION.value]: CFSService.suspend_cfs_account(cfs_account) cfs_account.save() if pay_account.statement_notification_enabled: pay_account.statement_notification_enabled = False pay_account.save()
def create_payment_receipt(auth_account_id: str, credit_request: Dict[str, str], **kwargs) -> Payment: """Create a payment record for the account.""" pay_account: PaymentAccountModel = PaymentAccountModel.find_by_auth_account_id( auth_account_id) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( pay_account.id) # Create a payment record # Create a receipt in CFS for the amount. payment = Payment.create( payment_method=credit_request.get('paymentMethod'), payment_system=PaymentSystem.PAYBC.value, payment_account_id=pay_account.id) receipt_number: str = generate_receipt_number(payment.id) receipt_date = credit_request.get('paymentDate') amount = credit_request.get('paidAmount') receipt_response = CFSService.create_cfs_receipt( cfs_account=cfs_account, rcpt_number=receipt_number, rcpt_date=receipt_date, amount=amount, payment_method=credit_request.get('paymentMethod')) payment.receipt_number = receipt_response.get('receipt_number', receipt_number) payment.paid_amount = amount payment.created_by = kwargs['user'].user_name payment.payment_date = parser.parse(receipt_date) payment.payment_status_code = PaymentStatus.COMPLETED.value payment.save() return payment
def test_get_statement_report_for_empty_invoices(session): """Assert that the get statement report works for statement with no invoices.""" bcol_account = factory_premium_payment_account() bcol_account.save() payment = factory_payment() payment.save() i = factory_invoice(payment_account=bcol_account) i.save() factory_invoice_reference(i.id).save() factory_payment_line_item(invoice_id=i.id, fee_schedule_id=1).save() settings_model = factory_statement_settings( payment_account_id=bcol_account.id, frequency=StatementFrequency.DAILY.value) statement_model = factory_statement( payment_account_id=bcol_account.id, frequency=StatementFrequency.DAILY.value, statement_settings_id=settings_model.id) payment_account = PaymentAccount.find_by_id(bcol_account.id) statements = StatementService.find_by_account_id( payment_account.auth_account_id, page=1, limit=10) assert statements is not None report_response, report_name = StatementService.get_statement_report( statement_id=statement_model.id, content_type='application/pdf', auth=get_auth_premium_user()) assert report_response is not None
def test_update_pad_account(session): """Test update account.""" # Create a pending account first, then call the job account = factory_create_pad_account(auth_account_id='2') CreateAccountTask.create_accounts() account = PaymentAccount.find_by_id(account.id) cfs_account = CfsAccount.find_effective_by_account_id(account.id) assert cfs_account.payment_instrument_number # Now update the account. new_payment_details = { 'bankInstitutionNumber': '111', 'bankTransitNumber': '222', 'bankAccountNumber': '3333333333' } PadService().update_account(name='Test', cfs_account=cfs_account, payment_info=new_payment_details) cfs_account = CfsAccount.find_by_id(cfs_account.id) # Run the job again CreateAccountTask.create_accounts() updated_cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(account.id) assert updated_cfs_account.id != cfs_account.id assert updated_cfs_account.bank_account_number == new_payment_details.get('bankAccountNumber') assert updated_cfs_account.bank_branch_number == new_payment_details.get('bankTransitNumber') assert updated_cfs_account.bank_number == new_payment_details.get('bankInstitutionNumber') assert cfs_account.status == CfsAccountStatus.INACTIVE.value assert updated_cfs_account.status == CfsAccountStatus.PENDING_PAD_ACTIVATION.value assert updated_cfs_account.payment_instrument_number
def test_create_zero_dollar_payment_record(session, public_user_mock): """Assert that the payment records are created and completed.""" payment_response = PaymentService.create_payment( get_zero_dollar_payment_request()) account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system( 'CP0001234', 'CP', 'INTERNAL') account_id = account_model.id assert account_id is not None assert payment_response.get('id') is not None assert payment_response.get('status_code') == 'COMPLETED' # Create another payment with same request, the account should be the same PaymentService.create_payment(get_zero_dollar_payment_request()) account_model = PaymentAccount.find_by_corp_number_and_corp_type_and_system( 'CP0001234', 'CP', 'INTERNAL') assert account_id == account_model.id assert payment_response.get('status_code') == 'COMPLETED'
def factory_payment_account(corp_number: str = 'CP1234', corp_type_code='CP', payment_system_code='PAYBC'): """Factory.""" return PaymentAccount(corp_number=corp_number, corp_type_code=corp_type_code, payment_system_code=payment_system_code)
def factory_premium_payment_account(bcol_user_id='PB25020', bcol_account_id='1234567890', auth_account_id='1234'): """Return Factory.""" account = PaymentAccount(auth_account_id=auth_account_id, bcol_user_id=bcol_user_id, bcol_account=bcol_account_id, ) return account
def _apply_routing_slips_to_pending_invoices(cls, routing_slip: RoutingSlipModel) -> float: """Apply the routing slips again, when routing slip is linked to an NSF parent.""" current_app.logger.info(f'Starting NSF recovery process for {routing_slip.number}') routing_slip_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id( routing_slip.payment_account_id) # apply invoice to the active CFS_ACCOUNT which will be the parent routing slip active_cfs_account = CfsAccountModel.find_effective_by_account_id(routing_slip_payment_account.id) invoices: List[InvoiceModel] = db.session.query(InvoiceModel) \ .filter(InvoiceModel.routing_slip == routing_slip.number, InvoiceModel.invoice_status_code.in_([InvoiceStatus.CREATED.value, InvoiceStatus.APPROVED.value])) \ .all() current_app.logger.info(f'Found {len(invoices)} to apply receipt') applied_amount = 0 for inv in invoices: inv_ref: InvoiceReferenceModel = InvoiceReferenceModel.find_reference_by_invoice_id_and_status( inv.id, InvoiceReferenceStatus.ACTIVE.value ) cls.apply_routing_slips_to_invoice( routing_slip_payment_account, active_cfs_account, routing_slip, inv, inv_ref.invoice_number ) # IF invoice balance is zero, then update records. if CFSService.get_invoice(cfs_account=active_cfs_account, inv_number=inv_ref.invoice_number) \ .get('amount_due') == 0: applied_amount += inv.total inv_ref.status_code = InvoiceReferenceStatus.COMPLETED.value inv.invoice_status_code = InvoiceStatus.PAID.value return applied_amount
def factory_payment_account(corp_number: str = 'CP0001234', corp_type_code: str = 'CP', payment_system_code: str = 'PAYBC', account_number='4101', bcol_user_id='test', auth_account_id: str = '1234'): """Factory.""" # Create a payment account account = PaymentAccount(auth_account_id=auth_account_id).save() if payment_system_code == PaymentSystem.BCOL.value: return BcolPaymentAccount(bcol_user_id=bcol_user_id, bcol_account_id='TEST', account_id=account.id) elif payment_system_code == PaymentSystem.PAYBC.value: return CreditPaymentAccount(corp_number=corp_number, corp_type_code=corp_type_code, paybc_party='11111', paybc_account=account_number, paybc_site='29921', account_id=account.id) elif payment_system_code == PaymentSystem.INTERNAL.value: return InternalPaymentAccount(corp_number=corp_number, corp_type_code=corp_type_code, account_id=account.id)
def _notify_for_ob(cls): # pylint: disable=too-many-locals """Notify for online banking. 1) Find the accounts with pending invoices 2) get total remaining for that account """ unpaid_status = (InvoiceStatus.SETTLEMENT_SCHEDULED.value, InvoiceStatus.PARTIAL.value, InvoiceStatus.CREATED.value) notification_date = datetime.today() - timedelta( days=current_app.config.get('NOTIFY_AFTER_DAYS')) # Get distinct accounts with pending invoices for that exact day notification_pending_accounts = db.session.query( InvoiceModel.payment_account_id ).distinct().filter( and_( InvoiceModel.invoice_status_code.in_(unpaid_status), InvoiceModel.payment_method_code == PaymentMethod.ONLINE_BANKING.value, # cast is used to get the exact match stripping the timestamp from date cast(InvoiceModel.created_on, Date) == notification_date.date())).all() current_app.logger.debug( f'Found {len(notification_pending_accounts)} invoices to notify admins.' ) for payment_account in notification_pending_accounts: try: payment_account_id = payment_account[0] total = db.session.query( func.sum(InvoiceModel.total).label('total') ).filter( and_( InvoiceModel.invoice_status_code.in_(unpaid_status), InvoiceModel.payment_account_id == payment_account_id, InvoiceModel.payment_method_code == PaymentMethod.ONLINE_BANKING.value)).group_by( InvoiceModel.payment_account_id).all() pay_account: PaymentAccountModel = \ PaymentAccountModel.find_by_id(payment_account_id) cfs_account = CfsAccountModel.find_effective_by_account_id( payment_account_id) # emit account mailer event addition_params_to_mailer = { 'transactionAmount': total[0][0], 'cfsAccountId': cfs_account.cfs_account, 'authAccountId': pay_account.auth_account_id, } mailer.publish_mailer_events('ob.outstandingInvoice', pay_account, addition_params_to_mailer) except Exception as e: # NOQA # pylint: disable=broad-except capture_message( f'Error on notifying mailer OB Pending invoice: account id={pay_account.id}, ' f'auth account : {pay_account.auth_account_id}, ERROR : {str(e)}', level='error') current_app.logger.error(e)
def activate_pad_account(auth_account_id: str): """Activate the pad account.""" payment_account: PaymentAccount = PaymentAccount.find_by_auth_account_id(auth_account_id) payment_account.pad_activation_date = datetime.now() payment_account.save() cfs_account: CfsAccount = CfsAccount.find_effective_by_account_id(payment_account.id) cfs_account.status = 'ACTIVE' cfs_account.save()
def factory_create_wire_account(auth_account_id='1234', status=CfsAccountStatus.PENDING.value): """Return Factory.""" account = PaymentAccount(auth_account_id=auth_account_id, payment_method=PaymentMethod.WIRE.value, name=f'Test {auth_account_id}').save() CfsAccount(status=status, account_id=account.id).save() return account
def _cancel_rs_invoices(cls): """Cancel routing slip invoices in CFS.""" invoices: List[InvoiceModel] = InvoiceModel.query \ .filter(InvoiceModel.payment_method_code == PaymentMethod.INTERNAL.value) \ .filter(InvoiceModel.invoice_status_code == InvoiceStatus.REFUND_REQUESTED.value) \ .filter(InvoiceModel.routing_slip is not None) \ .order_by(InvoiceModel.created_on.asc()).all() current_app.logger.info( f'Found {len(invoices)} to be cancelled in CFS.') for invoice in invoices: # call unapply rcpts # adjust invoice to zero current_app.logger.debug(f'Calling the invoice {invoice.id}') routing_slip = RoutingSlipModel.find_by_number( invoice.routing_slip) routing_slip_payment_account: PaymentAccountModel = PaymentAccountModel.find_by_id( routing_slip.payment_account_id) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( routing_slip_payment_account.id) # Find COMPLETED invoice reference; as unapply has to be done only if invoice is created and applied in CFS. invoice_reference = InvoiceReferenceModel. \ find_reference_by_invoice_id_and_status(invoice.id, status_code=InvoiceReferenceStatus.COMPLETED.value) if invoice_reference: current_app.logger.debug( f'Found invoice reference - {invoice_reference.invoice_number}' ) try: # find receipts against the invoice and unapply # apply receipt now receipts: List[ ReceiptModel] = ReceiptModel.find_all_receipts_for_invoice( invoice_id=invoice.id) for receipt in receipts: CFSService.unapply_receipt( cfs_account, receipt.receipt_number, invoice_reference.invoice_number) adjustment_negative_amount = -invoice.total CFSService.adjust_invoice( cfs_account=cfs_account, inv_number=invoice_reference.invoice_number, amount=adjustment_negative_amount) except Exception as e: # NOQA # pylint: disable=broad-except capture_message( f'Error on canelling Routing Slip invoice: invoice id={invoice.id}, ' f'routing slip : {routing_slip.id}, ERROR : {str(e)}', level='error') current_app.logger.error(e) # TODO stop execution ? what should be the invoice stats ; should we set it to error or retry? continue invoice_reference.status_code = InvoiceReferenceStatus.CANCELLED.value invoice.invoice_status_code = InvoiceStatus.REFUNDED.value invoice.save()
def _save_account(cls, account_request: Dict[str, any], payment_account: PaymentAccountModel, is_sandbox: bool = False): """Update and save payment account and CFS account model.""" # pylint:disable=cyclic-import, import-outside-toplevel from pay_api.factory.payment_system_factory import PaymentSystemFactory payment_account.auth_account_id = account_request.get('accountId') # If the payment method is CC, set the payment_method as DIRECT_PAY if payment_method := get_str_by_path(account_request, 'paymentInfo/methodOfPayment'): payment_account.payment_method = payment_method payment_account.bcol_account = account_request.get( 'bcolAccountNumber', None) payment_account.bcol_user_id = account_request.get( 'bcolUserId', None)
def find_by_id(cls, account_id: int): """Find pay account by id.""" current_app.logger.debug('<find_by_id') account = PaymentAccount() account._dao = PaymentAccountModel.find_by_id(account_id) # pylint: disable=protected-access current_app.logger.debug('>find_by_id') return account