fix: GST Purchasse register and other fixes

This commit is contained in:
Deepesh Garg
2021-01-14 14:05:23 +05:30
parent cfcb1a15f8
commit 9070ec3237
9 changed files with 94 additions and 43 deletions

View File

@@ -1562,7 +1562,7 @@ def validate_inter_company_transaction(doc, doctype):
details = get_inter_company_details(doc, doctype) details = get_inter_company_details(doc, doctype)
price_list = doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"] else doc.buying_price_list price_list = doc.selling_price_list if doctype in ["Sales Invoice", "Sales Order", "Delivery Note"] else doc.buying_price_list
valid_price_list = frappe.db.get_value("Price List", {"name": price_list, "buying": 1, "selling": 1}) valid_price_list = frappe.db.get_value("Price List", {"name": price_list, "buying": 1, "selling": 1})
if not valid_price_list: if not valid_price_list and not doc.is_internal_transfer():
frappe.throw(_("Selected Price List should have buying and selling fields checked.")) frappe.throw(_("Selected Price List should have buying and selling fields checked."))
party = details.get("party") party = details.get("party")
@@ -1636,7 +1636,7 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
if doctype in ["Sales Invoice", "Sales Order"]: if doctype in ["Sales Invoice", "Sales Order"]:
item_field_map["field_map"].update({ item_field_map["field_map"].update({
"name": target_detail_field "name": target_detail_field,
}) })
if source_doc.get('update_stock'): if source_doc.get('update_stock'):
@@ -1650,8 +1650,10 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
doctype: { doctype: {
"doctype": target_doctype, "doctype": target_doctype,
"postprocess": update_details, "postprocess": update_details,
"set_target_warehouse": "set_from_warehouse",
"field_no_map": [ "field_no_map": [
"taxes_and_charges" "taxes_and_charges",
"set_warehouse"
] ]
}, },
doctype +" Item": item_field_map doctype +" Item": item_field_map

View File

