def test_create_pad_invoice_multiple_transactions(session): """Assert PAD invoices are created.""" # Create an account and an invoice for the account account = factory_create_pad_account(auth_account_id='1', status=CfsAccountStatus.ACTIVE.value) previous_day = datetime.now() - timedelta(days=1) # Create an invoice for this account invoice = factory_invoice(payment_account=account, created_on=previous_day, total=10, payment_method_code=None) fee_schedule = FeeScheduleModel.find_by_filing_type_and_corp_type( 'CP', 'OTANN') line = factory_payment_line_item( invoice.id, fee_schedule_id=fee_schedule.fee_schedule_id) line.save() # Create another invoice for this account invoice2 = factory_invoice(payment_account=account, created_on=previous_day, total=10, payment_method_code=None) fee_schedule2 = FeeScheduleModel.find_by_filing_type_and_corp_type( 'CP', 'OTADD') line2 = factory_payment_line_item( invoice2.id, fee_schedule_id=fee_schedule2.fee_schedule_id) line2.save() CreateInvoiceTask.create_invoices() invoice2 = InvoiceModel.find_by_id(invoice2.id) invoice = InvoiceModel.find_by_id(invoice.id) assert invoice2.invoice_status_code == invoice.invoice_status_code == InvoiceStatus.SETTLEMENT_SCHEDULED.value
def test_update_distribution(session, public_user_mock, stan_server, monkeypatch): """Assert that the invoice status is updated when the distribution is updated.""" # 1. Create a distribution code # 2. Attach a fee schedule to the distribution # 3. Create and complete payment # 4. Update the distribution and assert the invoice status is changed. distribution_code_svc = services.DistributionCode() fee_schedule = FeeSchedule.find_by_filing_type_and_corp_type('CP', 'OTANN') # Create a direct pay current_app.config['DIRECT_PAY_ENABLED'] = True payment_account = factory_payment_account( payment_method_code=PaymentMethod.DIRECT_PAY.value) payment_account.save() invoice = factory_invoice(payment_account, total=30) invoice.save() invoice_reference = factory_invoice_reference(invoice.id).save() line = factory_payment_line_item( invoice.id, fee_schedule_id=fee_schedule.fee_schedule_id) line.save() factory_payment(invoice_number=invoice_reference.invoice_number, payment_method_code=PaymentMethod.DIRECT_PAY.value, invoice_amount=30).save() distribution_id = line.fee_distribution_id distribution_code = distribution_code_svc.find_by_id(distribution_id) transaction = PaymentTransactionService.create_transaction_for_invoice( invoice.id, get_paybc_transaction_request()) def get_receipt(cls, payment_account, pay_response_url: str, invoice_reference): # pylint: disable=unused-argument; mocks of library methods return '1234567890', datetime.now(), 30.00 monkeypatch.setattr( 'pay_api.services.direct_pay_service.DirectPayService.get_receipt', get_receipt) # Update transaction without response url, which should update the receipt PaymentTransactionService.update_transaction(transaction.id, pay_response_url=None) invoice = InvoiceModel.find_by_id(invoice.id) assert invoice.invoice_status_code == InvoiceStatus.PAID.value # Update distribution code distribution_code_svc.save_or_update(distribution_code, distribution_id) invoice = InvoiceModel.find_by_id(invoice.id) assert invoice.invoice_status_code == InvoiceStatus.UPDATE_REVENUE_ACCOUNT.value
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 create_refund(cls, invoice_id: int, request: Dict[str, str], **kwargs) -> None: """Create refund.""" current_app.logger.debug('<create refund') # Do validation by looking up the invoice invoice: InvoiceModel = InvoiceModel.find_by_id(invoice_id) # Allow refund only for direct pay payments, and only if the status of invoice is PAID/UPDATE_REVENUE_ACCOUNT paid_statuses = (InvoiceStatus.PAID.value, InvoiceStatus.APPROVED.value, InvoiceStatus.UPDATE_REVENUE_ACCOUNT.value) if invoice.invoice_status_code not in paid_statuses: raise BusinessException(Error.INVALID_REQUEST) refund: RefundService = RefundService() refund.invoice_id = invoice_id refund.reason = get_str_by_path(request, 'reason') refund.requested_by = kwargs['user'].user_name refund.requested_date = datetime.now() refund.flush() cls._process_cfs_refund(invoice) # set invoice status invoice.invoice_status_code = InvoiceStatus.REFUND_REQUESTED.value invoice.refund = invoice.total # no partial refund invoice.save()
def test_create_duplicate_refund_for_paid_invoice(session, monkeypatch): """Assert that the create duplicate refund fails for paid invoices.""" payment_account = factory_payment_account() payment_account.save() i = factory_invoice(payment_account=payment_account) i.save() inv_ref = factory_invoice_reference(i.id) inv_ref.status_code = InvoiceReferenceStatus.COMPLETED.value inv_ref.save() payment = factory_payment(invoice_number=inv_ref.invoice_number).save() factory_payment_transaction(payment_id=payment.id, status_code=TransactionStatus.COMPLETED.value).save() i.invoice_status_code = InvoiceStatus.PAID.value i.save() factory_receipt(invoice_id=i.id).save() monkeypatch.setattr('pay_api.services.payment_transaction.publish_response', lambda *args, **kwargs: None) RefundService.create_refund(invoice_id=i.id, request={'reason': 'Test'}) i = InvoiceModel.find_by_id(i.id) payment: PaymentModel = PaymentModel.find_by_id(payment.id) assert i.invoice_status_code == InvoiceStatus.REFUND_REQUESTED.value assert payment.payment_status_code == PaymentStatus.REFUNDED.value with pytest.raises(Exception) as excinfo: RefundService.create_refund(invoice_id=i.id, request={'reason': 'Test'}) assert excinfo.type == BusinessException
def test_create_refund_for_paid_invoice(session, monkeypatch, payment_method, invoice_status, pay_status, has_reference, expected_inv_status): """Assert that the create refund succeeds for paid invoices.""" expected = REFUND_SUCCESS_MESSAGES[f'{payment_method}.{invoice_status}'] payment_account = factory_payment_account() payment_account.save() i = factory_invoice(payment_account=payment_account, payment_method_code=payment_method) i.save() if has_reference: inv_ref = factory_invoice_reference(i.id) inv_ref.status_code = InvoiceReferenceStatus.COMPLETED.value inv_ref.save() payment = factory_payment(invoice_number=inv_ref.invoice_number, payment_status_code=pay_status).save() factory_payment_transaction(payment_id=payment.id, status_code=TransactionStatus.COMPLETED.value).save() i.invoice_status_code = invoice_status i.save() factory_receipt(invoice_id=i.id).save() monkeypatch.setattr('pay_api.services.payment_transaction.publish_response', lambda *args, **kwargs: None) message = RefundService.create_refund(invoice_id=i.id, request={'reason': 'Test'}) i = InvoiceModel.find_by_id(i.id) assert i.invoice_status_code == expected_inv_status assert message['message'] == expected
def _process_partial_paid_invoices(inv_ref: InvoiceReferenceModel, row): """Process partial payments. Update Payment as COMPLETED. Update Transaction is COMPLETED. Update Invoice as PARTIAL. """ receipt_date: datetime = datetime.strptime( _get_row_value(row, Column.APP_DATE), '%d-%b-%y') receipt_number: str = _get_row_value(row, Column.APP_ID) inv: InvoiceModel = InvoiceModel.find_by_id(inv_ref.invoice_id) _validate_account(inv, row) logger.debug('Partial Invoice. Invoice Reference ID : %s, invoice ID : %s', inv_ref.id, inv_ref.invoice_id) inv.invoice_status_code = InvoiceStatus.PARTIAL.value inv.paid = inv.total - float( _get_row_value(row, Column.TARGET_TXN_OUTSTANDING)) # Create Receipt records receipt: ReceiptModel = ReceiptModel() receipt.receipt_date = receipt_date receipt.receipt_amount = float(_get_row_value(row, Column.APP_AMOUNT)) receipt.invoice_id = inv.id receipt.receipt_number = receipt_number db.session.add(receipt)
async def _process_paid_invoices(inv_references, row): """Process PAID invoices. Update invoices as PAID Update payment as COMPLETED Update invoice_reference as COMPLETED Update payment_transaction as COMPLETED. """ receipt_date: datetime = datetime.strptime( _get_row_value(row, Column.APP_DATE), '%d-%b-%y') receipt_number: str = _get_row_value(row, Column.SOURCE_TXN_NO) for inv_ref in inv_references: inv_ref.status_code = InvoiceReferenceStatus.COMPLETED.value # Find invoice, update status inv: InvoiceModel = InvoiceModel.find_by_id(inv_ref.invoice_id) _validate_account(inv, row) logger.debug( 'PAID Invoice. Invoice Reference ID : %s, invoice ID : %s', inv_ref.id, inv_ref.invoice_id) inv.invoice_status_code = InvoiceStatus.PAID.value inv.paid = inv.total # Create Receipt records receipt: ReceiptModel = ReceiptModel() receipt.receipt_date = receipt_date receipt.receipt_amount = inv.total receipt.invoice_id = inv.id receipt.receipt_number = receipt_number db.session.add(receipt) # Publish to the queue if it's an Online Banking payment if inv.payment_method_code == PaymentMethod.ONLINE_BANKING.value: logger.debug('Publishing payment event for OB. Invoice : %s', inv.id) await _publish_payment_event(inv)
def test_create_pad_invoice_for_frozen_accounts(session): """Assert PAD invoices are created.""" # Create an account and an invoice for the account account = factory_create_pad_account(auth_account_id='1', status=CfsAccountStatus.FREEZE.value) previous_day = datetime.now() - timedelta(days=1) # Create an invoice for this account invoice = factory_invoice(payment_account=account, created_on=previous_day, total=10, payment_method_code=None) fee_schedule = FeeScheduleModel.find_by_filing_type_and_corp_type( 'CP', 'OTANN') line = factory_payment_line_item( invoice.id, fee_schedule_id=fee_schedule.fee_schedule_id) line.save() assert invoice.invoice_status_code == InvoiceStatus.CREATED.value CreateInvoiceTask.create_invoices() updated_invoice: InvoiceModel = InvoiceModel.find_by_id(invoice.id) inv_ref: InvoiceReferenceModel = InvoiceReferenceModel. \ find_reference_by_invoice_id_and_status(invoice.id, InvoiceReferenceStatus.ACTIVE.value) assert inv_ref is None assert updated_invoice.invoice_status_code == InvoiceStatus.CREATED.value
def test_create_refund_with_existing_routing_slip(session, client, jwt, app, stan_server): """Assert that the endpoint returns 202.""" claims = get_claims(roles=[ Role.FAS_CREATE.value, Role.FAS_SEARCH.value, Role.FAS_REFUND.value, Role.STAFF.value, 'make_payment' ]) token = jwt.create_jwt(claims, token_header) headers = { 'Authorization': f'Bearer {token}', 'content-type': 'application/json' } payload = get_routing_slip_request() routingslip_amount = payload.get('payments')[0].get('paidAmount') rv = client.post('/api/v1/fas/routing-slips', data=json.dumps(payload), headers=headers) rs_number = rv.json.get('number') headers = { 'Authorization': f'Bearer {token}', 'content-type': 'application/json' } data = get_payment_request() data['accountInfo'] = {'routingSlip': rs_number} rv = client.post('/api/v1/payment-requests', data=json.dumps(data), headers=headers) inv_id = rv.json.get('id') total = rv.json.get('total') rv = client.post('/api/v1/fas/routing-slips/queries', data=json.dumps({'routingSlipNumber': rs_number}), headers=headers) items = rv.json.get('items') inv: InvoiceModel = InvoiceModel.find_by_id(inv_id) inv.invoice_status_code = InvoiceStatus.PAID.value inv.save() assert items[0].get('remainingAmount') == payload.get('payments')[0].get( 'paidAmount') - total rv = client.post(f'/api/v1/payment-requests/{inv_id}/refunds', data=json.dumps({'reason': 'Test'}), headers=headers) assert rv.status_code == 202 assert rv.json.get( 'message') == REFUND_SUCCESS_MESSAGES['INTERNAL.REFUND_REQUESTED'] rv = client.post('/api/v1/fas/routing-slips/queries', data=json.dumps({'routingSlipNumber': rs_number}), headers=headers) # asssert refund amount goes to routing slip back assert rv.json.get('items')[0].get('remainingAmount') == routingslip_amount
def _process_failed_payments(row): """Handle failed payments.""" # 1. Set the cfs_account status as FREEZE. # 2. Call cfs api to Stop further PAD on this account. # 3. Reverse the invoice_reference status to ACTIVE, invoice status to SETTLEMENT_SCHED, and delete receipt. # 4. Create an NSF invoice for this account. # 5. Create invoice reference for the newly created NSF invoice. # 6. Adjust invoice in CFS to include NSF fees. inv_number = _get_row_value(row, Column.TARGET_TXN_NO) # If there is a FAILED payment record for this; it means it's a duplicate event. Ignore it. payment: PaymentModel = PaymentModel.find_payment_by_invoice_number_and_status( inv_number, PaymentStatus.FAILED.value) if payment: logger.info('Ignoring duplicate NSF message for invoice : %s ', inv_number) return # Set CFS Account Status. payment_account: PaymentAccountModel = _get_payment_account(row) cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( payment_account.id) logger.info('setting payment account id : %s status as FREEZE', payment_account.id) cfs_account.status = CfsAccountStatus.FREEZE.value # Call CFS to stop any further PAD transactions on this account. CFSService.suspend_cfs_account(cfs_account) # Find the invoice_reference for this invoice and mark it as ACTIVE. inv_references: List[InvoiceReferenceModel] = db.session.query(InvoiceReferenceModel). \ filter(InvoiceReferenceModel.status_code == InvoiceReferenceStatus.COMPLETED.value). \ filter(InvoiceReferenceModel.invoice_number == inv_number). \ all() # Update status to ACTIVE, if it was marked COMPLETED for inv_reference in inv_references: inv_reference.status_code = InvoiceReferenceStatus.ACTIVE.value # Find receipt and delete it. receipt: ReceiptModel = ReceiptModel.find_by_invoice_id_and_receipt_number( invoice_id=inv_reference.invoice_id) if receipt: db.session.delete(receipt) # Find invoice and update the status to SETTLEMENT_SCHED invoice: InvoiceModel = InvoiceModel.find_by_id( identifier=inv_reference.invoice_id) invoice.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value invoice.paid = 0 # Create an invoice for NSF for this account invoice = _create_nsf_invoice(cfs_account, inv_number, payment_account) # Adjust CFS invoice CFSService.add_nsf_adjustment(cfs_account=cfs_account, inv_number=inv_number, amount=invoice.total)
def test_patch_transaction_for_nsf_payment(session, monkeypatch): """Assert that the payment is saved to the table.""" # Create a FAILED payment (NSF), then clone the payment to create another one for CC payment # Create a transaction and assert it's success. # Patch transaction and check the status of records inv_number_1 = 'REG00001' payment_account = factory_payment_account( cfs_account_status=CfsAccountStatus.FREEZE.value, payment_method_code='PAD').save() invoice_1 = factory_invoice(payment_account, total=100) invoice_1.save() factory_payment_line_item(invoice_id=invoice_1.id, fee_schedule_id=1).save() factory_invoice_reference(invoice_1.id, invoice_number=inv_number_1).save() payment_1 = factory_payment(payment_status_code='FAILED', payment_account_id=payment_account.id, invoice_number=inv_number_1, invoice_amount=100, payment_method_code=PaymentMethod.PAD.value) payment_1.save() # Create payment for NSF payment. payment_2 = factory_payment(payment_status_code='CREATED', payment_account_id=payment_account.id, invoice_number=inv_number_1, invoice_amount=100, payment_method_code=PaymentMethod.CC.value) payment_2.save() def get_receipt(cls, payment_account, pay_response_url: str, invoice_reference): # pylint: disable=unused-argument; mocks of library methods return '1234567890', datetime.now(), 100.00 monkeypatch.setattr( 'pay_api.services.paybc_service.PaybcService.get_receipt', get_receipt) txn = PaymentTransactionService.create_transaction_for_payment( payment_2.id, get_paybc_transaction_request()) txn = PaymentTransactionService.update_transaction( txn.id, pay_response_url='receipt_number=123451') assert txn.status_code == 'COMPLETED' payment_2 = Payment.find_by_id(payment_2.id) assert payment_2.payment_status_code == 'COMPLETED' invoice_1: Invoice = Invoice.find_by_id(invoice_1.id) assert invoice_1.invoice_status_code == 'PAID' cfs_account = CfsAccount.find_effective_by_account_id(payment_account.id) assert cfs_account.status == 'ACTIVE'
def find_by_id(identifier: int, pay_id: int = None, skip_auth_check: bool = False): """Find invoice by id.""" invoice_dao = InvoiceModel.find_by_id(identifier) if not pay_id else InvoiceModel.find_by_id_and_payment_id( identifier, pay_id) if not invoice_dao: raise BusinessException(Error.INVALID_INVOICE_ID) if not skip_auth_check: Invoice._check_for_auth(invoice_dao) invoice = Invoice() invoice._dao = invoice_dao # pylint: disable=protected-access current_app.logger.debug('>find_by_id') return invoice
async def test_eft_wire_reconciliations(session, app, stan_server, event_loop, client_id, events_stan, future, mock_publish): """Test Reconciliations worker.""" # Call back for the subscription from reconciliations.worker import cb_subscription_handler # Create a Credit Card Payment # register the handler to test it await subscribe_to_queue( events_stan, current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'), cb_subscription_handler) # 1. Create payment account # 2. Create invoice and related records # 3. Create CFS Invoice records # 4. Create a CFS settlement file, and verify the records cfs_account_number = '1234' pay_account: PaymentAccountModel = factory_create_online_banking_account( status=CfsAccountStatus.ACTIVE.value, cfs_account=cfs_account_number) invoice: InvoiceModel = factory_invoice( payment_account=pay_account, total=100, service_fees=10.0, payment_method_code=PaymentMethod.ONLINE_BANKING.value) factory_payment_line_item(invoice_id=invoice.id, filing_fees=90.0, service_fees=10.0, total=90.0) invoice_number = '1234567890' factory_invoice_reference(invoice_id=invoice.id, invoice_number=invoice_number) invoice.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value invoice = invoice.save() invoice_id = invoice.id total = invoice.total # Create a payment for EFT Wire eft_wire_receipt = 'RCPT0012345' paid_amount = 100 PaymentModel(payment_method_code=PaymentMethod.EFT.value, payment_status_code=PaymentStatus.CREATED.value, payment_system_code='PAYBC', payment_account_id=pay_account.id, completed_on=datetime.now(), paid_amount=paid_amount, receipt_number=eft_wire_receipt).save() # Create a settlement file and publish. file_name: str = 'cas_settlement_file.csv' # Settlement row date = datetime.now().strftime('%d-%b-%y') row = [ RecordType.EFTP.value, SourceTransaction.EFT_WIRE.value, eft_wire_receipt, 100001, date, total, cfs_account_number, TargetTransaction.INV.value, invoice_number, total, 0, Status.PAID.value ] create_and_upload_settlement_file(file_name, [row]) await helper_add_event_to_queue(events_stan, file_name=file_name) # The invoice should be in PAID status and Payment should be completed updated_invoice = InvoiceModel.find_by_id(invoice_id) assert updated_invoice.invoice_status_code == InvoiceStatus.PAID.value payment: PaymentModel = PaymentModel.find_payment_by_receipt_number( eft_wire_receipt) assert payment.payment_status_code == PaymentStatus.COMPLETED.value assert payment.paid_amount == paid_amount assert payment.receipt_number == eft_wire_receipt
async def test_pad_reversal_reconciliations(session, app, stan_server, event_loop, client_id, events_stan, future, mock_publish): """Test Reconciliations worker for NSF.""" # Call back for the subscription from reconciliations.worker import cb_subscription_handler # register the handler to test it await subscribe_to_queue( events_stan, current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'), cb_subscription_handler) # 1. Create payment account # 2. Create invoices and related records for a completed payment # 3. Create CFS Invoice records # 4. Create a CFS settlement file, and verify the records cfs_account_number = '1234' pay_account: PaymentAccountModel = factory_create_pad_account( status=CfsAccountStatus.ACTIVE.value, account_number=cfs_account_number) invoice1: InvoiceModel = factory_invoice( payment_account=pay_account, total=100, service_fees=10.0, payment_method_code=PaymentMethod.PAD.value, status_code=InvoiceStatus.PAID.value) factory_payment_line_item(invoice_id=invoice1.id, filing_fees=90.0, service_fees=10.0, total=90.0) invoice2: InvoiceModel = factory_invoice( payment_account=pay_account, total=200, service_fees=10.0, payment_method_code=PaymentMethod.PAD.value, status_code=InvoiceStatus.PAID.value) factory_payment_line_item(invoice_id=invoice2.id, filing_fees=190.0, service_fees=10.0, total=190.0) invoice_number = '1234567890' receipt_number = '9999999999' factory_invoice_reference( invoice_id=invoice1.id, invoice_number=invoice_number, status_code=InvoiceReferenceStatus.COMPLETED.value) factory_invoice_reference( invoice_id=invoice2.id, invoice_number=invoice_number, status_code=InvoiceReferenceStatus.COMPLETED.value) receipt_id1 = factory_receipt(invoice_id=invoice1.id, receipt_number=receipt_number).save().id receipt_id2 = factory_receipt(invoice_id=invoice2.id, receipt_number=receipt_number).save().id invoice1_id = invoice1.id invoice2_id = invoice2.id pay_account_id = pay_account.id total = invoice1.total + invoice2.total payment = factory_payment(pay_account=pay_account, paid_amount=total, invoice_amount=total, invoice_number=invoice_number, receipt_number=receipt_number, status=PaymentStatus.COMPLETED.value) pay_id = payment.id # Now publish message saying payment has been reversed. # Create a settlement file and publish. file_name: str = 'cas_settlement_file.csv' # Settlement row date = datetime.now().strftime('%d-%b-%y') row = [ RecordType.PADR.value, SourceTransaction.PAD.value, receipt_number, 100001, date, 0, cfs_account_number, 'INV', invoice_number, total, total, Status.NOT_PAID.value ] create_and_upload_settlement_file(file_name, [row]) await helper_add_event_to_queue(events_stan, file_name=file_name) # The invoice should be in SETTLEMENT_SCHEDULED status and Payment should be FAILED updated_invoice1 = InvoiceModel.find_by_id(invoice1_id) assert updated_invoice1.invoice_status_code == InvoiceStatus.SETTLEMENT_SCHEDULED.value updated_invoice2 = InvoiceModel.find_by_id(invoice2_id) assert updated_invoice2.invoice_status_code == InvoiceStatus.SETTLEMENT_SCHEDULED.value payment: PaymentModel = PaymentModel.find_by_id(pay_id) assert payment.payment_status_code == PaymentStatus.FAILED.value assert payment.paid_amount == 0 assert payment.receipt_number == receipt_number assert payment.payment_method_code == PaymentMethod.PAD.value assert payment.invoice_number == invoice_number cfs_account: CfsAccountModel = CfsAccountModel.find_effective_by_account_id( pay_account_id) assert cfs_account.status == CfsAccountStatus.FREEZE.value # Receipt should be deleted assert ReceiptModel.find_by_id(receipt_id1) is None assert ReceiptModel.find_by_id(receipt_id2) is None
async def test_pad_reconciliations_with_credit_memo(session, app, stan_server, event_loop, client_id, events_stan, future, mock_publish): """Test Reconciliations worker.""" # Call back for the subscription from reconciliations.worker import cb_subscription_handler # Create a Credit Card Payment # register the handler to test it await subscribe_to_queue( events_stan, current_app.config.get('SUBSCRIPTION_OPTIONS').get('subject'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('queue'), current_app.config.get('SUBSCRIPTION_OPTIONS').get('durable_name'), cb_subscription_handler) # 1. Create payment account # 2. Create invoices and related records # 3. Create CFS Invoice records # 4. Mimic some credits on the account # 4. Create a CFS settlement file, and verify the records cfs_account_number = '1234' pay_account: PaymentAccountModel = factory_create_pad_account( status=CfsAccountStatus.ACTIVE.value, account_number=cfs_account_number) invoice1: InvoiceModel = factory_invoice( payment_account=pay_account, total=100, service_fees=10.0, payment_method_code=PaymentMethod.PAD.value) factory_payment_line_item(invoice_id=invoice1.id, filing_fees=90.0, service_fees=10.0, total=90.0) invoice2: InvoiceModel = factory_invoice( payment_account=pay_account, total=200, service_fees=10.0, payment_method_code=PaymentMethod.PAD.value) factory_payment_line_item(invoice_id=invoice2.id, filing_fees=190.0, service_fees=10.0, total=190.0) invoice_number = '1234567890' factory_invoice_reference(invoice_id=invoice1.id, invoice_number=invoice_number) factory_invoice_reference(invoice_id=invoice2.id, invoice_number=invoice_number) invoice1.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value invoice2.invoice_status_code = InvoiceStatus.SETTLEMENT_SCHEDULED.value invoice1.save() invoice2.save() invoice1_id = invoice1.id invoice2_id = invoice2.id total = invoice1.total + invoice2.total # Create a settlement file and publish. file_name: str = 'cas_settlement_file.csv' # Settlement row receipt_number = '1234567890' credit_memo_number = 'CM123' date = datetime.now().strftime('%d-%b-%y') credit_amount = 25 credit_row = [ RecordType.CMAP.value, SourceTransaction.CREDIT_MEMO.value, credit_memo_number, 100002, date, credit_amount, cfs_account_number, 'INV', invoice_number, total, 0, Status.PAID.value ] pad_row = [ RecordType.PAD.value, SourceTransaction.PAD.value, receipt_number, 100001, date, total - credit_amount, cfs_account_number, 'INV', invoice_number, total, 0, Status.PAID.value ] create_and_upload_settlement_file(file_name, [credit_row, pad_row]) await helper_add_event_to_queue(events_stan, file_name=file_name) # The invoice should be in PAID status and Payment should be completed updated_invoice1 = InvoiceModel.find_by_id(invoice1_id) assert updated_invoice1.invoice_status_code == InvoiceStatus.PAID.value updated_invoice2 = InvoiceModel.find_by_id(invoice2_id) assert updated_invoice2.invoice_status_code == InvoiceStatus.PAID.value payment: PaymentModel = PaymentModel.find_payment_by_receipt_number( receipt_number) assert payment.payment_status_code == PaymentStatus.COMPLETED.value assert payment.paid_amount == total - credit_amount assert payment.receipt_number == receipt_number assert payment.payment_method_code == PaymentMethod.PAD.value assert payment.invoice_number == invoice_number rcpt1: ReceiptModel = ReceiptModel.find_by_invoice_id_and_receipt_number( invoice1_id, receipt_number) rcpt2: ReceiptModel = ReceiptModel.find_by_invoice_id_and_receipt_number( invoice2_id, receipt_number) assert rcpt1 assert rcpt2 assert rcpt1.receipt_date == rcpt2.receipt_date