fix: Purchase Order and Invoice linking

This commit is contained in:
Deepesh Garg
2021-01-21 15:57:21 +05:30
parent d9a6a6fe6a
commit 3f6f20b0d2
9 changed files with 134 additions and 26 deletions

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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,

View File

@@ -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({

View File

@@ -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: {

View File

@@ -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",

View File

@@ -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'));
}
}
}
});

View File

@@ -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,