@@ -49,7 +49,8 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
elif d.po_detail: elif d.po_detail:
purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, [])) purchase_receipt = ", ".join(po_pr_map.get(d.po_detail, []))
expense_account = d.expense_account or aii_account_map.get(d.company) expense_account = d.unrealized_profit_loss_account or d.expense_account \
or aii_account_map.get(d.company)
row = { row = {
'item_code': d.item_code, 'item_code': d.item_code,
@@ -316,6 +317,7 @@ def get_items(filters, additional_query_columns):
`tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company, `tabPurchase Invoice`.posting_date, `tabPurchase Invoice`.credit_to, `tabPurchase Invoice`.company,
`tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total, `tabPurchase Invoice`.supplier, `tabPurchase Invoice`.remarks, `tabPurchase Invoice`.base_net_total,
`tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description, `tabPurchase Invoice Item`.`item_code`, `tabPurchase Invoice Item`.description,
`tabPurchase Invoice`.unrealized_profit_loss_account,
`tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`, `tabPurchase Invoice Item`.`project`, `tabPurchase Invoice Item`.`purchase_order`,
`tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`, `tabPurchase Invoice Item`.`purchase_receipt`, `tabPurchase Invoice Item`.`po_detail`,
`tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`, `tabPurchase Invoice Item`.`expense_account`, `tabPurchase Invoice Item`.`stock_qty`,

View File

@@ -14,13 +14,15 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
if not filters: filters = {} if not filters: filters = {}
invoice_list = get_invoices(filters, additional_query_columns) invoice_list = get_invoices(filters, additional_query_columns)
columns, expense_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns) columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts \
= get_columns(invoice_list, additional_table_columns)
if not invoice_list: if not invoice_list:
msgprint(_("No record found")) msgprint(_("No record found"))
return columns, invoice_list return columns, invoice_list
invoice_expense_map = get_invoice_expense_map(invoice_list) invoice_expense_map = get_invoice_expense_map(invoice_list)
internal_invoice_map = get_internal_invoice_map(invoice_list)
invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list, invoice_expense_map, invoice_tax_map = get_invoice_tax_map(invoice_list,
invoice_expense_map, expense_accounts) invoice_expense_map, expense_accounts)
invoice_po_pr_map = get_invoice_po_pr_map(invoice_list) invoice_po_pr_map = get_invoice_po_pr_map(invoice_list)
@@ -52,10 +54,17 @@ def _execute(filters=None, additional_table_columns=None, additional_query_colum
# map expense values # map expense values
base_net_total = 0 base_net_total = 0
for expense_acc in expense_accounts: for expense_acc in expense_accounts:
expense_amount = flt(invoice_expense_map.get(inv.name, {}).get(expense_acc)) if inv.is_internal_supplier and inv.company == inv.represents_company:
expense_amount = 0
else:
expense_amount = flt(invoice_expense_map.get(inv.name, {}).get(expense_acc))
base_net_total += expense_amount base_net_total += expense_amount
row.append(expense_amount) row.append(expense_amount)
# Add amount in unrealized account
for account in unrealized_profit_loss_accounts:
row.append(flt(internal_invoice_map.get((inv.name, account))))
# net total # net total
row.append(base_net_total or inv.base_net_total) row.append(base_net_total or inv.base_net_total)
@@ -96,7 +105,8 @@ def get_columns(invoice_list, additional_table_columns):
"width": 80 "width": 80
} }
] ]
expense_accounts = tax_accounts = expense_columns = tax_columns = [] expense_accounts = tax_accounts = expense_columns = tax_columns = unrealized_profit_loss_accounts = \
unrealized_profit_loss_account_columns = []
if invoice_list: if invoice_list:
expense_accounts = frappe.db.sql_list("""select distinct expense_account expense_accounts = frappe.db.sql_list("""select distinct expense_account
@@ -112,17 +122,25 @@ def get_columns(invoice_list, additional_table_columns):
and parent in (%s) order by account_head""" % and parent in (%s) order by account_head""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list])) ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
unrealized_profit_loss_accounts = frappe.db.sql_list("""SELECT distinct unrealized_profit_loss_account
from `tabPurchase Invoice` where docstatus = 1 and name in (%s)
and ifnull(unrealized_profit_loss_account, '') != ''
order by unrealized_profit_loss_account""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]))
expense_columns = [(account + ":Currency/currency:120") for account in expense_accounts] expense_columns = [(account + ":Currency/currency:120") for account in expense_accounts]
unrealized_profit_loss_account_columns = [(account + ":Currency/currency:120") for account in unrealized_profit_loss_accounts]
for account in tax_accounts: for account in tax_accounts:
if account not in expense_accounts: if account not in expense_accounts:
tax_columns.append(account + ":Currency/currency:120") tax_columns.append(account + ":Currency/currency:120")
columns = columns + expense_columns + [_("Net Total") + ":Currency/currency:120"] + tax_columns + \ columns = columns + expense_columns + unrealized_profit_loss_account_columns + \
[_("Net Total") + ":Currency/currency:120"] + tax_columns + \
[_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120", [_("Total Tax") + ":Currency/currency:120", _("Grand Total") + ":Currency/currency:120",
_("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"] _("Rounded Total") + ":Currency/currency:120", _("Outstanding Amount") + ":Currency/currency:120"]
return columns, expense_accounts, tax_accounts return columns, expense_accounts, tax_accounts, unrealized_profit_loss_accounts
def get_conditions(filters): def get_conditions(filters):
conditions = "" conditions = ""
@@ -199,6 +217,19 @@ def get_invoice_expense_map(invoice_list):
return invoice_expense_map return invoice_expense_map
def get_internal_invoice_map(invoice_list):
unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
base_net_total as amount from `tabPurchase Invoice` where name in (%s)
and is_internal_supplier = 1 and company = represents_company""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
internal_invoice_map = {}
for d in unrealized_amount_details:
if d.unrealized_profit_loss_account:
internal_invoice_map.setdefault((d.name, d.unrealized_profit_loss_account), d.amount)
return internal_invoice_map
def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts): def get_invoice_tax_map(invoice_list, invoice_expense_map, expense_accounts):
tax_details = frappe.db.sql(""" tax_details = frappe.db.sql("""
select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount) select parent, account_head, case add_deduct_tax when "Add" then sum(base_tax_amount_after_discount_amount)

View File

@@ -15,7 +15,7 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
if not filters: filters = frappe._dict({}) if not filters: filters = frappe._dict({})
invoice_list = get_invoices(filters, additional_query_columns) invoice_list = get_invoices(filters, additional_query_columns)
columns, income_accounts, tax_accounts = get_columns(invoice_list, additional_table_columns) columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts = get_columns(invoice_list, additional_table_columns)
if not invoice_list: if not invoice_list:
msgprint(_("No record found")) msgprint(_("No record found"))
@@ -82,12 +82,10 @@ def _execute(filters, additional_table_columns=None, additional_query_columns=No
}) })
# Add amount in unrealized account # Add amount in unrealized account
if inv.is_internal_customer and inv.company == inv.represents_company: for account in unrealized_profit_loss_accounts:
internal_invoice_details = internal_invoice_map.get(inv.name) row.update({
if internal_invoice_details: frappe.scrub(account): flt(internal_invoice_map.get((inv.name, account)))
row.update({ })
frappe.scrub(internal_invoice_details['account']): internal_invoice_details['amount']
})
# net total # net total
row.update({'net_total': base_net_total or inv.base_net_total}) row.update({'net_total': base_net_total or inv.base_net_total})
@@ -334,7 +332,7 @@ def get_columns(invoice_list, additional_table_columns):
columns = columns + income_columns + unrealized_profit_loss_account_columns + \ columns = columns + income_columns + unrealized_profit_loss_account_columns + \
net_total_column + tax_columns + total_columns net_total_column + tax_columns + total_columns
return columns, income_accounts, tax_accounts return columns, income_accounts, tax_accounts, unrealized_profit_loss_accounts
def get_conditions(filters): def get_conditions(filters):
conditions = "" conditions = ""
@@ -421,15 +419,12 @@ def get_internal_invoice_map(invoice_list):
unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account, unrealized_amount_details = frappe.db.sql("""SELECT name, unrealized_profit_loss_account,
base_net_total as amount from `tabSales Invoice` where name in (%s) base_net_total as amount from `tabSales Invoice` where name in (%s)
and is_internal_customer = 1 and company = represents_company""" % and is_internal_customer = 1 and company = represents_company""" %
', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1, debug=1) ', '.join(['%s']*len(invoice_list)), tuple([inv.name for inv in invoice_list]), as_dict=1)
internal_invoice_map = {} internal_invoice_map = {}
for d in unrealized_amount_details: for d in unrealized_amount_details:
if d.unrealized_profit_loss_account: if d.unrealized_profit_loss_account:
internal_invoice_map.setdefault(d.name, { internal_invoice_map.setdefault((d.name, d.unrealized_profit_loss_account), d.amount)
'account': d.unrealized_profit_loss_account,
'amount': d.amount
})
return internal_invoice_map return internal_invoice_map

View File

@@ -164,16 +164,16 @@ erpnext.buying.PurchaseOrderController = erpnext.buying.BuyingController.extend(
if (doc.docstatus === 1 && !doc.inter_company_order_reference) { if (doc.docstatus === 1 && !doc.inter_company_order_reference) {
let me = this; let me = this;
frappe.model.with_doc("Supplier", me.frm.doc.supplier, () => { let internal = me.frm.doc.is_internal_supplier;
let supplier = frappe.model.get_doc("Supplier", me.frm.doc.supplier); if (internal) {
let internal = supplier.is_internal_supplier; let button_label = (me.frm.doc.company === me.frm.doc.represents_company) ? "Internal Sales Order" :
let disabled = supplier.disabled; "Inter Company Sales Order";
if (internal === 1 && disabled === 0) {
me.frm.add_custom_button("Inter Company Order", function() { me.frm.add_custom_button(button_label, function() {
me.make_inter_company_order(me.frm); me.make_inter_company_order(me.frm);
}, __('Create')); }, __('Create'));
} }
});
} }
} }

View File

@@ -111,12 +111,12 @@ class AccountsController(TransactionBase):
self.set_inter_company_account() self.set_inter_company_account()
validate_regional(self) validate_regional(self)
validate_einvoice_fields(self) validate_einvoice_fields(self)
if self.doctype != 'Material Request': if self.doctype != 'Material Request':
apply_pricing_rule_on_transaction(self) apply_pricing_rule_on_transaction(self)
def before_cancel(self): def before_cancel(self):
validate_einvoice_fields(self) validate_einvoice_fields(self)
@@ -963,9 +963,9 @@ class AccountsController(TransactionBase):
It will an internal transfer if its an internal customer and representation It will an internal transfer if its an internal customer and representation
company is same as billing company company is same as billing company
""" """
if self.doctype in ('Sales Invoice', 'Delivery Note'): if self.doctype in ('Sales Invoice', 'Delivery Note', 'Sales Order'):
internal_party_field = 'is_internal_customer' internal_party_field = 'is_internal_customer'
elif self.doctype in ('Purchase Invoice', 'Purchase Receipt'): elif self.doctype in ('Purchase Invoice', 'Purchase Receipt', 'Purchase Order'):
internal_party_field = 'is_internal_supplier' internal_party_field = 'is_internal_supplier'
if self.get(internal_party_field) and (self.represents_company == self.company): if self.get(internal_party_field) and (self.represents_company == self.company):

View File

@@ -252,10 +252,13 @@ class BuyingController(StockController):
else: else:
rate = frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), 'rate') rate = frappe.db.get_value(ref_doctype, d.get(frappe.scrub(ref_doctype)), 'rate')
if rate != d.rate: if self.is_internal_transfer():
frappe.msgprint(_("Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer") if rate != d.rate:
.format(d.idx), alert=1) d.rate = rate
d.rate = rate d.discount_percentage = 0
d.discount_amount = 0
frappe.msgprint(_("Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer")
.format(d.idx), alert=1)
def get_supplied_items_cost(self, item_row_id, reset_outgoing_rate=True): def get_supplied_items_cost(self, item_row_id, reset_outgoing_rate=True):
supplied_items_cost = 0.0 supplied_items_cost = 0.0

View File

@@ -3,7 +3,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe.utils import cint, flt, cstr, comma_or, get_link_to_form from frappe.utils import cint, flt, cstr, comma_or, get_link_to_form, nowtime
from frappe import _, throw from frappe import _, throw
from erpnext.stock.get_item_details import get_bin_details from erpnext.stock.get_item_details import get_bin_details
from erpnext.stock.utils import get_incoming_rate from erpnext.stock.utils import get_incoming_rate
@@ -322,7 +322,7 @@ class SellingController(StockController):
"item_code": d.item_code, "item_code": d.item_code,
"warehouse": d.warehouse, "warehouse": d.warehouse,
"posting_date": self.get('posting_date') or self.get('transaction_date'), "posting_date": self.get('posting_date') or self.get('transaction_date'),
"posting_time": self.get('posting_time'), "posting_time": self.get('posting_time') or nowtime(),
"qty": -1 * flt(d.get('stock_qty') or d.get('actual_qty')), "qty": -1 * flt(d.get('stock_qty') or d.get('actual_qty')),
"serial_no": d.get('serial_no'), "serial_no": d.get('serial_no'),
"company": self.company, "company": self.company,
@@ -332,7 +332,7 @@ class SellingController(StockController):
}, raise_error_if_no_rate=False) }, raise_error_if_no_rate=False)
# For internal transfers use incoming rate as the valuation rate # For internal transfers use incoming rate as the valuation rate
if self.get('is_internal_customer'): if self.is_internal_transfer():
rate = flt(d.incoming_rate * d.conversion_factor, d.precision('rate')) rate = flt(d.incoming_rate * d.conversion_factor, d.precision('rate'))
if d.rate != rate: if d.rate != rate:
d.rate = rate d.rate = rate

View File

@@ -721,6 +721,24 @@ erpnext.TransactionController = erpnext.taxes_and_totals.extend({
this.calculate_taxes_and_totals(false); this.calculate_taxes_and_totals(false);
}, },
update_stock: function() {
let me = this;
if (['Delivery Note', 'Sales Invoice'].includes(me.frm.doc.doctype)) {
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.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);
});
}
}
},
company: function() { company: function() {
var me = this; var me = this;
var set_pricing = function() { var set_pricing = function() {