mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-09 00:01:18 +00:00
fix: Purchase Order and Invoice linking
This commit is contained in:
@@ -1601,6 +1601,7 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.run_method("set_missing_values")
|
||||
set_purchase_references(target)
|
||||
|
||||
def update_details(source_doc, target_doc, source_parent):
|
||||
target_doc.inter_company_invoice_reference = source_doc.name
|
||||
@@ -1682,6 +1683,90 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
|
||||
return doclist
|
||||
|
||||
def set_purchase_references(doc):
|
||||
# add internal PO or PR links if any
|
||||
if doc.is_internal_transfer():
|
||||
if doc.doctype == 'Purchase Receipt':
|
||||
so_item_map = get_delivery_note_details(doc.inter_company_invoice_reference)
|
||||
|
||||
if so_item_map:
|
||||
pd_item_map, parent_child_map, warehouse_map = \
|
||||
get_pd_details('Purchase Order Item', so_item_map, 'sales_order_item')
|
||||
|
||||
update_pr_items(doc, so_item_map, pd_item_map, parent_child_map, warehouse_map)
|
||||
|
||||
elif doc.doctype == 'Purchase Invoice':
|
||||
dn_item_map, so_item_map = get_sales_invoice_details(doc.inter_company_invoice_reference)
|
||||
# First check for Purchase receipt
|
||||
if list(dn_item_map.values()):
|
||||
pd_item_map, parent_child_map, warehouse_map = \
|
||||
get_pd_details('Purchase Receipt Item', dn_item_map, 'delivery_note_item')
|
||||
|
||||
update_pi_items(doc, 'pr_detail', 'purchase_receipt',
|
||||
dn_item_map, pd_item_map, parent_child_map, warehouse_map)
|
||||
|
||||
if list(so_item_map.values()):
|
||||
pd_item_map, parent_child_map, warehouse_map = \
|
||||
get_pd_details('Purchase Order Item', so_item_map, 'sales_order_item')
|
||||
|
||||
update_pi_items(doc, 'po_detail', 'purchase_order',
|
||||
so_item_map, pd_item_map, parent_child_map, warehouse_map)
|
||||
|
||||
def update_pi_items(doc, detail_field, parent_field, sales_item_map,
|
||||
purchase_item_map, parent_child_map, warehouse_map):
|
||||
for item in doc.get('items'):
|
||||
item.set(detail_field, purchase_item_map.get(sales_item_map.get(item.sales_invoice_item)))
|
||||
item.set(parent_field, parent_child_map.get(sales_item_map.get(item.sales_invoice_item)))
|
||||
if doc.update_stock:
|
||||
item.warehouse = warehouse_map.get(sales_item_map.get(item.sales_invoice_item))
|
||||
|
||||
def update_pr_items(doc, sales_item_map, purchase_item_map, parent_child_map, warehouse_map):
|
||||
for item in doc.get('items'):
|
||||
item.purchase_order_item = purchase_item_map.get(sales_item_map.get(item.delivery_note_item))
|
||||
item.warehouse = warehouse_map.get(sales_item_map.get(item.delivery_note_item))
|
||||
item.purchase_order = parent_child_map.get(sales_item_map.get(item.delivery_note_item))
|
||||
|
||||
def get_delivery_note_details(internal_reference):
|
||||
so_item_map = {}
|
||||
|
||||
si_item_details = frappe.get_all('Delivery Note Item', fields=['name', 'so_detail'],
|
||||
filters={'parent': internal_reference})
|
||||
|
||||
for d in si_item_details:
|
||||
so_item_map.setdefault(d.name, d.so_detail)
|
||||
|
||||
return so_item_map
|
||||
|
||||
def get_sales_invoice_details(internal_reference):
|
||||
dn_item_map = {}
|
||||
so_item_map = {}
|
||||
|
||||
si_item_details = frappe.get_all('Sales Invoice Item', fields=['name', 'so_detail',
|
||||
'dn_detail'], filters={'parent': internal_reference})
|
||||
|
||||
for d in si_item_details:
|
||||
if d.dn_detail:
|
||||
dn_item_map.setdefault(d.name, d.dn_detail)
|
||||
if d.so_detail:
|
||||
so_item_map.setdefault(d.name, d.so_detail)
|
||||
|
||||
return dn_item_map, so_item_map
|
||||
|
||||
def get_pd_details(doctype, sd_detail_map, sd_detail_field):
|
||||
pd_item_map = {}
|
||||
accepted_warehouse_map = {}
|
||||
parent_child_map = {}
|
||||
|
||||
pd_item_details = frappe.get_all(doctype,
|
||||
fields=[sd_detail_field, 'name', 'warehouse', 'parent'], filters={sd_detail_field: ('in', list(sd_detail_map.values()))})
|
||||
|
||||
for d in pd_item_details:
|
||||
pd_item_map.setdefault(d.get(sd_detail_field), d.name)
|
||||
parent_child_map.setdefault(d.get(sd_detail_field), d.parent)
|
||||
accepted_warehouse_map.setdefault(d.get(sd_detail_field), d.warehouse)
|
||||
|
||||
return pd_item_map, parent_child_map, accepted_warehouse_map
|
||||
|
||||
def update_taxes(doc, party=None, party_type=None, company=None, doctype=None, party_address=None,
|
||||
company_address=None, shipping_address_name=None, master_doctype=None):
|
||||
# Update Party Details
|
||||
|
||||
@@ -1116,14 +1116,15 @@
|
||||
"fieldname": "represents_company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Represents Company",
|
||||
"options": "Company"
|
||||
"options": "Company",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-01-10 20:50:41.545354",
|
||||
"modified": "2021-01-20 22:07:23.487138",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Buying",
|
||||
"name": "Purchase Order",
|
||||
|
||||
@@ -75,6 +75,8 @@ class AccountsController(TransactionBase):
|
||||
self.ensure_supplier_is_not_blocked()
|
||||
|
||||
self.validate_date_with_fiscal_year()
|
||||
self.validate_inter_company_reference()
|
||||
|
||||
self.set_incoming_rate()
|
||||
|
||||
if self.meta.get_field("currency"):
|
||||
@@ -207,6 +209,14 @@ class AccountsController(TransactionBase):
|
||||
validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company,
|
||||
self.meta.get_label(date_field), self)
|
||||
|
||||
def validate_inter_company_reference(self):
|
||||
if self.is_internal_transfer() and self.doctype in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
|
||||
if not (self.get('inter_company_reference') or self.get('inter_company_invoice_reference')
|
||||
or self.get('inter_company_order_reference')):
|
||||
msg = _("Internal Sale or Delivery Reference missing. ")
|
||||
msg += _("Please create purchase from internal sale or delivery document itself")
|
||||
frappe.throw(msg, title=_("Internal Sales Reference Missing"))
|
||||
|
||||
def validate_due_date(self):
|
||||
if self.get('is_pos'): return
|
||||
|
||||
|
||||
@@ -399,7 +399,6 @@ class StockController(AccountsController):
|
||||
self.validate_in_transit_warehouses()
|
||||
self.validate_multi_currency()
|
||||
self.validate_packed_items()
|
||||
self.validate_inter_company_reference()
|
||||
|
||||
def validate_in_transit_warehouses(self):
|
||||
if (self.doctype == 'Sales Invoice' and self.get('update_stock')) or self.doctype == 'Delivery Note':
|
||||
@@ -420,13 +419,6 @@ class StockController(AccountsController):
|
||||
if self.doctype in ('Sales Invoice', 'Delivery Note Item') and self.get('packed_items'):
|
||||
frappe.throw(_("Packed Items cannot be transferred internally"))
|
||||
|
||||
def validate_inter_company_reference(self):
|
||||
if self.doctype in ('Purchase Invoice', 'Purchase Receipt'):
|
||||
if not (self.get('inter_company_reference') or self.get('inter_company_invoice_reference')):
|
||||
msg = _("Internal Sale or Delivery Reference missing. ")
|
||||
msg += _("Please create purchase from internal sale or delivery document itself")
|
||||
frappe.throw(msg, title=_("Internal Sales Reference Missing"))
|
||||
|
||||
def repost_future_sle_and_gle(self):
|
||||
args = frappe._dict({
|
||||
"posting_date": self.posting_date,
|
||||
|
||||
@@ -235,6 +235,8 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
}
|
||||
};
|
||||
|
||||
this.frm.trigger('set_internal_warehouses');
|
||||
|
||||
return frappe.run_serially([
|
||||
() => set_value('currency', currency),
|
||||
() => set_value('price_list_currency', currency),
|
||||
@@ -731,16 +733,19 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
this.calculate_taxes_and_totals(false);
|
||||
},
|
||||
|
||||
update_stock: function() {
|
||||
set_internal_warehouses: function() {
|
||||
let me = this;
|
||||
if (['Delivery Note', 'Sales Invoice'].includes(me.frm.doc.doctype)) {
|
||||
if ((this.frm.doc.doctype === 'Sales Invoice' && me.frm.doc.update_stock)
|
||||
|| this.frm.doc.doctype == 'Delivery Note') {
|
||||
if (this.frm.doc.is_internal_customer && this.frm.doc.company === this.frm.doc.represents_company) {
|
||||
frappe.db.get_value('Company', this.frm.doc.company, 'default_in_transit_warehouse', function(value) {
|
||||
me.frm.set_value('set_target_warehouse', value.default_in_transit_warehouse);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (['Purchase Receipt', 'Purchase Invoice'].includes(me.frm.doc.doctype)) {
|
||||
|
||||
if ((this.frm.doc.doctype === 'Purchase Invoice' && me.frm.doc.update_stock)
|
||||
|| this.frm.doc.doctype == 'Purchase Receipt') {
|
||||
if (this.frm.doc.is_internal_supplier && this.frm.doc.company === this.frm.doc.represents_company) {
|
||||
frappe.db.get_value('Company', this.frm.doc.company, 'default_in_transit_warehouse', function(value) {
|
||||
me.frm.set_value('set_from_warehouse', value.default_in_transit_warehouse);
|
||||
@@ -835,7 +840,7 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
|
||||
in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
|
||||
erpnext.utils.get_shipping_address(this.frm, function(){
|
||||
set_party_account(set_pricing);
|
||||
})
|
||||
});
|
||||
|
||||
// Get default company billing address in Purchase Invoice, Order and Receipt
|
||||
frappe.call({
|
||||
|
||||
@@ -276,6 +276,12 @@ erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
|
||||
|
||||
erpnext.utils.get_shipping_address = function(frm, callback){
|
||||
if (frm.doc.company) {
|
||||
if (!(frm.doc.inter_com_order_reference || frm.doc.internal_invoice_reference ||
|
||||
frm.doc.internal_order_reference)) {
|
||||
if (callback) {
|
||||
return callback();
|
||||
}
|
||||
}
|
||||
frappe.call({
|
||||
method: "erpnext.accounts.custom.address.get_shipping_address",
|
||||
args: {
|
||||
|
||||
@@ -1105,7 +1105,8 @@
|
||||
"hide_days": 1,
|
||||
"hide_seconds": 1,
|
||||
"label": "Inter Company Order Reference",
|
||||
"options": "Purchase Order"
|
||||
"options": "Purchase Order",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"description": "Track this Sales Order against any Project",
|
||||
@@ -1471,14 +1472,15 @@
|
||||
"fieldname": "represents_company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Represents Company",
|
||||
"options": "Company"
|
||||
"options": "Company",
|
||||
"read_only": 1
|
||||
}
|
||||
],
|
||||
"icon": "fa fa-file-text",
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2021-01-10 20:49:51.118079",
|
||||
"modified": "2021-01-20 23:40:39.929296",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -95,13 +95,19 @@ frappe.ui.form.on("Delivery Note", {
|
||||
frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||
}
|
||||
|
||||
if (frm.doc.docstatus === 1 && frm.doc.is_internal_customer && !frm.doc.inter_company_reference) {
|
||||
frm.add_custom_button(__('Purchase Receipt'), function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
|
||||
frm: frm,
|
||||
})
|
||||
}, __('Create'));
|
||||
if (frm.doc.docstatus == 1 && !frm.doc.inter_company_reference) {
|
||||
let internal = me.frm.doc.is_internal_customer;
|
||||
if (internal) {
|
||||
let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Purchase Receipt" :
|
||||
"Inter Company Purchase Receipt";
|
||||
|
||||
me.frm.add_custom_button(button_label, function() {
|
||||
frappe.model.open_mapped_doc({
|
||||
method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
|
||||
frm: frm,
|
||||
});
|
||||
}, __('Create'));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -665,7 +665,7 @@ def make_inter_company_purchase_receipt(source_name, target_doc=None):
|
||||
|
||||
def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_transaction,
|
||||
get_inter_company_details, update_address, update_taxes)
|
||||
get_inter_company_details, update_address, update_taxes, set_purchase_references)
|
||||
|
||||
if doctype == 'Delivery Note':
|
||||
source_doc = frappe.get_doc(doctype, source_name)
|
||||
@@ -683,6 +683,7 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
|
||||
def set_missing_values(source, target):
|
||||
target.run_method("set_missing_values")
|
||||
set_purchase_references(target)
|
||||
|
||||
if target.doctype == 'Purchase Receipt':
|
||||
master_doctype = 'Purchase Taxes and Charges Template'
|
||||
@@ -726,7 +727,7 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||
doctype=target_doc.doctype, party_address=target_doc.customer_address,
|
||||
company_address=target_doc.company_address, shipping_address_name=target_doc.shipping_address_name)
|
||||
|
||||
doclist = get_mapped_doc(doctype, source_name, {
|
||||
doclist = get_mapped_doc(doctype, source_name, {
|
||||
doctype: {
|
||||
"doctype": target_doctype,
|
||||
"postprocess": update_details,
|
||||
|
||||
Reference in New Issue
Block a user