diff --git a/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.js b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.js new file mode 100644 index 0000000..509fa5e --- /dev/null +++ b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.js @@ -0,0 +1,9 @@ +// -*- coding: utf-8 -*- +// Copyright (c) 2025, Aakvatech and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Bank Statement Summary', { + // refresh: function(frm) { + // // Custom client-side code here + // } +}); diff --git a/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.json b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.json new file mode 100644 index 0000000..b487734 --- /dev/null +++ b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.json @@ -0,0 +1,119 @@ +{ + "actions": [], + "allow_import": 1, + "allow_rename": 1, + "creation": "2025-07-18 10:04:23.811854", + "doctype": "DocType", + "engine": "InnoDB", + "field_order": [ + "bank_account", + "end_of_month", + "column_break_ozsh", + "bank_account_currency", + "section_break_mmro", + "count_of_transaction", + "column_break_abtd", + "deposit", + "column_break_gegh", + "withdrawal", + "section_break_qsux", + "closing_balance" + ], + "fields": [ + { + "fieldname": "bank_account", + "fieldtype": "Link", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "Bank Account", + "link_filters": "[[\"Bank Account\",\"is_company_account\",\"=\",1]]", + "options": "Bank Account" + }, + { + "fieldname": "end_of_month", + "fieldtype": "Date", + "in_list_view": 1, + "in_standard_filter": 1, + "label": "End of Month" + }, + { + "fieldname": "column_break_ozsh", + "fieldtype": "Column Break" + }, + { + "fetch_from": "bank_account.company_account_currency", + "fieldname": "bank_account_currency", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Bank Account Currency", + "options": "Currency", + "read_only": 1 + }, + { + "fieldname": "section_break_mmro", + "fieldtype": "Section Break" + }, + { + "fieldname": "count_of_transaction", + "fieldtype": "Int", + "label": "Count of Transaction" + }, + { + "fieldname": "column_break_abtd", + "fieldtype": "Column Break" + }, + { + "fieldname": "deposit", + "fieldtype": "Currency", + "label": "Deposit", + "options": "bank_account_currency" + }, + { + "fieldname": "column_break_gegh", + "fieldtype": "Column Break" + }, + { + "fieldname": "withdrawal", + "fieldtype": "Currency", + "label": "Withdrawal", + "options": "bank_account_currency" + }, + { + "fieldname": "section_break_qsux", + "fieldtype": "Section Break" + }, + { + "fieldname": "closing_balance", + "fieldtype": "Currency", + "label": "Closing Balance", + "options": "bank_account_currency" + } + ], + "index_web_pages_for_search": 1, + "links": [], + "modified": "2025-07-23 12:55:41.154068", + "modified_by": "Administrator", + "module": "Av Tools", + "name": "Bank Statement Summary", + "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", + "show_title_field_in_link": 1, + "sort_field": "modified", + "sort_order": "DESC", + "states": [], + "title_field": "bank_account" +} \ No newline at end of file diff --git a/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.py b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.py new file mode 100644 index 0000000..80acdbd --- /dev/null +++ b/av_tools/av_tools/doctype/bank_statement_summary/bank_statement_summary.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2025, Aakvatech and contributors +# For license information, please see license.txt + +from frappe.model.document import Document + +class BankStatementSummary(Document): + pass diff --git a/av_tools/av_tools/doctype/employee_salary_component_limit/__init__.py b/av_tools/av_tools/doctype/employee_salary_component_limit/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.json b/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.json new file mode 100644 index 0000000..e7c1659 --- /dev/null +++ b/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.json @@ -0,0 +1,55 @@ +{ + "actions": [], + "creation": "2021-07-25 21:02:53.417249", + "doctype": "DocType", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "salary_component", + "valid_from", + "limit_amount", + "limit_number" + ], + "fields": [ + { + "fieldname": "salary_component", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Salary Component", + "options": "Salary Component", + "reqd": 1 + }, + { + "fieldname": "valid_from", + "fieldtype": "Date", + "in_list_view": 1, + "label": "Valid From", + "reqd": 1 + }, + { + "fieldname": "limit_amount", + "fieldtype": "Currency", + "in_list_view": 1, + "label": "Limit Amount", + "reqd": 1 + }, + { + "fieldname": "limit_number", + "fieldtype": "Int", + "in_list_view": 1, + "label": "Limit Number" + } + ], + "index_web_pages_for_search": 1, + "istable": 1, + "links": [], + "modified": "2021-07-25 21:02:53.417249", + "modified_by": "Administrator", + "module": "Av Tools", + "name": "Employee Salary Component Limit", + "owner": "Administrator", + "permissions": [], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.py b/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.py new file mode 100644 index 0000000..acc6afa --- /dev/null +++ b/av_tools/av_tools/doctype/employee_salary_component_limit/employee_salary_component_limit.py @@ -0,0 +1,8 @@ +# Copyright (c) 2021, Aakvatech and contributors +# For license information, please see license.txt + +# import frappe +from frappe.model.document import Document + +class EmployeeSalaryComponentLimit(Document): + pass diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/__init__.py b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.js b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.js new file mode 100644 index 0000000..8771fdf --- /dev/null +++ b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.js @@ -0,0 +1,52 @@ +// Copyright (c) 2019, Aakvatech and contributors +// For license information, please see license.txt + +frappe.ui.form.on('Open Invoice Exchange Rate Revaluation', { + refresh: function(frm) { + + }, + currency:function(frm,cdt,cdn){ + var doc=locals[cdt][cdn] + if(frm.doc.currency && frm.doc.revaluation_date){ + frappe.call({ + method:"av_tools.av_tools.doctype.open_invoice_exchange_rate_revaluation.open_invoice_exchange_rate_revaluation.getInvoiceExchangeRate", + args:{'currency':frm.doc.currency,'date':frm.doc.revaluation_date}, + callback:function(r){ + console.log(r.message) + cur_frm.set_value("exchange_rate_to_company_currency",r.message) + + } + + }) + } + + }, + get_invoices:function(frm,cdt,cdn){ + if(frm.doc.__islocal) { + frappe.throw("Save Document Before Get Invoice") + } + if(frm.doc.currency && frm.doc.name){ + frappe.call({ + method:"av_tools.av_tools.doctype.open_invoice_exchange_rate_revaluation.open_invoice_exchange_rate_revaluation.getInvoice", + args:{'currency':frm.doc.currency,'name':frm.doc.name}, + freeze: true, + freeze_message: "Please Wait...", + callback:function(data){ + if(data.message){ + frm.clear_table("inv_err_detail"); + frm.refresh_fields("inv_err_detail"); + frm.reload_doc(); + } + + } + + + }) + } + else{ + + frappe.msgprint("Currency Mandatory And Document Saved Before Get Invoice") + } + + } +}); diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.json b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.json new file mode 100644 index 0000000..d3d6ca4 --- /dev/null +++ b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.json @@ -0,0 +1,120 @@ +{ + "autoname": "OIERR.#####", + "creation": "2019-02-19 09:52:40.787084", + "doctype": "DocType", + "document_type": "Document", + "editable_grid": 1, + "engine": "InnoDB", + "field_order": [ + "company", + "revaluation_date", + "column_break_3", + "currency", + "exchange_rate_to_company_currency", + "get_invoices", + "section_break_7", + "inv_err_detail", + "amended_from", + "refrences_section", + "journal_entry", + "reverse_journal_entry" + ], + "fields": [ + { + "fieldname": "revaluation_date", + "fieldtype": "Date", + "label": "Revaluation Date" + }, + { + "default": "USD", + "fieldname": "currency", + "fieldtype": "Link", + "label": "Currency", + "options": "Currency" + }, + { + "fieldname": "exchange_rate_to_company_currency", + "fieldtype": "Currency", + "label": "Exchange rate to company currency", + "precision": "5" + }, + { + "fieldname": "get_invoices", + "fieldtype": "Button", + "label": "Get Invoices" + }, + { + "fieldname": "inv_err_detail", + "fieldtype": "Table", + "label": "Inv ERR Detail", + "options": "Inv ERR Detail" + }, + { + "fieldname": "amended_from", + "fieldtype": "Link", + "label": "Amended From", + "no_copy": 1, + "options": "Open Invoice Exchange Rate Revaluation", + "print_hide": 1, + "read_only": 1 + }, + { + "fieldname": "refrences_section", + "fieldtype": "Section Break", + "label": "Refrences" + }, + { + "fieldname": "journal_entry", + "fieldtype": "Link", + "label": "Journal Entry", + "options": "Journal Entry", + "read_only": 1 + }, + { + "fieldname": "reverse_journal_entry", + "fieldtype": "Link", + "label": "Reverse Journal Entry", + "options": "Journal Entry", + "read_only": 1 + }, + { + "fieldname": "company", + "fieldtype": "Link", + "in_list_view": 1, + "label": "Company", + "options": "Company", + "reqd": 1 + }, + { + "fieldname": "column_break_3", + "fieldtype": "Column Break" + }, + { + "fieldname": "section_break_7", + "fieldtype": "Section Break" + } + ], + "is_submittable": 1, + "modified": "2020-10-11 22:46:03.797861", + "modified_by": "Administrator", + "module": "Av Tools", + "name": "Open Invoice Exchange Rate Revaluation", + "owner": "Administrator", + "permissions": [ + { + "create": 1, + "delete": 1, + "email": 1, + "export": 1, + "print": 1, + "read": 1, + "report": 1, + "role": "System Manager", + "share": 1, + "write": 1 + } + ], + "sort_field": "modified", + "sort_order": "DESC", + "track_changes": 1 +} \ No newline at end of file diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.py b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.py new file mode 100644 index 0000000..7ae85f0 --- /dev/null +++ b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/open_invoice_exchange_rate_revaluation.py @@ -0,0 +1,227 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Aakvatech and contributors +# For license information, please see license.txt + +from __future__ import unicode_literals +import frappe +from erpnext.setup.utils import get_exchange_rate +from frappe.model.document import Document +from frappe.utils import flt + +class OpenInvoiceExchangeRateRevaluation(Document): + def on_submit(self): + last_doc_details=getLastCreatedDocument(self.name,self.currency) + if last_doc_details: + reverse_je = makeReverseJE(self.revaluation_date,last_doc_details[0].journal_entry) + frappe.db.set_value(self.doctype,last_doc_details[0].name,"reverse_journal_entry",reverse_je) + frappe.msgprint("Reverse Journal Entry Created: "+str(reverse_je)) + je_item = makeJEItem(self) + res = makeJournalEntry(self.revaluation_date,je_item) + frappe.db.set_value(self.doctype,self.name,"journal_entry",res) + url = frappe.utils.get_url_to_form("Journal Entry", res) + frappe.msgprint("Journal Entry for Exchange Rate Revaluation Created at {1}".format(url,res)) + + + +def getLastDocument(_self): + doc=frappe.get_all('Open Invoice Exchange Rate Revaluation', filters={}, fields=['name'], limit_page_length = 1) + return doc[0].name + + + +def makeJEItem(self): + item_dict = [] + for row in self.inv_err_detail: + first_row_je = getFirstRow(abs(row.invoice_gain_or_loss),row.invoice_type) + item_dict.append(first_row_je) + second_row_je=getSecondRow(abs(row.invoice_gain_or_loss),row.invoice_type,row.invoice_number) + item_dict.append(second_row_je) + return item_dict + + +def getFirstRow(invoice_gain_or_loss,invoice_type): + item_json={} + item_json["account"] = frappe.db.get_value("Company",frappe.defaults.get_global_default("company"),"unrealized_exchange_gain_loss_account") + if flt(invoice_gain_or_loss) > 0: + if invoice_type == "Sales Invoice": + item_json["credit_in_account_currency"] = invoice_gain_or_loss + else: + item_json["debit_in_account_currency"] = invoice_gain_or_loss + else: + if invoice_type == "Sales Invoice": + item_json["debit_in_account_currency"] = invoice_gain_or_loss + else: + item_json["credit_in_account_currency"] = invoice_gain_or_loss + return item_json + + +def getSecondRow(invoice_gain_or_loss,invoice_type,invoice_number): + item_json={} + item_json["reference_type"] = invoice_type + item_json["reference_name"] = invoice_number + item_json["user_remark"] = str(frappe.db.get_value(str(invoice_type),invoice_number,"currency"))+'@'+str(frappe.db.get_value(str(invoice_type),invoice_number,"conversion_rate")) + if invoice_type == "Sales Invoice": + item_json["account"] = frappe.db.get_value(invoice_type,invoice_number,"debit_to") + item_json["party_type"] = 'Customer' + item_json["party"] = frappe.db.get_value(invoice_type,invoice_number,"customer") + if flt(invoice_gain_or_loss) > 0: + item_json["debit_in_account_currency"] = invoice_gain_or_loss + else: + item_json["credit_in_account_currency"] = invoice_gain_or_loss + + else: + item_json["account"] = frappe.db.get_value(invoice_type,invoice_number,"credit_to") + item_json["party_type"] = 'Supplier' + item_json["party"] = frappe.db.get_value(invoice_type,invoice_number,"supplier") + if flt(invoice_gain_or_loss) > 0: + item_json["credit_in_account_currency"] = invoice_gain_or_loss + else: + item_json["debit_in_account_currency"] = invoice_gain_or_loss + return item_json + + +@frappe.whitelist() +def makeJournalEntry(date,je_item): + j_entry=frappe.get_doc(dict( + doctype="Journal Entry", + posting_date=date, + company=frappe.db.get_single_value('Global Defaults', 'default_company'), + accounts=je_item, + voucher_type='Exchange Rate Revaluation', + multi_currency=1 + )) + j_entry.save() + j_entry.submit() + return j_entry.name + +@frappe.whitelist() +def makeReverseJE(date,name): + je_doc = frappe.get_doc("Journal Entry",name) + je_dict = [] + for entry in je_doc.accounts: + je_json = {} + je_json["account"] = entry.account + je_json["credit_in_account_currency"] = entry.debit_in_account_currency + je_json["debit_in_account_currency"] = entry.credit_in_account_currency + je_json["party_type"] = entry.party_type if not entry.party_type is None else '' + je_json["party"] = entry.party if not entry.party is None else '' + je_json["reference_type"] = entry.reference_type if not entry.reference_type is None else '' + je_json["reference_name"] = entry.reference_name if not entry.reference_name is None else '' + je_dict.append(je_json) + return makeJournalEntry(date,je_dict) + + +@frappe.whitelist() +def getLastCreatedDocument(name,currency): + return frappe.get_all("Open Invoice Exchange Rate Revaluation",filters = [["Open Invoice Exchange Rate Revaluation","name","!=",name],["Open Invoice Exchange Rate Revaluation","docstatus","=","1"],["Open Invoice Exchange Rate Revaluation","currency","=",str(currency)]],fields = ["name","journal_entry"],order_by = "revaluation_date desc",limit_start = 0,limit_page_length = 1) + + +@frappe.whitelist() +def getInvoiceExchangeRate(date, currency): + return get_exchange_rate( + currency, frappe.defaults.get_global_default("currency"), str(date) + ) + + +@frappe.whitelist() +def getInvoice(currency, name): + doc = frappe.get_doc("Open Invoice Exchange Rate Revaluation", name) + sinv_details = frappe.get_all( + "Sales Invoice", + filters=[ + ["Sales Invoice", "currency", "=", str(currency)], + ["Sales Invoice", "party_account_currency", "!=", str(currency)], + ["Sales Invoice", "company", "=", doc.company], + ["Sales Invoice", "status", "in", ["Unpaid", "Overdue"]], + ], + fields=[ + "name", + "grand_total", + "conversion_rate", + "currency", + "party_account_currency", + "customer", + ], + ) + pinv_details = frappe.get_all( + "Purchase Invoice", + filters=[ + ["Purchase Invoice", "currency", "=", str(currency)], + ["Purchase Invoice", "party_account_currency", "!=", str(currency)], + ["Purchase Invoice", "company", "=", doc.company], + ["Purchase Invoice", "status", "in", ["Unpaid", "Overdue"]], + ], + fields=[ + "name", + "grand_total", + "conversion_rate", + "currency", + "party_account_currency", + "supplier", + ], + ) + doc.inv_err_detail = [] + doc.save() + count = 1 + for sinv in sinv_details: + if not flt(sinv.conversion_rate) == flt(doc.exchange_rate_to_company_currency): + addChildItem( + name, + sinv.name, + "Sales Invoice", + sinv.conversion_rate, + sinv.currency, + sinv.grand_total, + doc.exchange_rate_to_company_currency, + count, + ) + count += 1 + for pinv in pinv_details: + if not flt(pinv.conversion_rate) == flt(doc.exchange_rate_to_company_currency): + addChildItem( + name, + pinv.name, + "Purchase Invoice", + pinv.conversion_rate, + pinv.currency, + pinv.grand_total, + doc.exchange_rate_to_company_currency, + count, + ) + count += 1 + return sinv_details + + +def addChildItem( + name, + inv_no, + invoice_type, + invoice_exchange_rate, + invoice_currency, + invoice_amount, + current_exchange, + idx, +): + gain_loss = (flt(invoice_amount) * flt(invoice_exchange_rate)) - ( + flt(invoice_amount) * flt(current_exchange) + ) + frappe.get_doc( + dict( + doctype="Inv ERR Detail", + parent=name, + parenttype="Open Invoice Exchange Rate Revaluation", + parentfield="inv_err_detail", + invoice_number=inv_no, + invoice_type=invoice_type, + invoice_exchange_rate=invoice_exchange_rate, + invoice_currency=invoice_currency, + invoice_gain_or_loss=gain_loss, + invoice_amount=invoice_amount, + idx=idx, + ) + ).insert() + + + + + diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.js b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.js new file mode 100644 index 0000000..892a100 --- /dev/null +++ b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.js @@ -0,0 +1,23 @@ +/* eslint-disable */ +// rename this file from _test_[name] to test_[name] to activate +// and remove above this line + +QUnit.test("test: Open Invoice Exchange Rate Revaluation", function (assert) { + let done = assert.async(); + + // number of asserts + assert.expect(1); + + frappe.run_serially([ + // insert a new Open Invoice Exchange Rate Revaluation + () => frappe.tests.make('Open Invoice Exchange Rate Revaluation', [ + // values to be set + {key: 'value'} + ]), + () => { + assert.equal(cur_frm.doc.key, 'value'); + }, + () => done() + ]); + +}); diff --git a/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.py b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.py new file mode 100644 index 0000000..6c573d1 --- /dev/null +++ b/av_tools/av_tools/doctype/open_invoice_exchange_rate_revaluation/test_open_invoice_exchange_rate_revaluation.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- +# Copyright (c) 2019, Aakvatech and Contributors +# See license.txt +from __future__ import unicode_literals +import unittest + +class TestOpenInvoiceExchangeRateRevaluation(unittest.TestCase): + pass diff --git a/av_tools/patches.txt b/av_tools/patches.txt index 32ab44b..2c9e920 100644 --- a/av_tools/patches.txt +++ b/av_tools/patches.txt @@ -26,3 +26,4 @@ av_tools.patches.v1_0.move_csf_tz_print_formats av_tools.patches.v1_0.move_salary_register_reports av_tools.patches.v1_0.move_financial_and_trade_reports av_tools.patches.v1_0.move_hr_access_and_loan_reports +av_tools.patches.v1_0.move_finance_and_education_doctypes diff --git a/av_tools/patches/v1_0/move_finance_and_education_doctypes.py b/av_tools/patches/v1_0/move_finance_and_education_doctypes.py new file mode 100644 index 0000000..0020a02 --- /dev/null +++ b/av_tools/patches/v1_0/move_finance_and_education_doctypes.py @@ -0,0 +1,14 @@ +import frappe + + +DOCTYPES = ( + "Employee Salary Component Limit", + "Bank Statement Summary", + "Open Invoice Exchange Rate Revaluation", +) + + +def execute(): + for doctype_name in DOCTYPES: + if frappe.db.exists("DocType", doctype_name): + frappe.db.set_value("DocType", doctype_name, "module", "Av Tools")