Merge branch 'develop' into fix-mr-rate-and-amount
This commit is contained in:
commit
6e015fd6be
@ -32,8 +32,8 @@ repos:
|
|||||||
- id: black
|
- id: black
|
||||||
additional_dependencies: ['click==8.0.4']
|
additional_dependencies: ['click==8.0.4']
|
||||||
|
|
||||||
- repo: https://github.com/timothycrosley/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.9.1
|
rev: 5.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
exclude: ".*setup.py$"
|
exclude: ".*setup.py$"
|
||||||
|
|||||||
@ -1776,6 +1776,8 @@
|
|||||||
"width": "50%"
|
"width": "50%"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"fetch_from": "sales_partner.commission_rate",
|
||||||
|
"fetch_if_empty": 1,
|
||||||
"fieldname": "commission_rate",
|
"fieldname": "commission_rate",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
"hide_days": 1,
|
"hide_days": 1,
|
||||||
@ -2141,7 +2143,7 @@
|
|||||||
"link_fieldname": "consolidated_invoice"
|
"link_fieldname": "consolidated_invoice"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2022-12-12 18:34:33.409895",
|
"modified": "2023-01-28 19:45:47.538163",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Sales Invoice",
|
"name": "Sales Invoice",
|
||||||
|
|||||||
@ -655,10 +655,35 @@ class GrossProfitGenerator(object):
|
|||||||
return self.calculate_buying_amount_from_sle(
|
return self.calculate_buying_amount_from_sle(
|
||||||
row, my_sle, parenttype, parent, item_row, item_code
|
row, my_sle, parenttype, parent, item_row, item_code
|
||||||
)
|
)
|
||||||
|
elif row.sales_order and row.so_detail:
|
||||||
|
incoming_amount = self.get_buying_amount_from_so_dn(row.sales_order, row.so_detail, item_code)
|
||||||
|
if incoming_amount:
|
||||||
|
return incoming_amount
|
||||||
else:
|
else:
|
||||||
return flt(row.qty) * self.get_average_buying_rate(row, item_code)
|
return flt(row.qty) * self.get_average_buying_rate(row, item_code)
|
||||||
|
|
||||||
return 0.0
|
return flt(row.qty) * self.get_average_buying_rate(row, item_code)
|
||||||
|
|
||||||
|
def get_buying_amount_from_so_dn(self, sales_order, so_detail, item_code):
|
||||||
|
from frappe.query_builder.functions import Sum
|
||||||
|
|
||||||
|
delivery_note = frappe.qb.DocType("Delivery Note")
|
||||||
|
delivery_note_item = frappe.qb.DocType("Delivery Note Item")
|
||||||
|
|
||||||
|
query = (
|
||||||
|
frappe.qb.from_(delivery_note)
|
||||||
|
.inner_join(delivery_note_item)
|
||||||
|
.on(delivery_note.name == delivery_note_item.parent)
|
||||||
|
.select(Sum(delivery_note_item.incoming_rate * delivery_note_item.stock_qty))
|
||||||
|
.where(delivery_note.docstatus == 1)
|
||||||
|
.where(delivery_note_item.item_code == item_code)
|
||||||
|
.where(delivery_note_item.against_sales_order == sales_order)
|
||||||
|
.where(delivery_note_item.so_detail == so_detail)
|
||||||
|
.groupby(delivery_note_item.item_code)
|
||||||
|
)
|
||||||
|
|
||||||
|
incoming_amount = query.run()
|
||||||
|
return flt(incoming_amount[0][0]) if incoming_amount else 0
|
||||||
|
|
||||||
def get_average_buying_rate(self, row, item_code):
|
def get_average_buying_rate(self, row, item_code):
|
||||||
args = row
|
args = row
|
||||||
@ -760,7 +785,8 @@ class GrossProfitGenerator(object):
|
|||||||
`tabSales Invoice`.territory, `tabSales Invoice Item`.item_code,
|
`tabSales Invoice`.territory, `tabSales Invoice Item`.item_code,
|
||||||
`tabSales Invoice Item`.item_name, `tabSales Invoice Item`.description,
|
`tabSales Invoice Item`.item_name, `tabSales Invoice Item`.description,
|
||||||
`tabSales Invoice Item`.warehouse, `tabSales Invoice Item`.item_group,
|
`tabSales Invoice Item`.warehouse, `tabSales Invoice Item`.item_group,
|
||||||
`tabSales Invoice Item`.brand, `tabSales Invoice Item`.dn_detail,
|
`tabSales Invoice Item`.brand, `tabSales Invoice Item`.so_detail,
|
||||||
|
`tabSales Invoice Item`.sales_order, `tabSales Invoice Item`.dn_detail,
|
||||||
`tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty,
|
`tabSales Invoice Item`.delivery_note, `tabSales Invoice Item`.stock_qty as qty,
|
||||||
`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
|
`tabSales Invoice Item`.base_net_rate, `tabSales Invoice Item`.base_net_amount,
|
||||||
`tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return,
|
`tabSales Invoice Item`.name as "item_row", `tabSales Invoice`.is_return,
|
||||||
|
|||||||
@ -302,3 +302,82 @@ class TestGrossProfit(FrappeTestCase):
|
|||||||
|
|
||||||
columns, data = execute(filters=filters)
|
columns, data = execute(filters=filters)
|
||||||
self.assertGreater(len(data), 0)
|
self.assertGreater(len(data), 0)
|
||||||
|
|
||||||
|
def test_order_connected_dn_and_inv(self):
|
||||||
|
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
|
||||||
|
|
||||||
|
"""
|
||||||
|
Test gp calculation when invoice and delivery note aren't directly connected.
|
||||||
|
SO -- INV
|
||||||
|
|
|
||||||
|
DN
|
||||||
|
"""
|
||||||
|
se = make_stock_entry(
|
||||||
|
company=self.company,
|
||||||
|
item_code=self.item,
|
||||||
|
target=self.warehouse,
|
||||||
|
qty=3,
|
||||||
|
basic_rate=100,
|
||||||
|
do_not_submit=True,
|
||||||
|
)
|
||||||
|
item = se.items[0]
|
||||||
|
se.append(
|
||||||
|
"items",
|
||||||
|
{
|
||||||
|
"item_code": item.item_code,
|
||||||
|
"s_warehouse": item.s_warehouse,
|
||||||
|
"t_warehouse": item.t_warehouse,
|
||||||
|
"qty": 10,
|
||||||
|
"basic_rate": 200,
|
||||||
|
"conversion_factor": item.conversion_factor or 1.0,
|
||||||
|
"transfer_qty": flt(item.qty) * (flt(item.conversion_factor) or 1.0),
|
||||||
|
"serial_no": item.serial_no,
|
||||||
|
"batch_no": item.batch_no,
|
||||||
|
"cost_center": item.cost_center,
|
||||||
|
"expense_account": item.expense_account,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
se = se.save().submit()
|
||||||
|
|
||||||
|
so = make_sales_order(
|
||||||
|
customer=self.customer,
|
||||||
|
company=self.company,
|
||||||
|
warehouse=self.warehouse,
|
||||||
|
item=self.item,
|
||||||
|
qty=4,
|
||||||
|
do_not_save=False,
|
||||||
|
do_not_submit=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
from erpnext.selling.doctype.sales_order.sales_order import (
|
||||||
|
make_delivery_note,
|
||||||
|
make_sales_invoice,
|
||||||
|
)
|
||||||
|
|
||||||
|
make_delivery_note(so.name).submit()
|
||||||
|
sinv = make_sales_invoice(so.name).submit()
|
||||||
|
|
||||||
|
filters = frappe._dict(
|
||||||
|
company=self.company, from_date=nowdate(), to_date=nowdate(), group_by="Invoice"
|
||||||
|
)
|
||||||
|
|
||||||
|
columns, data = execute(filters=filters)
|
||||||
|
expected_entry = {
|
||||||
|
"parent_invoice": sinv.name,
|
||||||
|
"currency": "INR",
|
||||||
|
"sales_invoice": self.item,
|
||||||
|
"customer": self.customer,
|
||||||
|
"posting_date": frappe.utils.datetime.date.fromisoformat(nowdate()),
|
||||||
|
"item_code": self.item,
|
||||||
|
"item_name": self.item,
|
||||||
|
"warehouse": "Stores - _GP",
|
||||||
|
"qty": 4.0,
|
||||||
|
"avg._selling_rate": 100.0,
|
||||||
|
"valuation_rate": 125.0,
|
||||||
|
"selling_amount": 400.0,
|
||||||
|
"buying_amount": 500.0,
|
||||||
|
"gross_profit": -100.0,
|
||||||
|
"gross_profit_%": -25.0,
|
||||||
|
}
|
||||||
|
gp_entry = [x for x in data if x.parent_invoice == sinv.name]
|
||||||
|
self.assertDictContainsSubset(expected_entry, gp_entry[0])
|
||||||
|
|||||||
@ -4,7 +4,17 @@
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, nowdate, today
|
from frappe.utils import (
|
||||||
|
add_months,
|
||||||
|
cint,
|
||||||
|
flt,
|
||||||
|
get_last_day,
|
||||||
|
get_link_to_form,
|
||||||
|
getdate,
|
||||||
|
is_last_day_of_the_month,
|
||||||
|
nowdate,
|
||||||
|
today,
|
||||||
|
)
|
||||||
from frappe.utils.user import get_users_with_role
|
from frappe.utils.user import get_users_with_role
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||||
@ -400,6 +410,9 @@ def disposal_was_made_on_original_schedule_date(schedule_idx, row, posting_date_
|
|||||||
row.depreciation_start_date, schedule_idx * cint(row.frequency_of_depreciation)
|
row.depreciation_start_date, schedule_idx * cint(row.frequency_of_depreciation)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if is_last_day_of_the_month(row.depreciation_start_date):
|
||||||
|
orginal_schedule_date = get_last_day(orginal_schedule_date)
|
||||||
|
|
||||||
if orginal_schedule_date == posting_date_of_disposal:
|
if orginal_schedule_date == posting_date_of_disposal:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@ -126,16 +126,18 @@ def get_asset_value(asset, finance_book=None):
|
|||||||
if not asset.calculate_depreciation:
|
if not asset.calculate_depreciation:
|
||||||
return flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)
|
return flt(asset.gross_purchase_amount) - flt(asset.opening_accumulated_depreciation)
|
||||||
|
|
||||||
finance_book_filter = ["finance_book", "is", "not set"]
|
result = frappe.get_all(
|
||||||
if finance_book:
|
|
||||||
finance_book_filter = ["finance_book", "=", finance_book]
|
|
||||||
|
|
||||||
return frappe.db.get_value(
|
|
||||||
doctype="Asset Finance Book",
|
doctype="Asset Finance Book",
|
||||||
filters=[["parent", "=", asset.asset_id], finance_book_filter],
|
filters={
|
||||||
fieldname="value_after_depreciation",
|
"parent": asset.asset_id,
|
||||||
|
"finance_book": finance_book or ("is", "not set"),
|
||||||
|
},
|
||||||
|
pluck="value_after_depreciation",
|
||||||
|
limit=1,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
return result[0] if result else 0.0
|
||||||
|
|
||||||
|
|
||||||
def prepare_chart_data(data, filters):
|
def prepare_chart_data(data, filters):
|
||||||
labels_values_map = {}
|
labels_values_map = {}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user