Merge branch 'develop' of https://github.com/frappe/erpnext into ledger_preview
This commit is contained in:
commit
b523c779f5
@ -10,6 +10,7 @@ from frappe.model.document import Document
|
|||||||
from frappe.query_builder.custom import ConstantColumn
|
from frappe.query_builder.custom import ConstantColumn
|
||||||
from frappe.utils import cint, flt
|
from frappe.utils import cint, flt
|
||||||
|
|
||||||
|
from erpnext import get_default_cost_center
|
||||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
||||||
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
|
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import (
|
||||||
get_amounts_not_reflected_in_system,
|
get_amounts_not_reflected_in_system,
|
||||||
@ -140,6 +141,9 @@ def create_journal_entry_bts(
|
|||||||
second_account
|
second_account
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
company = frappe.get_value("Account", company_account, "company")
|
||||||
|
|
||||||
accounts = []
|
accounts = []
|
||||||
# Multi Currency?
|
# Multi Currency?
|
||||||
accounts.append(
|
accounts.append(
|
||||||
@ -149,6 +153,7 @@ def create_journal_entry_bts(
|
|||||||
"debit_in_account_currency": bank_transaction.withdrawal,
|
"debit_in_account_currency": bank_transaction.withdrawal,
|
||||||
"party_type": party_type,
|
"party_type": party_type,
|
||||||
"party": party,
|
"party": party,
|
||||||
|
"cost_center": get_default_cost_center(company),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -158,11 +163,10 @@ def create_journal_entry_bts(
|
|||||||
"bank_account": bank_transaction.bank_account,
|
"bank_account": bank_transaction.bank_account,
|
||||||
"credit_in_account_currency": bank_transaction.withdrawal,
|
"credit_in_account_currency": bank_transaction.withdrawal,
|
||||||
"debit_in_account_currency": bank_transaction.deposit,
|
"debit_in_account_currency": bank_transaction.deposit,
|
||||||
|
"cost_center": get_default_cost_center(company),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
company = frappe.get_value("Account", company_account, "company")
|
|
||||||
|
|
||||||
journal_entry_dict = {
|
journal_entry_dict = {
|
||||||
"voucher_type": entry_type,
|
"voucher_type": entry_type,
|
||||||
"company": company,
|
"company": company,
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
"fieldname": "current_exchange_rate",
|
"fieldname": "current_exchange_rate",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"label": "Current Exchange Rate",
|
"label": "Current Exchange Rate",
|
||||||
|
"precision": "9",
|
||||||
"read_only": 1
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -148,7 +149,7 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-06-20 07:21:40.743460",
|
"modified": "2023-06-22 12:39:56.446722",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Exchange Rate Revaluation Account",
|
"name": "Exchange Rate Revaluation Account",
|
||||||
|
@ -85,25 +85,29 @@ erpnext.accounts.PaymentReconciliationController = class PaymentReconciliationCo
|
|||||||
|
|
||||||
// check for any running reconciliation jobs
|
// check for any running reconciliation jobs
|
||||||
if (this.frm.doc.receivable_payable_account) {
|
if (this.frm.doc.receivable_payable_account) {
|
||||||
frappe.db.get_single_value("Accounts Settings", "auto_reconcile_payments").then((enabled) => {
|
this.frm.call({
|
||||||
if(enabled) {
|
doc: this.frm.doc,
|
||||||
this.frm.call({
|
method: 'is_auto_process_enabled',
|
||||||
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
|
callback: (r) => {
|
||||||
"args": {
|
if (r.message) {
|
||||||
for_filter: {
|
this.frm.call({
|
||||||
company: this.frm.doc.company,
|
'method': "erpnext.accounts.doctype.process_payment_reconciliation.process_payment_reconciliation.is_any_doc_running",
|
||||||
party_type: this.frm.doc.party_type,
|
"args": {
|
||||||
party: this.frm.doc.party,
|
for_filter: {
|
||||||
receivable_payable_account: this.frm.doc.receivable_payable_account
|
company: this.frm.doc.company,
|
||||||
|
party_type: this.frm.doc.party_type,
|
||||||
|
party: this.frm.doc.party,
|
||||||
|
receivable_payable_account: this.frm.doc.receivable_payable_account
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}).then(r => {
|
||||||
}).then(r => {
|
if (r.message) {
|
||||||
if (r.message) {
|
let doc_link = frappe.utils.get_form_link("Process Payment Reconciliation", r.message, true);
|
||||||
let doc_link = frappe.utils.get_form_link("Process Payment Reconciliation", r.message, true);
|
let msg = __("Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.", [doc_link]);
|
||||||
let msg = __("Payment Reconciliation Job: {0} is running for this party. Can't reconcile now.", [doc_link]);
|
this.frm.dashboard.add_comment(msg, "yellow");
|
||||||
this.frm.dashboard.add_comment(msg, "yellow");
|
}
|
||||||
}
|
});
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -252,6 +252,10 @@ class PaymentReconciliation(Document):
|
|||||||
|
|
||||||
return difference_amount
|
return difference_amount
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def is_auto_process_enabled(self):
|
||||||
|
return frappe.db.get_single_value("Accounts Settings", "auto_reconcile_payments")
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def calculate_difference_on_allocation_change(self, payment_entry, invoice, allocated_amount):
|
def calculate_difference_on_allocation_change(self, payment_entry, invoice, allocated_amount):
|
||||||
invoice_exchange_map = self.get_invoice_exchange_map(invoice, payment_entry)
|
invoice_exchange_map = self.get_invoice_exchange_map(invoice, payment_entry)
|
||||||
|
@ -320,7 +320,9 @@ def get_returned_qty_map_for_row(return_against, party, row_name, doctype):
|
|||||||
return data[0]
|
return data[0]
|
||||||
|
|
||||||
|
|
||||||
def make_return_doc(doctype: str, source_name: str, target_doc=None):
|
def make_return_doc(
|
||||||
|
doctype: str, source_name: str, target_doc=None, return_against_rejected_qty=False
|
||||||
|
):
|
||||||
from frappe.model.mapper import get_mapped_doc
|
from frappe.model.mapper import get_mapped_doc
|
||||||
|
|
||||||
company = frappe.db.get_value("Delivery Note", source_name, "company")
|
company = frappe.db.get_value("Delivery Note", source_name, "company")
|
||||||
@ -471,7 +473,7 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
|
|||||||
|
|
||||||
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get("qty") or 0))
|
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get("qty") or 0))
|
||||||
|
|
||||||
if hasattr(target_doc, "stock_qty"):
|
if hasattr(target_doc, "stock_qty") and not return_against_rejected_qty:
|
||||||
target_doc.stock_qty = -1 * flt(
|
target_doc.stock_qty = -1 * flt(
|
||||||
source_doc.stock_qty - (returned_qty_map.get("stock_qty") or 0)
|
source_doc.stock_qty - (returned_qty_map.get("stock_qty") or 0)
|
||||||
)
|
)
|
||||||
@ -490,6 +492,13 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
|
|||||||
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
target_doc.rejected_warehouse = source_doc.rejected_warehouse
|
||||||
target_doc.purchase_receipt_item = source_doc.name
|
target_doc.purchase_receipt_item = source_doc.name
|
||||||
|
|
||||||
|
if doctype == "Purchase Receipt" and return_against_rejected_qty:
|
||||||
|
target_doc.qty = -1 * flt(source_doc.rejected_qty - (returned_qty_map.get("qty") or 0))
|
||||||
|
target_doc.rejected_qty = 0.0
|
||||||
|
target_doc.rejected_warehouse = ""
|
||||||
|
target_doc.warehouse = source_doc.rejected_warehouse
|
||||||
|
target_doc.received_qty = target_doc.qty
|
||||||
|
|
||||||
elif doctype == "Purchase Invoice":
|
elif doctype == "Purchase Invoice":
|
||||||
returned_qty_map = get_returned_qty_map_for_row(
|
returned_qty_map = get_returned_qty_map_for_row(
|
||||||
source_parent.name, source_parent.supplier, source_doc.name, doctype
|
source_parent.name, source_parent.supplier, source_doc.name, doctype
|
||||||
|
@ -213,10 +213,43 @@ erpnext.stock.PurchaseReceiptController = class PurchaseReceiptController extend
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_purchase_return() {
|
make_purchase_return() {
|
||||||
frappe.model.open_mapped_doc({
|
let me = this;
|
||||||
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return",
|
|
||||||
frm: cur_frm
|
let has_rejected_items = cur_frm.doc.items.filter((item) => {
|
||||||
|
if (item.rejected_qty > 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (has_rejected_items && has_rejected_items.length > 0) {
|
||||||
|
frappe.prompt([
|
||||||
|
{
|
||||||
|
label: __("Return Qty from Rejected Warehouse"),
|
||||||
|
fieldtype: "Check",
|
||||||
|
fieldname: "return_for_rejected_warehouse",
|
||||||
|
default: 1
|
||||||
|
},
|
||||||
|
], function(values){
|
||||||
|
if (values.return_for_rejected_warehouse) {
|
||||||
|
frappe.call({
|
||||||
|
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return_against_rejected_warehouse",
|
||||||
|
args: {
|
||||||
|
source_name: cur_frm.doc.name
|
||||||
|
},
|
||||||
|
callback: function(r) {
|
||||||
|
if(r.message) {
|
||||||
|
frappe.model.sync(r.message);
|
||||||
|
frappe.set_route("Form", r.message.doctype, r.message.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
cur_frm.cscript._make_purchase_return();
|
||||||
|
}
|
||||||
|
}, __("Return Qty"), __("Make Return Entry"));
|
||||||
|
} else {
|
||||||
|
cur_frm.cscript._make_purchase_return();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
close_purchase_receipt() {
|
close_purchase_receipt() {
|
||||||
@ -326,6 +359,13 @@ frappe.ui.form.on('Purchase Receipt Item', {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
cur_frm.cscript._make_purchase_return = function() {
|
||||||
|
frappe.model.open_mapped_doc({
|
||||||
|
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_purchase_return",
|
||||||
|
frm: cur_frm
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
cur_frm.cscript['Make Stock Entry'] = function() {
|
cur_frm.cscript['Make Stock Entry'] = function() {
|
||||||
frappe.model.open_mapped_doc({
|
frappe.model.open_mapped_doc({
|
||||||
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_stock_entry",
|
method: "erpnext.stock.doctype.purchase_receipt.purchase_receipt.make_stock_entry",
|
||||||
|
@ -1136,6 +1136,13 @@ def get_returned_qty_map(purchase_receipt):
|
|||||||
return returned_qty_map
|
return returned_qty_map
|
||||||
|
|
||||||
|
|
||||||
|
@frappe.whitelist()
|
||||||
|
def make_purchase_return_against_rejected_warehouse(source_name):
|
||||||
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
|
|
||||||
|
return make_return_doc("Purchase Receipt", source_name, return_against_rejected_qty=True)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def make_purchase_return(source_name, target_doc=None):
|
def make_purchase_return(source_name, target_doc=None):
|
||||||
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
from erpnext.controllers.sales_and_purchase_return import make_return_doc
|
||||||
|
@ -1827,6 +1827,33 @@ class TestPurchaseReceipt(FrappeTestCase):
|
|||||||
|
|
||||||
self.assertEqual(abs(data["stock_value_difference"]), 400.00)
|
self.assertEqual(abs(data["stock_value_difference"]), 400.00)
|
||||||
|
|
||||||
|
def test_return_from_rejected_warehouse(self):
|
||||||
|
from erpnext.stock.doctype.purchase_receipt.purchase_receipt import (
|
||||||
|
make_purchase_return_against_rejected_warehouse,
|
||||||
|
)
|
||||||
|
|
||||||
|
item_code = "_Test Item Return from Rejected Warehouse"
|
||||||
|
create_item(item_code)
|
||||||
|
|
||||||
|
warehouse = create_warehouse("_Test Warehouse Return Qty Warehouse")
|
||||||
|
rejected_warehouse = create_warehouse("_Test Rejected Warehouse Return Qty Warehouse")
|
||||||
|
|
||||||
|
# Step 1: Create Purchase Receipt with valuation rate 100
|
||||||
|
pr = make_purchase_receipt(
|
||||||
|
item_code=item_code,
|
||||||
|
warehouse=warehouse,
|
||||||
|
qty=10,
|
||||||
|
rate=100,
|
||||||
|
rejected_qty=2,
|
||||||
|
rejected_warehouse=rejected_warehouse,
|
||||||
|
)
|
||||||
|
|
||||||
|
pr_return = make_purchase_return_against_rejected_warehouse(pr.name)
|
||||||
|
self.assertEqual(pr_return.items[0].warehouse, rejected_warehouse)
|
||||||
|
self.assertEqual(pr_return.items[0].qty, 2.0 * -1)
|
||||||
|
self.assertEqual(pr_return.items[0].rejected_qty, 0.0)
|
||||||
|
self.assertEqual(pr_return.items[0].rejected_warehouse, "")
|
||||||
|
|
||||||
|
|
||||||
def prepare_data_for_internal_transfer():
|
def prepare_data_for_internal_transfer():
|
||||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_internal_supplier
|
||||||
|
Loading…
Reference in New Issue
Block a user