Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 60 additions & 68 deletions petpooja_integration/api/api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import frappe
from frappe.utils import getdate, get_time
from petpooja_integration.utils import get_mop_account

@frappe.whitelist(allow_guest=True)
def response(message, data, success, status_code):
Expand Down Expand Up @@ -99,7 +100,7 @@ def create_invoice():
sales_invoice_doc.append('items', {
'item_code': item.get('item_code'),
'item_name': item.get('item_name'),
'qty': item.get('qty'),
'qty': item.get('quantity'),
'rate': item.get('rate'),
'amount': item.get('amount'),
'income_account': income_account
Expand Down Expand Up @@ -149,7 +150,7 @@ def create_invoice():
handle_payment(sales_invoice_doc.name, order_details)

response('Invoice created', { 'doc':sales_invoice_doc.as_dict() }, True, 200)

except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Petpooja Integration Error')
response('Something went wrong', {}, False, 500)
Expand Down Expand Up @@ -221,73 +222,64 @@ def handle_payment(sales_invoice, order_details):
'''
Method to handle payment entry against the created Sales Invoice
'''
if frappe.db.exists('Sales Invoice', sales_invoice):
sales_invoice_doc = frappe.get_doc('Sales Invoice', sales_invoice)
try:
if frappe.db.exists('Sales Invoice', sales_invoice):
sales_invoice_doc = frappe.get_doc('Sales Invoice', sales_invoice)

#Getting Payment Methods
payment_methods = []
if order_details.get('part_payments', []):
for part_payment in order_details.get('part_payments', []):
#Getting Payment Methods
payment_methods = []
if order_details.get('part_payments', []):
for part_payment in order_details.get('part_payments', []):
payment_methods.append({
'method': part_payment.get('payment_type'),
'amount': part_payment.get('amount')
})
else:
payment_methods.append({
'method': part_payment.get('payment_type'),
'amount': part_payment.get('amount')
'method': order_details.get('payment_type'),
'amount': order_details.get('total')
})
else:
payment_methods.append({
'method': order_details.get('payment_type'),
'amount': order_details.get('total')
})

#Creating Payment Entry for each payment method
for mode in payment_methods:
mode_of_payment = ''
if frappe.db.exists('Mode of Payment', { 'petpooja_payment_type': mode.get('method') }):
mode_of_payment = frappe.get_value('Mode of Payment', { 'petpooja_payment_type': mode.get('method') }, 'name')
if not mode_of_payment:
sales_invoice_doc.add_comment(
'Comment',
'Mode of Payment mapping not found for {0}, Skipped Payment Entry creation.'.format(frappe.bold(mode.get('method')))
)
continue

mode_of_payment_account = get_mop_account(mode_of_payment, sales_invoice_doc.company)
if not mode_of_payment_account:
sales_invoice_doc.add_comment(
'Comment',
'Default account not found for Mode of Payment {0}, Skipped Payment Entry creation.'.format(frappe.bold(mode_of_payment))
)
continue

payment_entry = frappe.new_doc('Payment Entry')
payment_entry.payment_type = 'Receive'
payment_entry.posting_date = getdate(order_details.get('created_on'))
payment_entry.party_type = 'Customer'
payment_entry.party = sales_invoice_doc.customer
payment_entry.reference_no = order_details.get('orderID')
payment_entry.reference_date = getdate(order_details.get('created_on'))
payment_entry.mode_of_payment = mode_of_payment
payment_entry.paid_from = sales_invoice_doc.debit_to
payment_entry.paid_to = mode_of_payment_account
payment_entry.received_amount = mode.get('amount')
payment_entry.paid_amount = mode.get('amount')
payment_entry.append('references', {
'reference_doctype': 'Sales Invoice',
'reference_name': sales_invoice,
'allocated_amount': mode.get('amount'),
'outstanding_amount': frappe.get_value('Sales Invoice', sales_invoice, 'outstanding_amount'),
'paid_amount': mode.get('amount')
})
payment_entry.save(ignore_permissions=True)
payment_entry.submit()

def get_mop_account(mode_of_payment, company):
'''
Method to get default account for a given Mode of Payment and Company
'''
result = frappe.db.sql('''
SELECT default_account
FROM `tabMode of Payment Account`
WHERE parent=%s AND company=%s
LIMIT 1
''', (mode_of_payment, company), as_dict=True)
return result[0].default_account if result else None
#Creating Payment Entry for each payment method
for mode in payment_methods:
mode_of_payment = ''
if frappe.db.exists('Mode of Payment', { 'petpooja_payment_type': mode.get('method') }):
mode_of_payment = frappe.get_value('Mode of Payment', { 'petpooja_payment_type': mode.get('method') }, 'name')
if not mode_of_payment:
sales_invoice_doc.add_comment(
'Comment',
'Mode of Payment mapping not found for {0}, Skipped Payment Entry creation.'.format(frappe.bold(mode.get('method')))
)
continue

mode_of_payment_account = get_mop_account(mode_of_payment, sales_invoice_doc.company)
if not mode_of_payment_account:
sales_invoice_doc.add_comment(
'Comment',
'Default account not found for Mode of Payment {0}, Skipped Payment Entry creation.'.format(frappe.bold(mode_of_payment))
)
continue

payment_entry = frappe.new_doc('Payment Entry')
payment_entry.payment_type = 'Receive'
payment_entry.posting_date = getdate(order_details.get('created_on'))
payment_entry.party_type = 'Customer'
payment_entry.party = sales_invoice_doc.customer
payment_entry.reference_no = order_details.get('orderID')
payment_entry.reference_date = getdate(order_details.get('created_on'))
payment_entry.mode_of_payment = mode_of_payment
payment_entry.paid_from = sales_invoice_doc.debit_to
payment_entry.paid_to = mode_of_payment_account
payment_entry.received_amount = mode.get('amount')
payment_entry.paid_amount = mode.get('amount')
payment_entry.append('references', {
'reference_doctype': 'Sales Invoice',
'reference_name': sales_invoice,
'allocated_amount': mode.get('amount'),
'outstanding_amount': frappe.get_value('Sales Invoice', sales_invoice, 'outstanding_amount'),
'paid_amount': mode.get('amount')
})
payment_entry.save(ignore_permissions=True)
payment_entry.submit()
except Exception as e:
sales_invoice_doc.add_comment('Comment', 'Error while creating Payment Entry: {0}'.format(frappe.bold(str(e))))
7 changes: 7 additions & 0 deletions petpooja_integration/custom/custom_field/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ def get_item_custom_fields():
"label": "Petpooja Item Code",
"insert_after": "item_code",
"unique": 1
},
{
"fieldname": "rista_item_code",
"fieldtype": "Data",
"label": "Rista Item Code",
"insert_after": "petpooja_item_code",
"unique": 1
}
]
}
6 changes: 6 additions & 0 deletions petpooja_integration/custom/custom_field/mode_of_payment.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ def get_mode_of_payment_custom_fields():
"fieldtype": "Data",
"label": "Petpooja Payment Type",
"insert_after": "type",
},
{
"fieldname": "rista_payment_type",
"fieldtype": "Data",
"label": "Rista Payment Type",
"insert_after": "petpooja_payment_type",
}
]
}
40 changes: 40 additions & 0 deletions petpooja_integration/custom/custom_field/sales_invoice.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,46 @@ def get_sales_invoice_custom_fields():
"label": "Petpooja Table No.",
"insert_after": "petpooja_order_type",
"read_only": 1,
},
{
"fieldname": "rista_details",
"fieldtype": "Section Break",
"label": "Rista Details",
"insert_after": "petpooja_table_no",
},
{
"fieldname": "rista_branch",
"fieldtype": "Link",
"label": "Rista Branch",
"options": "Rista Branch",
"insert_after": "rista_details",
"read_only": 1,
},
{
"fieldname": "rista_invoice_number",
"fieldtype": "Data",
"label": "Rista Invoice Number",
"insert_after": "rista_branch",
"read_only": 1,
},
{
"fieldname": "rista_cb1",
"fieldtype": "Column Break",
"insert_after": "rista_invoice_number",
},
{
"fieldname": "rista_channel",
"fieldtype": "Data",
"label": "Rista Channel",
"insert_after": "rista_cb1",
"read_only": 1,
},
{
"fieldname": "rista_order_url",
"fieldtype": "Small Text",
"label": "Rista Order URL",
"insert_after": "rista_channel",
"read_only": 1,
}
]
}
49 changes: 49 additions & 0 deletions petpooja_integration/custom_script/sales_invoice/sales_invoice.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import frappe

