mirror of
https://github.com/frappe/erpnext.git
synced 2026-04-15 04:45:09 +00:00
Merge branch 'develop' into print-language
This commit is contained in:
@@ -82,7 +82,7 @@
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2024-01-30 12:35:38.645968",
|
||||
"modified": "2024-05-27 17:29:55.560840",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
@@ -127,6 +127,10 @@
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Stock Manager"
|
||||
},
|
||||
{
|
||||
"read": 1,
|
||||
"role": "Auditor"
|
||||
}
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
|
||||
@@ -481,7 +481,7 @@ def create_merge_logs(invoice_by_customer, closing_entry=None):
|
||||
if closing_entry:
|
||||
closing_entry.set_status(update=True, status="Failed")
|
||||
if isinstance(error_message, list):
|
||||
error_message = frappe.json.dumps(error_message)
|
||||
error_message = json.dumps(error_message)
|
||||
closing_entry.db_set("error_message", error_message)
|
||||
raise
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, qb
|
||||
from frappe.model.document import Document
|
||||
@@ -502,7 +504,7 @@ def is_any_doc_running(for_filter: str | dict | None = None) -> str | None:
|
||||
running_doc = None
|
||||
if for_filter:
|
||||
if isinstance(for_filter, str):
|
||||
for_filter = frappe.json.loads(for_filter)
|
||||
for_filter = json.loads(for_filter)
|
||||
|
||||
running_doc = frappe.db.get_value(
|
||||
"Process Payment Reconciliation",
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
import copy
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.model.dynamic_links import get_dynamic_link_map
|
||||
@@ -3733,9 +3734,9 @@ class TestSalesInvoice(FrappeTestCase):
|
||||
|
||||
map_docs(
|
||||
method="erpnext.stock.doctype.delivery_note.delivery_note.make_sales_invoice",
|
||||
source_names=frappe.json.dumps([dn1.name, dn2.name]),
|
||||
source_names=json.dumps([dn1.name, dn2.name]),
|
||||
target_doc=si,
|
||||
args=frappe.json.dumps({"customer": dn1.customer, "merge_taxes": 1, "filtered_children": []}),
|
||||
args=json.dumps({"customer": dn1.customer, "merge_taxes": 1, "filtered_children": []}),
|
||||
)
|
||||
si.save().submit()
|
||||
|
||||
|
||||
@@ -870,7 +870,8 @@
|
||||
"label": "Purchase Order",
|
||||
"options": "Purchase Order",
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_92",
|
||||
@@ -926,7 +927,7 @@
|
||||
"idx": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:10:36.139679",
|
||||
"modified": "2024-05-23 16:36:18.970862",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice Item",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, qb
|
||||
from frappe.model.document import Document
|
||||
@@ -163,7 +165,7 @@ def get_linked_payments_for_doc(
|
||||
@frappe.whitelist()
|
||||
def create_unreconcile_doc_for_selection(selections=None):
|
||||
if selections:
|
||||
selections = frappe.json.loads(selections)
|
||||
selections = json.loads(selections)
|
||||
# assuming each row is a unique voucher
|
||||
for row in selections:
|
||||
unrecon = frappe.new_doc("Unreconcile Payment")
|
||||
|
||||
@@ -56,7 +56,7 @@ def get_fiscal_year(
|
||||
date=None, fiscal_year=None, label="Date", verbose=1, company=None, as_dict=False, boolean=False
|
||||
):
|
||||
if isinstance(boolean, str):
|
||||
boolean = frappe.json.loads(boolean)
|
||||
boolean = loads(boolean)
|
||||
|
||||
fiscal_years = get_fiscal_years(
|
||||
date, fiscal_year, label, verbose, company, as_dict=as_dict, boolean=boolean
|
||||
@@ -1109,7 +1109,7 @@ def get_companies():
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent, company, is_root=False, include_disabled=False):
|
||||
if isinstance(include_disabled, str):
|
||||
include_disabled = frappe.json.loads(include_disabled)
|
||||
include_disabled = loads(include_disabled)
|
||||
from erpnext.accounts.report.financial_statements import sort_accounts
|
||||
|
||||
parent_fieldname = "parent_" + doctype.lower().replace(" ", "_")
|
||||
|
||||
@@ -513,7 +513,7 @@ erpnext.buying.RequestforQuotationController = class RequestforQuotationControll
|
||||
method: "frappe.desk.doctype.tag.tag.get_tagged_docs",
|
||||
args: {
|
||||
doctype: "Supplier",
|
||||
tag: args.tag,
|
||||
tag: "%" + args.tag + "%",
|
||||
},
|
||||
callback: load_suppliers,
|
||||
});
|
||||
|
||||
@@ -1942,7 +1942,7 @@ class AccountsController(TransactionBase):
|
||||
def set_advance_payment_status(self):
|
||||
new_status = None
|
||||
|
||||
stati = frappe.get_list(
|
||||
stati = frappe.get_all(
|
||||
"Payment Request",
|
||||
{
|
||||
"reference_doctype": self.doctype,
|
||||
|
||||
1311
erpnext/locale/ar.po
1311
erpnext/locale/ar.po
File diff suppressed because it is too large
Load Diff
1311
erpnext/locale/bs.po
1311
erpnext/locale/bs.po
File diff suppressed because it is too large
Load Diff
1315
erpnext/locale/de.po
1315
erpnext/locale/de.po
File diff suppressed because it is too large
Load Diff
1317
erpnext/locale/eo.po
1317
erpnext/locale/eo.po
File diff suppressed because it is too large
Load Diff
1311
erpnext/locale/es.po
1311
erpnext/locale/es.po
File diff suppressed because it is too large
Load Diff
1402
erpnext/locale/fa.po
1402
erpnext/locale/fa.po
File diff suppressed because it is too large
Load Diff
1313
erpnext/locale/fr.po
1313
erpnext/locale/fr.po
File diff suppressed because it is too large
Load Diff
1392
erpnext/locale/tr.po
1392
erpnext/locale/tr.po
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,14 @@ frappe.ui.form.on("Project", {
|
||||
filters: filters,
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("cost_center", () => {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company,
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.test_runner import make_test_records
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
@@ -321,7 +323,7 @@ class TestCustomer(FrappeTestCase):
|
||||
frappe.ValidationError,
|
||||
update_child_qty_rate,
|
||||
so.doctype,
|
||||
frappe.json.dumps([modified_item]),
|
||||
json.dumps([modified_item]),
|
||||
so.name,
|
||||
)
|
||||
|
||||
|
||||
@@ -770,13 +770,11 @@ erpnext.selling.SalesOrderController = class SalesOrderController extends erpnex
|
||||
flt(doc.per_billed, precision("per_billed", doc)) <
|
||||
100 + frappe.boot.sysdefaults.over_billing_allowance
|
||||
) {
|
||||
if (frappe.model.can_create("Payment Request")) {
|
||||
this.frm.add_custom_button(
|
||||
__("Payment Request"),
|
||||
() => this.make_payment_request(),
|
||||
__("Create")
|
||||
);
|
||||
}
|
||||
this.frm.add_custom_button(
|
||||
__("Payment Request"),
|
||||
() => this.make_payment_request(),
|
||||
__("Create")
|
||||
);
|
||||
|
||||
if (frappe.model.can_create("Payment Entry")) {
|
||||
this.frm.add_custom_button(
|
||||
|
||||
@@ -1140,7 +1140,8 @@
|
||||
"hide_seconds": 1,
|
||||
"label": "Inter Company Order Reference",
|
||||
"options": "Purchase Order",
|
||||
"read_only": 1
|
||||
"read_only": 1,
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "project",
|
||||
@@ -1661,7 +1662,7 @@
|
||||
"idx": 105,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-04-20 01:20:11.190908",
|
||||
"modified": "2024-05-27 18:51:54.905804",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Selling",
|
||||
"name": "Sales Order",
|
||||
|
||||
@@ -21,9 +21,17 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
},
|
||||
{
|
||||
fieldname: "doc_type",
|
||||
label: __("based_on"),
|
||||
label: __("Based On"),
|
||||
fieldtype: "Select",
|
||||
options: ["Sales Order", "Delivery Note", "Sales Invoice"],
|
||||
options: [
|
||||
"All",
|
||||
"Quotation",
|
||||
"Sales Order",
|
||||
"Delivery Note",
|
||||
"Sales Invoice",
|
||||
"Sales Invoice (due)",
|
||||
"Payment Entry",
|
||||
],
|
||||
default: "Sales Invoice",
|
||||
reqd: 1,
|
||||
},
|
||||
@@ -42,14 +50,18 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
fieldtype: "Date",
|
||||
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||
default:
|
||||
frappe.defaults.get_user_default("sales_start_date") ||
|
||||
erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[1],
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "to_date",
|
||||
label: __("To Date"),
|
||||
fieldtype: "Date",
|
||||
default: erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
||||
default:
|
||||
frappe.defaults.get_user_default("sales_end_date") ||
|
||||
erpnext.utils.get_fiscal_year(frappe.datetime.get_today(), true)[2],
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
@@ -73,6 +85,19 @@ frappe.query_reports["Sales Analytics"] = {
|
||||
default: "Monthly",
|
||||
reqd: 1,
|
||||
},
|
||||
{
|
||||
fieldname: "curves",
|
||||
label: __("Curves"),
|
||||
fieldtype: "Select",
|
||||
options: [
|
||||
{ value: "select", label: __("Select") },
|
||||
{ value: "all", label: __("All") },
|
||||
{ value: "non-zeros", label: __("Non-Zeros") },
|
||||
{ value: "total", label: __("Total Only") },
|
||||
],
|
||||
default: "select",
|
||||
reqd: 1,
|
||||
},
|
||||
],
|
||||
get_datatable_options(options) {
|
||||
return Object.assign(options, {
|
||||
|
||||
@@ -10,17 +10,58 @@ from erpnext.accounts.utils import get_fiscal_year
|
||||
|
||||
|
||||
def execute(filters=None):
|
||||
return Analytics(filters).run()
|
||||
filters = frappe._dict(filters or {})
|
||||
# Special report showing all doctype totals on a single chart; overrides some filters
|
||||
if filters.doc_type == "All":
|
||||
filters.tree_type = "Customer"
|
||||
filters.value_quantity = "Value"
|
||||
filters.curves = "total"
|
||||
output = None
|
||||
for dt in [
|
||||
"Quotation",
|
||||
"Sales Order",
|
||||
"Delivery Note",
|
||||
"Sales Invoice",
|
||||
"Sales Invoice (due)",
|
||||
"Payment Entry",
|
||||
]:
|
||||
filters.doc_type = dt
|
||||
output = append_report(dt, output, Analytics(filters).run())
|
||||
return output
|
||||
else:
|
||||
return Analytics(filters).run()
|
||||
|
||||
|
||||
def append_report(dt, org, new):
|
||||
# idx 1 is data, 3 is chart
|
||||
new[1].insert(0, {"entity": dt}) # heading
|
||||
new[1].append({}) # empty row
|
||||
# datasets can be an empty list if no dates are supplied by the Dashboard Chart
|
||||
if not new[3]["data"]["datasets"]:
|
||||
new[3]["data"]["datasets"].append({"name": None, "values": []})
|
||||
new[3]["data"]["datasets"][0]["name"] = dt # override curve name
|
||||
if org:
|
||||
org[1].extend(new[1])
|
||||
org[3]["data"]["datasets"].extend(new[3]["data"]["datasets"])
|
||||
return org
|
||||
else:
|
||||
return new
|
||||
|
||||
|
||||
class Analytics:
|
||||
def __init__(self, filters=None):
|
||||
self.filters = frappe._dict(filters or {})
|
||||
if self.filters.doc_type == "Payment Entry" and self.filters.value_quantity == "Quantity":
|
||||
frappe.throw(_("Only Value available for Payment Entry"))
|
||||
self.date_field = (
|
||||
"transaction_date"
|
||||
if self.filters.doc_type in ["Sales Order", "Purchase Order"]
|
||||
if self.filters.doc_type in ["Quotation", "Sales Order", "Purchase Order"]
|
||||
else "due_date"
|
||||
if self.filters.doc_type == "Sales Invoice (due)"
|
||||
else "posting_date"
|
||||
)
|
||||
if self.filters.doc_type.startswith("Sales Invoice"):
|
||||
self.filters.doc_type = "Sales Invoice"
|
||||
self.months = [
|
||||
"Jan",
|
||||
"Feb",
|
||||
@@ -95,25 +136,37 @@ class Analytics:
|
||||
self.get_rows()
|
||||
|
||||
elif self.filters.tree_type == "Item":
|
||||
if self.filters.doc_type == "Payment Entry":
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_items()
|
||||
self.get_rows()
|
||||
|
||||
elif self.filters.tree_type in ["Customer Group", "Supplier Group", "Territory"]:
|
||||
if self.filters.doc_type == "Payment Entry":
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_customer_or_territory_group()
|
||||
self.get_rows_by_group()
|
||||
|
||||
elif self.filters.tree_type == "Item Group":
|
||||
if self.filters.doc_type == "Payment Entry":
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_item_group()
|
||||
self.get_rows_by_group()
|
||||
|
||||
elif self.filters.tree_type == "Order Type":
|
||||
if self.filters.doc_type != "Sales Order":
|
||||
if self.filters.doc_type not in ["Quotation", "Sales Order"]:
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_order_type()
|
||||
self.get_rows_by_group()
|
||||
|
||||
elif self.filters.tree_type == "Project":
|
||||
if self.filters.doc_type == "Quotation":
|
||||
self.data = []
|
||||
return
|
||||
self.get_sales_transactions_based_on_project()
|
||||
self.get_rows()
|
||||
|
||||
@@ -141,11 +194,22 @@ class Analytics:
|
||||
value_field = "total_qty as value_field"
|
||||
|
||||
if self.filters.tree_type == "Customer":
|
||||
entity = "customer as entity"
|
||||
entity_name = "customer_name as entity_name"
|
||||
if self.filters.doc_type == "Quotation":
|
||||
entity = "party_name as entity"
|
||||
elif self.filters.doc_type == "Payment Entry":
|
||||
entity = "party as entity"
|
||||
entity_name = "party_name as entity_name"
|
||||
value_field = "base_received_amount as value_field"
|
||||
else:
|
||||
entity = "customer as entity"
|
||||
else:
|
||||
entity = "supplier as entity"
|
||||
entity_name = "supplier_name as entity_name"
|
||||
if self.filters.doc_type == "Payment Entry":
|
||||
entity = "party as entity"
|
||||
entity_name = "party_name as entity_name"
|
||||
value_field = "base_paid_amount as value_field"
|
||||
|
||||
self.entries = frappe.get_all(
|
||||
self.filters.doc_type,
|
||||
@@ -232,6 +296,9 @@ class Analytics:
|
||||
else:
|
||||
value_field = "total_qty as value_field"
|
||||
|
||||
if self.filters.doc_type == "Payment Entry":
|
||||
value_field = "base_received_amount as value_field"
|
||||
|
||||
entity = "project as entity"
|
||||
|
||||
self.entries = frappe.get_all(
|
||||
@@ -401,7 +468,33 @@ class Analytics:
|
||||
labels = [d.get("label") for d in self.columns[3 : length - 1]]
|
||||
else:
|
||||
labels = [d.get("label") for d in self.columns[1 : length - 1]]
|
||||
self.chart = {"data": {"labels": labels, "datasets": []}, "type": "line"}
|
||||
|
||||
datasets = []
|
||||
if self.filters.curves != "select":
|
||||
for curve in self.data:
|
||||
data = {
|
||||
"name": curve.get("entity_name", curve["entity"]),
|
||||
"values": [curve[scrub(label)] for label in labels],
|
||||
}
|
||||
if self.filters.curves == "non-zeros" and not sum(data["values"]):
|
||||
continue
|
||||
elif self.filters.curves == "total" and "indent" in curve:
|
||||
if curve["indent"] == 0:
|
||||
datasets.append(data)
|
||||
elif self.filters.curves == "total":
|
||||
if datasets:
|
||||
a = [
|
||||
data["values"][idx] + datasets[0]["values"][idx]
|
||||
for idx in range(len(data["values"]))
|
||||
]
|
||||
datasets[0]["values"] = a
|
||||
else:
|
||||
datasets.append(data)
|
||||
datasets[0]["name"] = _("Total")
|
||||
else:
|
||||
datasets.append(data)
|
||||
|
||||
self.chart = {"data": {"labels": labels, "datasets": datasets}, "type": "line"}
|
||||
|
||||
if self.filters["value_quantity"] == "Value":
|
||||
self.chart["fieldtype"] = "Currency"
|
||||
|
||||
@@ -779,7 +779,7 @@
|
||||
"image_field": "company_logo",
|
||||
"is_tree": 1,
|
||||
"links": [],
|
||||
"modified": "2024-05-16 12:39:54.694232",
|
||||
"modified": "2024-05-27 17:32:49.057386",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Setup",
|
||||
"name": "Company",
|
||||
@@ -835,6 +835,10 @@
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"role": "Auditor",
|
||||
"select": 1
|
||||
}
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.utils.nestedset import NestedSet, get_root_of
|
||||
|
||||
@@ -71,7 +73,7 @@ def get_abbreviated_name(name, company):
|
||||
@frappe.whitelist()
|
||||
def get_children(doctype, parent=None, company=None, is_root=False, include_disabled=False):
|
||||
if isinstance(include_disabled, str):
|
||||
include_disabled = frappe.json.loads(include_disabled)
|
||||
include_disabled = json.loads(include_disabled)
|
||||
fields = ["name as value", "is_group as expandable"]
|
||||
filters = {}
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe import _, throw
|
||||
from frappe.contacts.address_and_contact import load_address_and_contact
|
||||
@@ -186,7 +188,7 @@ def get_children(doctype, parent=None, company=None, is_root=False, include_disa
|
||||
parent = ""
|
||||
|
||||
if isinstance(include_disabled, str):
|
||||
include_disabled = frappe.json.loads(include_disabled)
|
||||
include_disabled = json.loads(include_disabled)
|
||||
|
||||
fields = ["name as value", "is_group as expandable"]
|
||||
filters = [
|
||||
|
||||
Reference in New Issue
Block a user