def test_pos_closing_entry(self): test_user, pos_profile = init_user_and_profile() opening_entry = create_opening_entry(pos_profile, test_user.name) pos_inv1 = create_pos_invoice(rate=3500, do_not_submit=1) pos_inv1.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3500 }) pos_inv1.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200 }) pos_inv2.submit() pcv_doc = make_closing_entry_from_opening(opening_entry) payment = pcv_doc.payment_reconciliation[0] self.assertEqual(payment.mode_of_payment, 'Cash') for d in pcv_doc.payment_reconciliation: if d.mode_of_payment == 'Cash': d.closing_amount = 6700 pcv_doc.submit() self.assertEqual(pcv_doc.total_quantity, 2) self.assertEqual(pcv_doc.net_total, 6700) frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`")
def test_processing_of_callback_payload(self): create_mpesa_settings(payment_gateway_name="Payment") mpesa_account = frappe.db.get_value( "Payment Gateway Account", {"payment_gateway": 'Mpesa-Payment'}, "payment_account") frappe.db.set_value("Account", mpesa_account, "account_currency", "KES") frappe.db.set_value("Customer", "_Test Customer", "default_currency", "KES") pos_invoice = create_pos_invoice(do_not_submit=1) pos_invoice.append( "payments", { 'mode_of_payment': 'Mpesa-Payment', 'account': mpesa_account, 'amount': 500 }) pos_invoice.contact_mobile = "093456543894" pos_invoice.currency = "KES" pos_invoice.save() pr = pos_invoice.create_payment_request() # test payment request creation self.assertEquals(pr.payment_gateway, "Mpesa-Payment") callback_response = get_payment_callback_payload() verify_transaction(**callback_response) # test creation of integration request integration_request = frappe.get_doc("Integration Request", "ws_CO_061020201133231972") # test integration request creation and successful update of the status on receiving callback response self.assertTrue(integration_request) self.assertEquals(integration_request.status, "Completed") pos_invoice.reload() integration_request.reload() self.assertEquals(pos_invoice.mpesa_receipt_number, "LGR7OWQX0R") self.assertEquals(integration_request.status, "Completed") frappe.db.set_value("Customer", "_Test Customer", "default_currency", "")
def test_consolidated_credit_note_creation(self): frappe.db.sql("delete from `tabPOS Invoice`") test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(rate=300, do_not_submit=1) pos_inv.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 300 }) pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 3200 }) pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) pos_inv3.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': 2300 }) pos_inv3.submit() pos_inv_cn = make_sales_return(pos_inv.name) pos_inv_cn.set("payments", []) pos_inv_cn.append('payments', { 'mode_of_payment': 'Cash', 'account': 'Cash - _TC', 'amount': -300 }) pos_inv_cn.paid_amount = -300 pos_inv_cn.submit() consolidate_pos_invoices() pos_inv.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv.consolidated_invoice)) pos_inv3.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv3.consolidated_invoice)) pos_inv_cn.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv_cn.consolidated_invoice)) self.assertTrue( frappe.db.get_value("Sales Invoice", pos_inv_cn.consolidated_invoice, "is_return")) frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def test_consolidated_credit_note_creation(self): frappe.db.sql("delete from `tabPOS Invoice`") try: test_user, pos_profile = init_user_and_profile() pos_inv = create_pos_invoice(rate=300, do_not_submit=1) pos_inv.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 300 }) pos_inv.submit() pos_inv2 = create_pos_invoice(rate=3200, do_not_submit=1) pos_inv2.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 3200 }) pos_inv2.submit() pos_inv3 = create_pos_invoice(customer="_Test Customer 2", rate=2300, do_not_submit=1) pos_inv3.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 2300 }) pos_inv3.submit() pos_inv_cn = make_sales_return(pos_inv.name) pos_inv_cn.set("payments", []) pos_inv_cn.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -100 }) pos_inv_cn.append( "payments", { "mode_of_payment": "Bank Draft", "account": "_Test Bank - _TC", "amount": -200 }) pos_inv_cn.paid_amount = -300 pos_inv_cn.submit() consolidate_pos_invoices() pos_inv.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv.consolidated_invoice)) pos_inv3.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv3.consolidated_invoice)) pos_inv_cn.load_from_db() self.assertTrue( frappe.db.exists("Sales Invoice", pos_inv_cn.consolidated_invoice)) consolidated_credit_note = frappe.get_doc( "Sales Invoice", pos_inv_cn.consolidated_invoice) self.assertEqual(consolidated_credit_note.is_return, 1) self.assertEqual( consolidated_credit_note.payments[0].mode_of_payment, "Cash") self.assertEqual(consolidated_credit_note.payments[0].amount, -100) self.assertEqual( consolidated_credit_note.payments[1].mode_of_payment, "Bank Draft") self.assertEqual(consolidated_credit_note.payments[1].amount, -200) finally: frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def test_serial_no_case_1(self): """ Create a POS Invoice with serial no Create a Return Invoice with serial no Create a POS Invoice with serial no again Consolidate the invoices The first POS Invoice should be consolidated with a separate single Merge Log The second and third POS Invoice should be consolidated with a single Merge Log """ from erpnext.stock.doctype.serial_no.test_serial_no import get_serial_nos from erpnext.stock.doctype.stock_entry.test_stock_entry import make_serialized_item frappe.db.sql("delete from `tabPOS Invoice`") try: se = make_serialized_item() serial_no = get_serial_nos(se.get("items")[0].serial_no)[0] init_user_and_profile() pos_inv = create_pos_invoice( item_code="_Test Serialized Item With Series", serial_no=serial_no, qty=1, rate=100, do_not_submit=1, ) pos_inv.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100 }) pos_inv.submit() pos_inv_cn = make_sales_return(pos_inv.name) pos_inv_cn.paid_amount = -100 pos_inv_cn.submit() pos_inv2 = create_pos_invoice( item_code="_Test Serialized Item With Series", serial_no=serial_no, qty=1, rate=100, do_not_submit=1, ) pos_inv2.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 100 }) pos_inv2.submit() consolidate_pos_invoices() pos_inv.load_from_db() pos_inv2.load_from_db() self.assertNotEqual(pos_inv.consolidated_invoice, pos_inv2.consolidated_invoice) finally: frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def test_consolidation_round_off_error_3(self): frappe.db.sql("delete from `tabPOS Invoice`") try: make_stock_entry( to_warehouse="_Test Warehouse - _TC", item_code="_Test Item", rate=8000, qty=10, ) init_user_and_profile() item_rates = [69, 59, 29] for i in [1, 2]: inv = create_pos_invoice(is_return=1, do_not_save=1) inv.items = [] for rate in item_rates: inv.append( "items", { "item_code": "_Test Item", "warehouse": "_Test Warehouse - _TC", "qty": -1, "rate": rate, "income_account": "Sales - _TC", "expense_account": "Cost of Goods Sold - _TC", "cost_center": "_Test Cost Center - _TC", }, ) inv.append( "taxes", { "account_head": "_Test Account VAT - _TC", "charge_type": "On Net Total", "cost_center": "_Test Cost Center - _TC", "description": "VAT", "doctype": "Sales Taxes and Charges", "rate": 15, "included_in_print_rate": 1, }, ) inv.payments = [] inv.append( "payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": -157 }) inv.paid_amount = -157 inv.save() inv.submit() consolidate_pos_invoices() inv.load_from_db() consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice) self.assertEqual(consolidated_invoice.status, "Return") self.assertEqual(consolidated_invoice.rounding_adjustment, -0.001) finally: frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def test_consolidation_round_off_error_2(self): """ Test the same case as above but with an Unpaid POS Invoice """ frappe.db.sql("delete from `tabPOS Invoice`") try: make_stock_entry( to_warehouse="_Test Warehouse - _TC", item_code="_Test Item", rate=8000, qty=10, ) init_user_and_profile() inv = create_pos_invoice(qty=6, rate=10000, do_not_save=True) inv.append( "taxes", { "account_head": "_Test Account VAT - _TC", "charge_type": "On Net Total", "cost_center": "_Test Cost Center - _TC", "description": "VAT", "doctype": "Sales Taxes and Charges", "rate": 7.5, "included_in_print_rate": 1, }, ) inv.append( "payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 60000 }) inv.insert() inv.submit() inv2 = create_pos_invoice(qty=6, rate=10000, do_not_save=True) inv2.append( "taxes", { "account_head": "_Test Account VAT - _TC", "charge_type": "On Net Total", "cost_center": "_Test Cost Center - _TC", "description": "VAT", "doctype": "Sales Taxes and Charges", "rate": 7.5, "included_in_print_rate": 1, }, ) inv2.append( "payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 60000 }) inv2.insert() inv2.submit() inv3 = create_pos_invoice(qty=3, rate=600, do_not_save=True) inv3.append("payments", { "mode_of_payment": "Cash", "account": "Cash - _TC", "amount": 1000 }) inv3.insert() inv3.submit() consolidate_pos_invoices() inv.load_from_db() consolidated_invoice = frappe.get_doc("Sales Invoice", inv.consolidated_invoice) self.assertEqual(consolidated_invoice.outstanding_amount, 800) self.assertNotEqual(consolidated_invoice.status, "Paid") finally: frappe.set_user("Administrator") frappe.db.sql("delete from `tabPOS Profile`") frappe.db.sql("delete from `tabPOS Invoice`")
def test_processing_of_only_one_succes_callback_payload(self): mpesa_account = frappe.db.get_value( "Payment Gateway Account", {"payment_gateway": "Mpesa-Payment"}, "payment_account") frappe.db.set_value("Account", mpesa_account, "account_currency", "KES") frappe.db.set_value("Mpesa Settings", "Payment", "transaction_limit", "500") frappe.db.set_value("Customer", "_Test Customer", "default_currency", "KES") pos_invoice = create_pos_invoice(do_not_submit=1) pos_invoice.append( "payments", { "mode_of_payment": "Mpesa-Payment", "account": mpesa_account, "amount": 1000 }) pos_invoice.contact_mobile = "093456543894" pos_invoice.currency = "KES" pos_invoice.save() pr = pos_invoice.create_payment_request() # test payment request creation self.assertEqual(pr.payment_gateway, "Mpesa-Payment") # submitting payment request creates integration requests with random id integration_req_ids = frappe.get_all( "Integration Request", filters={ "reference_doctype": pr.doctype, "reference_docname": pr.name, }, pluck="name", ) # create random receipt nos and send it as response to callback handler mpesa_receipt_numbers = [ frappe.utils.random_string(5) for d in integration_req_ids ] callback_response = get_payment_callback_payload( Amount=500, CheckoutRequestID=integration_req_ids[0], MpesaReceiptNumber=mpesa_receipt_numbers[0], ) # handle response manually verify_transaction(**callback_response) # test completion of integration request integration_request = frappe.get_doc("Integration Request", integration_req_ids[0]) self.assertEqual(integration_request.status, "Completed") # now one request is completed # second integration request fails # now retrying payment request should make only one integration request again pr = pos_invoice.create_payment_request() new_integration_req_ids = frappe.get_all( "Integration Request", filters={ "reference_doctype": pr.doctype, "reference_docname": pr.name, "name": ["not in", integration_req_ids], }, pluck="name", ) self.assertEqual(len(new_integration_req_ids), 1) frappe.db.set_value("Customer", "_Test Customer", "default_currency", "") frappe.db.sql( "delete from `tabIntegration Request` where integration_request_service = 'Mpesa'" ) pr.reload() pr.cancel() pr.delete() pos_invoice.delete()
def test_processing_of_multiple_callback_payload(self): mpesa_account = frappe.db.get_value( "Payment Gateway Account", {"payment_gateway": "Mpesa-Payment"}, "payment_account") frappe.db.set_value("Account", mpesa_account, "account_currency", "KES") frappe.db.set_value("Mpesa Settings", "Payment", "transaction_limit", "500") frappe.db.set_value("Customer", "_Test Customer", "default_currency", "KES") pos_invoice = create_pos_invoice(do_not_submit=1) pos_invoice.append( "payments", { "mode_of_payment": "Mpesa-Payment", "account": mpesa_account, "amount": 1000 }) pos_invoice.contact_mobile = "093456543894" pos_invoice.currency = "KES" pos_invoice.save() pr = pos_invoice.create_payment_request() # test payment request creation self.assertEqual(pr.payment_gateway, "Mpesa-Payment") # submitting payment request creates integration requests with random id integration_req_ids = frappe.get_all( "Integration Request", filters={ "reference_doctype": pr.doctype, "reference_docname": pr.name, }, pluck="name", ) # create random receipt nos and send it as response to callback handler mpesa_receipt_numbers = [ frappe.utils.random_string(5) for d in integration_req_ids ] integration_requests = [] for i in range(len(integration_req_ids)): callback_response = get_payment_callback_payload( Amount=500, CheckoutRequestID=integration_req_ids[i], MpesaReceiptNumber=mpesa_receipt_numbers[i], ) # handle response manually verify_transaction(**callback_response) # test completion of integration request integration_request = frappe.get_doc("Integration Request", integration_req_ids[i]) self.assertEqual(integration_request.status, "Completed") integration_requests.append(integration_request) # check receipt number once all the integration requests are completed pos_invoice.reload() self.assertEqual(pos_invoice.mpesa_receipt_number, ", ".join(mpesa_receipt_numbers)) frappe.db.set_value("Customer", "_Test Customer", "default_currency", "") [d.delete() for d in integration_requests] pr.reload() pr.cancel() pr.delete() pos_invoice.delete()