def after_insert(doc, method):
'''
Method to handle actions after Sales Invoice insertion.
'''
link_to_rista_sales_log(doc)

def on_submit(doc, method):
'''
Method to handle actions on Sales Invoice submission.
'''
if doc.update_stock:
for item in doc.items:
handle_bom_stock_update(item.item_code, item.qty, item.warehouse)

def handle_bom_stock_update(item_code, qty, warehouse):
'''
Function to handle stock update for BOM items.
'''
bom = frappe.get_all('BOM', filters={'item': item_code, 'is_active': 1, 'is_default': 1}, fields=['name'])
if bom:
bom_doc = frappe.get_doc('BOM', bom[0].name)
stock_entry = frappe.new_doc('Stock Entry')
stock_entry.stock_entry_type = 'Material Issue'
for bom_item in bom_doc.items:
required_qty = bom_item.qty * qty
stock_entry.append('items', {
'item_code': bom_item.item_code,
'qty': required_qty,
's_warehouse': warehouse
})
stock_entry.save(ignore_permissions=True)
stock_entry.submit()

def link_to_rista_sales_log(doc):
'''
Function to link Sales Invoice to Rista Sales Log if applicable.
'''
if doc.rista_invoice_number and doc.rista_branch:
if frappe.db.exists('Rista Sales Log', {
'invoice_number': doc.rista_invoice_number,
'branch_code': doc.rista_branch,
}):
log = frappe.db.get_value('Rista Sales Log', {
'invoice_number': doc.rista_invoice_number,
'branch_code': doc.rista_branch,
}, 'name')
frappe.db.set_value('Rista Sales Log', log, 'sales_invoice_reference', doc.name, update_modified=False)
7 changes: 7 additions & 0 deletions petpooja_integration/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,13 @@
# }
# }

