Merge pull request #35806 from frappe/version-13-hotfix

chore: release v13
This commit is contained in:
Deepesh Garg
2023-06-21 07:34:34 +05:30
committed by GitHub
10 changed files with 299 additions and 187 deletions

View File

@@ -623,7 +623,7 @@ frappe.ui.form.on('Payment Entry', {
frm.events.set_unallocated_amount(frm); frm.events.set_unallocated_amount(frm);
}, },
get_outstanding_invoice: function(frm) { get_outstanding_invoices_or_orders: function(frm, get_outstanding_invoices, get_orders_to_be_billed) {
const today = frappe.datetime.get_today(); const today = frappe.datetime.get_today();
const fields = [ const fields = [
{fieldtype:"Section Break", label: __("Posting Date")}, {fieldtype:"Section Break", label: __("Posting Date")},
@@ -653,12 +653,29 @@ frappe.ui.form.on('Payment Entry', {
{fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1}, {fieldtype:"Check", label: __("Allocate Payment Amount"), fieldname:"allocate_payment_amount", default:1},
]; ];
let btn_text = "";
if (get_outstanding_invoices) {
btn_text = "Get Outstanding Invoices";
}
else if (get_orders_to_be_billed) {
btn_text = "Get Outstanding Orders";
}
frappe.prompt(fields, function(filters){ frappe.prompt(fields, function(filters){
frappe.flags.allocate_payment_amount = true; frappe.flags.allocate_payment_amount = true;
frm.events.validate_filters_data(frm, filters); frm.events.validate_filters_data(frm, filters);
frm.doc.cost_center = filters.cost_center; frm.doc.cost_center = filters.cost_center;
frm.events.get_outstanding_documents(frm, filters); frm.events.get_outstanding_documents(frm, filters, get_outstanding_invoices, get_orders_to_be_billed);
}, __("Filters"), __("Get Outstanding Documents")); }, __("Filters"), __(btn_text));
},
get_outstanding_invoices: function(frm) {
frm.events.get_outstanding_invoices_or_orders(frm, true, false);
},
get_outstanding_orders: function(frm) {
frm.events.get_outstanding_invoices_or_orders(frm, false, true);
}, },
validate_filters_data: function(frm, filters) { validate_filters_data: function(frm, filters) {
@@ -684,7 +701,7 @@ frappe.ui.form.on('Payment Entry', {
} }
}, },
get_outstanding_documents: function(frm, filters) { get_outstanding_documents: function(frm, filters, get_outstanding_invoices, get_orders_to_be_billed) {
frm.clear_table("references"); frm.clear_table("references");
if(!frm.doc.party) { if(!frm.doc.party) {
@@ -708,6 +725,13 @@ frappe.ui.form.on('Payment Entry', {
args[key] = filters[key]; args[key] = filters[key];
} }
if (get_outstanding_invoices) {
args["get_outstanding_invoices"] = true;
}
else if (get_orders_to_be_billed) {
args["get_orders_to_be_billed"] = true;
}
frappe.flags.allocate_payment_amount = filters['allocate_payment_amount']; frappe.flags.allocate_payment_amount = filters['allocate_payment_amount'];
return frappe.call({ return frappe.call({

View File

@@ -48,7 +48,8 @@
"base_received_amount", "base_received_amount",
"base_received_amount_after_tax", "base_received_amount_after_tax",
"section_break_14", "section_break_14",
"get_outstanding_invoice", "get_outstanding_invoices",
"get_outstanding_orders",
"references", "references",
"section_break_34", "section_break_34",
"total_allocated_amount", "total_allocated_amount",
@@ -353,12 +354,6 @@
"fieldtype": "Section Break", "fieldtype": "Section Break",
"label": "Reference" "label": "Reference"
}, },
{
"depends_on": "eval:doc.docstatus==0",
"fieldname": "get_outstanding_invoice",
"fieldtype": "Button",
"label": "Get Outstanding Invoice"
},
{ {
"fieldname": "references", "fieldname": "references",
"fieldtype": "Table", "fieldtype": "Table",
@@ -726,12 +721,24 @@
"fieldname": "section_break_60", "fieldname": "section_break_60",
"fieldtype": "Section Break", "fieldtype": "Section Break",
"hide_border": 1 "hide_border": 1
},
{
"depends_on": "eval:doc.docstatus==0",
"fieldname": "get_outstanding_invoices",
"fieldtype": "Button",
"label": "Get Outstanding Invoices"
},
{
"depends_on": "eval:doc.docstatus==0",
"fieldname": "get_outstanding_orders",
"fieldtype": "Button",
"label": "Get Outstanding Orders"
} }
], ],
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-02-23 20:08:39.559814", "modified": "2023-06-19 11:38:04.387219",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Payment Entry", "name": "Payment Entry",

View File

@@ -174,6 +174,8 @@ class PaymentEntry(AccountsController):
"payment_type": self.payment_type, "payment_type": self.payment_type,
"party": self.party, "party": self.party,
"party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to, "party_account": self.paid_from if self.payment_type == "Receive" else self.paid_to,
"get_outstanding_invoices": True,
"get_orders_to_be_billed": True,
} }
) )
@@ -198,7 +200,7 @@ class PaymentEntry(AccountsController):
): ):
frappe.throw( frappe.throw(
_( _(
"{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' button to get the latest outstanding amount." "{0} {1} has already been partly paid. Please use the 'Get Outstanding Invoice' or the 'Get Outstanding Orders' button to get the latest outstanding amounts."
).format(d.reference_doctype, d.reference_name) ).format(d.reference_doctype, d.reference_name)
) )
@@ -1365,32 +1367,48 @@ def get_outstanding_reference_documents(args):
if args.get("company"): if args.get("company"):
condition += " and company = {0}".format(frappe.db.escape(args.get("company"))) condition += " and company = {0}".format(frappe.db.escape(args.get("company")))
outstanding_invoices = get_outstanding_invoices( outstanding_invoices = []
args.get("party_type"), negative_outstanding_invoices = []
args.get("party"),
args.get("party_account"),
args.get("company"),
filters=args,
condition=condition,
)
outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices) if args.get("get_outstanding_invoices"):
outstanding_invoices = get_outstanding_invoices(
args.get("party_type"),
args.get("party"),
args.get("party_account"),
args.get("company"),
filters=args,
condition=condition,
)
for d in outstanding_invoices: outstanding_invoices = split_invoices_based_on_payment_terms(outstanding_invoices)
d["exchange_rate"] = 1
if party_account_currency != company_currency: for d in outstanding_invoices:
if d.voucher_type in ("Sales Invoice", "Purchase Invoice", "Expense Claim"): d["exchange_rate"] = 1
d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate") if party_account_currency != company_currency:
elif d.voucher_type == "Journal Entry": if d.voucher_type in ("Sales Invoice", "Purchase Invoice", "Expense Claim"):
d["exchange_rate"] = get_exchange_rate( d["exchange_rate"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "conversion_rate")
party_account_currency, company_currency, d.posting_date elif d.voucher_type == "Journal Entry":
) d["exchange_rate"] = get_exchange_rate(
if d.voucher_type in ("Purchase Invoice"): party_account_currency, company_currency, d.posting_date
d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no") )
if d.voucher_type in ("Purchase Invoice"):
d["bill_no"] = frappe.db.get_value(d.voucher_type, d.voucher_no, "bill_no")
# Get negative outstanding sales /purchase invoices
negative_outstanding_invoices = []
if args.get("party_type") not in ["Student", "Employee"] and not args.get("voucher_no"):
negative_outstanding_invoices = get_negative_outstanding_invoices(
args.get("party_type"),
args.get("party"),
args.get("party_account"),
party_account_currency,
company_currency,
condition=condition,
)
# Get all SO / PO which are not fully billed or against which full advance not paid # Get all SO / PO which are not fully billed or against which full advance not paid
orders_to_be_billed = [] orders_to_be_billed = []
if args.get("party_type") != "Student": if args.get("get_orders_to_be_billed") and args.get("party_type") != "Student":
orders_to_be_billed = get_orders_to_be_billed( orders_to_be_billed = get_orders_to_be_billed(
args.get("posting_date"), args.get("posting_date"),
args.get("party_type"), args.get("party_type"),
@@ -1401,25 +1419,22 @@ def get_outstanding_reference_documents(args):
filters=args, filters=args,
) )
# Get negative outstanding sales /purchase invoices
negative_outstanding_invoices = []
if args.get("party_type") not in ["Student", "Employee"] and not args.get("voucher_no"):
negative_outstanding_invoices = get_negative_outstanding_invoices(
args.get("party_type"),
args.get("party"),
args.get("party_account"),
party_account_currency,
company_currency,
condition=condition,
)
data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed data = negative_outstanding_invoices + outstanding_invoices + orders_to_be_billed
if not data: if not data:
if args.get("get_outstanding_invoices") and args.get("get_orders_to_be_billed"):
ref_document_type = "invoices or orders"
elif args.get("get_outstanding_invoices"):
ref_document_type = "invoices"
elif args.get("get_orders_to_be_billed"):
ref_document_type = "orders"
frappe.msgprint( frappe.msgprint(
_( _(
"No outstanding invoices found for the {0} {1} which qualify the filters you have specified." "No outstanding {0} found for the {1} {2} which qualify the filters you have specified."
).format(_(args.get("party_type")).lower(), frappe.bold(args.get("party"))) ).format(
ref_document_type, _(args.get("party_type")).lower(), frappe.bold(args.get("party"))
)
) )
return data return data

View File

@@ -125,12 +125,14 @@ def get_revenue(data, period_list, include_in_gross=1):
data_to_be_removed = True data_to_be_removed = True
while data_to_be_removed: while data_to_be_removed:
revenue, data_to_be_removed = remove_parent_with_no_child(revenue, period_list) revenue, data_to_be_removed = remove_parent_with_no_child(revenue)
revenue = adjust_account(revenue, period_list)
adjust_account_totals(revenue, period_list)
return copy.deepcopy(revenue) return copy.deepcopy(revenue)
def remove_parent_with_no_child(data, period_list): def remove_parent_with_no_child(data):
data_to_be_removed = False data_to_be_removed = False
for parent in data: for parent in data:
if "is_group" in parent and parent.get("is_group") == 1: if "is_group" in parent and parent.get("is_group") == 1:
@@ -147,16 +149,19 @@ def remove_parent_with_no_child(data, period_list):
return data, data_to_be_removed return data, data_to_be_removed
def adjust_account(data, period_list, consolidated=False): def adjust_account_totals(data, period_list):
leaf_nodes = [item for item in data if item["is_group"] == 0]
totals = {} totals = {}
for node in leaf_nodes: for d in reversed(data):
set_total(node, node["total"], data, totals) if d.get("is_group"):
for d in data: for period in period_list:
for period in period_list: # reset totals for group accounts as totals set by get_data doesn't consider include_in_gross check
key = period if consolidated else period.key d[period.key] = sum(
d["total"] = totals[d["account"]] item[period.key] for item in data if item.get("parent_account") == d.get("account")
return data )
else:
set_total(d, d["total"], data, totals)
d["total"] = totals[d["account"]]
def set_total(node, value, complete_list, totals): def set_total(node, value, complete_list, totals):
@@ -191,6 +196,9 @@ def get_profit(
if profit_loss[key]: if profit_loss[key]:
has_value = True has_value = True
if not profit_loss.get("total"):
profit_loss["total"] = 0
profit_loss["total"] += profit_loss[key]
if has_value: if has_value:
return profit_loss return profit_loss
@@ -229,6 +237,9 @@ def get_net_profit(
if profit_loss[key]: if profit_loss[key]:
has_value = True has_value = True
if not profit_loss.get("total"):
profit_loss["total"] = 0
profit_loss["total"] += profit_loss[key]
if has_value: if has_value:
return profit_loss return profit_loss

View File

@@ -466,15 +466,19 @@ def get_gl_entries_on_asset_disposal(asset, selling_amount=0, finance_book=None,
"cost_center": depreciation_cost_center, "cost_center": depreciation_cost_center,
"posting_date": date, "posting_date": date,
}, },
{
"account": accumulated_depr_account,
"debit_in_account_currency": accumulated_depr_amount,
"debit": accumulated_depr_amount,
"cost_center": depreciation_cost_center,
"posting_date": date,
},
] ]
if accumulated_depr_amount:
gl_entries.append(
{
"account": accumulated_depr_account,
"debit_in_account_currency": accumulated_depr_amount,
"debit": accumulated_depr_amount,
"cost_center": depreciation_cost_center,
"posting_date": date,
},
)
profit_amount = flt(selling_amount) - flt(value_after_depreciation) profit_amount = flt(selling_amount) - flt(value_after_depreciation)
if profit_amount: if profit_amount:
get_profit_gl_entries( get_profit_gl_entries(

View File

@@ -19,56 +19,6 @@ frappe.query_reports["Fixed Asset Register"] = {
options: "\nIn Location\nDisposed", options: "\nIn Location\nDisposed",
default: 'In Location' default: 'In Location'
}, },
{
"fieldname":"filter_based_on",
"label": __("Period Based On"),
"fieldtype": "Select",
"options": ["Fiscal Year", "Date Range"],
"default": "Fiscal Year",
"reqd": 1
},
{
"fieldname":"from_date",
"label": __("Start Date"),
"fieldtype": "Date",
"default": frappe.datetime.add_months(frappe.datetime.nowdate(), -12),
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
"reqd": 1
},
{
"fieldname":"to_date",
"label": __("End Date"),
"fieldtype": "Date",
"default": frappe.datetime.nowdate(),
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
"reqd": 1
},
{
"fieldname":"from_fiscal_year",
"label": __("Start Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
"reqd": 1
},
{
"fieldname":"to_fiscal_year",
"label": __("End Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
"reqd": 1
},
{
"fieldname":"date_based_on",
"label": __("Date Based On"),
"fieldtype": "Select",
"options": ["Purchase Date", "Available For Use Date"],
"default": "Purchase Date",
"reqd": 1
},
{ {
fieldname:"asset_category", fieldname:"asset_category",
label: __("Asset Category"), label: __("Asset Category"),
@@ -89,22 +39,67 @@ frappe.query_reports["Fixed Asset Register"] = {
default: "--Select a group--", default: "--Select a group--",
reqd: 1 reqd: 1
}, },
{
fieldname:"finance_book",
label: __("Finance Book"),
fieldtype: "Link",
options: "Finance Book",
depends_on: "eval: doc.filter_by_finance_book == 1",
},
{
fieldname:"filter_by_finance_book",
label: __("Filter by Finance Book"),
fieldtype: "Check"
},
{ {
fieldname:"only_existing_assets", fieldname:"only_existing_assets",
label: __("Only existing assets"), label: __("Only existing assets"),
fieldtype: "Check" fieldtype: "Check"
}, },
{
fieldname:"finance_book",
label: __("Finance Book"),
fieldtype: "Link",
options: "Finance Book",
},
{
"fieldname": "include_default_book_assets",
"label": __("Include Default Book Assets"),
"fieldtype": "Check",
"default": 1
},
{
"fieldname":"filter_based_on",
"label": __("Period Based On"),
"fieldtype": "Select",
"options": ["--Select a period--", "Fiscal Year", "Date Range"],
"default": "--Select a period--",
},
{
"fieldname":"from_date",
"label": __("Start Date"),
"fieldtype": "Date",
"default": frappe.datetime.add_months(frappe.datetime.nowdate(), -12),
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
},
{
"fieldname":"to_date",
"label": __("End Date"),
"fieldtype": "Date",
"default": frappe.datetime.nowdate(),
"depends_on": "eval: doc.filter_based_on == 'Date Range'",
},
{
"fieldname":"from_fiscal_year",
"label": __("Start Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
},
{
"fieldname":"to_fiscal_year",
"label": __("End Year"),
"fieldtype": "Link",
"options": "Fiscal Year",
"default": frappe.defaults.get_user_default("fiscal_year"),
"depends_on": "eval: doc.filter_based_on == 'Fiscal Year'",
},
{
"fieldname":"date_based_on",
"label": __("Date Based On"),
"fieldtype": "Select",
"options": ["Purchase Date", "Available For Use Date"],
"default": "Purchase Date",
"depends_on": "eval: doc.filter_based_on == 'Date Range' || doc.filter_based_on == 'Fiscal Year'",
},
] ]
}; };

View File

@@ -2,9 +2,11 @@
# For license information, please see license.txt # For license information, please see license.txt
from itertools import chain
import frappe import frappe
from frappe import _ from frappe import _
from frappe.query_builder.functions import Sum from frappe.query_builder.functions import IfNull, Sum
from frappe.utils import cstr, flt, formatdate, getdate from frappe.utils import cstr, flt, formatdate, getdate
from erpnext.accounts.report.financial_statements import ( from erpnext.accounts.report.financial_statements import (
@@ -13,7 +15,6 @@ from erpnext.accounts.report.financial_statements import (
validate_fiscal_year, validate_fiscal_year,
) )
from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
def execute(filters=None): def execute(filters=None):
@@ -64,11 +65,9 @@ def get_conditions(filters):
def get_data(filters): def get_data(filters):
data = [] data = []
conditions = get_conditions(filters) conditions = get_conditions(filters)
depreciation_amount_map = get_finance_book_value_map(filters)
pr_supplier_map = get_purchase_receipt_supplier_map() pr_supplier_map = get_purchase_receipt_supplier_map()
pi_supplier_map = get_purchase_invoice_supplier_map() pi_supplier_map = get_purchase_invoice_supplier_map()
@@ -102,20 +101,27 @@ def get_data(filters):
] ]
assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields) assets_record = frappe.db.get_all("Asset", filters=conditions, fields=fields)
assets_linked_to_fb = None assets_linked_to_fb = get_assets_linked_to_fb(filters)
if filters.filter_by_finance_book: company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
assets_linked_to_fb = frappe.db.get_all(
doctype="Asset Finance Book", if filters.include_default_book_assets and company_fb:
filters={"finance_book": filters.finance_book or ("is", "not set")}, finance_book = company_fb
pluck="parent", elif filters.finance_book:
) finance_book = filters.finance_book
else:
finance_book = None
depreciation_amount_map = get_asset_depreciation_amount_map(filters, finance_book)
for asset in assets_record: for asset in assets_record:
if assets_linked_to_fb and asset.asset_id not in assets_linked_to_fb: if assets_linked_to_fb and asset.asset_id not in assets_linked_to_fb:
continue continue
asset_value = get_asset_value_after_depreciation(asset.asset_id, filters.finance_book) asset_value = get_asset_value_after_depreciation(
asset.asset_id, finance_book
) or get_asset_value_after_depreciation(asset.asset_id)
row = { row = {
"asset_id": asset.asset_id, "asset_id": asset.asset_id,
"asset_name": asset.asset_name, "asset_name": asset.asset_name,
@@ -126,7 +132,7 @@ def get_data(filters):
or pi_supplier_map.get(asset.purchase_invoice), or pi_supplier_map.get(asset.purchase_invoice),
"gross_purchase_amount": asset.gross_purchase_amount, "gross_purchase_amount": asset.gross_purchase_amount,
"opening_accumulated_depreciation": asset.opening_accumulated_depreciation, "opening_accumulated_depreciation": asset.opening_accumulated_depreciation,
"depreciated_amount": get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters), "depreciated_amount": get_depreciation_amount_of_asset(asset, depreciation_amount_map),
"available_for_use_date": asset.available_for_use_date, "available_for_use_date": asset.available_for_use_date,
"location": asset.location, "location": asset.location,
"asset_category": asset.asset_category, "asset_category": asset.asset_category,
@@ -140,14 +146,23 @@ def get_data(filters):
def prepare_chart_data(data, filters): def prepare_chart_data(data, filters):
labels_values_map = {} labels_values_map = {}
date_field = frappe.scrub(filters.date_based_on) if filters.filter_based_on not in ("Date Range", "Fiscal Year"):
filters_filter_based_on = "Date Range"
date_field = "purchase_date"
filters_from_date = min(data, key=lambda a: a.get(date_field)).get(date_field)
filters_to_date = max(data, key=lambda a: a.get(date_field)).get(date_field)
else:
filters_filter_based_on = filters.filter_based_on
date_field = frappe.scrub(filters.date_based_on)
filters_from_date = filters.from_date
filters_to_date = filters.to_date
period_list = get_period_list( period_list = get_period_list(
filters.from_fiscal_year, filters.from_fiscal_year,
filters.to_fiscal_year, filters.to_fiscal_year,
filters.from_date, filters_from_date,
filters.to_date, filters_to_date,
filters.filter_based_on, filters_filter_based_on,
"Monthly", "Monthly",
company=filters.company, company=filters.company,
ignore_fiscal_year=True, ignore_fiscal_year=True,
@@ -184,57 +199,76 @@ def prepare_chart_data(data, filters):
} }
def get_depreciation_amount_of_asset(asset, depreciation_amount_map, filters): def get_assets_linked_to_fb(filters):
if asset.calculate_depreciation: afb = frappe.qb.DocType("Asset Finance Book")
depr_amount = depreciation_amount_map.get(asset.asset_id) or 0.0
else:
depr_amount = get_manual_depreciation_amount_of_asset(asset, filters)
return flt(depr_amount, 2) query = frappe.qb.from_(afb).select(
afb.parent,
def get_finance_book_value_map(filters):
date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
return frappe._dict(
frappe.db.sql(
""" Select
parent, SUM(depreciation_amount)
FROM `tabDepreciation Schedule`
WHERE
parentfield='schedules'
AND schedule_date<=%s
AND journal_entry IS NOT NULL
AND ifnull(finance_book, '')=%s
GROUP BY parent""",
(date, cstr(filters.finance_book or "")),
)
) )
if filters.include_default_book_assets:
company_fb = frappe.get_cached_value("Company", filters.company, "default_finance_book")
def get_manual_depreciation_amount_of_asset(asset, filters): if filters.finance_book and company_fb and cstr(filters.finance_book) != cstr(company_fb):
frappe.throw(_("To use a different finance book, please uncheck 'Include Default Book Assets'"))
query = query.where(
(afb.finance_book.isin([cstr(filters.finance_book), cstr(company_fb), ""]))
| (afb.finance_book.isnull())
)
else:
query = query.where(
(afb.finance_book.isin([cstr(filters.finance_book), ""])) | (afb.finance_book.isnull())
)
assets_linked_to_fb = list(chain(*query.run(as_list=1)))
return assets_linked_to_fb
def get_depreciation_amount_of_asset(asset, depreciation_amount_map):
return depreciation_amount_map.get(asset.asset_id) or 0.0
def get_asset_depreciation_amount_map(filters, finance_book):
date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date date = filters.to_date if filters.filter_based_on == "Date Range" else filters.year_end_date
(_, _, depreciation_expense_account) = get_depreciation_accounts(asset) asset = frappe.qb.DocType("Asset")
gle = frappe.qb.DocType("GL Entry") gle = frappe.qb.DocType("GL Entry")
aca = frappe.qb.DocType("Asset Category Account")
company = frappe.qb.DocType("Company")
result = ( query = (
frappe.qb.from_(gle) frappe.qb.from_(gle)
.select(Sum(gle.debit)) .join(asset)
.where(gle.against_voucher == asset.asset_id) .on(gle.against_voucher == asset.name)
.where(gle.account == depreciation_expense_account) .join(aca)
.on((aca.parent == asset.asset_category) & (aca.company_name == asset.company))
.join(company)
.on(company.name == asset.company)
.select(asset.name.as_("asset"), Sum(gle.debit).as_("depreciation_amount"))
.where(
gle.account == IfNull(aca.depreciation_expense_account, company.depreciation_expense_account)
)
.where(gle.debit != 0) .where(gle.debit != 0)
.where(gle.is_cancelled == 0) .where(gle.is_cancelled == 0)
.where(gle.posting_date <= date) .where(asset.docstatus == 1)
).run() .groupby(asset.name)
)
if result and result[0] and result[0][0]: if finance_book:
depr_amount = result[0][0] query = query.where(
(gle.finance_book.isin([cstr(finance_book), ""])) | (gle.finance_book.isnull())
)
else: else:
depr_amount = 0 query = query.where((gle.finance_book.isin([""])) | (gle.finance_book.isnull()))
return depr_amount if filters.filter_based_on in ("Date Range", "Fiscal Year"):
query = query.where(gle.posting_date <= date)
asset_depr_amount_map = query.run()
return dict(asset_depr_amount_map)
def get_purchase_receipt_supplier_map(): def get_purchase_receipt_supplier_map():

View File

@@ -293,8 +293,8 @@ def get_last_accrual_date(loan, posting_date):
# interest for last interest accrual date is already booked, so add 1 day # interest for last interest accrual date is already booked, so add 1 day
last_disbursement_date = get_last_disbursement_date(loan, posting_date) last_disbursement_date = get_last_disbursement_date(loan, posting_date)
if last_disbursement_date and getdate(last_disbursement_date) > getdate( if last_disbursement_date and getdate(last_disbursement_date) > add_days(
last_interest_accrual_date getdate(last_interest_accrual_date), 1
): ):
last_interest_accrual_date = last_disbursement_date last_interest_accrual_date = last_disbursement_date

View File

@@ -113,6 +113,7 @@ class PurchaseReceipt(BuyingController):
self.set_status() self.set_status()
self.po_required() self.po_required()
self.validate_items_quality_inspection()
self.validate_with_previous_doc() self.validate_with_previous_doc()
self.validate_uom_is_integer("uom", ["qty", "received_qty"]) self.validate_uom_is_integer("uom", ["qty", "received_qty"])
self.validate_uom_is_integer("stock_uom", "stock_qty") self.validate_uom_is_integer("stock_uom", "stock_qty")
@@ -183,6 +184,26 @@ class PurchaseReceipt(BuyingController):
if not d.purchase_order: if not d.purchase_order:
frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code)) frappe.throw(_("Purchase Order number required for Item {0}").format(d.item_code))
def validate_items_quality_inspection(self):
for item in self.get("items"):
if item.quality_inspection:
qi = frappe.db.get_value(
"Quality Inspection",
item.quality_inspection,
["reference_type", "reference_name", "item_code"],
as_dict=True,
)
if qi.reference_type != self.doctype or qi.reference_name != self.name:
msg = f"""Row #{item.idx}: Please select a valid Quality Inspection with Reference Type
{frappe.bold(self.doctype)} and Reference Name {frappe.bold(self.name)}."""
frappe.throw(_(msg))
if qi.item_code != item.item_code:
msg = f"""Row #{item.idx}: Please select a valid Quality Inspection with Item Code
{frappe.bold(item.item_code)}."""
frappe.throw(_(msg))
def get_already_received_qty(self, po, po_detail): def get_already_received_qty(self, po, po_detail):
qty = frappe.db.sql( qty = frappe.db.sql(
"""select sum(qty) from `tabPurchase Receipt Item` """select sum(qty) from `tabPurchase Receipt Item`

View File

@@ -122,7 +122,8 @@
"oldfieldname": "purpose", "oldfieldname": "purpose",
"oldfieldtype": "Select", "oldfieldtype": "Select",
"options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor", "options": "Material Issue\nMaterial Receipt\nMaterial Transfer\nMaterial Transfer for Manufacture\nMaterial Consumption for Manufacture\nManufacture\nRepack\nSend to Subcontractor",
"read_only": 1 "read_only": 1,
"search_index": 1
}, },
{ {
"fieldname": "company", "fieldname": "company",
@@ -619,7 +620,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-05-02 05:21:39.060501", "modified": "2023-06-19 18:23:40.748114",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Stock", "module": "Stock",
"name": "Stock Entry", "name": "Stock Entry",