mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-08 23:52:57 +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):
|
def set_missing_values(source, target):
|
||||||
target.run_method("set_missing_values")
|
target.run_method("set_missing_values")
|
||||||
|
set_purchase_references(target)
|
||||||
|
|
||||||
def update_details(source_doc, target_doc, source_parent):
|
def update_details(source_doc, target_doc, source_parent):
|
||||||
target_doc.inter_company_invoice_reference = source_doc.name
|
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
|
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,
|
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):
|
company_address=None, shipping_address_name=None, master_doctype=None):
|
||||||
# Update Party Details
|
# Update Party Details
|
||||||
|
|||||||
@@ -1116,14 +1116,15 @@
|
|||||||
"fieldname": "represents_company",
|
"fieldname": "represents_company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Represents Company",
|
"label": "Represents Company",
|
||||||
"options": "Company"
|
"options": "Company",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-01-10 20:50:41.545354",
|
"modified": "2021-01-20 22:07:23.487138",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Buying",
|
"module": "Buying",
|
||||||
"name": "Purchase Order",
|
"name": "Purchase Order",
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ class AccountsController(TransactionBase):
|
|||||||
self.ensure_supplier_is_not_blocked()
|
self.ensure_supplier_is_not_blocked()
|
||||||
|
|
||||||
self.validate_date_with_fiscal_year()
|
self.validate_date_with_fiscal_year()
|
||||||
|
self.validate_inter_company_reference()
|
||||||
|
|
||||||
self.set_incoming_rate()
|
self.set_incoming_rate()
|
||||||
|
|
||||||
if self.meta.get_field("currency"):
|
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,
|
validate_fiscal_year(self.get(date_field), self.fiscal_year, self.company,
|
||||||
self.meta.get_label(date_field), self)
|
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):
|
def validate_due_date(self):
|
||||||
if self.get('is_pos'): return
|
if self.get('is_pos'): return
|
||||||
|
|
||||||
|
|||||||
@@ -399,7 +399,6 @@ class StockController(AccountsController):
|
|||||||
self.validate_in_transit_warehouses()
|
self.validate_in_transit_warehouses()
|
||||||
self.validate_multi_currency()
|
self.validate_multi_currency()
|
||||||
self.validate_packed_items()
|
self.validate_packed_items()
|
||||||
self.validate_inter_company_reference()
|
|
||||||
|
|
||||||
def validate_in_transit_warehouses(self):
|
def validate_in_transit_warehouses(self):
|
||||||
if (self.doctype == 'Sales Invoice' and self.get('update_stock')) or self.doctype == 'Delivery Note':
|
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'):
|
if self.doctype in ('Sales Invoice', 'Delivery Note Item') and self.get('packed_items'):
|
||||||
frappe.throw(_("Packed Items cannot be transferred internally"))
|
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):
|
def repost_future_sle_and_gle(self):
|
||||||
args = frappe._dict({
|
args = frappe._dict({
|
||||||
"posting_date": self.posting_date,
|
"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([
|
return frappe.run_serially([
|
||||||
() => set_value('currency', currency),
|
() => set_value('currency', currency),
|
||||||
() => set_value('price_list_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);
|
this.calculate_taxes_and_totals(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
update_stock: function() {
|
set_internal_warehouses: function() {
|
||||||
let me = this;
|
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) {
|
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) {
|
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);
|
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) {
|
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) {
|
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);
|
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)) {
|
in_list(['Purchase Order', 'Purchase Receipt', 'Purchase Invoice'], this.frm.doctype)) {
|
||||||
erpnext.utils.get_shipping_address(this.frm, function(){
|
erpnext.utils.get_shipping_address(this.frm, function(){
|
||||||
set_party_account(set_pricing);
|
set_party_account(set_pricing);
|
||||||
})
|
});
|
||||||
|
|
||||||
// Get default company billing address in Purchase Invoice, Order and Receipt
|
// Get default company billing address in Purchase Invoice, Order and Receipt
|
||||||
frappe.call({
|
frappe.call({
|
||||||
|
|||||||
@@ -276,6 +276,12 @@ erpnext.utils.validate_mandatory = function(frm, label, value, trigger_on) {
|
|||||||
|
|
||||||
erpnext.utils.get_shipping_address = function(frm, callback){
|
erpnext.utils.get_shipping_address = function(frm, callback){
|
||||||
if (frm.doc.company) {
|
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({
|
frappe.call({
|
||||||
method: "erpnext.accounts.custom.address.get_shipping_address",
|
method: "erpnext.accounts.custom.address.get_shipping_address",
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1105,7 +1105,8 @@
|
|||||||
"hide_days": 1,
|
"hide_days": 1,
|
||||||
"hide_seconds": 1,
|
"hide_seconds": 1,
|
||||||
"label": "Inter Company Order Reference",
|
"label": "Inter Company Order Reference",
|
||||||
"options": "Purchase Order"
|
"options": "Purchase Order",
|
||||||
|
"read_only": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"description": "Track this Sales Order against any Project",
|
"description": "Track this Sales Order against any Project",
|
||||||
@@ -1471,14 +1472,15 @@
|
|||||||
"fieldname": "represents_company",
|
"fieldname": "represents_company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"label": "Represents Company",
|
"label": "Represents Company",
|
||||||
"options": "Company"
|
"options": "Company",
|
||||||
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-file-text",
|
"icon": "fa fa-file-text",
|
||||||
"idx": 105,
|
"idx": 105,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2021-01-10 20:49:51.118079",
|
"modified": "2021-01-20 23:40:39.929296",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Selling",
|
"module": "Selling",
|
||||||
"name": "Sales Order",
|
"name": "Sales Order",
|
||||||
|
|||||||
@@ -95,15 +95,21 @@ frappe.ui.form.on("Delivery Note", {
|
|||||||
frm.page.set_inner_btn_group_as_primary(__('Create'));
|
frm.page.set_inner_btn_group_as_primary(__('Create'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frm.doc.docstatus === 1 && frm.doc.is_internal_customer && !frm.doc.inter_company_reference) {
|
if (frm.doc.docstatus == 1 && !frm.doc.inter_company_reference) {
|
||||||
frm.add_custom_button(__('Purchase Receipt'), function() {
|
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({
|
frappe.model.open_mapped_doc({
|
||||||
method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
|
method: 'erpnext.stock.doctype.delivery_note.delivery_note.make_inter_company_purchase_receipt',
|
||||||
frm: frm,
|
frm: frm,
|
||||||
})
|
});
|
||||||
}, __('Create'));
|
}, __('Create'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
frappe.ui.form.on("Delivery Note Item", {
|
frappe.ui.form.on("Delivery Note Item", {
|
||||||
|
|||||||
@@ -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):
|
def make_inter_company_transaction(doctype, source_name, target_doc=None):
|
||||||
from erpnext.accounts.doctype.sales_invoice.sales_invoice import (validate_inter_company_transaction,
|
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':
|
if doctype == 'Delivery Note':
|
||||||
source_doc = frappe.get_doc(doctype, source_name)
|
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):
|
def set_missing_values(source, target):
|
||||||
target.run_method("set_missing_values")
|
target.run_method("set_missing_values")
|
||||||
|
set_purchase_references(target)
|
||||||
|
|
||||||
if target.doctype == 'Purchase Receipt':
|
if target.doctype == 'Purchase Receipt':
|
||||||
master_doctype = 'Purchase Taxes and Charges Template'
|
master_doctype = 'Purchase Taxes and Charges Template'
|
||||||
|
|||||||
Reference in New Issue
Block a user