doc_events = {
"Sales Invoice": {
"after_insert": "petpooja_integration.custom_script.sales_invoice.sales_invoice.after_insert",
"on_submit": "petpooja_integration.custom_script.sales_invoice.sales_invoice.on_submit",
}
}

# Scheduled Tasks
# ---------------

Expand Down
3 changes: 2 additions & 1 deletion petpooja_integration/modules.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Petpooja Integration
Petpooja Integration
Rista Integration
Empty file.
Empty file.
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2026, efeone and contributors
// For license information, please see license.txt

// frappe.ui.form.on("Rista Branch", {
// refresh(frm) {

// },
// });
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"actions": [],
"autoname": "field:branch_code",
"creation": "2026-01-13 11:06:34.517926",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"branch_code",
"branch_name",
"company"
],
"fields": [
{
"fieldname": "branch_code",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Branch Code",
"reqd": 1,
"unique": 1
},
{
"fieldname": "branch_name",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Branch Name",
"reqd": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Company",
"options": "Company"
}
],
"grid_page_length": 50,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2026-01-13 11:10:22.687168",
"modified_by": "Administrator",
"module": "Rista Integration",
"name": "Rista Branch",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"row_format": "Dynamic",
"rows_threshold_for_grid_search": 20,
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2026, efeone and contributors
# For license information, please see license.txt

# import frappe
from frappe.model.document import Document


class RistaBranch(Document):
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2026, efeone and Contributors
# See license.txt

# import frappe
from frappe.tests.utils import FrappeTestCase


class TestRistaBranch(FrappeTestCase):
pass
Loading